LibreOffice Module svx (master) 1
numfmtsh.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <tools/color.hxx>
21
22#include <tools/debug.hxx>
24#include <o3tl/safeint.hxx>
25#include <svl/numformat.hxx>
26#include <svl/zforlist.hxx>
27#include <svl/zformat.hxx>
28#include <svl/currencytable.hxx>
29
30#include <svx/numfmtsh.hxx>
31#include <svx/flagsdef.hxx>
32#include <svx/tbcontrl.hxx>
33
34#include <limits>
35
36namespace
37{
38double GetDefaultValNum(const SvNumFormatType nType)
39{
40 switch (nType)
41 {
42 case SvNumFormatType::NUMBER:
44 case SvNumFormatType::CURRENCY:
46 case SvNumFormatType::PERCENT:
48 case SvNumFormatType::DATE:
49 case SvNumFormatType::DATETIME:
51 case SvNumFormatType::TIME:
53 case SvNumFormatType::SCIENTIFIC:
55 case SvNumFormatType::FRACTION:
57 case SvNumFormatType::LOGICAL:
59 default:
60 break;
61 }
63}
64}
65
67 sal_uInt32 nFormatKey,
68 SvxNumberValueType eNumValType,
69 const OUString& rNumStr)
70{
71 return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, rNumStr);
72}
73
75 sal_uInt32 nFormatKey,
76 SvxNumberValueType eNumValType, double nNumVal,
77 const OUString* pNumStr)
78{
79 return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, nNumVal, pNumStr);
80}
81
83 SvxNumberValueType eNumValType, const OUString& rNumStr)
84 : pFormatter(pNumFormatter)
85 , pCurFmtTable(nullptr)
86 , eValType(eNumValType)
87 , bUndoAddList(true)
88 , nCurFormatKey(nFormatKey)
89 , nCurCategory(SvNumFormatType::ALL)
90 , eCurLanguage(LANGUAGE_NONE)
91 , pCurCurrencyEntry(nullptr)
92 , bBankingSymbol(false)
93 , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
94 , bUseStarFormat(false)
95 , bIsDefaultValNum(true)
96{
97 nValNum = 0;
98
99 switch (eValType)
100 {
102 aValStr = rNumStr;
103 break;
105 if (pFormatter)
106 {
107 nValNum = GetDefaultValNum(pFormatter->GetType(nCurFormatKey));
108 }
109 [[fallthrough]];
111 default:
112 aValStr.clear();
113 }
114}
115
117 SvxNumberValueType eNumValType, double nNumVal,
118 const OUString* pNumStr)
119 : pFormatter(pNumFormatter)
120 , pCurFmtTable(nullptr)
121 , eValType(eNumValType)
122 , bUndoAddList(true)
123 , nCurFormatKey(nFormatKey)
124 , nCurCategory(SvNumFormatType::ALL)
125 , eCurLanguage(LANGUAGE_NONE)
126 , pCurCurrencyEntry(nullptr)
127 , bBankingSymbol(false)
128 , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
129 , bUseStarFormat(false)
130 , bIsDefaultValNum(false)
131{
132 // #50441# When used in Writer, the SvxNumberInfoItem contains the
133 // original string in addition to the value
134
135 if (pNumStr)
136 aValStr = *pNumStr;
137
138 switch (eValType)
139 {
141 nValNum = nNumVal;
142 break;
145 default:
146 nValNum = 0;
147 bIsDefaultValNum = true;
148 }
149}
150
152{
153 /*
154 * At this point, depending on whether the added user-defined were
155 * validated (ValidateNewEntries()), the add list is removed from
156 * the number formatter again.
157 *
158 * Deleting formats from the formatter happens for Undo reasons
159 * only in the calling instance.
160 */
161
162 if (bUndoAddList)
163 {
164 // Added formats are invalid => remove them
165
166 for (const auto& rItem : aAddList)
167 pFormatter->DeleteEntry(rItem);
168 }
169}
170
171std::vector<sal_uInt32> const& SvxNumberFormatShell::GetUpdateData() const { return aDelList; }
172
173void SvxNumberFormatShell::CategoryChanged(sal_uInt16 nCatLbPos, short& rFmtSelPos,
174 std::vector<OUString>& rFmtEntries)
175{
176 SvNumFormatType nOldCategory = nCurCategory;
179 // reinitialize currency if category newly entered
180 if (nCurCategory == SvNumFormatType::CURRENCY && nOldCategory != nCurCategory)
181 pCurCurrencyEntry = nullptr;
182 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
183}
184
185void SvxNumberFormatShell::LanguageChanged(LanguageType eLangType, short& rFmtSelPos,
186 std::vector<OUString>& rFmtEntries)
187{
188 eCurLanguage = eLangType;
190 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
191}
192
193void SvxNumberFormatShell::FormatChanged(sal_uInt16 nFmtLbPos, OUString& rPreviewStr,
194 const Color*& rpFontColor)
195{
196 if (static_cast<size_t>(nFmtLbPos) >= aCurEntryList.size())
197 return;
198
199 nCurFormatKey = aCurEntryList[nFmtLbPos];
200
202 {
203 GetPreviewString_Impl(rPreviewStr, rpFontColor);
204 }
205 else if (nCurCategory == SvNumFormatType::CURRENCY)
206 {
207 if (static_cast<size_t>(nFmtLbPos) < aCurrencyFormatList.size())
208 {
209 MakePrevStringFromVal(aCurrencyFormatList[nFmtLbPos], rPreviewStr, rpFontColor,
210 nValNum);
211 }
212 }
213}
214
215bool SvxNumberFormatShell::AddFormat(OUString& rFormat, sal_Int32& rErrPos,
216 sal_uInt16& rCatLbSelPos, short& rFmtSelPos,
217 std::vector<OUString>& rFmtEntries)
218{
219 bool bInserted = false;
220 sal_uInt32 nAddKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
221
222 if (nAddKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // exists already?
223 {
224 ::std::vector<sal_uInt32>::iterator nAt = GetRemoved_Impl(nAddKey);
225 if (nAt != aDelList.end())
226 {
227 aDelList.erase(nAt);
228 bInserted = true;
229 }
230 else
231 {
232 OSL_FAIL("duplicate format!");
233 }
234 }
235 else // new format
236 {
237 sal_Int32 nPos;
238 bInserted = pFormatter->PutEntry(rFormat, nPos, nCurCategory, nAddKey, eCurLanguage);
239 rErrPos = (nPos >= 0) ? nPos : -1;
240
241 if (bInserted)
242 {
243 // May be sorted under a different locale if LCID was parsed.
244 const SvNumberformat* pEntry = pFormatter->GetEntry(nAddKey);
245 if (pEntry)
246 {
247 LanguageType nLang = pEntry->GetLanguage();
248 if (eCurLanguage != nLang)
249 {
250 // Current language's list would not show entry, adapt.
251 eCurLanguage = nLang;
252 }
253 }
254 }
255 }
256
257 if (bInserted)
258 {
259 nCurFormatKey = nAddKey;
260 DBG_ASSERT(GetAdded_Impl(nCurFormatKey) == aAddList.end(), "duplicate format!");
261 aAddList.push_back(nCurFormatKey);
262
263 // get current table
265 nCurCategory = pFormatter->GetType(nAddKey);
266 CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
267 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
268 }
269 else if (rErrPos != 0) // syntax error
270 {
271 ;
272 }
273 else // insert twice not possible
274 {
275 OSL_FAIL("duplicate format!");
276 }
277
278 return bInserted;
279}
280
281void SvxNumberFormatShell::RemoveFormat(std::u16string_view rFormat, sal_uInt16& rCatLbSelPos,
282 short& rFmtSelPos, std::vector<OUString>& rFmtEntries)
283{
284 sal_uInt32 nDelKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
285
286 DBG_ASSERT(nDelKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "entry not found!");
287 DBG_ASSERT(!IsRemoved_Impl(nDelKey), "entry already removed!");
288
289 if ((nDelKey == NUMBERFORMAT_ENTRY_NOT_FOUND) || IsRemoved_Impl(nDelKey))
290 return;
291
292 aDelList.push_back(nDelKey);
293
294 ::std::vector<sal_uInt32>::iterator nAt = GetAdded_Impl(nDelKey);
295 if (nAt != aAddList.end())
296 {
297 aAddList.erase(nAt);
298 }
299
300 nCurCategory = pFormatter->GetType(nDelKey);
302
304
305 CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
306 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
307}
308
309void SvxNumberFormatShell::MakeFormat(OUString& rFormat, bool bThousand, bool bNegRed,
310 sal_uInt16 nPrecision, sal_uInt16 nLeadingZeroes,
311 sal_uInt16 nCurrencyPos)
312{
313 if (aCurrencyFormatList.size() > static_cast<size_t>(nCurrencyPos))
314 {
315 sal_Int32 rErrPos = 0;
316 std::vector<OUString> aFmtEList;
317
318 sal_uInt32 nFound
320
321 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
322 {
323 sal_uInt16 rCatLbSelPos = 0;
324 short rFmtSelPos = 0;
325 AddFormat(aCurrencyFormatList[nCurrencyPos], rErrPos, rCatLbSelPos, rFmtSelPos,
326 aFmtEList);
327 }
328
329 if (rErrPos == 0)
330 {
331 rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
332 nPrecision, nLeadingZeroes);
333 }
334 }
335 else
336 {
337 rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
338 nPrecision, nLeadingZeroes);
339 }
340}
341
342sal_uInt16 SvxNumberFormatShell::GetFormatIntegerDigits(std::u16string_view rFormat) const
343{
344 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
345
346 return pFormatter->GetFormatIntegerDigits(nFmtKey);
347}
348
349void SvxNumberFormatShell::GetOptions(const OUString& rFormat, bool& rThousand, bool& rNegRed,
350 sal_uInt16& rPrecision, sal_uInt16& rLeadingZeroes,
351 sal_uInt16& rCatLbPos)
352{
353 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
354
355 if (nFmtKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
356 {
357 pFormatter->GetFormatSpecialInfo(nFmtKey, rThousand, rNegRed, rPrecision, rLeadingZeroes);
358
359 CategoryToPos_Impl(pFormatter->GetType(nFmtKey), rCatLbPos);
360 }
361 else
362 {
363 bool bTestBanking = false;
364 sal_uInt16 nPos = FindCurrencyTableEntry(rFormat, bTestBanking);
365
366 if (IsInTable(nPos, bTestBanking, rFormat)
367 && pFormatter->GetFormatSpecialInfo(rFormat, rThousand, rNegRed, rPrecision,
368 rLeadingZeroes, eCurLanguage)
369 == 0)
370 {
371 rCatLbPos = CAT_CURRENCY;
372 }
373 else
374 rCatLbPos = CAT_USERDEFINED;
375 }
376}
377
378void SvxNumberFormatShell::MakePreviewString(const OUString& rFormatStr, OUString& rPreviewStr,
379 const Color*& rpFontColor)
380{
381 rpFontColor = nullptr;
382
383 sal_uInt32 nExistingFormat = pFormatter->GetEntryKey(rFormatStr, eCurLanguage);
384 if (nExistingFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
385 {
386 // real preview - not implemented in NumberFormatter for text formats
387 pFormatter->GetPreviewString(rFormatStr, nValNum, rPreviewStr, &rpFontColor, eCurLanguage,
389 }
390 else
391 {
392 // format exists
393
394 // #50441# if a string was set in addition to the value, use it for text formats
395 bool bUseText = (eValType == SvxNumberValueType::String
396 || (!aValStr.isEmpty()
397 && (pFormatter->GetType(nExistingFormat) & SvNumFormatType::TEXT)));
398
399 if (bUseText)
400 {
401 pFormatter->GetOutputString(aValStr, nExistingFormat, rPreviewStr, &rpFontColor);
402 }
403 else
404 {
406 nValNum = GetDefaultValNum(pFormatter->GetType(nExistingFormat));
407 pFormatter->GetOutputString(nValNum, nExistingFormat, rPreviewStr, &rpFontColor,
409 }
410 }
411}
412
413bool SvxNumberFormatShell::IsUserDefined(const OUString& rFmtString)
414{
415 sal_uInt32 nFound = pFormatter->GetEntryKey(rFmtString, eCurLanguage);
416
417 bool bFlag = false;
418 if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND)
419 {
420 bFlag = pFormatter->IsUserDefined(rFmtString, eCurLanguage);
421
422 if (bFlag)
423 {
424 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nFound);
425
426 if (pNumEntry != nullptr && pNumEntry->HasNewCurrency())
427 {
428 bool bTestBanking;
429 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
430 bFlag = !IsInTable(nPos, bTestBanking, rFmtString);
431 }
432 }
433 }
434 return bFlag;
435}
436
437bool SvxNumberFormatShell::FindEntry(const OUString& rFmtString, sal_uInt32* pAt /* = NULL */)
438{
439 bool bRes = false;
440
441 sal_uInt32 nFound = NUMBERFORMAT_ENTRY_NOT_FOUND;
442 // There may be multiple builtin entries with the same format code, first
443 // try if the current key matches.
445 if (pEntry && pEntry->GetLanguage() == eCurLanguage && pEntry->GetFormatstring() == rFmtString)
446 nFound = nCurFormatKey;
447
448 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
449 // Find the first matching format code.
450 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
451
452 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
453 {
454 bool bTestBanking = false;
455 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
456
457 if (IsInTable(nPos, bTestBanking, rFmtString))
458 {
460 bRes = true;
461 }
462 }
463 else
464 {
465 bRes = !IsRemoved_Impl(nFound);
466 }
467
468 if (pAt)
469 *pAt = nFound;
470
471 return bRes;
472}
473
474void SvxNumberFormatShell::GetInitSettings(sal_uInt16& nCatLbPos, LanguageType& rLangType,
475 sal_uInt16& nFmtLbSelPos,
476 std::vector<OUString>& rFmtEntries,
477 OUString& rPrevString, const Color*& rpPrevColor)
478{
479 // precondition: number formater found
480 DBG_ASSERT(pFormatter != nullptr, "Number formatter not found!");
481
482 short nSelPos = SELPOS_NONE;
483
484 // special treatment for undefined number format:
486 PosToCategory_Impl(CAT_ALL, nCurCategory); // category = all
487 else
488 nCurCategory = SvNumFormatType::UNDEFINED; // category = undefined
489
491
493 rLangType = eCurLanguage;
494
495 nSelPos = FillEntryList_Impl(rFmtEntries);
496
497 DBG_ASSERT(nSelPos != SELPOS_NONE, "Leere Formatliste!");
498
499 nFmtLbSelPos = (nSelPos != SELPOS_NONE) ? static_cast<sal_uInt16>(nSelPos) : 0;
500 GetPreviewString_Impl(rPrevString, rpPrevColor);
501}
502
503short SvxNumberFormatShell::FillEntryList_Impl(std::vector<OUString>& rList)
504{
505 /* Create a current list of format entries. The return value is
506 * the list position of the current format. If the list is empty
507 * or if there is no current format, SELPOS_NONE is delivered.
508 */
509 short nSelPos = SELPOS_NONE;
510
511 aCurEntryList.clear();
512
513 if (nCurCategory == SvNumFormatType::ALL)
514 {
515 FillEListWithStd_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
516 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
517
518 FillEListWithStd_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
519 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
520
521 FillEListWithStd_Impl(rList, SvNumFormatType::CURRENCY, nSelPos);
522 // No FillEListWithUsD_Impl() here, user defined currency formats
523 // were already added.
524
525 FillEListWithStd_Impl(rList, SvNumFormatType::DATE, nSelPos);
526 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATE, nSelPos);
527
528 FillEListWithStd_Impl(rList, SvNumFormatType::TIME, nSelPos);
529 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TIME, nSelPos);
530
531 nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, false);
532 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATETIME, nSelPos);
533
534 FillEListWithStd_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
535 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
536
537 FillEListWithStd_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
538 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
539
540 FillEListWithStd_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
541 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
542
543 FillEListWithStd_Impl(rList, SvNumFormatType::TEXT, nSelPos);
544 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TEXT, nSelPos);
545 }
546 else
547 {
548 FillEListWithStd_Impl(rList, nCurCategory, nSelPos, true);
549 nSelPos = FillEListWithUsD_Impl(rList, nCurCategory, nSelPos);
550 if (nCurCategory == SvNumFormatType::DATE || nCurCategory == SvNumFormatType::TIME)
551 nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, true);
552 }
553
554 return nSelPos;
555}
556
557void SvxNumberFormatShell::FillEListWithStd_Impl(std::vector<OUString>& rList,
558 SvNumFormatType eCategory, short& nSelPos,
559 bool bSuppressDuplicates)
560{
561 /* Create a current list of format entries. The return value is
562 * the list position of the current format. If the list is empty
563 * or if there is no current format, SELPOS_NONE is delivered.
564 */
565
566 assert(pCurFmtTable != nullptr);
567
568 aCurrencyFormatList.clear();
569
570 NfIndexTableOffset eOffsetStart;
571 NfIndexTableOffset eOffsetEnd;
572
573 switch (eCategory)
574 {
575 case SvNumFormatType::NUMBER:
576 eOffsetStart = NF_NUMBER_START;
577 eOffsetEnd = NF_NUMBER_END;
578 break;
579 case SvNumFormatType::PERCENT:
580 eOffsetStart = NF_PERCENT_START;
581 eOffsetEnd = NF_PERCENT_END;
582 break;
583 case SvNumFormatType::CURRENCY:
584 // Currency entries are generated and assembled, ignore
585 // bSuppressDuplicates.
586 nSelPos = FillEListWithCurrency_Impl(rList, nSelPos);
587 return;
588 case SvNumFormatType::DATE:
589 eOffsetStart = NF_DATE_START;
590 eOffsetEnd = NF_DATE_END;
591 break;
592 case SvNumFormatType::TIME:
593 eOffsetStart = NF_TIME_START;
594 eOffsetEnd = NF_TIME_END;
595 break;
596 case SvNumFormatType::SCIENTIFIC:
597 eOffsetStart = NF_SCIENTIFIC_START;
598 eOffsetEnd = NF_SCIENTIFIC_END;
599 break;
600 case SvNumFormatType::FRACTION:
601 eOffsetStart = NF_FRACTION_START;
602 eOffsetEnd = NF_FRACTION_END;
603 // Fraction formats are internally generated by the number
604 // formatter and are not supposed to contain duplicates anyway.
605 nSelPos = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, false);
606 nSelPos
608 return;
609 case SvNumFormatType::LOGICAL:
610 eOffsetStart = NF_BOOLEAN;
611 eOffsetEnd = NF_BOOLEAN;
612 break;
613 case SvNumFormatType::TEXT:
614 eOffsetStart = NF_TEXT;
615 eOffsetEnd = NF_TEXT;
616 break;
617 default:
618 return;
619 }
620
621 nSelPos
622 = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, bSuppressDuplicates);
623}
624
625short SvxNumberFormatShell::FillEListWithFormats_Impl(std::vector<OUString>& rList, short nSelPos,
626 NfIndexTableOffset eOffsetStart,
627 NfIndexTableOffset eOffsetEnd,
628 bool bSuppressDuplicates)
629{
630 /* Create a current list of format entries. The return value is
631 * the list position of the current format. If the list is empty
632 * or if there is no current format, SELPOS_NONE is delivered.
633 */
634 for (tools::Long nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex)
635 {
636 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
637 static_cast<NfIndexTableOffset>(nIndex), false);
638 }
639
640 return nSelPos;
641}
642
643short SvxNumberFormatShell::FillEListWithDateTime_Impl(std::vector<OUString>& rList, short nSelPos,
644 bool bSuppressDuplicates)
645{
646 // Append a list of date+time formats.
647
648 // Add first, so a NF_DATETIME_SYSTEM_SHORT_HHMM may be suppressed in
649 // locales that do not use 2-digit years there and this here is the
650 // default.
651 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates, NF_DATETIME_SYS_DDMMYYYY_HHMM,
652 true);
653
655 {
656 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
657 static_cast<NfIndexTableOffset>(nIndex), true);
658 }
659
660 // Always add the internally generated ISO formats.
663
664 return nSelPos;
665}
666
667void SvxNumberFormatShell::FillEListWithOneFormat_Impl(std::vector<OUString>& rList, short& nSelPos,
668 bool bSuppressDuplicates,
669 NfIndexTableOffset nOffset,
670 bool bSuppressIsoDateTime)
671{
672 sal_uInt32 nNFEntry = pFormatter->GetFormatIndex(nOffset, eCurLanguage);
673
674 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
675 if (pNumEntry == nullptr)
676 return;
677
678 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
679 sal_uInt16 nMyType;
680 CategoryToPos_Impl(nMyCat, nMyType);
681 OUString aNewFormNInfo = pNumEntry->GetFormatstring();
682
683 if (nNFEntry == nCurFormatKey)
684 {
685 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
686 }
687
688 // Ugly hack to suppress an ISO date+time format that is the default
689 // date+time format of the locale and identical to the internally generated
690 // one always to be added after/below.
691 const bool bSupIso
692 = bSuppressIsoDateTime && bSuppressDuplicates
693 && (aNewFormNInfo == "YYYY-MM-DD HH:MM:SS" || aNewFormNInfo == "YYYY-MM-DD\"T\"HH:MM:SS");
694
695 if (!bSupIso
696 && (!bSuppressDuplicates || IsEssentialFormat_Impl(nMyCat, nNFEntry)
697 || std::find(rList.begin(), rList.end(), aNewFormNInfo) == rList.end()))
698 {
699 rList.push_back(aNewFormNInfo);
700 aCurEntryList.push_back(nNFEntry);
701 }
702}
703
705{
706 if (nKey == nCurFormatKey)
707 return true;
708
710 switch (nIndex)
711 {
712 // These are preferred or edit formats.
715 case NF_TIME_HH_MMSS:
716 case NF_TIME_MMSS00:
724 return true;
725 default:
726 break;
727 }
728
730}
731
732short SvxNumberFormatShell::FillEListWithCurrency_Impl(std::vector<OUString>& rList, short nSelPos)
733{
734 /* Create a current list of format entries. The return value is
735 * the list position of the current format. If the list is empty
736 * or if there is no current format, SELPOS_NONE is delivered.
737 */
738 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
739
740 const NfCurrencyEntry* pTmpCurrencyEntry;
741 bool bTmpBanking;
742 OUString rSymbol;
743
744 bool bFlag = pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
745 &bTmpBanking);
746
747 if ((!bFlag && pCurCurrencyEntry == nullptr)
748 || (bFlag && pTmpCurrencyEntry == nullptr && rSymbol.isEmpty())
749 || (nCurCategory == SvNumFormatType::ALL))
750 {
751 if (nCurCategory == SvNumFormatType::ALL)
752 FillEListWithUserCurrencys(rList, nSelPos);
753 nSelPos = FillEListWithSysCurrencys(rList, nSelPos);
754 }
755 else
756 {
757 nSelPos = FillEListWithUserCurrencys(rList, nSelPos);
758 }
759
760 return nSelPos;
761}
762
763short SvxNumberFormatShell::FillEListWithSysCurrencys(std::vector<OUString>& rList, short nSelPos)
764{
765 /* Create a current list of format entries. The return value is
766 * the list position of the current format. If the list is empty
767 * or if there is no current format, SELPOS_NONE is delivered.
768 */
769 sal_uInt16 nMyType;
770
771 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
772
773 sal_uInt32 nNFEntry;
774 OUString aNewFormNInfo;
775
777
779 {
780 nNFEntry
782
783 if (nCurCategory == SvNumFormatType::ALL && nNFEntry != nCurFormatKey)
784 // Deprecated old currency entries, for ALL add only if used as
785 // current format key.
786 continue;
787
788 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
789
790 if (pNumEntry == nullptr)
791 continue;
792
793 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
794 CategoryToPos_Impl(nMyCat, nMyType);
795 aNewFormNInfo = pNumEntry->GetFormatstring();
796
797 if (nNFEntry == nCurFormatKey)
798 {
799 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
800 }
801
802 rList.push_back(aNewFormNInfo);
803 aCurEntryList.push_back(nNFEntry);
804 }
805
806 if (nCurCategory != SvNumFormatType::ALL)
807 {
808 for (const auto& rEntry : *pCurFmtTable)
809 {
810 sal_uInt32 nKey = rEntry.first;
811 const SvNumberformat* pNumEntry = rEntry.second;
812
813 if (!IsRemoved_Impl(nKey))
814 {
815 bool bUserNewCurrency = false;
816 if (pNumEntry->HasNewCurrency())
817 {
818 const NfCurrencyEntry* pTmpCurrencyEntry;
819 bool bTmpBanking;
820 OUString rSymbol;
821
822 pFormatter->GetNewCurrencySymbolString(nKey, rSymbol, &pTmpCurrencyEntry,
823 &bTmpBanking);
824
825 bUserNewCurrency = (pTmpCurrencyEntry != nullptr);
826 }
827
828 if (!bUserNewCurrency && (pNumEntry->GetType() & SvNumFormatType::DEFINED))
829 {
830 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
831 CategoryToPos_Impl(nMyCat, nMyType);
832 aNewFormNInfo = pNumEntry->GetFormatstring();
833
834 if (nKey == nCurFormatKey)
835 nSelPos = aCurEntryList.size();
836 rList.push_back(aNewFormNInfo);
837 aCurEntryList.push_back(nKey);
838 }
839 }
840 }
841 }
842 return nSelPos;
843}
844
845short SvxNumberFormatShell::FillEListWithUserCurrencys(std::vector<OUString>& rList, short nSelPos)
846{
847 /* Create a current list of format entries. The return value is
848 * the list position of the current format. If the list is empty
849 * or if there is no current format, SELPOS_NONE is delivered.
850 */
851 sal_uInt16 nMyType;
852
853 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
854
855 OUString aNewFormNInfo;
856
857 const NfCurrencyEntry* pTmpCurrencyEntry;
858 bool bTmpBanking, bAdaptSelPos;
859 OUString rSymbol;
860 OUString rBankSymbol;
861
862 std::vector<OUString> aList;
863 std::vector<sal_uInt32> aKeyList;
864
865 pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
866 &bTmpBanking);
867
868 OUString rShortSymbol;
869
870 if (pCurCurrencyEntry == nullptr)
871 {
872 // #110398# If no currency format was previously selected (we're not
873 // about to add another currency), try to select the initial currency
874 // format (nCurFormatKey) that was set in FormatChanged() after
875 // matching the format string entered in the dialog.
876 bAdaptSelPos = true;
877 pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(pTmpCurrencyEntry);
878 bBankingSymbol = bTmpBanking;
879 nCurCurrencyEntryPos = FindCurrencyFormat(pTmpCurrencyEntry, bTmpBanking);
880 }
881 else
882 {
883 if (pTmpCurrencyEntry == pCurCurrencyEntry)
884 bAdaptSelPos = true;
885 else
886 {
887 bAdaptSelPos = false;
888 pTmpCurrencyEntry = pCurCurrencyEntry;
889 }
890 bTmpBanking = bBankingSymbol;
891 }
892
893 if (pTmpCurrencyEntry != nullptr)
894 {
895 rSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
896 rBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
897 rShortSymbol = pTmpCurrencyEntry->BuildSymbolString(bTmpBanking, true);
898 }
899
900 for (const auto& rEntry : *pCurFmtTable)
901 {
902 sal_uInt32 nKey = rEntry.first;
903 const SvNumberformat* pNumEntry = rEntry.second;
904
905 if (!IsRemoved_Impl(nKey))
906 {
907 if (pNumEntry->GetType() & SvNumFormatType::DEFINED || pNumEntry->IsAdditionalBuiltin())
908 {
909 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
910 CategoryToPos_Impl(nMyCat, nMyType);
911 aNewFormNInfo = pNumEntry->GetFormatstring();
912
913 bool bInsFlag = false;
914 if (pNumEntry->HasNewCurrency())
915 {
916 bInsFlag = true; // merge locale formats into currency selection
917 }
918 else if ((!bTmpBanking && aNewFormNInfo.indexOf(rSymbol) >= 0)
919 || (bTmpBanking && aNewFormNInfo.indexOf(rBankSymbol) >= 0))
920 {
921 bInsFlag = true;
922 }
923 else if (aNewFormNInfo.indexOf(rShortSymbol) >= 0)
924 {
925 OUString rTstSymbol;
926 const NfCurrencyEntry* pTstCurrencyEntry;
927 bool bTstBanking;
928
929 pFormatter->GetNewCurrencySymbolString(nKey, rTstSymbol, &pTstCurrencyEntry,
930 &bTstBanking);
931
932 if (pTmpCurrencyEntry == pTstCurrencyEntry && bTstBanking == bTmpBanking)
933 {
934 bInsFlag = true;
935 }
936 }
937
938 if (bInsFlag)
939 {
940 aList.push_back(aNewFormNInfo);
941 aKeyList.push_back(nKey);
942 }
943 }
944 }
945 }
946
947 NfWSStringsDtor aWSStringsDtor;
948 sal_uInt16 nDefault;
949 if (pTmpCurrencyEntry && nCurCategory != SvNumFormatType::ALL)
950 {
951 nDefault
952 = pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, bTmpBanking);
953 if (!bTmpBanking)
954 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, true);
955 }
956 else
957 nDefault = 0;
958 if (!bTmpBanking && nCurCategory != SvNumFormatType::ALL)
959 {
960 // append formats for all currencies defined in the current I18N locale
962 sal_uInt16 nCurrCount = rCurrencyTable.size();
964 for (sal_uInt16 i = 0; i < nCurrCount; ++i)
965 {
966 const NfCurrencyEntry* pCurr = &rCurrencyTable[i];
967 if (pCurr->GetLanguage() == eLang && pTmpCurrencyEntry != pCurr)
968 {
969 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, false);
970 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, true);
971 }
972 }
973 }
974
975 size_t nOldListCount = rList.size();
976 for (size_t i = 0, nPos = nOldListCount; i < aWSStringsDtor.size(); ++i)
977 {
978 bool bFlag = true;
979 OUString aInsStr(aWSStringsDtor[i]);
980 size_t j;
981 for (j = 0; j < aList.size(); ++j)
982 {
983 if (aList[j] == aInsStr)
984 {
985 bFlag = false;
986 break;
987 }
988 }
989 if (bFlag)
990 {
991 rList.push_back(aInsStr);
993 }
994 else
995 {
996 rList.push_back(aList[j]);
997 aList.erase(aList.begin() + j);
998 aCurEntryList.insert(aCurEntryList.begin() + (nPos++), aKeyList[j]);
999 aKeyList.erase(aKeyList.begin() + j);
1000 }
1001 }
1002
1003 for (size_t i = 0; i < aKeyList.size(); ++i)
1004 {
1005 if (aKeyList[i] != NUMBERFORMAT_ENTRY_NOT_FOUND)
1006 {
1007 rList.push_back(aList[i]);
1008 aCurEntryList.push_back(aKeyList[i]);
1009 }
1010 }
1011
1012 for (size_t i = nOldListCount; i < rList.size(); ++i)
1013 {
1014 aCurrencyFormatList.push_back(rList[i]);
1015
1016 if (nSelPos == SELPOS_NONE && bAdaptSelPos && aCurEntryList[i] == nCurFormatKey)
1017 nSelPos = i;
1018 }
1019
1020 if (nSelPos == SELPOS_NONE && nCurCategory != SvNumFormatType::ALL)
1021 nSelPos = nDefault;
1022
1023 return nSelPos;
1024}
1025
1026short SvxNumberFormatShell::FillEListWithUsD_Impl(std::vector<OUString>& rList,
1027 SvNumFormatType eCategory, short nSelPos)
1028{
1029 /* Create a current list of format entries. The return value is
1030 * the list position of the current format. If the list is empty
1031 * or if there is no current format, SELPOS_NONE is delivered.
1032 */
1033
1034 assert(pCurFmtTable != nullptr);
1035
1036 OUString aNewFormNInfo;
1037
1038 const bool bCatDefined = (eCategory == SvNumFormatType::DEFINED);
1039 const bool bCategoryMatch = (eCategory != SvNumFormatType::ALL && !bCatDefined);
1040 const bool bNatNumCurrency = (eCategory == SvNumFormatType::CURRENCY);
1041
1042 for (const auto& rEntry : *pCurFmtTable)
1043 {
1044 const SvNumberformat* pNumEntry = rEntry.second;
1045
1046 if (bCategoryMatch && (pNumEntry->GetMaskedType() & eCategory) != eCategory)
1047 continue; // for; type does not match category if not ALL
1048
1049 const bool bUserDefined = bool(pNumEntry->GetType() & SvNumFormatType::DEFINED);
1050 if (!bUserDefined && bCatDefined)
1051 continue; // for; not user defined in DEFINED category
1052
1053 if (!(bUserDefined || (!bCatDefined && pNumEntry->IsAdditionalBuiltin())))
1054 continue; // for; does not match criteria at all
1055
1056 const sal_uInt32 nKey = rEntry.first;
1057 if (!IsRemoved_Impl(nKey))
1058 {
1059 aNewFormNInfo = pNumEntry->GetFormatstring();
1060
1061 if (bNatNumCurrency && (aNewFormNInfo.indexOf("NatNum12") < 0 || bUserDefined))
1062 continue; // for; extra CURRENCY must be not user-defined NatNum12 type
1063
1064 bool bAdd = true;
1065 if (pNumEntry->HasNewCurrency())
1066 {
1067 bool bTestBanking;
1068 sal_uInt16 nPos = FindCurrencyTableEntry(aNewFormNInfo, bTestBanking);
1069 bAdd = !IsInTable(nPos, bTestBanking, aNewFormNInfo);
1070 }
1071 if (bAdd)
1072 {
1073 if (nKey == nCurFormatKey)
1074 nSelPos = aCurEntryList.size();
1075 rList.push_back(aNewFormNInfo);
1076 aCurEntryList.push_back(nKey);
1077 }
1078 }
1079 }
1080 return nSelPos;
1081}
1082
1083void SvxNumberFormatShell::GetPreviewString_Impl(OUString& rString, const Color*& rpColor)
1084{
1085 rpColor = nullptr;
1086
1087 // #50441# if a string was set in addition to the value, use it for text formats
1088 bool bUseText
1090 || (!aValStr.isEmpty() && (pFormatter->GetType(nCurFormatKey) & SvNumFormatType::TEXT)));
1091
1092 if (bUseText)
1093 {
1094 pFormatter->GetOutputString(aValStr, nCurFormatKey, rString, &rpColor);
1095 }
1096 else
1097 {
1099 }
1100}
1101
1102::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetRemoved_Impl(size_t nKey)
1103{
1104 return ::std::find(aDelList.begin(), aDelList.end(), nKey);
1105}
1106
1108{
1109 return GetRemoved_Impl(nKey) != aDelList.end();
1110}
1111
1112::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetAdded_Impl(size_t nKey)
1113{
1114 return ::std::find(aAddList.begin(), aAddList.end(), nKey);
1115}
1116
1117// Conversion routines:
1119{
1120 // map category css::form positions (->resource)
1121 switch (nPos)
1122 {
1123 case CAT_USERDEFINED:
1124 rCategory = SvNumFormatType::DEFINED;
1125 break;
1126 case CAT_NUMBER:
1127 rCategory = SvNumFormatType::NUMBER;
1128 break;
1129 case CAT_PERCENT:
1130 rCategory = SvNumFormatType::PERCENT;
1131 break;
1132 case CAT_CURRENCY:
1133 rCategory = SvNumFormatType::CURRENCY;
1134 break;
1135 case CAT_DATE:
1136 rCategory = SvNumFormatType::DATE;
1137 break;
1138 case CAT_TIME:
1139 rCategory = SvNumFormatType::TIME;
1140 break;
1141 case CAT_SCIENTIFIC:
1142 rCategory = SvNumFormatType::SCIENTIFIC;
1143 break;
1144 case CAT_FRACTION:
1145 rCategory = SvNumFormatType::FRACTION;
1146 break;
1147 case CAT_BOOLEAN:
1148 rCategory = SvNumFormatType::LOGICAL;
1149 break;
1150 case CAT_TEXT:
1151 rCategory = SvNumFormatType::TEXT;
1152 break;
1153 case CAT_ALL:
1154 default:
1155 rCategory = SvNumFormatType::ALL;
1156 break;
1157 }
1158}
1159
1161{
1162 // map category to css::form positions (->resource)
1163 switch (nCategory)
1164 {
1165 case SvNumFormatType::DEFINED:
1166 rPos = CAT_USERDEFINED;
1167 break;
1168 case SvNumFormatType::NUMBER:
1169 rPos = CAT_NUMBER;
1170 break;
1171 case SvNumFormatType::PERCENT:
1172 rPos = CAT_PERCENT;
1173 break;
1174 case SvNumFormatType::CURRENCY:
1175 rPos = CAT_CURRENCY;
1176 break;
1177 case SvNumFormatType::DATETIME:
1178 case SvNumFormatType::DATE:
1179 rPos = CAT_DATE;
1180 break;
1181 case SvNumFormatType::TIME:
1182 rPos = CAT_TIME;
1183 break;
1184 case SvNumFormatType::SCIENTIFIC:
1185 rPos = CAT_SCIENTIFIC;
1186 break;
1187 case SvNumFormatType::FRACTION:
1188 rPos = CAT_FRACTION;
1189 break;
1190 case SvNumFormatType::LOGICAL:
1191 rPos = CAT_BOOLEAN;
1192 break;
1193 case SvNumFormatType::TEXT:
1194 rPos = CAT_TEXT;
1195 break;
1196 case SvNumFormatType::ALL:
1197 default:
1198 rPos = CAT_ALL;
1199 }
1200}
1201
1202/*
1203 * Function: Formats the number nValue dependent on rFormatStr
1204 * and stores the result in rPreviewStr.
1205 * Input: FormatString, color, number to format
1206 * Output: Output string rPreviewStr
1207 */
1208void SvxNumberFormatShell::MakePrevStringFromVal(const OUString& rFormatStr, OUString& rPreviewStr,
1209 const Color*& rpFontColor, double nValue)
1210{
1211 rpFontColor = nullptr;
1212 pFormatter->GetPreviewString(rFormatStr, nValue, rPreviewStr, &rpFontColor, eCurLanguage);
1213}
1214
1215/*
1216 * Function: Returns the comment for a given entry.
1217 * Input: Number of the entry
1218 * Output: Comment string
1219 */
1220void SvxNumberFormatShell::SetComment4Entry(short nEntry, const OUString& aEntStr)
1221{
1222 SvNumberformat* pNumEntry;
1223 if (nEntry < 0)
1224 return;
1225 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1226 pNumEntry = const_cast<SvNumberformat*>(pFormatter->GetEntry(nMyNfEntry));
1227 if (pNumEntry != nullptr)
1228 pNumEntry->SetComment(aEntStr);
1229}
1230
1231/*
1232 * Function: Returns the comment for a given entry.
1233 * Input: Number of the entry
1234 * Output: Comment string
1235 */
1237{
1238 if (nEntry < 0)
1239 return OUString();
1240
1241 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1242 {
1243 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1244 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1245 if (pNumEntry != nullptr)
1246 return pNumEntry->GetComment();
1247 }
1248
1249 return OUString();
1250}
1251
1252/*
1253 * Function: Returns the category number for a given entry.
1254 * Input: Number of the entry
1255 * Output: Category number
1256 */
1258{
1259 if (nEntry < 0)
1260 return 0;
1261 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1262 {
1263 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1264
1265 if (nMyNfEntry != NUMBERFORMAT_ENTRY_NOT_FOUND)
1266 {
1267 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1268 if (pNumEntry != nullptr)
1269 {
1270 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
1271 sal_uInt16 nMyType;
1272 CategoryToPos_Impl(nMyCat, nMyType);
1273
1274 return static_cast<short>(nMyType);
1275 }
1276 return 0;
1277 }
1278 else if (!aCurrencyFormatList.empty())
1279 {
1280 return CAT_CURRENCY;
1281 }
1282 }
1283 return 0;
1284}
1285
1286/*
1287 * Function: Returns the information about whether an entry is user-specific.
1288 * Input: Number of the entry
1289 * Output: User-specific?
1290 */
1292{
1293 if (nEntry < 0)
1294 return false;
1295 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1296 {
1297 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1298 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1299
1300 if (pNumEntry != nullptr)
1301 {
1302 if (pNumEntry->GetType() & SvNumFormatType::DEFINED)
1303 {
1304 return true;
1305 }
1306 }
1307 }
1308 return false;
1309}
1310
1311/*
1312 * Function: Returns the format string for a given entry.
1313 * Input: Number of the entry
1314 * Output: Format string
1315 */
1317{
1318 if (nEntry < 0)
1319 return OUString();
1320
1321 if (!aCurrencyFormatList.empty()
1322 && (!pFormatter->GetEntry(aCurEntryList[nEntry])
1323 || pFormatter->GetEntry(aCurEntryList[nEntry])->GetFormatstring().indexOf("NatNum12")
1324 < 0))
1325 {
1326 if (aCurrencyFormatList.size() > o3tl::make_unsigned(nEntry))
1327 return aCurrencyFormatList[nEntry];
1328 }
1329 else
1330 {
1331 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1332 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1333
1334 if (pNumEntry != nullptr)
1335 return pNumEntry->GetFormatstring();
1336 }
1337 return OUString();
1338}
1339
1340/*
1341 * Function: Returns the list number for a given format index.
1342 * Input: Number of the entry
1343 * Output: Category number
1344 */
1345short SvxNumberFormatShell::GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
1346{
1347 short nSelP = SELPOS_NONE;
1349 {
1350 // Check list size against return type limit.
1351 if (aCurEntryList.size() <= o3tl::make_unsigned(::std::numeric_limits<short>::max()))
1352 {
1353 for (size_t i = 0; i < aCurEntryList.size(); ++i)
1354 {
1355 if (aCurEntryList[i] == nIdx)
1356 {
1357 nSelP = i;
1358 break;
1359 }
1360 }
1361 }
1362 else
1363 {
1364 OSL_FAIL("svx::SvxNumberFormatShell::GetListPos4Entry(), list got too large!");
1365 }
1366 }
1367 else
1368 {
1369 // A second list holds the generated currency formats.
1370 for (size_t i = 0; i < aCurrencyFormatList.size(); ++i)
1371 {
1372 if (rFmtString == aCurrencyFormatList[i])
1373 {
1374 nSelP = static_cast<short>(i);
1375 break;
1376 }
1377 }
1378 }
1379 return nSelP;
1380}
1381
1383{
1385}
1386
1387void SvxNumberFormatShell::GetCurrencySymbols(std::vector<OUString>& rList, sal_uInt16* pPos)
1388{
1389 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::MatchSystemCurrency();
1390
1391 bool bFlag = (pTmpCurrencyEntry == nullptr);
1392
1393 SvxCurrencyToolBoxControl::GetCurrencySymbols(rList, bFlag, aCurCurrencyList);
1394
1395 if (pPos == nullptr)
1396 return;
1397
1399 sal_uInt16 nTableCount = rCurrencyTable.size();
1400
1401 *pPos = 0;
1402 size_t nCount = aCurCurrencyList.size();
1403
1404 if (bFlag)
1405 {
1406 *pPos = 1;
1408 }
1409 else
1410 {
1411 for (size_t i = 1; i < nCount; i++)
1412 {
1413 const sal_uInt16 j = aCurCurrencyList[i];
1414 if (j != sal_uInt16(-1) && j < nTableCount && pTmpCurrencyEntry == &rCurrencyTable[j])
1415 {
1416 *pPos = static_cast<sal_uInt16>(i);
1417 nCurCurrencyEntryPos = static_cast<sal_uInt16>(i);
1418 break;
1419 }
1420 }
1421 }
1422}
1423
1425{
1427 sal_uInt16 nCount = rCurrencyTable.size();
1428
1429 bBankingSymbol = (nPos >= nCount);
1430
1431 if (nPos >= aCurCurrencyList.size())
1432 return;
1433
1434 sal_uInt16 nCurrencyPos = aCurCurrencyList[nPos];
1435 if (nCurrencyPos != sal_uInt16(-1))
1436 {
1437 pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(&rCurrencyTable[nCurrencyPos]);
1439 }
1440 else
1441 {
1442 pCurCurrencyEntry = nullptr;
1445 }
1446}
1447
1448void SvxNumberFormatShell::SetCurCurrencyEntry(NfCurrencyEntry* pCEntry)
1449{
1450 pCurCurrencyEntry = pCEntry;
1451}
1452
1453bool SvxNumberFormatShell::IsTmpCurrencyFormat(const OUString& rFmtString)
1454{
1455 sal_uInt32 nFound;
1456 FindEntry(rFmtString, &nFound);
1457 return nFound == NUMBERFORMAT_ENTRY_NEW_CURRENCY;
1458}
1459
1460sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const OUString& rFmtString)
1461{
1463 sal_uInt16 nCount = rCurrencyTable.size();
1464
1465 bool bTestBanking = false;
1466
1467 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
1468
1469 if (nPos != sal_uInt16(-1))
1470 {
1471 sal_uInt16 nStart = 0;
1472 if (bTestBanking && aCurCurrencyList.size() > nPos)
1473 {
1474 nStart = nCount;
1475 }
1476 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1477 {
1478 if (aCurCurrencyList[j] == nPos)
1479 return j;
1480 }
1481 }
1482 return sal_uInt16(-1);
1483}
1484
1485sal_uInt16 SvxNumberFormatShell::FindCurrencyTableEntry(const OUString& rFmtString,
1486 bool& bTestBanking)
1487{
1488 sal_uInt16 nPos = sal_uInt16(-1);
1489
1491 sal_uInt16 nCount = rCurrencyTable.size();
1492
1493 const SvNumberformat* pFormat;
1494 OUString aSymbol, aExtension;
1495 sal_uInt32 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
1496 if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND
1497 && ((pFormat = pFormatter->GetEntry(nFound)) != nullptr)
1498 && pFormat->GetNewCurrencySymbol(aSymbol, aExtension))
1499 {
1500 // eventually match with format locale
1501 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::GetCurrencyEntry(
1502 bTestBanking, aSymbol, aExtension, pFormat->GetLanguage());
1503 if (pTmpCurrencyEntry)
1504 {
1505 for (sal_uInt16 i = 0; i < nCount; i++)
1506 {
1507 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1508 {
1509 nPos = i;
1510 break;
1511 }
1512 }
1513 }
1514 }
1515 else
1516 {
1517 // search symbol string only
1518 for (sal_uInt16 i = 0; i < nCount; i++)
1519 {
1520 const NfCurrencyEntry* pTmpCurrencyEntry = &rCurrencyTable[i];
1521 OUString _aSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
1522 OUString aBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
1523
1524 if (rFmtString.indexOf(_aSymbol) != -1)
1525 {
1526 bTestBanking = false;
1527 nPos = i;
1528 break;
1529 }
1530 else if (rFmtString.indexOf(aBankSymbol) != -1)
1531 {
1532 bTestBanking = true;
1533 nPos = i;
1534 break;
1535 }
1536 }
1537 }
1538
1539 return nPos;
1540}
1541
1542sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry* pTmpCurrencyEntry,
1543 bool bTmpBanking)
1544{
1546 sal_uInt16 nCount = rCurrencyTable.size();
1547
1548 sal_uInt16 nPos = 0;
1549 for (sal_uInt16 i = 0; i < nCount; i++)
1550 {
1551 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1552 {
1553 nPos = i;
1554 break;
1555 }
1556 }
1557
1558 sal_uInt16 nStart = 0;
1559 if (bTmpBanking && aCurCurrencyList.size() > nPos)
1560 {
1561 nStart = nCount;
1562 }
1563 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1564 {
1565 if (aCurCurrencyList[j] == nPos)
1566 return j;
1567 }
1568 return sal_uInt16(-1);
1569}
1570
1571bool SvxNumberFormatShell::IsInTable(sal_uInt16 const nPos, bool const bTmpBanking,
1572 std::u16string_view rFmtString) const
1573{
1574 bool bFlag = false;
1575
1576 if (nPos != sal_uInt16(-1))
1577 {
1579
1580 if (nPos < rCurrencyTable.size())
1581 {
1582 NfWSStringsDtor aWSStringsDtor;
1583 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, rCurrencyTable[nPos], bTmpBanking);
1584
1585 for (const OUString& s : aWSStringsDtor)
1586 {
1587 if (s == rFmtString)
1588 {
1589 bFlag = true;
1590 break;
1591 }
1592 }
1593 }
1594 }
1595
1596 return bFlag;
1597}
1598
1599/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static LanguageType getRealLanguage(LanguageType nLang)
size_t size() const
static const NfCurrencyTable & GetTheCurrencyTable()
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent=true)
sal_uInt32 TestNewString(const OUString &sFormatString, LanguageType eLnge=LANGUAGE_DONTKNOW)
OUString GenerateFormat(sal_uInt32 nIndex, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bThousand=false, bool IsRed=false, sal_uInt16 nPrecision=0, sal_uInt16 nLeadingCnt=1)
bool GetPreviewString(const OUString &sFormatString, double fPreviewNumber, OUString &sOutString, const Color **ppColor, LanguageType eLnge, bool bUseStarFormat=false)
NfIndexTableOffset GetIndexTableOffset(sal_uInt32 nFormat) const
void DeleteEntry(sal_uInt32 nKey)
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)
sal_uInt32 GetEntryKey(std::u16string_view sStr, LanguageType eLnge=LANGUAGE_DONTKNOW)
sal_uInt16 GetFormatIntegerDigits(sal_uInt32 nFormat) const
bool GetNewCurrencySymbolString(sal_uInt32 nFormat, OUString &rSymbol, const NfCurrencyEntry **ppEntry, bool *pBank=nullptr) const
SvNumFormatType GetType(sal_uInt32 nFIndex) const
sal_uInt32 GetFormatIndex(NfIndexTableOffset, LanguageType eLnge=LANGUAGE_DONTKNOW)
static const NfCurrencyEntry & GetCurrencyEntry(LanguageType)
const SvNumberformat * GetEntry(sal_uInt32 nKey) const
static const NfCurrencyEntry * MatchSystemCurrency()
sal_uInt16 GetCurrencyFormatStrings(NfWSStringsDtor &, const NfCurrencyEntry &, bool bBank) const
OUString GetStandardName(LanguageType eLnge)
void GetFormatSpecialInfo(sal_uInt32 nFormat, bool &bThousand, bool &IsRed, sal_uInt16 &nPrecision, sal_uInt16 &nLeadingCnt)
SvNumberFormatTable & GetEntryTable(SvNumFormatType eType, sal_uInt32 &FIndex, LanguageType eLnge)
SvNumberFormatTable & GetFirstEntryTable(SvNumFormatType &eType, sal_uInt32 &FIndex, LanguageType &rLnge)
SvNumberFormatTable & ChangeCL(SvNumFormatType eType, sal_uInt32 &FIndex, LanguageType eLnge)
bool IsUserDefined(sal_uInt32 F_Index) const
SvNumFormatType GetMaskedType() const
LanguageType GetLanguage() const
void SetComment(const OUString &rStr)
bool HasNewCurrency() const
bool IsAdditionalBuiltin() const
const OUString & GetComment() const
const OUString & GetFormatstring() const
bool GetNewCurrencySymbol(OUString &rSymbol, OUString &rExtension) const
SvNumFormatType GetType() const
OUString GetFormat4Entry(short nEntry)
Definition: numfmtsh.cxx:1316
SVX_DLLPRIVATE::std::vector< sal_uInt32 >::iterator GetAdded_Impl(size_t nKey)
Definition: numfmtsh.cxx:1112
void FormatChanged(sal_uInt16 nFmtLbPos, OUString &rPreviewStr, const Color *&rpFontColor)
Definition: numfmtsh.cxx:193
SVX_DLLPRIVATE void GetPreviewString_Impl(OUString &rString, const Color *&rpColor)
Definition: numfmtsh.cxx:1083
SvxNumberValueType eValType
Definition: numfmtsh.hxx:180
sal_uInt32 nCurFormatKey
Definition: numfmtsh.hxx:187
bool IsUserDefined(const OUString &rFmtString)
Definition: numfmtsh.cxx:413
void SetComment4Entry(short nEntry, const OUString &aCommentString)
Definition: numfmtsh.cxx:1220
LanguageType eCurLanguage
Definition: numfmtsh.hxx:189
SVX_DLLPRIVATE short FillEListWithDateTime_Impl(std::vector< OUString > &rList, short nSelPos, bool bSuppressDuplicates)
Definition: numfmtsh.cxx:643
void GetOptions(const OUString &rFormat, bool &rThousand, bool &rNegRed, sal_uInt16 &rPrecision, sal_uInt16 &rLeadingZeroes, sal_uInt16 &rCatLbPos)
Definition: numfmtsh.cxx:349
void SetCurrencySymbol(sal_uInt32 nPos)
Definition: numfmtsh.cxx:1424
short GetCategory4Entry(short nEntry) const
Definition: numfmtsh.cxx:1257
SVX_DLLPRIVATE short FillEListWithCurrency_Impl(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:732
SVX_DLLPRIVATE short FillEListWithUsD_Impl(std::vector< OUString > &rList, SvNumFormatType eCategory, short Pos)
Definition: numfmtsh.cxx:1026
std::vector< sal_uInt32 > const & GetUpdateData() const
Definition: numfmtsh.cxx:171
SVX_DLLPRIVATE bool IsEssentialFormat_Impl(SvNumFormatType eType, sal_uInt32 nKey)
Definition: numfmtsh.cxx:704
void SetCurCurrencyEntry(NfCurrencyEntry *)
Definition: numfmtsh.cxx:1448
SVX_DLLPRIVATE short FillEntryList_Impl(std::vector< OUString > &rList)
Definition: numfmtsh.cxx:503
std::vector< sal_uInt16 > aCurCurrencyList
Definition: numfmtsh.hxx:190
sal_uInt16 FindCurrencyTableEntry(const OUString &rFmtString, bool &bTestBanking)
Definition: numfmtsh.cxx:1485
std::vector< sal_uInt32 > aCurEntryList
Definition: numfmtsh.hxx:186
SVX_DLLPRIVATE short FillEListWithUserCurrencys(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:845
std::vector< sal_uInt32 > aAddList
Definition: numfmtsh.hxx:184
std::vector< OUString > aCurrencyFormatList
Definition: numfmtsh.hxx:194
void RemoveFormat(std::u16string_view rFormat, sal_uInt16 &rCatLbSelPos, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:281
SVX_DLLPRIVATE bool IsRemoved_Impl(size_t nKey)
Definition: numfmtsh.cxx:1107
void MakeFormat(OUString &rFormat, bool bThousand, bool bNegRed, sal_uInt16 nPrecision, sal_uInt16 nLeadingZeroes, sal_uInt16 nCurrencyEntryPos)
Definition: numfmtsh.cxx:309
void LanguageChanged(LanguageType eLangType, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:185
SvxNumberFormatShell(SvNumberFormatter *pNumFormatter, sal_uInt32 nFormatKey, SvxNumberValueType eNumValType, const OUString &rNumStr)
Definition: numfmtsh.cxx:82
bool IsTmpCurrencyFormat(const OUString &rFmtString)
Definition: numfmtsh.cxx:1453
sal_uInt32 nCurCurrencyEntryPos
Definition: numfmtsh.hxx:193
SVX_DLLPRIVATE void FillEListWithStd_Impl(std::vector< OUString > &rList, SvNumFormatType eCategory, short &Pos, bool bSuppressDuplicates=false)
Definition: numfmtsh.cxx:557
void CategoryChanged(sal_uInt16 nCatLbPos, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:173
void MakePrevStringFromVal(const OUString &rFormatStr, OUString &rPreviewStr, const Color *&rpFontColor, double nValue)
Definition: numfmtsh.cxx:1208
OUString GetStandardName() const
Returns the name of Standard, General, ... for the current language.
Definition: numfmtsh.cxx:1382
bool FindEntry(const OUString &rFmtString, sal_uInt32 *pAt=nullptr)
Definition: numfmtsh.cxx:437
SvNumberFormatter * pFormatter
Definition: numfmtsh.hxx:178
OUString GetComment4Entry(short nEntry)
Definition: numfmtsh.cxx:1236
static SvxNumberFormatShell * Create(SvNumberFormatter *pNumFormatter, sal_uInt32 nFormatKey, SvxNumberValueType eNumValType, const OUString &rNumStr)
Definition: numfmtsh.cxx:66
static SVX_DLLPRIVATE void PosToCategory_Impl(sal_uInt16 nPos, SvNumFormatType &rCategory)
Definition: numfmtsh.cxx:1118
NfCurrencyEntry * pCurCurrencyEntry
Definition: numfmtsh.hxx:191
SVX_DLLPRIVATE short FillEListWithFormats_Impl(std::vector< OUString > &rList, short nSelPos, NfIndexTableOffset eOffsetStart, NfIndexTableOffset eOffsetEnd, bool bSuppressDuplicates)
Definition: numfmtsh.cxx:625
bool IsInTable(sal_uInt16 nPos, bool bTmpBanking, std::u16string_view rFmtString) const
Definition: numfmtsh.cxx:1571
std::vector< sal_uInt32 > aDelList
Definition: numfmtsh.hxx:185
sal_uInt16 FindCurrencyFormat(const OUString &rFmtString)
Definition: numfmtsh.cxx:1460
SVX_DLLPRIVATE void FillEListWithOneFormat_Impl(std::vector< OUString > &rList, short &nSelPos, bool bSuppressDuplicates, NfIndexTableOffset nOffset, bool bSuppressIsoDateTime)
Definition: numfmtsh.cxx:667
SVX_DLLPRIVATE short FillEListWithSysCurrencys(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:763
void GetCurrencySymbols(std::vector< OUString > &rList, sal_uInt16 *pPos)
Definition: numfmtsh.cxx:1387
static SVX_DLLPRIVATE void CategoryToPos_Impl(SvNumFormatType nCategory, sal_uInt16 &rPos)
Definition: numfmtsh.cxx:1160
void GetInitSettings(sal_uInt16 &nCatLbPos, LanguageType &rLangType, sal_uInt16 &nFmtLbSelPos, std::vector< OUString > &rFmtEntries, OUString &rPrevString, const Color *&rpPrevColor)
Definition: numfmtsh.cxx:474
SvNumberFormatTable * pCurFmtTable
Definition: numfmtsh.hxx:179
void MakePreviewString(const OUString &rFormatStr, OUString &rPreviewStr, const Color *&rpFontColor)
Definition: numfmtsh.cxx:378
SvNumFormatType nCurCategory
Definition: numfmtsh.hxx:188
short GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
Definition: numfmtsh.cxx:1345
SVX_DLLPRIVATE::std::vector< sal_uInt32 >::iterator GetRemoved_Impl(size_t nKey)
Definition: numfmtsh.cxx:1102
sal_uInt16 GetFormatIntegerDigits(std::u16string_view rFormat) const
Definition: numfmtsh.cxx:342
bool AddFormat(OUString &rFormat, sal_Int32 &rErrPos, sal_uInt16 &rCatLbSelPos, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:215
bool GetUserDefined4Entry(short nEntry)
Definition: numfmtsh.cxx:1291
int nCount
#define DBG_ASSERT(sCon, aError)
const o3tl::enumarray< SvxNumValCategory, double > fSvxNumValConst
Definition: flagsdef.hxx:83
DocumentType eType
sal_Int16 nValue
Definition: fmsrccfg.cxx:81
sal_Int32 nIndex
#define LANGUAGE_NONE
sal_uInt16 nPos
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
long Long
#define CAT_ALL
Definition: numfmtsh.hxx:41
#define CAT_FRACTION
Definition: numfmtsh.hxx:49
#define SELPOS_NONE
Definition: numfmtsh.hxx:53
#define CAT_TEXT
Definition: numfmtsh.hxx:51
SvxNumberValueType
Definition: numfmtsh.hxx:34
#define CAT_DATE
Definition: numfmtsh.hxx:46
#define CAT_PERCENT
Definition: numfmtsh.hxx:44
#define NUMBERFORMAT_ENTRY_NEW_CURRENCY
Definition: numfmtsh.hxx:55
#define CAT_TIME
Definition: numfmtsh.hxx:47
#define CAT_NUMBER
Definition: numfmtsh.hxx:43
#define CAT_SCIENTIFIC
Definition: numfmtsh.hxx:48
#define CAT_CURRENCY
Definition: numfmtsh.hxx:45
#define CAT_USERDEFINED
Definition: numfmtsh.hxx:42
#define CAT_BOOLEAN
Definition: numfmtsh.hxx:50
std::vector< OUString > NfWSStringsDtor
SvNumFormatType
NfIndexTableOffset
NF_TIME_END
NF_FRACTION_3D
NF_SCIENTIFIC_START
NF_DATETIME_START
NF_DATETIME_SYS_DDMMYYYY_HHMMSS
NF_DATETIME_ISO_YYYYMMDDTHHMMSS000
NF_CURRENCY_1000DEC2_RED
NF_TIME_MMSS00
NF_TIME_HH_MMSS00
NF_DATETIME_ISO_YYYYMMDD_HHMMSS000
NF_DATE_END
NF_DATE_ISO_YYYYMMDD
NF_SCIENTIFIC_END
NF_NUMBER_END
NF_FRACTION_END
NF_FRACTION_START
NF_CURRENCY_START
NF_TEXT
NF_BOOLEAN
NF_CURRENCY_END
NF_TIME_START
NF_PERCENT_START
NF_TIME_HH_MMSS
NF_DATE_START
NF_DATETIME_SYS_DDMMYYYY_HHMM
NF_DATETIME_END
NF_PERCENT_END
NF_DATETIME_ISO_YYYYMMDD_HHMMSS
NF_DATE_SYS_DDMMYYYY
NF_NUMBER_START
NF_DATETIME_ISO_YYYYMMDDTHHMMSS
NF_FRACTION_100
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND