Bump version to 24.04.3.4
[LibreOffice.git] / svx / source / items / numfmtsh.cxx
blobaa9e668169cb0932669801f34364dab10ed1fa73
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/color.hxx>
22 #include <tools/debug.hxx>
23 #include <i18nlangtag/mslangid.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>
30 #include <svx/numfmtsh.hxx>
31 #include <svx/flagsdef.hxx>
32 #include <svx/tbcontrl.hxx>
33 #include <sfx2/IDocumentModelAccessor.hxx>
35 #include <limits>
37 namespace
39 double GetDefaultValNum(const SvNumFormatType nType)
41 switch (nType)
43 case SvNumFormatType::NUMBER:
44 return fSvxNumValConst[SvxNumValCategory::Standard];
45 case SvNumFormatType::CURRENCY:
46 return fSvxNumValConst[SvxNumValCategory::Currency];
47 case SvNumFormatType::PERCENT:
48 return fSvxNumValConst[SvxNumValCategory::Percent];
49 case SvNumFormatType::DATE:
50 case SvNumFormatType::DATETIME:
51 return fSvxNumValConst[SvxNumValCategory::Date];
52 case SvNumFormatType::TIME:
53 return fSvxNumValConst[SvxNumValCategory::Time];
54 case SvNumFormatType::SCIENTIFIC:
55 return fSvxNumValConst[SvxNumValCategory::Scientific];
56 case SvNumFormatType::FRACTION:
57 return fSvxNumValConst[SvxNumValCategory::Fraction];
58 case SvNumFormatType::LOGICAL:
59 return fSvxNumValConst[SvxNumValCategory::Boolean];
60 default:
61 break;
63 return fSvxNumValConst[SvxNumValCategory::NoValue];
67 SvxNumberFormatShell* SvxNumberFormatShell::Create(SvNumberFormatter* pNumFormatter,
68 sal_uInt32 nFormatKey,
69 SvxNumberValueType eNumValType,
70 const OUString& rNumStr)
72 return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, rNumStr);
75 SvxNumberFormatShell* SvxNumberFormatShell::Create(SvNumberFormatter* pNumFormatter,
76 sal_uInt32 nFormatKey,
77 SvxNumberValueType eNumValType, double nNumVal,
78 const OUString* pNumStr)
80 return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, nNumVal, pNumStr);
83 SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
84 SvxNumberValueType eNumValType, const OUString& rNumStr)
85 : pFormatter(pNumFormatter)
86 , pCurFmtTable(nullptr)
87 , eValType(eNumValType)
88 , bUndoAddList(true)
89 , nCurFormatKey(nFormatKey)
90 , nCurCategory(SvNumFormatType::ALL)
91 , eCurLanguage(LANGUAGE_NONE)
92 , pCurCurrencyEntry(nullptr)
93 , bBankingSymbol(false)
94 , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
95 , bUseStarFormat(false)
96 , bIsDefaultValNum(true)
98 nValNum = 0;
100 switch (eValType)
102 case SvxNumberValueType::String:
103 aValStr = rNumStr;
104 break;
105 case SvxNumberValueType::Number:
106 if (pFormatter)
108 nValNum = GetDefaultValNum(pFormatter->GetType(nCurFormatKey));
110 [[fallthrough]];
111 case SvxNumberValueType::Undefined:
112 default:
113 aValStr.clear();
117 SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
118 SvxNumberValueType eNumValType, double nNumVal,
119 const OUString* pNumStr)
120 : pFormatter(pNumFormatter)
121 , pCurFmtTable(nullptr)
122 , eValType(eNumValType)
123 , bUndoAddList(true)
124 , nCurFormatKey(nFormatKey)
125 , nCurCategory(SvNumFormatType::ALL)
126 , eCurLanguage(LANGUAGE_NONE)
127 , pCurCurrencyEntry(nullptr)
128 , bBankingSymbol(false)
129 , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
130 , bUseStarFormat(false)
131 , bIsDefaultValNum(false)
133 // #50441# When used in Writer, the SvxNumberInfoItem contains the
134 // original string in addition to the value
136 if (pNumStr)
137 aValStr = *pNumStr;
139 switch (eValType)
141 case SvxNumberValueType::Number:
142 nValNum = nNumVal;
143 break;
144 case SvxNumberValueType::String:
145 case SvxNumberValueType::Undefined:
146 default:
147 nValNum = 0;
148 bIsDefaultValNum = true;
152 SvxNumberFormatShell::~SvxNumberFormatShell()
155 * At this point, depending on whether the added user-defined were
156 * validated (ValidateNewEntries()), the add list is removed from
157 * the number formatter again.
159 * Deleting formats from the formatter happens for Undo reasons
160 * only in the calling instance.
163 if (bUndoAddList)
165 // Added formats are invalid => remove them
167 for (const auto& rItem : aAddList)
168 pFormatter->DeleteEntry(rItem);
172 std::vector<sal_uInt32> const& SvxNumberFormatShell::GetUpdateData() const { return aDelList; }
174 void SvxNumberFormatShell::CategoryChanged(sal_uInt16 nCatLbPos, short& rFmtSelPos,
175 std::vector<OUString>& rFmtEntries)
177 SvNumFormatType nOldCategory = nCurCategory;
178 PosToCategory_Impl(nCatLbPos, nCurCategory);
179 pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
180 // reinitialize currency if category newly entered
181 if (nCurCategory == SvNumFormatType::CURRENCY && nOldCategory != nCurCategory)
182 pCurCurrencyEntry = nullptr;
183 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
186 void SvxNumberFormatShell::LanguageChanged(LanguageType eLangType, short& rFmtSelPos,
187 std::vector<OUString>& rFmtEntries)
189 eCurLanguage = eLangType;
190 pCurFmtTable = &(pFormatter->ChangeCL(nCurCategory, nCurFormatKey, eCurLanguage));
191 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
194 void SvxNumberFormatShell::FormatChanged(sal_uInt16 nFmtLbPos, OUString& rPreviewStr,
195 const Color*& rpFontColor)
197 if (static_cast<size_t>(nFmtLbPos) >= aCurEntryList.size())
198 return;
200 nCurFormatKey = aCurEntryList[nFmtLbPos];
202 if (nCurFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
204 GetPreviewString_Impl(rPreviewStr, rpFontColor);
206 else if (nCurCategory == SvNumFormatType::CURRENCY)
208 if (static_cast<size_t>(nFmtLbPos) < aCurrencyFormatList.size())
210 MakePrevStringFromVal(aCurrencyFormatList[nFmtLbPos], rPreviewStr, rpFontColor,
211 nValNum);
216 bool SvxNumberFormatShell::AddFormat(OUString& rFormat, sal_Int32& rErrPos,
217 sal_uInt16& rCatLbSelPos, short& rFmtSelPos,
218 std::vector<OUString>& rFmtEntries)
220 bool bInserted = false;
221 sal_uInt32 nAddKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
223 if (nAddKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // exists already?
225 ::std::vector<sal_uInt32>::iterator nAt = GetRemoved_Impl(nAddKey);
226 if (nAt != aDelList.end())
228 aDelList.erase(nAt);
229 bInserted = true;
231 else
233 OSL_FAIL("duplicate format!");
236 else // new format
238 sal_Int32 nPos;
239 bInserted = pFormatter->PutEntry(rFormat, nPos, nCurCategory, nAddKey, eCurLanguage);
240 rErrPos = (nPos >= 0) ? nPos : -1;
242 if (bInserted)
244 // May be sorted under a different locale if LCID was parsed.
245 const SvNumberformat* pEntry = pFormatter->GetEntry(nAddKey);
246 if (pEntry)
248 LanguageType nLang = pEntry->GetLanguage();
249 if (eCurLanguage != nLang)
251 // Current language's list would not show entry, adapt.
252 eCurLanguage = nLang;
258 if (bInserted)
260 nCurFormatKey = nAddKey;
261 DBG_ASSERT(GetAdded_Impl(nCurFormatKey) == aAddList.end(), "duplicate format!");
262 aAddList.push_back(nCurFormatKey);
264 // get current table
265 pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
266 nCurCategory = pFormatter->GetType(nAddKey);
267 CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
268 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
270 else if (rErrPos != 0) // syntax error
274 else // insert twice not possible
276 OSL_FAIL("duplicate format!");
279 return bInserted;
282 void SvxNumberFormatShell::RemoveFormat(std::u16string_view rFormat, sal_uInt16& rCatLbSelPos,
283 short& rFmtSelPos, std::vector<OUString>& rFmtEntries)
285 sal_uInt32 nDelKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
287 DBG_ASSERT(nDelKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "entry not found!");
288 DBG_ASSERT(!IsRemoved_Impl(nDelKey), "entry already removed!");
290 if ((nDelKey == NUMBERFORMAT_ENTRY_NOT_FOUND) || IsRemoved_Impl(nDelKey))
291 return;
293 aDelList.push_back(nDelKey);
295 ::std::vector<sal_uInt32>::iterator nAt = GetAdded_Impl(nDelKey);
296 if (nAt != aAddList.end())
298 aAddList.erase(nAt);
301 nCurCategory = pFormatter->GetType(nDelKey);
302 pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
304 nCurFormatKey = pFormatter->GetStandardFormat(nCurCategory, eCurLanguage);
306 CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
307 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
310 void SvxNumberFormatShell::MakeFormat(OUString& rFormat, bool bThousand, bool bNegRed,
311 sal_uInt16 nPrecision, sal_uInt16 nLeadingZeroes,
312 sal_uInt16 nCurrencyPos)
314 if (aCurrencyFormatList.size() > static_cast<size_t>(nCurrencyPos))
316 sal_Int32 rErrPos = 0;
317 std::vector<OUString> aFmtEList;
319 sal_uInt32 nFound
320 = pFormatter->TestNewString(aCurrencyFormatList[nCurrencyPos], eCurLanguage);
322 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
324 sal_uInt16 rCatLbSelPos = 0;
325 short rFmtSelPos = 0;
326 AddFormat(aCurrencyFormatList[nCurrencyPos], rErrPos, rCatLbSelPos, rFmtSelPos,
327 aFmtEList);
330 if (rErrPos == 0)
332 rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
333 nPrecision, nLeadingZeroes);
336 else
338 rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
339 nPrecision, nLeadingZeroes);
343 sal_uInt16 SvxNumberFormatShell::GetFormatIntegerDigits(std::u16string_view rFormat) const
345 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
347 return pFormatter->GetFormatIntegerDigits(nFmtKey);
350 bool SvxNumberFormatShell::IsNatNum12(std::u16string_view rFormat) const
352 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
354 return pFormatter->IsNatNum12(nFmtKey);
357 void SvxNumberFormatShell::GetOptions(const OUString& rFormat, bool& rThousand, bool& rNegRed,
358 sal_uInt16& rPrecision, sal_uInt16& rLeadingZeroes,
359 sal_uInt16& rCatLbPos)
361 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
363 if (nFmtKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
365 pFormatter->GetFormatSpecialInfo(nFmtKey, rThousand, rNegRed, rPrecision, rLeadingZeroes);
367 CategoryToPos_Impl(pFormatter->GetType(nFmtKey), rCatLbPos);
369 else
371 bool bTestBanking = false;
372 sal_uInt16 nPos = FindCurrencyTableEntry(rFormat, bTestBanking);
374 if (IsInTable(nPos, bTestBanking, rFormat)
375 && pFormatter->GetFormatSpecialInfo(rFormat, rThousand, rNegRed, rPrecision,
376 rLeadingZeroes, eCurLanguage)
377 == 0)
379 rCatLbPos = CAT_CURRENCY;
381 else
382 rCatLbPos = CAT_USERDEFINED;
386 void SvxNumberFormatShell::MakePreviewString(const OUString& rFormatStr, OUString& rPreviewStr,
387 const Color*& rpFontColor)
389 rpFontColor = nullptr;
391 sal_uInt32 nExistingFormat = pFormatter->GetEntryKey(rFormatStr, eCurLanguage);
392 if (nExistingFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
394 // real preview - not implemented in NumberFormatter for text formats
395 pFormatter->GetPreviewString(rFormatStr, nValNum, rPreviewStr, &rpFontColor, eCurLanguage,
396 bUseStarFormat);
398 else
400 // format exists
402 // #50441# if a string was set in addition to the value, use it for text formats
403 bool bUseText = (eValType == SvxNumberValueType::String
404 || (!aValStr.isEmpty()
405 && (pFormatter->GetType(nExistingFormat) & SvNumFormatType::TEXT)));
407 if (bUseText)
409 pFormatter->GetOutputString(aValStr, nExistingFormat, rPreviewStr, &rpFontColor);
411 else
413 if (bIsDefaultValNum)
414 nValNum = GetDefaultValNum(pFormatter->GetType(nExistingFormat));
415 pFormatter->GetOutputString(nValNum, nExistingFormat, rPreviewStr, &rpFontColor,
416 bUseStarFormat);
421 bool SvxNumberFormatShell::IsUserDefined(const OUString& rFmtString)
423 sal_uInt32 nFound = pFormatter->GetEntryKey(rFmtString, eCurLanguage);
425 bool bFlag = false;
426 if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND)
428 bFlag = pFormatter->IsUserDefined(rFmtString, eCurLanguage);
430 if (bFlag)
432 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nFound);
434 if (pNumEntry != nullptr && pNumEntry->HasNewCurrency())
436 bool bTestBanking;
437 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
438 bFlag = !IsInTable(nPos, bTestBanking, rFmtString);
442 return bFlag;
445 bool SvxNumberFormatShell::FindEntry(const OUString& rFmtString, sal_uInt32* pAt /* = NULL */)
447 bool bRes = false;
449 sal_uInt32 nFound = NUMBERFORMAT_ENTRY_NOT_FOUND;
450 // There may be multiple builtin entries with the same format code, first
451 // try if the current key matches.
452 const SvNumberformat* pEntry = pFormatter->GetEntry(nCurFormatKey);
453 if (pEntry && pEntry->GetLanguage() == eCurLanguage && pEntry->GetFormatstring() == rFmtString)
454 nFound = nCurFormatKey;
456 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
457 // Find the first matching format code.
458 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
460 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
462 bool bTestBanking = false;
463 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
465 if (IsInTable(nPos, bTestBanking, rFmtString))
467 nFound = NUMBERFORMAT_ENTRY_NEW_CURRENCY;
468 bRes = true;
471 else
473 bRes = !IsRemoved_Impl(nFound);
476 if (pAt)
477 *pAt = nFound;
479 return bRes;
482 void SvxNumberFormatShell::GetInitSettings(sal_uInt16& nCatLbPos, LanguageType& rLangType,
483 sal_uInt16& nFmtLbSelPos,
484 std::vector<OUString>& rFmtEntries,
485 OUString& rPrevString, const Color*& rpPrevColor)
487 // precondition: number formater found
488 DBG_ASSERT(pFormatter != nullptr, "Number formatter not found!");
490 short nSelPos = SELPOS_NONE;
492 // special treatment for undefined number format:
493 if ((eValType == SvxNumberValueType::Undefined) && (nCurFormatKey == 0))
494 PosToCategory_Impl(CAT_ALL, nCurCategory); // category = all
495 else
496 nCurCategory = SvNumFormatType::UNDEFINED; // category = undefined
498 pCurFmtTable = &(pFormatter->GetFirstEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
500 CategoryToPos_Impl(nCurCategory, nCatLbPos);
501 rLangType = eCurLanguage;
503 nSelPos = FillEntryList_Impl(rFmtEntries);
505 DBG_ASSERT(nSelPos != SELPOS_NONE, "Leere Formatliste!");
507 nFmtLbSelPos = (nSelPos != SELPOS_NONE) ? static_cast<sal_uInt16>(nSelPos) : 0;
508 GetPreviewString_Impl(rPrevString, rpPrevColor);
511 short SvxNumberFormatShell::FillEntryList_Impl(std::vector<OUString>& rList)
513 /* Create a current list of format entries. The return value is
514 * the list position of the current format. If the list is empty
515 * or if there is no current format, SELPOS_NONE is delivered.
517 short nSelPos = SELPOS_NONE;
519 aCurEntryList.clear();
521 if (nCurCategory == SvNumFormatType::ALL)
523 FillEListWithStd_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
524 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
526 FillEListWithStd_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
527 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
529 FillEListWithStd_Impl(rList, SvNumFormatType::CURRENCY, nSelPos);
530 // No FillEListWithUsD_Impl() here, user defined currency formats
531 // were already added.
533 FillEListWithStd_Impl(rList, SvNumFormatType::DATE, nSelPos);
534 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATE, nSelPos);
536 FillEListWithStd_Impl(rList, SvNumFormatType::TIME, nSelPos);
537 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TIME, nSelPos);
539 nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, false);
540 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATETIME, nSelPos);
542 FillEListWithStd_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
543 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
545 FillEListWithStd_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
546 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
548 FillEListWithStd_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
549 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
551 FillEListWithStd_Impl(rList, SvNumFormatType::TEXT, nSelPos);
552 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TEXT, nSelPos);
554 else
556 FillEListWithStd_Impl(rList, nCurCategory, nSelPos, true);
557 nSelPos = FillEListWithUsD_Impl(rList, nCurCategory, nSelPos);
558 if (nCurCategory == SvNumFormatType::DATE || nCurCategory == SvNumFormatType::TIME)
559 nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, true);
562 return nSelPos;
565 void SvxNumberFormatShell::FillEListWithStd_Impl(std::vector<OUString>& rList,
566 SvNumFormatType eCategory, short& nSelPos,
567 bool bSuppressDuplicates)
569 /* Create a current list of format entries. The return value is
570 * the list position of the current format. If the list is empty
571 * or if there is no current format, SELPOS_NONE is delivered.
574 assert(pCurFmtTable != nullptr);
576 aCurrencyFormatList.clear();
578 NfIndexTableOffset eOffsetStart;
579 NfIndexTableOffset eOffsetEnd;
581 switch (eCategory)
583 case SvNumFormatType::NUMBER:
584 eOffsetStart = NF_NUMBER_START;
585 eOffsetEnd = NF_NUMBER_END;
586 break;
587 case SvNumFormatType::PERCENT:
588 eOffsetStart = NF_PERCENT_START;
589 eOffsetEnd = NF_PERCENT_END;
590 break;
591 case SvNumFormatType::CURRENCY:
592 // Currency entries are generated and assembled, ignore
593 // bSuppressDuplicates.
594 nSelPos = FillEListWithCurrency_Impl(rList, nSelPos);
595 return;
596 case SvNumFormatType::DATE:
597 eOffsetStart = NF_DATE_START;
598 eOffsetEnd = NF_DATE_END;
599 break;
600 case SvNumFormatType::TIME:
601 eOffsetStart = NF_TIME_START;
602 eOffsetEnd = NF_TIME_END;
603 break;
604 case SvNumFormatType::SCIENTIFIC:
605 eOffsetStart = NF_SCIENTIFIC_START;
606 eOffsetEnd = NF_SCIENTIFIC_END;
607 break;
608 case SvNumFormatType::FRACTION:
609 eOffsetStart = NF_FRACTION_START;
610 eOffsetEnd = NF_FRACTION_END;
611 // Fraction formats are internally generated by the number
612 // formatter and are not supposed to contain duplicates anyway.
613 nSelPos = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, false);
614 nSelPos
615 = FillEListWithFormats_Impl(rList, nSelPos, NF_FRACTION_3D, NF_FRACTION_100, false);
616 return;
617 case SvNumFormatType::LOGICAL:
618 eOffsetStart = NF_BOOLEAN;
619 eOffsetEnd = NF_BOOLEAN;
620 break;
621 case SvNumFormatType::TEXT:
622 eOffsetStart = NF_TEXT;
623 eOffsetEnd = NF_TEXT;
624 break;
625 default:
626 return;
629 nSelPos
630 = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, bSuppressDuplicates);
633 short SvxNumberFormatShell::FillEListWithFormats_Impl(std::vector<OUString>& rList, short nSelPos,
634 NfIndexTableOffset eOffsetStart,
635 NfIndexTableOffset eOffsetEnd,
636 bool bSuppressDuplicates)
638 /* Create a current list of format entries. The return value is
639 * the list position of the current format. If the list is empty
640 * or if there is no current format, SELPOS_NONE is delivered.
642 for (tools::Long nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex)
644 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
645 static_cast<NfIndexTableOffset>(nIndex), false);
648 return nSelPos;
651 short SvxNumberFormatShell::FillEListWithDateTime_Impl(std::vector<OUString>& rList, short nSelPos,
652 bool bSuppressDuplicates)
654 // Append a list of date+time formats.
656 // Add first, so a NF_DATETIME_SYSTEM_SHORT_HHMM may be suppressed in
657 // locales that do not use 2-digit years there and this here is the
658 // default.
659 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates, NF_DATETIME_SYS_DDMMYYYY_HHMM,
660 true);
662 for (tools::Long nIndex = NF_DATETIME_START; nIndex <= NF_DATETIME_END; ++nIndex)
664 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
665 static_cast<NfIndexTableOffset>(nIndex), true);
668 // Always add the internally generated ISO formats.
669 nSelPos = FillEListWithFormats_Impl(rList, nSelPos, NF_DATETIME_ISO_YYYYMMDD_HHMMSS,
670 NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, false);
672 return nSelPos;
675 void SvxNumberFormatShell::FillEListWithOneFormat_Impl(std::vector<OUString>& rList, short& nSelPos,
676 bool bSuppressDuplicates,
677 NfIndexTableOffset nOffset,
678 bool bSuppressIsoDateTime)
680 sal_uInt32 nNFEntry = pFormatter->GetFormatIndex(nOffset, eCurLanguage);
682 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
683 if (pNumEntry == nullptr)
684 return;
686 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
687 sal_uInt16 nMyType;
688 CategoryToPos_Impl(nMyCat, nMyType);
689 OUString aNewFormNInfo = pNumEntry->GetFormatstring();
691 if (nNFEntry == nCurFormatKey)
693 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
696 // Ugly hack to suppress an ISO date+time format that is the default
697 // date+time format of the locale and identical to the internally generated
698 // one always to be added after/below.
699 const bool bSupIso
700 = bSuppressIsoDateTime && bSuppressDuplicates
701 && (aNewFormNInfo == "YYYY-MM-DD HH:MM:SS" || aNewFormNInfo == "YYYY-MM-DD\"T\"HH:MM:SS");
703 if (!bSupIso
704 && (!bSuppressDuplicates || IsEssentialFormat_Impl(nMyCat, nNFEntry)
705 || std::find(rList.begin(), rList.end(), aNewFormNInfo) == rList.end()))
707 rList.push_back(aNewFormNInfo);
708 aCurEntryList.push_back(nNFEntry);
712 bool SvxNumberFormatShell::IsEssentialFormat_Impl(SvNumFormatType eType, sal_uInt32 nKey)
714 if (nKey == nCurFormatKey)
715 return true;
717 const NfIndexTableOffset nIndex = SvNumberFormatter::GetIndexTableOffset(nKey);
718 switch (nIndex)
720 // These are preferred or edit formats.
721 case NF_DATE_SYS_DDMMYYYY:
722 case NF_DATE_ISO_YYYYMMDD:
723 case NF_TIME_HH_MMSS:
724 case NF_TIME_MMSS00:
725 case NF_TIME_HH_MMSS00:
726 case NF_DATETIME_SYS_DDMMYYYY_HHMM:
727 case NF_DATETIME_SYS_DDMMYYYY_HHMMSS:
728 case NF_DATETIME_ISO_YYYYMMDD_HHMMSS:
729 case NF_DATETIME_ISO_YYYYMMDD_HHMMSS000:
730 case NF_DATETIME_ISO_YYYYMMDDTHHMMSS:
731 case NF_DATETIME_ISO_YYYYMMDDTHHMMSS000:
732 return true;
733 default:
734 break;
737 return nKey == pFormatter->GetStandardFormat(eType, eCurLanguage);
740 short SvxNumberFormatShell::FillEListWithCurrency_Impl(std::vector<OUString>& rList, short nSelPos)
742 /* Create a current list of format entries. The return value is
743 * the list position of the current format. If the list is empty
744 * or if there is no current format, SELPOS_NONE is delivered.
746 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
748 const NfCurrencyEntry* pTmpCurrencyEntry;
749 bool bTmpBanking;
750 OUString rSymbol;
752 bool bFlag = pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
753 &bTmpBanking);
755 if ((!bFlag && pCurCurrencyEntry == nullptr)
756 || (bFlag && pTmpCurrencyEntry == nullptr && rSymbol.isEmpty())
757 || (nCurCategory == SvNumFormatType::ALL))
759 if (nCurCategory == SvNumFormatType::ALL)
760 FillEListWithUserCurrencys(rList, nSelPos);
761 nSelPos = FillEListWithSysCurrencys(rList, nSelPos);
763 else
765 nSelPos = FillEListWithUserCurrencys(rList, nSelPos);
768 return nSelPos;
771 short SvxNumberFormatShell::FillEListWithSysCurrencys(std::vector<OUString>& rList, short nSelPos)
773 /* Create a current list of format entries. The return value is
774 * the list position of the current format. If the list is empty
775 * or if there is no current format, SELPOS_NONE is delivered.
777 sal_uInt16 nMyType;
779 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
781 sal_uInt32 nNFEntry;
782 OUString aNewFormNInfo;
784 nCurCurrencyEntryPos = 0;
786 for (tools::Long nIndex = NF_CURRENCY_START; nIndex <= NF_CURRENCY_END; nIndex++)
788 nNFEntry
789 = pFormatter->GetFormatIndex(static_cast<NfIndexTableOffset>(nIndex), eCurLanguage);
791 if (nCurCategory == SvNumFormatType::ALL && nNFEntry != nCurFormatKey)
792 // Deprecated old currency entries, for ALL add only if used as
793 // current format key.
794 continue;
796 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
798 if (pNumEntry == nullptr)
799 continue;
801 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
802 CategoryToPos_Impl(nMyCat, nMyType);
803 aNewFormNInfo = pNumEntry->GetFormatstring();
805 if (nNFEntry == nCurFormatKey)
807 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
810 rList.push_back(aNewFormNInfo);
811 aCurEntryList.push_back(nNFEntry);
814 if (nCurCategory != SvNumFormatType::ALL)
816 for (const auto& rEntry : *pCurFmtTable)
818 sal_uInt32 nKey = rEntry.first;
819 const SvNumberformat* pNumEntry = rEntry.second;
821 if (!IsRemoved_Impl(nKey))
823 bool bUserNewCurrency = false;
824 if (pNumEntry->HasNewCurrency())
826 const NfCurrencyEntry* pTmpCurrencyEntry;
827 bool bTmpBanking;
828 OUString rSymbol;
830 pFormatter->GetNewCurrencySymbolString(nKey, rSymbol, &pTmpCurrencyEntry,
831 &bTmpBanking);
833 bUserNewCurrency = (pTmpCurrencyEntry != nullptr);
836 if (!bUserNewCurrency && (pNumEntry->GetType() & SvNumFormatType::DEFINED))
838 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
839 CategoryToPos_Impl(nMyCat, nMyType);
840 aNewFormNInfo = pNumEntry->GetFormatstring();
842 if (nKey == nCurFormatKey)
843 nSelPos = aCurEntryList.size();
844 rList.push_back(aNewFormNInfo);
845 aCurEntryList.push_back(nKey);
850 return nSelPos;
853 short SvxNumberFormatShell::FillEListWithUserCurrencys(std::vector<OUString>& rList, short nSelPos)
855 /* Create a current list of format entries. The return value is
856 * the list position of the current format. If the list is empty
857 * or if there is no current format, SELPOS_NONE is delivered.
859 sal_uInt16 nMyType;
861 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
863 OUString aNewFormNInfo;
865 const NfCurrencyEntry* pTmpCurrencyEntry;
866 bool bTmpBanking, bAdaptSelPos;
867 OUString rSymbol;
868 OUString rBankSymbol;
870 std::vector<OUString> aList;
871 std::vector<sal_uInt32> aKeyList;
873 pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
874 &bTmpBanking);
876 OUString rShortSymbol;
878 if (pCurCurrencyEntry == nullptr)
880 // #110398# If no currency format was previously selected (we're not
881 // about to add another currency), try to select the initial currency
882 // format (nCurFormatKey) that was set in FormatChanged() after
883 // matching the format string entered in the dialog.
884 bAdaptSelPos = true;
885 pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(pTmpCurrencyEntry);
886 bBankingSymbol = bTmpBanking;
887 nCurCurrencyEntryPos = FindCurrencyFormat(pTmpCurrencyEntry, bTmpBanking);
889 else
891 if (pTmpCurrencyEntry == pCurCurrencyEntry)
892 bAdaptSelPos = true;
893 else
895 bAdaptSelPos = false;
896 pTmpCurrencyEntry = pCurCurrencyEntry;
898 bTmpBanking = bBankingSymbol;
901 if (pTmpCurrencyEntry != nullptr)
903 rSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
904 rBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
905 rShortSymbol = pTmpCurrencyEntry->BuildSymbolString(bTmpBanking, true);
908 for (const auto& rEntry : *pCurFmtTable)
910 sal_uInt32 nKey = rEntry.first;
911 const SvNumberformat* pNumEntry = rEntry.second;
913 if (!IsRemoved_Impl(nKey))
915 if (pNumEntry->GetType() & SvNumFormatType::DEFINED || pNumEntry->IsAdditionalBuiltin())
917 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
918 CategoryToPos_Impl(nMyCat, nMyType);
919 aNewFormNInfo = pNumEntry->GetFormatstring();
921 bool bInsFlag = false;
922 if (pNumEntry->HasNewCurrency())
924 bInsFlag = true; // merge locale formats into currency selection
926 else if ((!bTmpBanking && aNewFormNInfo.indexOf(rSymbol) >= 0)
927 || (bTmpBanking && aNewFormNInfo.indexOf(rBankSymbol) >= 0))
929 bInsFlag = true;
931 else if (aNewFormNInfo.indexOf(rShortSymbol) >= 0)
933 OUString rTstSymbol;
934 const NfCurrencyEntry* pTstCurrencyEntry;
935 bool bTstBanking;
937 pFormatter->GetNewCurrencySymbolString(nKey, rTstSymbol, &pTstCurrencyEntry,
938 &bTstBanking);
940 if (pTmpCurrencyEntry == pTstCurrencyEntry && bTstBanking == bTmpBanking)
942 bInsFlag = true;
946 if (bInsFlag)
948 aList.push_back(aNewFormNInfo);
949 aKeyList.push_back(nKey);
955 NfWSStringsDtor aWSStringsDtor;
956 sal_uInt16 nDefault;
957 if (pTmpCurrencyEntry && nCurCategory != SvNumFormatType::ALL)
959 nDefault
960 = pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, bTmpBanking);
961 if (!bTmpBanking)
962 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, true);
964 else
965 nDefault = 0;
966 if (!bTmpBanking && nCurCategory != SvNumFormatType::ALL)
968 // append formats for all currencies defined in the current I18N locale
969 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
970 sal_uInt16 nCurrCount = rCurrencyTable.size();
971 LanguageType eLang = MsLangId::getRealLanguage(eCurLanguage);
972 for (sal_uInt16 i = 0; i < nCurrCount; ++i)
974 const NfCurrencyEntry* pCurr = &rCurrencyTable[i];
975 if (pCurr->GetLanguage() == eLang && pTmpCurrencyEntry != pCurr)
977 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, false);
978 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, true);
983 size_t nOldListCount = rList.size();
984 for (size_t i = 0, nPos = nOldListCount; i < aWSStringsDtor.size(); ++i)
986 bool bFlag = true;
987 OUString aInsStr(aWSStringsDtor[i]);
988 size_t j;
989 for (j = 0; j < aList.size(); ++j)
991 if (aList[j] == aInsStr)
993 bFlag = false;
994 break;
997 if (bFlag)
999 rList.push_back(aInsStr);
1000 aCurEntryList.insert(aCurEntryList.begin() + (nPos++), NUMBERFORMAT_ENTRY_NOT_FOUND);
1002 else
1004 rList.push_back(aList[j]);
1005 aList.erase(aList.begin() + j);
1006 aCurEntryList.insert(aCurEntryList.begin() + (nPos++), aKeyList[j]);
1007 aKeyList.erase(aKeyList.begin() + j);
1011 for (size_t i = 0; i < aKeyList.size(); ++i)
1013 if (aKeyList[i] != NUMBERFORMAT_ENTRY_NOT_FOUND)
1015 rList.push_back(aList[i]);
1016 aCurEntryList.push_back(aKeyList[i]);
1020 for (size_t i = nOldListCount; i < rList.size(); ++i)
1022 aCurrencyFormatList.push_back(rList[i]);
1024 if (nSelPos == SELPOS_NONE && bAdaptSelPos && aCurEntryList[i] == nCurFormatKey)
1025 nSelPos = i;
1028 if (nSelPos == SELPOS_NONE && nCurCategory != SvNumFormatType::ALL)
1029 nSelPos = nDefault;
1031 return nSelPos;
1034 short SvxNumberFormatShell::FillEListWithUsD_Impl(std::vector<OUString>& rList,
1035 SvNumFormatType eCategory, short nSelPos)
1037 /* Create a current list of format entries. The return value is
1038 * the list position of the current format. If the list is empty
1039 * or if there is no current format, SELPOS_NONE is delivered.
1042 assert(pCurFmtTable != nullptr);
1044 OUString aNewFormNInfo;
1046 const bool bCatDefined = (eCategory == SvNumFormatType::DEFINED);
1047 const bool bCategoryMatch = (eCategory != SvNumFormatType::ALL && !bCatDefined);
1048 const bool bNatNumCurrency = (eCategory == SvNumFormatType::CURRENCY);
1050 for (const auto& rEntry : *pCurFmtTable)
1052 const SvNumberformat* pNumEntry = rEntry.second;
1054 if (bCategoryMatch && (pNumEntry->GetMaskedType() & eCategory) != eCategory)
1055 continue; // for; type does not match category if not ALL
1057 const bool bUserDefined = bool(pNumEntry->GetType() & SvNumFormatType::DEFINED);
1058 if (!bUserDefined && bCatDefined)
1059 continue; // for; not user defined in DEFINED category
1061 if (!(bUserDefined || (!bCatDefined && pNumEntry->IsAdditionalBuiltin())))
1062 continue; // for; does not match criteria at all
1064 const sal_uInt32 nKey = rEntry.first;
1065 if (!IsRemoved_Impl(nKey))
1067 aNewFormNInfo = pNumEntry->GetFormatstring();
1069 if (bNatNumCurrency && (aNewFormNInfo.indexOf("NatNum12") < 0 || bUserDefined))
1070 continue; // for; extra CURRENCY must be not user-defined NatNum12 type
1072 bool bAdd = true;
1073 if (pNumEntry->HasNewCurrency())
1075 bool bTestBanking;
1076 sal_uInt16 nPos = FindCurrencyTableEntry(aNewFormNInfo, bTestBanking);
1077 bAdd = !IsInTable(nPos, bTestBanking, aNewFormNInfo);
1079 if (bAdd)
1081 if (nKey == nCurFormatKey)
1082 nSelPos = aCurEntryList.size();
1083 rList.push_back(aNewFormNInfo);
1084 aCurEntryList.push_back(nKey);
1088 return nSelPos;
1091 void SvxNumberFormatShell::GetPreviewString_Impl(OUString& rString, const Color*& rpColor)
1093 rpColor = nullptr;
1095 // #50441# if a string was set in addition to the value, use it for text formats
1096 bool bUseText
1097 = (eValType == SvxNumberValueType::String
1098 || (!aValStr.isEmpty() && (pFormatter->GetType(nCurFormatKey) & SvNumFormatType::TEXT)));
1100 if (bUseText)
1102 pFormatter->GetOutputString(aValStr, nCurFormatKey, rString, &rpColor);
1104 else
1106 pFormatter->GetOutputString(nValNum, nCurFormatKey, rString, &rpColor, bUseStarFormat);
1110 ::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetRemoved_Impl(size_t nKey)
1112 return ::std::find(aDelList.begin(), aDelList.end(), nKey);
1115 bool SvxNumberFormatShell::IsRemoved_Impl(size_t nKey)
1117 return GetRemoved_Impl(nKey) != aDelList.end();
1120 ::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetAdded_Impl(size_t nKey)
1122 return ::std::find(aAddList.begin(), aAddList.end(), nKey);
1125 // Conversion routines:
1126 void SvxNumberFormatShell::PosToCategory_Impl(sal_uInt16 nPos, SvNumFormatType& rCategory)
1128 // map category css::form positions (->resource)
1129 switch (nPos)
1131 case CAT_USERDEFINED:
1132 rCategory = SvNumFormatType::DEFINED;
1133 break;
1134 case CAT_NUMBER:
1135 rCategory = SvNumFormatType::NUMBER;
1136 break;
1137 case CAT_PERCENT:
1138 rCategory = SvNumFormatType::PERCENT;
1139 break;
1140 case CAT_CURRENCY:
1141 rCategory = SvNumFormatType::CURRENCY;
1142 break;
1143 case CAT_DATE:
1144 rCategory = SvNumFormatType::DATE;
1145 break;
1146 case CAT_TIME:
1147 rCategory = SvNumFormatType::TIME;
1148 break;
1149 case CAT_SCIENTIFIC:
1150 rCategory = SvNumFormatType::SCIENTIFIC;
1151 break;
1152 case CAT_FRACTION:
1153 rCategory = SvNumFormatType::FRACTION;
1154 break;
1155 case CAT_BOOLEAN:
1156 rCategory = SvNumFormatType::LOGICAL;
1157 break;
1158 case CAT_TEXT:
1159 rCategory = SvNumFormatType::TEXT;
1160 break;
1161 case CAT_ALL:
1162 default:
1163 rCategory = SvNumFormatType::ALL;
1164 break;
1168 void SvxNumberFormatShell::CategoryToPos_Impl(SvNumFormatType nCategory, sal_uInt16& rPos)
1170 // map category to css::form positions (->resource)
1171 switch (nCategory)
1173 case SvNumFormatType::DEFINED:
1174 rPos = CAT_USERDEFINED;
1175 break;
1176 case SvNumFormatType::NUMBER:
1177 rPos = CAT_NUMBER;
1178 break;
1179 case SvNumFormatType::PERCENT:
1180 rPos = CAT_PERCENT;
1181 break;
1182 case SvNumFormatType::CURRENCY:
1183 rPos = CAT_CURRENCY;
1184 break;
1185 case SvNumFormatType::DATETIME:
1186 case SvNumFormatType::DATE:
1187 rPos = CAT_DATE;
1188 break;
1189 case SvNumFormatType::TIME:
1190 rPos = CAT_TIME;
1191 break;
1192 case SvNumFormatType::SCIENTIFIC:
1193 rPos = CAT_SCIENTIFIC;
1194 break;
1195 case SvNumFormatType::FRACTION:
1196 rPos = CAT_FRACTION;
1197 break;
1198 case SvNumFormatType::LOGICAL:
1199 rPos = CAT_BOOLEAN;
1200 break;
1201 case SvNumFormatType::TEXT:
1202 rPos = CAT_TEXT;
1203 break;
1204 case SvNumFormatType::ALL:
1205 default:
1206 rPos = CAT_ALL;
1211 * Function: Formats the number nValue dependent on rFormatStr
1212 * and stores the result in rPreviewStr.
1213 * Input: FormatString, color, number to format
1214 * Output: Output string rPreviewStr
1216 void SvxNumberFormatShell::MakePrevStringFromVal(const OUString& rFormatStr, OUString& rPreviewStr,
1217 const Color*& rpFontColor, double nValue)
1219 rpFontColor = nullptr;
1220 pFormatter->GetPreviewString(rFormatStr, nValue, rPreviewStr, &rpFontColor, eCurLanguage);
1224 * Function: Returns the comment for a given entry.
1225 * Input: Number of the entry
1226 * Output: Comment string
1228 void SvxNumberFormatShell::SetComment4Entry(short nEntry, const OUString& aEntStr)
1230 SvNumberformat* pNumEntry;
1231 if (nEntry < 0)
1232 return;
1233 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1234 pNumEntry = const_cast<SvNumberformat*>(pFormatter->GetEntry(nMyNfEntry));
1235 if (pNumEntry != nullptr)
1236 pNumEntry->SetComment(aEntStr);
1240 * Function: Returns the comment for a given entry.
1241 * Input: Number of the entry
1242 * Output: Comment string
1244 OUString SvxNumberFormatShell::GetComment4Entry(short nEntry)
1246 if (nEntry < 0)
1247 return OUString();
1249 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1251 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1252 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1253 if (pNumEntry != nullptr)
1254 return pNumEntry->GetComment();
1257 return OUString();
1261 * Function: Returns the category number for a given entry.
1262 * Input: Number of the entry
1263 * Output: Category number
1265 short SvxNumberFormatShell::GetCategory4Entry(short nEntry) const
1267 if (nEntry < 0)
1268 return 0;
1269 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1271 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1273 if (nMyNfEntry != NUMBERFORMAT_ENTRY_NOT_FOUND)
1275 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1276 if (pNumEntry != nullptr)
1278 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
1279 sal_uInt16 nMyType;
1280 CategoryToPos_Impl(nMyCat, nMyType);
1282 return static_cast<short>(nMyType);
1284 return 0;
1286 else if (!aCurrencyFormatList.empty())
1288 return CAT_CURRENCY;
1291 return 0;
1295 * Function: Returns the information about whether an entry is user-specific.
1296 * Input: Number of the entry
1297 * Output: User-specific?
1299 bool SvxNumberFormatShell::GetUserDefined4Entry(short nEntry)
1301 if (nEntry < 0)
1302 return false;
1303 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1305 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1306 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1308 if (pNumEntry != nullptr)
1310 if (pNumEntry->GetType() & SvNumFormatType::DEFINED)
1312 return true;
1316 return false;
1320 * Function: Returns the format string for a given entry.
1321 * Input: Number of the entry
1322 * Output: Format string
1324 OUString SvxNumberFormatShell::GetFormat4Entry(short nEntry)
1326 if (nEntry < 0)
1327 return OUString();
1329 if (!aCurrencyFormatList.empty()
1330 && (!pFormatter->GetEntry(aCurEntryList[nEntry])
1331 || pFormatter->GetEntry(aCurEntryList[nEntry])->GetFormatstring().indexOf("NatNum12")
1332 < 0))
1334 if (aCurrencyFormatList.size() > o3tl::make_unsigned(nEntry))
1335 return aCurrencyFormatList[nEntry];
1337 else
1339 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1340 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1342 if (pNumEntry != nullptr)
1343 return pNumEntry->GetFormatstring();
1345 return OUString();
1349 * Function: Returns the list number for a given format index.
1350 * Input: Number of the entry
1351 * Output: Category number
1353 short SvxNumberFormatShell::GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
1355 short nSelP = SELPOS_NONE;
1356 if (nIdx != NUMBERFORMAT_ENTRY_NEW_CURRENCY)
1358 // Check list size against return type limit.
1359 if (aCurEntryList.size() <= o3tl::make_unsigned(::std::numeric_limits<short>::max()))
1361 for (size_t i = 0; i < aCurEntryList.size(); ++i)
1363 if (aCurEntryList[i] == nIdx)
1365 nSelP = i;
1366 break;
1370 else
1372 OSL_FAIL("svx::SvxNumberFormatShell::GetListPos4Entry(), list got too large!");
1375 else
1377 // A second list holds the generated currency formats.
1378 for (size_t i = 0; i < aCurrencyFormatList.size(); ++i)
1380 if (rFmtString == aCurrencyFormatList[i])
1382 nSelP = static_cast<short>(i);
1383 break;
1387 return nSelP;
1390 OUString SvxNumberFormatShell::GetStandardName() const
1392 return pFormatter->GetStandardName(eCurLanguage);
1395 void SvxNumberFormatShell::GetCurrencySymbols(std::vector<OUString>& rList, sal_uInt16* pPos)
1397 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::MatchSystemCurrency();
1399 bool bFlag = (pTmpCurrencyEntry == nullptr);
1401 std::vector<sfx::CurrencyID> aDocumentCurrencyIDs;
1402 SvxCurrencyToolBoxControl::GetCurrencySymbols(rList, bFlag, aCurCurrencyList,
1403 aDocumentCurrencyIDs);
1405 if (pPos == nullptr)
1406 return;
1408 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1409 sal_uInt16 nTableCount = rCurrencyTable.size();
1411 *pPos = 0;
1412 size_t nCount = aCurCurrencyList.size();
1414 if (bFlag)
1416 *pPos = 1;
1417 nCurCurrencyEntryPos = 1;
1419 else
1421 for (size_t i = 1; i < nCount; i++)
1423 const sal_uInt16 j = aCurCurrencyList[i];
1424 if (j != sal_uInt16(-1) && j < nTableCount && pTmpCurrencyEntry == &rCurrencyTable[j])
1426 *pPos = static_cast<sal_uInt16>(i);
1427 nCurCurrencyEntryPos = static_cast<sal_uInt16>(i);
1428 break;
1434 void SvxNumberFormatShell::SetCurrencySymbol(sal_uInt32 nPos)
1436 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1437 sal_uInt16 nCount = rCurrencyTable.size();
1439 bBankingSymbol = (nPos >= nCount);
1441 if (nPos >= aCurCurrencyList.size())
1442 return;
1444 sal_uInt16 nCurrencyPos = aCurCurrencyList[nPos];
1445 if (nCurrencyPos != sal_uInt16(-1))
1447 pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(&rCurrencyTable[nCurrencyPos]);
1448 nCurCurrencyEntryPos = nPos;
1450 else
1452 pCurCurrencyEntry = nullptr;
1453 nCurCurrencyEntryPos = 0;
1454 nCurFormatKey = pFormatter->GetFormatIndex(NF_CURRENCY_1000DEC2_RED, eCurLanguage);
1458 void SvxNumberFormatShell::SetCurCurrencyEntry(NfCurrencyEntry* pCEntry)
1460 pCurCurrencyEntry = pCEntry;
1463 bool SvxNumberFormatShell::IsTmpCurrencyFormat(const OUString& rFmtString)
1465 sal_uInt32 nFound;
1466 FindEntry(rFmtString, &nFound);
1467 return nFound == NUMBERFORMAT_ENTRY_NEW_CURRENCY;
1470 sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const OUString& rFmtString)
1472 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1473 sal_uInt16 nCount = rCurrencyTable.size();
1475 bool bTestBanking = false;
1477 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
1479 if (nPos != sal_uInt16(-1))
1481 sal_uInt16 nStart = 0;
1482 if (bTestBanking && aCurCurrencyList.size() > nPos)
1484 nStart = nCount;
1486 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1488 if (aCurCurrencyList[j] == nPos)
1489 return j;
1492 return sal_uInt16(-1);
1495 sal_uInt16 SvxNumberFormatShell::FindCurrencyTableEntry(const OUString& rFmtString,
1496 bool& bTestBanking)
1498 sal_uInt16 nPos = sal_uInt16(-1);
1500 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1501 sal_uInt16 nCount = rCurrencyTable.size();
1503 const SvNumberformat* pFormat;
1504 OUString aSymbol, aExtension;
1505 sal_uInt32 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
1506 if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND
1507 && ((pFormat = pFormatter->GetEntry(nFound)) != nullptr)
1508 && pFormat->GetNewCurrencySymbol(aSymbol, aExtension))
1510 // eventually match with format locale
1511 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::GetCurrencyEntry(
1512 bTestBanking, aSymbol, aExtension, pFormat->GetLanguage());
1513 if (pTmpCurrencyEntry)
1515 for (sal_uInt16 i = 0; i < nCount; i++)
1517 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1519 nPos = i;
1520 break;
1525 else
1527 // search symbol string only
1528 for (sal_uInt16 i = 0; i < nCount; i++)
1530 const NfCurrencyEntry* pTmpCurrencyEntry = &rCurrencyTable[i];
1531 OUString _aSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
1532 OUString aBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
1534 if (rFmtString.indexOf(_aSymbol) != -1)
1536 bTestBanking = false;
1537 nPos = i;
1538 break;
1540 else if (rFmtString.indexOf(aBankSymbol) != -1)
1542 bTestBanking = true;
1543 nPos = i;
1544 break;
1549 return nPos;
1552 sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry* pTmpCurrencyEntry,
1553 bool bTmpBanking)
1555 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1556 sal_uInt16 nCount = rCurrencyTable.size();
1558 sal_uInt16 nPos = 0;
1559 for (sal_uInt16 i = 0; i < nCount; i++)
1561 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1563 nPos = i;
1564 break;
1568 sal_uInt16 nStart = 0;
1569 if (bTmpBanking && aCurCurrencyList.size() > nPos)
1571 nStart = nCount;
1573 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1575 if (aCurCurrencyList[j] == nPos)
1576 return j;
1578 return sal_uInt16(-1);
1581 bool SvxNumberFormatShell::IsInTable(sal_uInt16 const nPos, bool const bTmpBanking,
1582 std::u16string_view rFmtString) const
1584 bool bFlag = false;
1586 if (nPos != sal_uInt16(-1))
1588 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1590 if (nPos < rCurrencyTable.size())
1592 NfWSStringsDtor aWSStringsDtor;
1593 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, rCurrencyTable[nPos], bTmpBanking);
1595 for (const OUString& s : aWSStringsDtor)
1597 if (s == rFmtString)
1599 bFlag = true;
1600 break;
1606 return bFlag;
1609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */