calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / svx / source / items / numfmtsh.cxx
blob1aa58a32340a5c1369af37065cb35b966857eb1c
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>
34 #include <limits>
36 namespace
38 double GetDefaultValNum(const SvNumFormatType nType)
40 switch (nType)
42 case SvNumFormatType::NUMBER:
43 return fSvxNumValConst[SvxNumValCategory::Standard];
44 case SvNumFormatType::CURRENCY:
45 return fSvxNumValConst[SvxNumValCategory::Currency];
46 case SvNumFormatType::PERCENT:
47 return fSvxNumValConst[SvxNumValCategory::Percent];
48 case SvNumFormatType::DATE:
49 case SvNumFormatType::DATETIME:
50 return fSvxNumValConst[SvxNumValCategory::Date];
51 case SvNumFormatType::TIME:
52 return fSvxNumValConst[SvxNumValCategory::Time];
53 case SvNumFormatType::SCIENTIFIC:
54 return fSvxNumValConst[SvxNumValCategory::Scientific];
55 case SvNumFormatType::FRACTION:
56 return fSvxNumValConst[SvxNumValCategory::Fraction];
57 case SvNumFormatType::LOGICAL:
58 return fSvxNumValConst[SvxNumValCategory::Boolean];
59 default:
60 break;
62 return fSvxNumValConst[SvxNumValCategory::NoValue];
66 SvxNumberFormatShell* SvxNumberFormatShell::Create(SvNumberFormatter* pNumFormatter,
67 sal_uInt32 nFormatKey,
68 SvxNumberValueType eNumValType,
69 const OUString& rNumStr)
71 return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, rNumStr);
74 SvxNumberFormatShell* SvxNumberFormatShell::Create(SvNumberFormatter* pNumFormatter,
75 sal_uInt32 nFormatKey,
76 SvxNumberValueType eNumValType, double nNumVal,
77 const OUString* pNumStr)
79 return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, nNumVal, pNumStr);
82 SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
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)
97 nValNum = 0;
99 switch (eValType)
101 case SvxNumberValueType::String:
102 aValStr = rNumStr;
103 break;
104 case SvxNumberValueType::Number:
105 if (pFormatter)
107 nValNum = GetDefaultValNum(pFormatter->GetType(nCurFormatKey));
109 [[fallthrough]];
110 case SvxNumberValueType::Undefined:
111 default:
112 aValStr.clear();
116 SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
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)
132 // #50441# When used in Writer, the SvxNumberInfoItem contains the
133 // original string in addition to the value
135 if (pNumStr)
136 aValStr = *pNumStr;
138 switch (eValType)
140 case SvxNumberValueType::Number:
141 nValNum = nNumVal;
142 break;
143 case SvxNumberValueType::String:
144 case SvxNumberValueType::Undefined:
145 default:
146 nValNum = 0;
147 bIsDefaultValNum = true;
151 SvxNumberFormatShell::~SvxNumberFormatShell()
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.
158 * Deleting formats from the formatter happens for Undo reasons
159 * only in the calling instance.
162 if (bUndoAddList)
164 // Added formats are invalid => remove them
166 for (const auto& rItem : aAddList)
167 pFormatter->DeleteEntry(rItem);
171 std::vector<sal_uInt32> const& SvxNumberFormatShell::GetUpdateData() const { return aDelList; }
173 void SvxNumberFormatShell::CategoryChanged(sal_uInt16 nCatLbPos, short& rFmtSelPos,
174 std::vector<OUString>& rFmtEntries)
176 SvNumFormatType nOldCategory = nCurCategory;
177 PosToCategory_Impl(nCatLbPos, nCurCategory);
178 pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
179 // reinitialize currency if category newly entered
180 if (nCurCategory == SvNumFormatType::CURRENCY && nOldCategory != nCurCategory)
181 pCurCurrencyEntry = nullptr;
182 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
185 void SvxNumberFormatShell::LanguageChanged(LanguageType eLangType, short& rFmtSelPos,
186 std::vector<OUString>& rFmtEntries)
188 eCurLanguage = eLangType;
189 pCurFmtTable = &(pFormatter->ChangeCL(nCurCategory, nCurFormatKey, eCurLanguage));
190 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
193 void SvxNumberFormatShell::FormatChanged(sal_uInt16 nFmtLbPos, OUString& rPreviewStr,
194 const Color*& rpFontColor)
196 if (static_cast<size_t>(nFmtLbPos) >= aCurEntryList.size())
197 return;
199 nCurFormatKey = aCurEntryList[nFmtLbPos];
201 if (nCurFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
203 GetPreviewString_Impl(rPreviewStr, rpFontColor);
205 else if (nCurCategory == SvNumFormatType::CURRENCY)
207 if (static_cast<size_t>(nFmtLbPos) < aCurrencyFormatList.size())
209 MakePrevStringFromVal(aCurrencyFormatList[nFmtLbPos], rPreviewStr, rpFontColor,
210 nValNum);
215 bool SvxNumberFormatShell::AddFormat(OUString& rFormat, sal_Int32& rErrPos,
216 sal_uInt16& rCatLbSelPos, short& rFmtSelPos,
217 std::vector<OUString>& rFmtEntries)
219 bool bInserted = false;
220 sal_uInt32 nAddKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
222 if (nAddKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // exists already?
224 ::std::vector<sal_uInt32>::iterator nAt = GetRemoved_Impl(nAddKey);
225 if (nAt != aDelList.end())
227 aDelList.erase(nAt);
228 bInserted = true;
230 else
232 OSL_FAIL("duplicate format!");
235 else // new format
237 sal_Int32 nPos;
238 bInserted = pFormatter->PutEntry(rFormat, nPos, nCurCategory, nAddKey, eCurLanguage);
239 rErrPos = (nPos >= 0) ? nPos : -1;
241 if (bInserted)
243 // May be sorted under a different locale if LCID was parsed.
244 const SvNumberformat* pEntry = pFormatter->GetEntry(nAddKey);
245 if (pEntry)
247 LanguageType nLang = pEntry->GetLanguage();
248 if (eCurLanguage != nLang)
250 // Current language's list would not show entry, adapt.
251 eCurLanguage = nLang;
257 if (bInserted)
259 nCurFormatKey = nAddKey;
260 DBG_ASSERT(GetAdded_Impl(nCurFormatKey) == aAddList.end(), "duplicate format!");
261 aAddList.push_back(nCurFormatKey);
263 // get current table
264 pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
265 nCurCategory = pFormatter->GetType(nAddKey);
266 CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
267 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
269 else if (rErrPos != 0) // syntax error
273 else // insert twice not possible
275 OSL_FAIL("duplicate format!");
278 return bInserted;
281 void SvxNumberFormatShell::RemoveFormat(std::u16string_view rFormat, sal_uInt16& rCatLbSelPos,
282 short& rFmtSelPos, std::vector<OUString>& rFmtEntries)
284 sal_uInt32 nDelKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
286 DBG_ASSERT(nDelKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "entry not found!");
287 DBG_ASSERT(!IsRemoved_Impl(nDelKey), "entry already removed!");
289 if ((nDelKey == NUMBERFORMAT_ENTRY_NOT_FOUND) || IsRemoved_Impl(nDelKey))
290 return;
292 aDelList.push_back(nDelKey);
294 ::std::vector<sal_uInt32>::iterator nAt = GetAdded_Impl(nDelKey);
295 if (nAt != aAddList.end())
297 aAddList.erase(nAt);
300 nCurCategory = pFormatter->GetType(nDelKey);
301 pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
303 nCurFormatKey = pFormatter->GetStandardFormat(nCurCategory, eCurLanguage);
305 CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
306 rFmtSelPos = FillEntryList_Impl(rFmtEntries);
309 void SvxNumberFormatShell::MakeFormat(OUString& rFormat, bool bThousand, bool bNegRed,
310 sal_uInt16 nPrecision, sal_uInt16 nLeadingZeroes,
311 sal_uInt16 nCurrencyPos)
313 if (aCurrencyFormatList.size() > static_cast<size_t>(nCurrencyPos))
315 sal_Int32 rErrPos = 0;
316 std::vector<OUString> aFmtEList;
318 sal_uInt32 nFound
319 = pFormatter->TestNewString(aCurrencyFormatList[nCurrencyPos], eCurLanguage);
321 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
323 sal_uInt16 rCatLbSelPos = 0;
324 short rFmtSelPos = 0;
325 AddFormat(aCurrencyFormatList[nCurrencyPos], rErrPos, rCatLbSelPos, rFmtSelPos,
326 aFmtEList);
329 if (rErrPos == 0)
331 rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
332 nPrecision, nLeadingZeroes);
335 else
337 rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
338 nPrecision, nLeadingZeroes);
342 sal_uInt16 SvxNumberFormatShell::GetFormatIntegerDigits(std::u16string_view rFormat) const
344 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
346 return pFormatter->GetFormatIntegerDigits(nFmtKey);
349 void SvxNumberFormatShell::GetOptions(const OUString& rFormat, bool& rThousand, bool& rNegRed,
350 sal_uInt16& rPrecision, sal_uInt16& rLeadingZeroes,
351 sal_uInt16& rCatLbPos)
353 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
355 if (nFmtKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
357 pFormatter->GetFormatSpecialInfo(nFmtKey, rThousand, rNegRed, rPrecision, rLeadingZeroes);
359 CategoryToPos_Impl(pFormatter->GetType(nFmtKey), rCatLbPos);
361 else
363 bool bTestBanking = false;
364 sal_uInt16 nPos = FindCurrencyTableEntry(rFormat, bTestBanking);
366 if (IsInTable(nPos, bTestBanking, rFormat)
367 && pFormatter->GetFormatSpecialInfo(rFormat, rThousand, rNegRed, rPrecision,
368 rLeadingZeroes, eCurLanguage)
369 == 0)
371 rCatLbPos = CAT_CURRENCY;
373 else
374 rCatLbPos = CAT_USERDEFINED;
378 void SvxNumberFormatShell::MakePreviewString(const OUString& rFormatStr, OUString& rPreviewStr,
379 const Color*& rpFontColor)
381 rpFontColor = nullptr;
383 sal_uInt32 nExistingFormat = pFormatter->GetEntryKey(rFormatStr, eCurLanguage);
384 if (nExistingFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
386 // real preview - not implemented in NumberFormatter for text formats
387 pFormatter->GetPreviewString(rFormatStr, nValNum, rPreviewStr, &rpFontColor, eCurLanguage,
388 bUseStarFormat);
390 else
392 // format exists
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)));
399 if (bUseText)
401 pFormatter->GetOutputString(aValStr, nExistingFormat, rPreviewStr, &rpFontColor);
403 else
405 if (bIsDefaultValNum)
406 nValNum = GetDefaultValNum(pFormatter->GetType(nExistingFormat));
407 pFormatter->GetOutputString(nValNum, nExistingFormat, rPreviewStr, &rpFontColor,
408 bUseStarFormat);
413 bool SvxNumberFormatShell::IsUserDefined(const OUString& rFmtString)
415 sal_uInt32 nFound = pFormatter->GetEntryKey(rFmtString, eCurLanguage);
417 bool bFlag = false;
418 if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND)
420 bFlag = pFormatter->IsUserDefined(rFmtString, eCurLanguage);
422 if (bFlag)
424 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nFound);
426 if (pNumEntry != nullptr && pNumEntry->HasNewCurrency())
428 bool bTestBanking;
429 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
430 bFlag = !IsInTable(nPos, bTestBanking, rFmtString);
434 return bFlag;
437 bool SvxNumberFormatShell::FindEntry(const OUString& rFmtString, sal_uInt32* pAt /* = NULL */)
439 bool bRes = false;
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.
444 const SvNumberformat* pEntry = pFormatter->GetEntry(nCurFormatKey);
445 if (pEntry && pEntry->GetLanguage() == eCurLanguage && pEntry->GetFormatstring() == rFmtString)
446 nFound = nCurFormatKey;
448 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
449 // Find the first matching format code.
450 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
452 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
454 bool bTestBanking = false;
455 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
457 if (IsInTable(nPos, bTestBanking, rFmtString))
459 nFound = NUMBERFORMAT_ENTRY_NEW_CURRENCY;
460 bRes = true;
463 else
465 bRes = !IsRemoved_Impl(nFound);
468 if (pAt)
469 *pAt = nFound;
471 return bRes;
474 void SvxNumberFormatShell::GetInitSettings(sal_uInt16& nCatLbPos, LanguageType& rLangType,
475 sal_uInt16& nFmtLbSelPos,
476 std::vector<OUString>& rFmtEntries,
477 OUString& rPrevString, const Color*& rpPrevColor)
479 // precondition: number formater found
480 DBG_ASSERT(pFormatter != nullptr, "Number formatter not found!");
482 short nSelPos = SELPOS_NONE;
484 // special treatment for undefined number format:
485 if ((eValType == SvxNumberValueType::Undefined) && (nCurFormatKey == 0))
486 PosToCategory_Impl(CAT_ALL, nCurCategory); // category = all
487 else
488 nCurCategory = SvNumFormatType::UNDEFINED; // category = undefined
490 pCurFmtTable = &(pFormatter->GetFirstEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
492 CategoryToPos_Impl(nCurCategory, nCatLbPos);
493 rLangType = eCurLanguage;
495 nSelPos = FillEntryList_Impl(rFmtEntries);
497 DBG_ASSERT(nSelPos != SELPOS_NONE, "Leere Formatliste!");
499 nFmtLbSelPos = (nSelPos != SELPOS_NONE) ? static_cast<sal_uInt16>(nSelPos) : 0;
500 GetPreviewString_Impl(rPrevString, rpPrevColor);
503 short SvxNumberFormatShell::FillEntryList_Impl(std::vector<OUString>& rList)
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.
509 short nSelPos = SELPOS_NONE;
511 aCurEntryList.clear();
513 if (nCurCategory == SvNumFormatType::ALL)
515 FillEListWithStd_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
516 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
518 FillEListWithStd_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
519 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
521 FillEListWithStd_Impl(rList, SvNumFormatType::CURRENCY, nSelPos);
522 // No FillEListWithUsD_Impl() here, user defined currency formats
523 // were already added.
525 FillEListWithStd_Impl(rList, SvNumFormatType::DATE, nSelPos);
526 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATE, nSelPos);
528 FillEListWithStd_Impl(rList, SvNumFormatType::TIME, nSelPos);
529 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TIME, nSelPos);
531 nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, false);
532 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATETIME, nSelPos);
534 FillEListWithStd_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
535 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
537 FillEListWithStd_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
538 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
540 FillEListWithStd_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
541 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
543 FillEListWithStd_Impl(rList, SvNumFormatType::TEXT, nSelPos);
544 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TEXT, nSelPos);
546 else
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);
554 return nSelPos;
557 void SvxNumberFormatShell::FillEListWithStd_Impl(std::vector<OUString>& rList,
558 SvNumFormatType eCategory, short& nSelPos,
559 bool bSuppressDuplicates)
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.
566 assert(pCurFmtTable != nullptr);
568 aCurrencyFormatList.clear();
570 NfIndexTableOffset eOffsetStart;
571 NfIndexTableOffset eOffsetEnd;
573 switch (eCategory)
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
607 = FillEListWithFormats_Impl(rList, nSelPos, NF_FRACTION_3D, NF_FRACTION_100, false);
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;
621 nSelPos
622 = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, bSuppressDuplicates);
625 short SvxNumberFormatShell::FillEListWithFormats_Impl(std::vector<OUString>& rList, short nSelPos,
626 NfIndexTableOffset eOffsetStart,
627 NfIndexTableOffset eOffsetEnd,
628 bool bSuppressDuplicates)
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.
634 for (tools::Long nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex)
636 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
637 static_cast<NfIndexTableOffset>(nIndex), false);
640 return nSelPos;
643 short SvxNumberFormatShell::FillEListWithDateTime_Impl(std::vector<OUString>& rList, short nSelPos,
644 bool bSuppressDuplicates)
646 // Append a list of date+time formats.
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);
654 for (tools::Long nIndex = NF_DATETIME_START; nIndex <= NF_DATETIME_END; ++nIndex)
656 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
657 static_cast<NfIndexTableOffset>(nIndex), true);
660 // Always add the internally generated ISO formats.
661 nSelPos = FillEListWithFormats_Impl(rList, nSelPos, NF_DATETIME_ISO_YYYYMMDD_HHMMSS,
662 NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, false);
664 return nSelPos;
667 void SvxNumberFormatShell::FillEListWithOneFormat_Impl(std::vector<OUString>& rList, short& nSelPos,
668 bool bSuppressDuplicates,
669 NfIndexTableOffset nOffset,
670 bool bSuppressIsoDateTime)
672 sal_uInt32 nNFEntry = pFormatter->GetFormatIndex(nOffset, eCurLanguage);
674 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
675 if (pNumEntry == nullptr)
676 return;
678 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
679 sal_uInt16 nMyType;
680 CategoryToPos_Impl(nMyCat, nMyType);
681 OUString aNewFormNInfo = pNumEntry->GetFormatstring();
683 if (nNFEntry == nCurFormatKey)
685 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
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");
695 if (!bSupIso
696 && (!bSuppressDuplicates || IsEssentialFormat_Impl(nMyCat, nNFEntry)
697 || std::find(rList.begin(), rList.end(), aNewFormNInfo) == rList.end()))
699 rList.push_back(aNewFormNInfo);
700 aCurEntryList.push_back(nNFEntry);
704 bool SvxNumberFormatShell::IsEssentialFormat_Impl(SvNumFormatType eType, sal_uInt32 nKey)
706 if (nKey == nCurFormatKey)
707 return true;
709 const NfIndexTableOffset nIndex = pFormatter->GetIndexTableOffset(nKey);
710 switch (nIndex)
712 // These are preferred or edit formats.
713 case NF_DATE_SYS_DDMMYYYY:
714 case NF_DATE_ISO_YYYYMMDD:
715 case NF_TIME_HH_MMSS:
716 case NF_TIME_MMSS00:
717 case NF_TIME_HH_MMSS00:
718 case NF_DATETIME_SYS_DDMMYYYY_HHMM:
719 case NF_DATETIME_SYS_DDMMYYYY_HHMMSS:
720 case NF_DATETIME_ISO_YYYYMMDD_HHMMSS:
721 case NF_DATETIME_ISO_YYYYMMDD_HHMMSS000:
722 case NF_DATETIME_ISO_YYYYMMDDTHHMMSS:
723 case NF_DATETIME_ISO_YYYYMMDDTHHMMSS000:
724 return true;
725 default:
726 break;
729 return nKey == pFormatter->GetStandardFormat(eType, eCurLanguage);
732 short SvxNumberFormatShell::FillEListWithCurrency_Impl(std::vector<OUString>& rList, short nSelPos)
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.
738 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
740 const NfCurrencyEntry* pTmpCurrencyEntry;
741 bool bTmpBanking;
742 OUString rSymbol;
744 bool bFlag = pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
745 &bTmpBanking);
747 if ((!bFlag && pCurCurrencyEntry == nullptr)
748 || (bFlag && pTmpCurrencyEntry == nullptr && rSymbol.isEmpty())
749 || (nCurCategory == SvNumFormatType::ALL))
751 if (nCurCategory == SvNumFormatType::ALL)
752 FillEListWithUserCurrencys(rList, nSelPos);
753 nSelPos = FillEListWithSysCurrencys(rList, nSelPos);
755 else
757 nSelPos = FillEListWithUserCurrencys(rList, nSelPos);
760 return nSelPos;
763 short SvxNumberFormatShell::FillEListWithSysCurrencys(std::vector<OUString>& rList, short nSelPos)
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.
769 sal_uInt16 nMyType;
771 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
773 sal_uInt32 nNFEntry;
774 OUString aNewFormNInfo;
776 nCurCurrencyEntryPos = 0;
778 for (tools::Long nIndex = NF_CURRENCY_START; nIndex <= NF_CURRENCY_END; nIndex++)
780 nNFEntry
781 = pFormatter->GetFormatIndex(static_cast<NfIndexTableOffset>(nIndex), eCurLanguage);
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;
788 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
790 if (pNumEntry == nullptr)
791 continue;
793 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
794 CategoryToPos_Impl(nMyCat, nMyType);
795 aNewFormNInfo = pNumEntry->GetFormatstring();
797 if (nNFEntry == nCurFormatKey)
799 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
802 rList.push_back(aNewFormNInfo);
803 aCurEntryList.push_back(nNFEntry);
806 if (nCurCategory != SvNumFormatType::ALL)
808 for (const auto& rEntry : *pCurFmtTable)
810 sal_uInt32 nKey = rEntry.first;
811 const SvNumberformat* pNumEntry = rEntry.second;
813 if (!IsRemoved_Impl(nKey))
815 bool bUserNewCurrency = false;
816 if (pNumEntry->HasNewCurrency())
818 const NfCurrencyEntry* pTmpCurrencyEntry;
819 bool bTmpBanking;
820 OUString rSymbol;
822 pFormatter->GetNewCurrencySymbolString(nKey, rSymbol, &pTmpCurrencyEntry,
823 &bTmpBanking);
825 bUserNewCurrency = (pTmpCurrencyEntry != nullptr);
828 if (!bUserNewCurrency && (pNumEntry->GetType() & SvNumFormatType::DEFINED))
830 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
831 CategoryToPos_Impl(nMyCat, nMyType);
832 aNewFormNInfo = pNumEntry->GetFormatstring();
834 if (nKey == nCurFormatKey)
835 nSelPos = aCurEntryList.size();
836 rList.push_back(aNewFormNInfo);
837 aCurEntryList.push_back(nKey);
842 return nSelPos;
845 short SvxNumberFormatShell::FillEListWithUserCurrencys(std::vector<OUString>& rList, short nSelPos)
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.
851 sal_uInt16 nMyType;
853 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
855 OUString aNewFormNInfo;
857 const NfCurrencyEntry* pTmpCurrencyEntry;
858 bool bTmpBanking, bAdaptSelPos;
859 OUString rSymbol;
860 OUString rBankSymbol;
862 std::vector<OUString> aList;
863 std::vector<sal_uInt32> aKeyList;
865 pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
866 &bTmpBanking);
868 OUString rShortSymbol;
870 if (pCurCurrencyEntry == nullptr)
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);
881 else
883 if (pTmpCurrencyEntry == pCurCurrencyEntry)
884 bAdaptSelPos = true;
885 else
887 bAdaptSelPos = false;
888 pTmpCurrencyEntry = pCurCurrencyEntry;
890 bTmpBanking = bBankingSymbol;
893 if (pTmpCurrencyEntry != nullptr)
895 rSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
896 rBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
897 rShortSymbol = pTmpCurrencyEntry->BuildSymbolString(bTmpBanking, true);
900 for (const auto& rEntry : *pCurFmtTable)
902 sal_uInt32 nKey = rEntry.first;
903 const SvNumberformat* pNumEntry = rEntry.second;
905 if (!IsRemoved_Impl(nKey))
907 if (pNumEntry->GetType() & SvNumFormatType::DEFINED || pNumEntry->IsAdditionalBuiltin())
909 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
910 CategoryToPos_Impl(nMyCat, nMyType);
911 aNewFormNInfo = pNumEntry->GetFormatstring();
913 bool bInsFlag = false;
914 if (pNumEntry->HasNewCurrency())
916 bInsFlag = true; // merge locale formats into currency selection
918 else if ((!bTmpBanking && aNewFormNInfo.indexOf(rSymbol) >= 0)
919 || (bTmpBanking && aNewFormNInfo.indexOf(rBankSymbol) >= 0))
921 bInsFlag = true;
923 else if (aNewFormNInfo.indexOf(rShortSymbol) >= 0)
925 OUString rTstSymbol;
926 const NfCurrencyEntry* pTstCurrencyEntry;
927 bool bTstBanking;
929 pFormatter->GetNewCurrencySymbolString(nKey, rTstSymbol, &pTstCurrencyEntry,
930 &bTstBanking);
932 if (pTmpCurrencyEntry == pTstCurrencyEntry && bTstBanking == bTmpBanking)
934 bInsFlag = true;
938 if (bInsFlag)
940 aList.push_back(aNewFormNInfo);
941 aKeyList.push_back(nKey);
947 NfWSStringsDtor aWSStringsDtor;
948 sal_uInt16 nDefault;
949 if (pTmpCurrencyEntry && nCurCategory != SvNumFormatType::ALL)
951 nDefault
952 = pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, bTmpBanking);
953 if (!bTmpBanking)
954 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, true);
956 else
957 nDefault = 0;
958 if (!bTmpBanking && nCurCategory != SvNumFormatType::ALL)
960 // append formats for all currencies defined in the current I18N locale
961 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
962 sal_uInt16 nCurrCount = rCurrencyTable.size();
963 LanguageType eLang = MsLangId::getRealLanguage(eCurLanguage);
964 for (sal_uInt16 i = 0; i < nCurrCount; ++i)
966 const NfCurrencyEntry* pCurr = &rCurrencyTable[i];
967 if (pCurr->GetLanguage() == eLang && pTmpCurrencyEntry != pCurr)
969 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, false);
970 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, true);
975 size_t nOldListCount = rList.size();
976 for (size_t i = 0, nPos = nOldListCount; i < aWSStringsDtor.size(); ++i)
978 bool bFlag = true;
979 OUString aInsStr(aWSStringsDtor[i]);
980 size_t j;
981 for (j = 0; j < aList.size(); ++j)
983 if (aList[j] == aInsStr)
985 bFlag = false;
986 break;
989 if (bFlag)
991 rList.push_back(aInsStr);
992 aCurEntryList.insert(aCurEntryList.begin() + (nPos++), NUMBERFORMAT_ENTRY_NOT_FOUND);
994 else
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);
1003 for (size_t i = 0; i < aKeyList.size(); ++i)
1005 if (aKeyList[i] != NUMBERFORMAT_ENTRY_NOT_FOUND)
1007 rList.push_back(aList[i]);
1008 aCurEntryList.push_back(aKeyList[i]);
1012 for (size_t i = nOldListCount; i < rList.size(); ++i)
1014 aCurrencyFormatList.push_back(rList[i]);
1016 if (nSelPos == SELPOS_NONE && bAdaptSelPos && aCurEntryList[i] == nCurFormatKey)
1017 nSelPos = i;
1020 if (nSelPos == SELPOS_NONE && nCurCategory != SvNumFormatType::ALL)
1021 nSelPos = nDefault;
1023 return nSelPos;
1026 short SvxNumberFormatShell::FillEListWithUsD_Impl(std::vector<OUString>& rList,
1027 SvNumFormatType eCategory, short nSelPos)
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.
1034 assert(pCurFmtTable != nullptr);
1036 OUString aNewFormNInfo;
1038 const bool bCatDefined = (eCategory == SvNumFormatType::DEFINED);
1039 const bool bCategoryMatch = (eCategory != SvNumFormatType::ALL && !bCatDefined);
1040 const bool bNatNumCurrency = (eCategory == SvNumFormatType::CURRENCY);
1042 for (const auto& rEntry : *pCurFmtTable)
1044 const SvNumberformat* pNumEntry = rEntry.second;
1046 if (bCategoryMatch && (pNumEntry->GetMaskedType() & eCategory) != eCategory)
1047 continue; // for; type does not match category if not ALL
1049 const bool bUserDefined = bool(pNumEntry->GetType() & SvNumFormatType::DEFINED);
1050 if (!bUserDefined && bCatDefined)
1051 continue; // for; not user defined in DEFINED category
1053 if (!(bUserDefined || (!bCatDefined && pNumEntry->IsAdditionalBuiltin())))
1054 continue; // for; does not match criteria at all
1056 const sal_uInt32 nKey = rEntry.first;
1057 if (!IsRemoved_Impl(nKey))
1059 aNewFormNInfo = pNumEntry->GetFormatstring();
1061 if (bNatNumCurrency && (aNewFormNInfo.indexOf("NatNum12") < 0 || bUserDefined))
1062 continue; // for; extra CURRENCY must be not user-defined NatNum12 type
1064 bool bAdd = true;
1065 if (pNumEntry->HasNewCurrency())
1067 bool bTestBanking;
1068 sal_uInt16 nPos = FindCurrencyTableEntry(aNewFormNInfo, bTestBanking);
1069 bAdd = !IsInTable(nPos, bTestBanking, aNewFormNInfo);
1071 if (bAdd)
1073 if (nKey == nCurFormatKey)
1074 nSelPos = aCurEntryList.size();
1075 rList.push_back(aNewFormNInfo);
1076 aCurEntryList.push_back(nKey);
1080 return nSelPos;
1083 void SvxNumberFormatShell::GetPreviewString_Impl(OUString& rString, const Color*& rpColor)
1085 rpColor = nullptr;
1087 // #50441# if a string was set in addition to the value, use it for text formats
1088 bool bUseText
1089 = (eValType == SvxNumberValueType::String
1090 || (!aValStr.isEmpty() && (pFormatter->GetType(nCurFormatKey) & SvNumFormatType::TEXT)));
1092 if (bUseText)
1094 pFormatter->GetOutputString(aValStr, nCurFormatKey, rString, &rpColor);
1096 else
1098 pFormatter->GetOutputString(nValNum, nCurFormatKey, rString, &rpColor, bUseStarFormat);
1102 ::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetRemoved_Impl(size_t nKey)
1104 return ::std::find(aDelList.begin(), aDelList.end(), nKey);
1107 bool SvxNumberFormatShell::IsRemoved_Impl(size_t nKey)
1109 return GetRemoved_Impl(nKey) != aDelList.end();
1112 ::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetAdded_Impl(size_t nKey)
1114 return ::std::find(aAddList.begin(), aAddList.end(), nKey);
1117 // Conversion routines:
1118 void SvxNumberFormatShell::PosToCategory_Impl(sal_uInt16 nPos, SvNumFormatType& rCategory)
1120 // map category css::form positions (->resource)
1121 switch (nPos)
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;
1160 void SvxNumberFormatShell::CategoryToPos_Impl(SvNumFormatType nCategory, sal_uInt16& rPos)
1162 // map category to css::form positions (->resource)
1163 switch (nCategory)
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;
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
1208 void SvxNumberFormatShell::MakePrevStringFromVal(const OUString& rFormatStr, OUString& rPreviewStr,
1209 const Color*& rpFontColor, double nValue)
1211 rpFontColor = nullptr;
1212 pFormatter->GetPreviewString(rFormatStr, nValue, rPreviewStr, &rpFontColor, eCurLanguage);
1216 * Function: Returns the comment for a given entry.
1217 * Input: Number of the entry
1218 * Output: Comment string
1220 void SvxNumberFormatShell::SetComment4Entry(short nEntry, const OUString& aEntStr)
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);
1232 * Function: Returns the comment for a given entry.
1233 * Input: Number of the entry
1234 * Output: Comment string
1236 OUString SvxNumberFormatShell::GetComment4Entry(short nEntry)
1238 if (nEntry < 0)
1239 return OUString();
1241 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1243 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1244 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1245 if (pNumEntry != nullptr)
1246 return pNumEntry->GetComment();
1249 return OUString();
1253 * Function: Returns the category number for a given entry.
1254 * Input: Number of the entry
1255 * Output: Category number
1257 short SvxNumberFormatShell::GetCategory4Entry(short nEntry) const
1259 if (nEntry < 0)
1260 return 0;
1261 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1263 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1265 if (nMyNfEntry != NUMBERFORMAT_ENTRY_NOT_FOUND)
1267 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1268 if (pNumEntry != nullptr)
1270 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
1271 sal_uInt16 nMyType;
1272 CategoryToPos_Impl(nMyCat, nMyType);
1274 return static_cast<short>(nMyType);
1276 return 0;
1278 else if (!aCurrencyFormatList.empty())
1280 return CAT_CURRENCY;
1283 return 0;
1287 * Function: Returns the information about whether an entry is user-specific.
1288 * Input: Number of the entry
1289 * Output: User-specific?
1291 bool SvxNumberFormatShell::GetUserDefined4Entry(short nEntry)
1293 if (nEntry < 0)
1294 return false;
1295 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1297 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1298 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1300 if (pNumEntry != nullptr)
1302 if (pNumEntry->GetType() & SvNumFormatType::DEFINED)
1304 return true;
1308 return false;
1312 * Function: Returns the format string for a given entry.
1313 * Input: Number of the entry
1314 * Output: Format string
1316 OUString SvxNumberFormatShell::GetFormat4Entry(short nEntry)
1318 if (nEntry < 0)
1319 return OUString();
1321 if (!aCurrencyFormatList.empty()
1322 && (!pFormatter->GetEntry(aCurEntryList[nEntry])
1323 || pFormatter->GetEntry(aCurEntryList[nEntry])->GetFormatstring().indexOf("NatNum12")
1324 < 0))
1326 if (aCurrencyFormatList.size() > o3tl::make_unsigned(nEntry))
1327 return aCurrencyFormatList[nEntry];
1329 else
1331 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1332 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1334 if (pNumEntry != nullptr)
1335 return pNumEntry->GetFormatstring();
1337 return OUString();
1341 * Function: Returns the list number for a given format index.
1342 * Input: Number of the entry
1343 * Output: Category number
1345 short SvxNumberFormatShell::GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
1347 short nSelP = SELPOS_NONE;
1348 if (nIdx != NUMBERFORMAT_ENTRY_NEW_CURRENCY)
1350 // Check list size against return type limit.
1351 if (aCurEntryList.size() <= o3tl::make_unsigned(::std::numeric_limits<short>::max()))
1353 for (size_t i = 0; i < aCurEntryList.size(); ++i)
1355 if (aCurEntryList[i] == nIdx)
1357 nSelP = i;
1358 break;
1362 else
1364 OSL_FAIL("svx::SvxNumberFormatShell::GetListPos4Entry(), list got too large!");
1367 else
1369 // A second list holds the generated currency formats.
1370 for (size_t i = 0; i < aCurrencyFormatList.size(); ++i)
1372 if (rFmtString == aCurrencyFormatList[i])
1374 nSelP = static_cast<short>(i);
1375 break;
1379 return nSelP;
1382 OUString SvxNumberFormatShell::GetStandardName() const
1384 return pFormatter->GetStandardName(eCurLanguage);
1387 void SvxNumberFormatShell::GetCurrencySymbols(std::vector<OUString>& rList, sal_uInt16* pPos)
1389 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::MatchSystemCurrency();
1391 bool bFlag = (pTmpCurrencyEntry == nullptr);
1393 SvxCurrencyToolBoxControl::GetCurrencySymbols(rList, bFlag, aCurCurrencyList);
1395 if (pPos == nullptr)
1396 return;
1398 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1399 sal_uInt16 nTableCount = rCurrencyTable.size();
1401 *pPos = 0;
1402 size_t nCount = aCurCurrencyList.size();
1404 if (bFlag)
1406 *pPos = 1;
1407 nCurCurrencyEntryPos = 1;
1409 else
1411 for (size_t i = 1; i < nCount; i++)
1413 const sal_uInt16 j = aCurCurrencyList[i];
1414 if (j != sal_uInt16(-1) && j < nTableCount && pTmpCurrencyEntry == &rCurrencyTable[j])
1416 *pPos = static_cast<sal_uInt16>(i);
1417 nCurCurrencyEntryPos = static_cast<sal_uInt16>(i);
1418 break;
1424 void SvxNumberFormatShell::SetCurrencySymbol(sal_uInt32 nPos)
1426 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1427 sal_uInt16 nCount = rCurrencyTable.size();
1429 bBankingSymbol = (nPos >= nCount);
1431 if (nPos >= aCurCurrencyList.size())
1432 return;
1434 sal_uInt16 nCurrencyPos = aCurCurrencyList[nPos];
1435 if (nCurrencyPos != sal_uInt16(-1))
1437 pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(&rCurrencyTable[nCurrencyPos]);
1438 nCurCurrencyEntryPos = nPos;
1440 else
1442 pCurCurrencyEntry = nullptr;
1443 nCurCurrencyEntryPos = 0;
1444 nCurFormatKey = pFormatter->GetFormatIndex(NF_CURRENCY_1000DEC2_RED, eCurLanguage);
1448 void SvxNumberFormatShell::SetCurCurrencyEntry(NfCurrencyEntry* pCEntry)
1450 pCurCurrencyEntry = pCEntry;
1453 bool SvxNumberFormatShell::IsTmpCurrencyFormat(const OUString& rFmtString)
1455 sal_uInt32 nFound;
1456 FindEntry(rFmtString, &nFound);
1457 return nFound == NUMBERFORMAT_ENTRY_NEW_CURRENCY;
1460 sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const OUString& rFmtString)
1462 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1463 sal_uInt16 nCount = rCurrencyTable.size();
1465 bool bTestBanking = false;
1467 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
1469 if (nPos != sal_uInt16(-1))
1471 sal_uInt16 nStart = 0;
1472 if (bTestBanking && aCurCurrencyList.size() > nPos)
1474 nStart = nCount;
1476 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1478 if (aCurCurrencyList[j] == nPos)
1479 return j;
1482 return sal_uInt16(-1);
1485 sal_uInt16 SvxNumberFormatShell::FindCurrencyTableEntry(const OUString& rFmtString,
1486 bool& bTestBanking)
1488 sal_uInt16 nPos = sal_uInt16(-1);
1490 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1491 sal_uInt16 nCount = rCurrencyTable.size();
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))
1500 // eventually match with format locale
1501 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::GetCurrencyEntry(
1502 bTestBanking, aSymbol, aExtension, pFormat->GetLanguage());
1503 if (pTmpCurrencyEntry)
1505 for (sal_uInt16 i = 0; i < nCount; i++)
1507 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1509 nPos = i;
1510 break;
1515 else
1517 // search symbol string only
1518 for (sal_uInt16 i = 0; i < nCount; i++)
1520 const NfCurrencyEntry* pTmpCurrencyEntry = &rCurrencyTable[i];
1521 OUString _aSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
1522 OUString aBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
1524 if (rFmtString.indexOf(_aSymbol) != -1)
1526 bTestBanking = false;
1527 nPos = i;
1528 break;
1530 else if (rFmtString.indexOf(aBankSymbol) != -1)
1532 bTestBanking = true;
1533 nPos = i;
1534 break;
1539 return nPos;
1542 sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry* pTmpCurrencyEntry,
1543 bool bTmpBanking)
1545 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1546 sal_uInt16 nCount = rCurrencyTable.size();
1548 sal_uInt16 nPos = 0;
1549 for (sal_uInt16 i = 0; i < nCount; i++)
1551 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1553 nPos = i;
1554 break;
1558 sal_uInt16 nStart = 0;
1559 if (bTmpBanking && aCurCurrencyList.size() > nPos)
1561 nStart = nCount;
1563 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1565 if (aCurCurrencyList[j] == nPos)
1566 return j;
1568 return sal_uInt16(-1);
1571 bool SvxNumberFormatShell::IsInTable(sal_uInt16 const nPos, bool const bTmpBanking,
1572 std::u16string_view rFmtString) const
1574 bool bFlag = false;
1576 if (nPos != sal_uInt16(-1))
1578 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
1580 if (nPos < rCurrencyTable.size())
1582 NfWSStringsDtor aWSStringsDtor;
1583 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, rCurrencyTable[nPos], bTmpBanking);
1585 for (const OUString& s : aWSStringsDtor)
1587 if (s == rFmtString)
1589 bFlag = true;
1590 break;
1596 return bFlag;
1599 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */