1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
38 double GetDefaultValNum(const SvNumFormatType 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
];
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
)
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)
101 case SvxNumberValueType::String
:
104 case SvxNumberValueType::Number
:
107 nValNum
= GetDefaultValNum(pFormatter
->GetType(nCurFormatKey
));
110 case SvxNumberValueType::Undefined
:
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
)
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
140 case SvxNumberValueType::Number
:
143 case SvxNumberValueType::String
:
144 case SvxNumberValueType::Undefined
:
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.
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())
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
,
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())
232 OSL_FAIL("duplicate format!");
238 bInserted
= pFormatter
->PutEntry(rFormat
, nPos
, nCurCategory
, nAddKey
, eCurLanguage
);
239 rErrPos
= (nPos
>= 0) ? nPos
: -1;
243 // May be sorted under a different locale if LCID was parsed.
244 const SvNumberformat
* pEntry
= pFormatter
->GetEntry(nAddKey
);
247 LanguageType nLang
= pEntry
->GetLanguage();
248 if (eCurLanguage
!= nLang
)
250 // Current language's list would not show entry, adapt.
251 eCurLanguage
= nLang
;
259 nCurFormatKey
= nAddKey
;
260 DBG_ASSERT(GetAdded_Impl(nCurFormatKey
) == aAddList
.end(), "duplicate format!");
261 aAddList
.push_back(nCurFormatKey
);
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!");
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
))
292 aDelList
.push_back(nDelKey
);
294 ::std::vector
<sal_uInt32
>::iterator nAt
= GetAdded_Impl(nDelKey
);
295 if (nAt
!= aAddList
.end())
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
;
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
,
331 rFormat
= pFormatter
->GenerateFormat(nCurFormatKey
, eCurLanguage
, bThousand
, bNegRed
,
332 nPrecision
, nLeadingZeroes
);
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 bool SvxNumberFormatShell::IsNatNum12(std::u16string_view rFormat
) const
351 sal_uInt32 nFmtKey
= pFormatter
->GetEntryKey(rFormat
, eCurLanguage
);
353 return pFormatter
->IsNatNum12(nFmtKey
);
356 void SvxNumberFormatShell::GetOptions(const OUString
& rFormat
, bool& rThousand
, bool& rNegRed
,
357 sal_uInt16
& rPrecision
, sal_uInt16
& rLeadingZeroes
,
358 sal_uInt16
& rCatLbPos
)
360 sal_uInt32 nFmtKey
= pFormatter
->GetEntryKey(rFormat
, eCurLanguage
);
362 if (nFmtKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
364 pFormatter
->GetFormatSpecialInfo(nFmtKey
, rThousand
, rNegRed
, rPrecision
, rLeadingZeroes
);
366 CategoryToPos_Impl(pFormatter
->GetType(nFmtKey
), rCatLbPos
);
370 bool bTestBanking
= false;
371 sal_uInt16 nPos
= FindCurrencyTableEntry(rFormat
, bTestBanking
);
373 if (IsInTable(nPos
, bTestBanking
, rFormat
)
374 && pFormatter
->GetFormatSpecialInfo(rFormat
, rThousand
, rNegRed
, rPrecision
,
375 rLeadingZeroes
, eCurLanguage
)
378 rCatLbPos
= CAT_CURRENCY
;
381 rCatLbPos
= CAT_USERDEFINED
;
385 void SvxNumberFormatShell::MakePreviewString(const OUString
& rFormatStr
, OUString
& rPreviewStr
,
386 const Color
*& rpFontColor
)
388 rpFontColor
= nullptr;
390 sal_uInt32 nExistingFormat
= pFormatter
->GetEntryKey(rFormatStr
, eCurLanguage
);
391 if (nExistingFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
393 // real preview - not implemented in NumberFormatter for text formats
394 pFormatter
->GetPreviewString(rFormatStr
, nValNum
, rPreviewStr
, &rpFontColor
, eCurLanguage
,
401 // #50441# if a string was set in addition to the value, use it for text formats
402 bool bUseText
= (eValType
== SvxNumberValueType::String
403 || (!aValStr
.isEmpty()
404 && (pFormatter
->GetType(nExistingFormat
) & SvNumFormatType::TEXT
)));
408 pFormatter
->GetOutputString(aValStr
, nExistingFormat
, rPreviewStr
, &rpFontColor
);
412 if (bIsDefaultValNum
)
413 nValNum
= GetDefaultValNum(pFormatter
->GetType(nExistingFormat
));
414 pFormatter
->GetOutputString(nValNum
, nExistingFormat
, rPreviewStr
, &rpFontColor
,
420 bool SvxNumberFormatShell::IsUserDefined(const OUString
& rFmtString
)
422 sal_uInt32 nFound
= pFormatter
->GetEntryKey(rFmtString
, eCurLanguage
);
425 if (nFound
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
427 bFlag
= pFormatter
->IsUserDefined(rFmtString
, eCurLanguage
);
431 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nFound
);
433 if (pNumEntry
!= nullptr && pNumEntry
->HasNewCurrency())
436 sal_uInt16 nPos
= FindCurrencyTableEntry(rFmtString
, bTestBanking
);
437 bFlag
= !IsInTable(nPos
, bTestBanking
, rFmtString
);
444 bool SvxNumberFormatShell::FindEntry(const OUString
& rFmtString
, sal_uInt32
* pAt
/* = NULL */)
448 sal_uInt32 nFound
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
449 // There may be multiple builtin entries with the same format code, first
450 // try if the current key matches.
451 const SvNumberformat
* pEntry
= pFormatter
->GetEntry(nCurFormatKey
);
452 if (pEntry
&& pEntry
->GetLanguage() == eCurLanguage
&& pEntry
->GetFormatstring() == rFmtString
)
453 nFound
= nCurFormatKey
;
455 if (nFound
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
456 // Find the first matching format code.
457 nFound
= pFormatter
->TestNewString(rFmtString
, eCurLanguage
);
459 if (nFound
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
461 bool bTestBanking
= false;
462 sal_uInt16 nPos
= FindCurrencyTableEntry(rFmtString
, bTestBanking
);
464 if (IsInTable(nPos
, bTestBanking
, rFmtString
))
466 nFound
= NUMBERFORMAT_ENTRY_NEW_CURRENCY
;
472 bRes
= !IsRemoved_Impl(nFound
);
481 void SvxNumberFormatShell::GetInitSettings(sal_uInt16
& nCatLbPos
, LanguageType
& rLangType
,
482 sal_uInt16
& nFmtLbSelPos
,
483 std::vector
<OUString
>& rFmtEntries
,
484 OUString
& rPrevString
, const Color
*& rpPrevColor
)
486 // precondition: number formater found
487 DBG_ASSERT(pFormatter
!= nullptr, "Number formatter not found!");
489 short nSelPos
= SELPOS_NONE
;
491 // special treatment for undefined number format:
492 if ((eValType
== SvxNumberValueType::Undefined
) && (nCurFormatKey
== 0))
493 PosToCategory_Impl(CAT_ALL
, nCurCategory
); // category = all
495 nCurCategory
= SvNumFormatType::UNDEFINED
; // category = undefined
497 pCurFmtTable
= &(pFormatter
->GetFirstEntryTable(nCurCategory
, nCurFormatKey
, eCurLanguage
));
499 CategoryToPos_Impl(nCurCategory
, nCatLbPos
);
500 rLangType
= eCurLanguage
;
502 nSelPos
= FillEntryList_Impl(rFmtEntries
);
504 DBG_ASSERT(nSelPos
!= SELPOS_NONE
, "Leere Formatliste!");
506 nFmtLbSelPos
= (nSelPos
!= SELPOS_NONE
) ? static_cast<sal_uInt16
>(nSelPos
) : 0;
507 GetPreviewString_Impl(rPrevString
, rpPrevColor
);
510 short SvxNumberFormatShell::FillEntryList_Impl(std::vector
<OUString
>& rList
)
512 /* Create a current list of format entries. The return value is
513 * the list position of the current format. If the list is empty
514 * or if there is no current format, SELPOS_NONE is delivered.
516 short nSelPos
= SELPOS_NONE
;
518 aCurEntryList
.clear();
520 if (nCurCategory
== SvNumFormatType::ALL
)
522 FillEListWithStd_Impl(rList
, SvNumFormatType::NUMBER
, nSelPos
);
523 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::NUMBER
, nSelPos
);
525 FillEListWithStd_Impl(rList
, SvNumFormatType::PERCENT
, nSelPos
);
526 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::PERCENT
, nSelPos
);
528 FillEListWithStd_Impl(rList
, SvNumFormatType::CURRENCY
, nSelPos
);
529 // No FillEListWithUsD_Impl() here, user defined currency formats
530 // were already added.
532 FillEListWithStd_Impl(rList
, SvNumFormatType::DATE
, nSelPos
);
533 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::DATE
, nSelPos
);
535 FillEListWithStd_Impl(rList
, SvNumFormatType::TIME
, nSelPos
);
536 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::TIME
, nSelPos
);
538 nSelPos
= FillEListWithDateTime_Impl(rList
, nSelPos
, false);
539 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::DATETIME
, nSelPos
);
541 FillEListWithStd_Impl(rList
, SvNumFormatType::SCIENTIFIC
, nSelPos
);
542 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::SCIENTIFIC
, nSelPos
);
544 FillEListWithStd_Impl(rList
, SvNumFormatType::FRACTION
, nSelPos
);
545 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::FRACTION
, nSelPos
);
547 FillEListWithStd_Impl(rList
, SvNumFormatType::LOGICAL
, nSelPos
);
548 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::LOGICAL
, nSelPos
);
550 FillEListWithStd_Impl(rList
, SvNumFormatType::TEXT
, nSelPos
);
551 nSelPos
= FillEListWithUsD_Impl(rList
, SvNumFormatType::TEXT
, nSelPos
);
555 FillEListWithStd_Impl(rList
, nCurCategory
, nSelPos
, true);
556 nSelPos
= FillEListWithUsD_Impl(rList
, nCurCategory
, nSelPos
);
557 if (nCurCategory
== SvNumFormatType::DATE
|| nCurCategory
== SvNumFormatType::TIME
)
558 nSelPos
= FillEListWithDateTime_Impl(rList
, nSelPos
, true);
564 void SvxNumberFormatShell::FillEListWithStd_Impl(std::vector
<OUString
>& rList
,
565 SvNumFormatType eCategory
, short& nSelPos
,
566 bool bSuppressDuplicates
)
568 /* Create a current list of format entries. The return value is
569 * the list position of the current format. If the list is empty
570 * or if there is no current format, SELPOS_NONE is delivered.
573 assert(pCurFmtTable
!= nullptr);
575 aCurrencyFormatList
.clear();
577 NfIndexTableOffset eOffsetStart
;
578 NfIndexTableOffset eOffsetEnd
;
582 case SvNumFormatType::NUMBER
:
583 eOffsetStart
= NF_NUMBER_START
;
584 eOffsetEnd
= NF_NUMBER_END
;
586 case SvNumFormatType::PERCENT
:
587 eOffsetStart
= NF_PERCENT_START
;
588 eOffsetEnd
= NF_PERCENT_END
;
590 case SvNumFormatType::CURRENCY
:
591 // Currency entries are generated and assembled, ignore
592 // bSuppressDuplicates.
593 nSelPos
= FillEListWithCurrency_Impl(rList
, nSelPos
);
595 case SvNumFormatType::DATE
:
596 eOffsetStart
= NF_DATE_START
;
597 eOffsetEnd
= NF_DATE_END
;
599 case SvNumFormatType::TIME
:
600 eOffsetStart
= NF_TIME_START
;
601 eOffsetEnd
= NF_TIME_END
;
603 case SvNumFormatType::SCIENTIFIC
:
604 eOffsetStart
= NF_SCIENTIFIC_START
;
605 eOffsetEnd
= NF_SCIENTIFIC_END
;
607 case SvNumFormatType::FRACTION
:
608 eOffsetStart
= NF_FRACTION_START
;
609 eOffsetEnd
= NF_FRACTION_END
;
610 // Fraction formats are internally generated by the number
611 // formatter and are not supposed to contain duplicates anyway.
612 nSelPos
= FillEListWithFormats_Impl(rList
, nSelPos
, eOffsetStart
, eOffsetEnd
, false);
614 = FillEListWithFormats_Impl(rList
, nSelPos
, NF_FRACTION_3D
, NF_FRACTION_100
, false);
616 case SvNumFormatType::LOGICAL
:
617 eOffsetStart
= NF_BOOLEAN
;
618 eOffsetEnd
= NF_BOOLEAN
;
620 case SvNumFormatType::TEXT
:
621 eOffsetStart
= NF_TEXT
;
622 eOffsetEnd
= NF_TEXT
;
629 = FillEListWithFormats_Impl(rList
, nSelPos
, eOffsetStart
, eOffsetEnd
, bSuppressDuplicates
);
632 short SvxNumberFormatShell::FillEListWithFormats_Impl(std::vector
<OUString
>& rList
, short nSelPos
,
633 NfIndexTableOffset eOffsetStart
,
634 NfIndexTableOffset eOffsetEnd
,
635 bool bSuppressDuplicates
)
637 /* Create a current list of format entries. The return value is
638 * the list position of the current format. If the list is empty
639 * or if there is no current format, SELPOS_NONE is delivered.
641 for (tools::Long nIndex
= eOffsetStart
; nIndex
<= eOffsetEnd
; ++nIndex
)
643 FillEListWithOneFormat_Impl(rList
, nSelPos
, bSuppressDuplicates
,
644 static_cast<NfIndexTableOffset
>(nIndex
), false);
650 short SvxNumberFormatShell::FillEListWithDateTime_Impl(std::vector
<OUString
>& rList
, short nSelPos
,
651 bool bSuppressDuplicates
)
653 // Append a list of date+time formats.
655 // Add first, so a NF_DATETIME_SYSTEM_SHORT_HHMM may be suppressed in
656 // locales that do not use 2-digit years there and this here is the
658 FillEListWithOneFormat_Impl(rList
, nSelPos
, bSuppressDuplicates
, NF_DATETIME_SYS_DDMMYYYY_HHMM
,
661 for (tools::Long nIndex
= NF_DATETIME_START
; nIndex
<= NF_DATETIME_END
; ++nIndex
)
663 FillEListWithOneFormat_Impl(rList
, nSelPos
, bSuppressDuplicates
,
664 static_cast<NfIndexTableOffset
>(nIndex
), true);
667 // Always add the internally generated ISO formats.
668 nSelPos
= FillEListWithFormats_Impl(rList
, nSelPos
, NF_DATETIME_ISO_YYYYMMDD_HHMMSS
,
669 NF_DATETIME_ISO_YYYYMMDDTHHMMSS000
, false);
674 void SvxNumberFormatShell::FillEListWithOneFormat_Impl(std::vector
<OUString
>& rList
, short& nSelPos
,
675 bool bSuppressDuplicates
,
676 NfIndexTableOffset nOffset
,
677 bool bSuppressIsoDateTime
)
679 sal_uInt32 nNFEntry
= pFormatter
->GetFormatIndex(nOffset
, eCurLanguage
);
681 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nNFEntry
);
682 if (pNumEntry
== nullptr)
685 SvNumFormatType nMyCat
= pNumEntry
->GetMaskedType();
687 CategoryToPos_Impl(nMyCat
, nMyType
);
688 OUString aNewFormNInfo
= pNumEntry
->GetFormatstring();
690 if (nNFEntry
== nCurFormatKey
)
692 nSelPos
= (!IsRemoved_Impl(nNFEntry
)) ? aCurEntryList
.size() : SELPOS_NONE
;
695 // Ugly hack to suppress an ISO date+time format that is the default
696 // date+time format of the locale and identical to the internally generated
697 // one always to be added after/below.
699 = bSuppressIsoDateTime
&& bSuppressDuplicates
700 && (aNewFormNInfo
== "YYYY-MM-DD HH:MM:SS" || aNewFormNInfo
== "YYYY-MM-DD\"T\"HH:MM:SS");
703 && (!bSuppressDuplicates
|| IsEssentialFormat_Impl(nMyCat
, nNFEntry
)
704 || std::find(rList
.begin(), rList
.end(), aNewFormNInfo
) == rList
.end()))
706 rList
.push_back(aNewFormNInfo
);
707 aCurEntryList
.push_back(nNFEntry
);
711 bool SvxNumberFormatShell::IsEssentialFormat_Impl(SvNumFormatType eType
, sal_uInt32 nKey
)
713 if (nKey
== nCurFormatKey
)
716 const NfIndexTableOffset nIndex
= pFormatter
->GetIndexTableOffset(nKey
);
719 // These are preferred or edit formats.
720 case NF_DATE_SYS_DDMMYYYY
:
721 case NF_DATE_ISO_YYYYMMDD
:
722 case NF_TIME_HH_MMSS
:
724 case NF_TIME_HH_MMSS00
:
725 case NF_DATETIME_SYS_DDMMYYYY_HHMM
:
726 case NF_DATETIME_SYS_DDMMYYYY_HHMMSS
:
727 case NF_DATETIME_ISO_YYYYMMDD_HHMMSS
:
728 case NF_DATETIME_ISO_YYYYMMDD_HHMMSS000
:
729 case NF_DATETIME_ISO_YYYYMMDDTHHMMSS
:
730 case NF_DATETIME_ISO_YYYYMMDDTHHMMSS000
:
736 return nKey
== pFormatter
->GetStandardFormat(eType
, eCurLanguage
);
739 short SvxNumberFormatShell::FillEListWithCurrency_Impl(std::vector
<OUString
>& rList
, short nSelPos
)
741 /* Create a current list of format entries. The return value is
742 * the list position of the current format. If the list is empty
743 * or if there is no current format, SELPOS_NONE is delivered.
745 DBG_ASSERT(pCurFmtTable
!= nullptr, "unknown NumberFormat");
747 const NfCurrencyEntry
* pTmpCurrencyEntry
;
751 bool bFlag
= pFormatter
->GetNewCurrencySymbolString(nCurFormatKey
, rSymbol
, &pTmpCurrencyEntry
,
754 if ((!bFlag
&& pCurCurrencyEntry
== nullptr)
755 || (bFlag
&& pTmpCurrencyEntry
== nullptr && rSymbol
.isEmpty())
756 || (nCurCategory
== SvNumFormatType::ALL
))
758 if (nCurCategory
== SvNumFormatType::ALL
)
759 FillEListWithUserCurrencys(rList
, nSelPos
);
760 nSelPos
= FillEListWithSysCurrencys(rList
, nSelPos
);
764 nSelPos
= FillEListWithUserCurrencys(rList
, nSelPos
);
770 short SvxNumberFormatShell::FillEListWithSysCurrencys(std::vector
<OUString
>& rList
, short nSelPos
)
772 /* Create a current list of format entries. The return value is
773 * the list position of the current format. If the list is empty
774 * or if there is no current format, SELPOS_NONE is delivered.
778 DBG_ASSERT(pCurFmtTable
!= nullptr, "unknown NumberFormat");
781 OUString aNewFormNInfo
;
783 nCurCurrencyEntryPos
= 0;
785 for (tools::Long nIndex
= NF_CURRENCY_START
; nIndex
<= NF_CURRENCY_END
; nIndex
++)
788 = pFormatter
->GetFormatIndex(static_cast<NfIndexTableOffset
>(nIndex
), eCurLanguage
);
790 if (nCurCategory
== SvNumFormatType::ALL
&& nNFEntry
!= nCurFormatKey
)
791 // Deprecated old currency entries, for ALL add only if used as
792 // current format key.
795 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nNFEntry
);
797 if (pNumEntry
== nullptr)
800 SvNumFormatType nMyCat
= pNumEntry
->GetMaskedType();
801 CategoryToPos_Impl(nMyCat
, nMyType
);
802 aNewFormNInfo
= pNumEntry
->GetFormatstring();
804 if (nNFEntry
== nCurFormatKey
)
806 nSelPos
= (!IsRemoved_Impl(nNFEntry
)) ? aCurEntryList
.size() : SELPOS_NONE
;
809 rList
.push_back(aNewFormNInfo
);
810 aCurEntryList
.push_back(nNFEntry
);
813 if (nCurCategory
!= SvNumFormatType::ALL
)
815 for (const auto& rEntry
: *pCurFmtTable
)
817 sal_uInt32 nKey
= rEntry
.first
;
818 const SvNumberformat
* pNumEntry
= rEntry
.second
;
820 if (!IsRemoved_Impl(nKey
))
822 bool bUserNewCurrency
= false;
823 if (pNumEntry
->HasNewCurrency())
825 const NfCurrencyEntry
* pTmpCurrencyEntry
;
829 pFormatter
->GetNewCurrencySymbolString(nKey
, rSymbol
, &pTmpCurrencyEntry
,
832 bUserNewCurrency
= (pTmpCurrencyEntry
!= nullptr);
835 if (!bUserNewCurrency
&& (pNumEntry
->GetType() & SvNumFormatType::DEFINED
))
837 SvNumFormatType nMyCat
= pNumEntry
->GetMaskedType();
838 CategoryToPos_Impl(nMyCat
, nMyType
);
839 aNewFormNInfo
= pNumEntry
->GetFormatstring();
841 if (nKey
== nCurFormatKey
)
842 nSelPos
= aCurEntryList
.size();
843 rList
.push_back(aNewFormNInfo
);
844 aCurEntryList
.push_back(nKey
);
852 short SvxNumberFormatShell::FillEListWithUserCurrencys(std::vector
<OUString
>& rList
, short nSelPos
)
854 /* Create a current list of format entries. The return value is
855 * the list position of the current format. If the list is empty
856 * or if there is no current format, SELPOS_NONE is delivered.
860 DBG_ASSERT(pCurFmtTable
!= nullptr, "unknown NumberFormat");
862 OUString aNewFormNInfo
;
864 const NfCurrencyEntry
* pTmpCurrencyEntry
;
865 bool bTmpBanking
, bAdaptSelPos
;
867 OUString rBankSymbol
;
869 std::vector
<OUString
> aList
;
870 std::vector
<sal_uInt32
> aKeyList
;
872 pFormatter
->GetNewCurrencySymbolString(nCurFormatKey
, rSymbol
, &pTmpCurrencyEntry
,
875 OUString rShortSymbol
;
877 if (pCurCurrencyEntry
== nullptr)
879 // #110398# If no currency format was previously selected (we're not
880 // about to add another currency), try to select the initial currency
881 // format (nCurFormatKey) that was set in FormatChanged() after
882 // matching the format string entered in the dialog.
884 pCurCurrencyEntry
= const_cast<NfCurrencyEntry
*>(pTmpCurrencyEntry
);
885 bBankingSymbol
= bTmpBanking
;
886 nCurCurrencyEntryPos
= FindCurrencyFormat(pTmpCurrencyEntry
, bTmpBanking
);
890 if (pTmpCurrencyEntry
== pCurCurrencyEntry
)
894 bAdaptSelPos
= false;
895 pTmpCurrencyEntry
= pCurCurrencyEntry
;
897 bTmpBanking
= bBankingSymbol
;
900 if (pTmpCurrencyEntry
!= nullptr)
902 rSymbol
= pTmpCurrencyEntry
->BuildSymbolString(false);
903 rBankSymbol
= pTmpCurrencyEntry
->BuildSymbolString(true);
904 rShortSymbol
= pTmpCurrencyEntry
->BuildSymbolString(bTmpBanking
, true);
907 for (const auto& rEntry
: *pCurFmtTable
)
909 sal_uInt32 nKey
= rEntry
.first
;
910 const SvNumberformat
* pNumEntry
= rEntry
.second
;
912 if (!IsRemoved_Impl(nKey
))
914 if (pNumEntry
->GetType() & SvNumFormatType::DEFINED
|| pNumEntry
->IsAdditionalBuiltin())
916 SvNumFormatType nMyCat
= pNumEntry
->GetMaskedType();
917 CategoryToPos_Impl(nMyCat
, nMyType
);
918 aNewFormNInfo
= pNumEntry
->GetFormatstring();
920 bool bInsFlag
= false;
921 if (pNumEntry
->HasNewCurrency())
923 bInsFlag
= true; // merge locale formats into currency selection
925 else if ((!bTmpBanking
&& aNewFormNInfo
.indexOf(rSymbol
) >= 0)
926 || (bTmpBanking
&& aNewFormNInfo
.indexOf(rBankSymbol
) >= 0))
930 else if (aNewFormNInfo
.indexOf(rShortSymbol
) >= 0)
933 const NfCurrencyEntry
* pTstCurrencyEntry
;
936 pFormatter
->GetNewCurrencySymbolString(nKey
, rTstSymbol
, &pTstCurrencyEntry
,
939 if (pTmpCurrencyEntry
== pTstCurrencyEntry
&& bTstBanking
== bTmpBanking
)
947 aList
.push_back(aNewFormNInfo
);
948 aKeyList
.push_back(nKey
);
954 NfWSStringsDtor aWSStringsDtor
;
956 if (pTmpCurrencyEntry
&& nCurCategory
!= SvNumFormatType::ALL
)
959 = pFormatter
->GetCurrencyFormatStrings(aWSStringsDtor
, *pTmpCurrencyEntry
, bTmpBanking
);
961 pFormatter
->GetCurrencyFormatStrings(aWSStringsDtor
, *pTmpCurrencyEntry
, true);
965 if (!bTmpBanking
&& nCurCategory
!= SvNumFormatType::ALL
)
967 // append formats for all currencies defined in the current I18N locale
968 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
969 sal_uInt16 nCurrCount
= rCurrencyTable
.size();
970 LanguageType eLang
= MsLangId::getRealLanguage(eCurLanguage
);
971 for (sal_uInt16 i
= 0; i
< nCurrCount
; ++i
)
973 const NfCurrencyEntry
* pCurr
= &rCurrencyTable
[i
];
974 if (pCurr
->GetLanguage() == eLang
&& pTmpCurrencyEntry
!= pCurr
)
976 pFormatter
->GetCurrencyFormatStrings(aWSStringsDtor
, *pCurr
, false);
977 pFormatter
->GetCurrencyFormatStrings(aWSStringsDtor
, *pCurr
, true);
982 size_t nOldListCount
= rList
.size();
983 for (size_t i
= 0, nPos
= nOldListCount
; i
< aWSStringsDtor
.size(); ++i
)
986 OUString
aInsStr(aWSStringsDtor
[i
]);
988 for (j
= 0; j
< aList
.size(); ++j
)
990 if (aList
[j
] == aInsStr
)
998 rList
.push_back(aInsStr
);
999 aCurEntryList
.insert(aCurEntryList
.begin() + (nPos
++), NUMBERFORMAT_ENTRY_NOT_FOUND
);
1003 rList
.push_back(aList
[j
]);
1004 aList
.erase(aList
.begin() + j
);
1005 aCurEntryList
.insert(aCurEntryList
.begin() + (nPos
++), aKeyList
[j
]);
1006 aKeyList
.erase(aKeyList
.begin() + j
);
1010 for (size_t i
= 0; i
< aKeyList
.size(); ++i
)
1012 if (aKeyList
[i
] != NUMBERFORMAT_ENTRY_NOT_FOUND
)
1014 rList
.push_back(aList
[i
]);
1015 aCurEntryList
.push_back(aKeyList
[i
]);
1019 for (size_t i
= nOldListCount
; i
< rList
.size(); ++i
)
1021 aCurrencyFormatList
.push_back(rList
[i
]);
1023 if (nSelPos
== SELPOS_NONE
&& bAdaptSelPos
&& aCurEntryList
[i
] == nCurFormatKey
)
1027 if (nSelPos
== SELPOS_NONE
&& nCurCategory
!= SvNumFormatType::ALL
)
1033 short SvxNumberFormatShell::FillEListWithUsD_Impl(std::vector
<OUString
>& rList
,
1034 SvNumFormatType eCategory
, short nSelPos
)
1036 /* Create a current list of format entries. The return value is
1037 * the list position of the current format. If the list is empty
1038 * or if there is no current format, SELPOS_NONE is delivered.
1041 assert(pCurFmtTable
!= nullptr);
1043 OUString aNewFormNInfo
;
1045 const bool bCatDefined
= (eCategory
== SvNumFormatType::DEFINED
);
1046 const bool bCategoryMatch
= (eCategory
!= SvNumFormatType::ALL
&& !bCatDefined
);
1047 const bool bNatNumCurrency
= (eCategory
== SvNumFormatType::CURRENCY
);
1049 for (const auto& rEntry
: *pCurFmtTable
)
1051 const SvNumberformat
* pNumEntry
= rEntry
.second
;
1053 if (bCategoryMatch
&& (pNumEntry
->GetMaskedType() & eCategory
) != eCategory
)
1054 continue; // for; type does not match category if not ALL
1056 const bool bUserDefined
= bool(pNumEntry
->GetType() & SvNumFormatType::DEFINED
);
1057 if (!bUserDefined
&& bCatDefined
)
1058 continue; // for; not user defined in DEFINED category
1060 if (!(bUserDefined
|| (!bCatDefined
&& pNumEntry
->IsAdditionalBuiltin())))
1061 continue; // for; does not match criteria at all
1063 const sal_uInt32 nKey
= rEntry
.first
;
1064 if (!IsRemoved_Impl(nKey
))
1066 aNewFormNInfo
= pNumEntry
->GetFormatstring();
1068 if (bNatNumCurrency
&& (aNewFormNInfo
.indexOf("NatNum12") < 0 || bUserDefined
))
1069 continue; // for; extra CURRENCY must be not user-defined NatNum12 type
1072 if (pNumEntry
->HasNewCurrency())
1075 sal_uInt16 nPos
= FindCurrencyTableEntry(aNewFormNInfo
, bTestBanking
);
1076 bAdd
= !IsInTable(nPos
, bTestBanking
, aNewFormNInfo
);
1080 if (nKey
== nCurFormatKey
)
1081 nSelPos
= aCurEntryList
.size();
1082 rList
.push_back(aNewFormNInfo
);
1083 aCurEntryList
.push_back(nKey
);
1090 void SvxNumberFormatShell::GetPreviewString_Impl(OUString
& rString
, const Color
*& rpColor
)
1094 // #50441# if a string was set in addition to the value, use it for text formats
1096 = (eValType
== SvxNumberValueType::String
1097 || (!aValStr
.isEmpty() && (pFormatter
->GetType(nCurFormatKey
) & SvNumFormatType::TEXT
)));
1101 pFormatter
->GetOutputString(aValStr
, nCurFormatKey
, rString
, &rpColor
);
1105 pFormatter
->GetOutputString(nValNum
, nCurFormatKey
, rString
, &rpColor
, bUseStarFormat
);
1109 ::std::vector
<sal_uInt32
>::iterator
SvxNumberFormatShell::GetRemoved_Impl(size_t nKey
)
1111 return ::std::find(aDelList
.begin(), aDelList
.end(), nKey
);
1114 bool SvxNumberFormatShell::IsRemoved_Impl(size_t nKey
)
1116 return GetRemoved_Impl(nKey
) != aDelList
.end();
1119 ::std::vector
<sal_uInt32
>::iterator
SvxNumberFormatShell::GetAdded_Impl(size_t nKey
)
1121 return ::std::find(aAddList
.begin(), aAddList
.end(), nKey
);
1124 // Conversion routines:
1125 void SvxNumberFormatShell::PosToCategory_Impl(sal_uInt16 nPos
, SvNumFormatType
& rCategory
)
1127 // map category css::form positions (->resource)
1130 case CAT_USERDEFINED
:
1131 rCategory
= SvNumFormatType::DEFINED
;
1134 rCategory
= SvNumFormatType::NUMBER
;
1137 rCategory
= SvNumFormatType::PERCENT
;
1140 rCategory
= SvNumFormatType::CURRENCY
;
1143 rCategory
= SvNumFormatType::DATE
;
1146 rCategory
= SvNumFormatType::TIME
;
1148 case CAT_SCIENTIFIC
:
1149 rCategory
= SvNumFormatType::SCIENTIFIC
;
1152 rCategory
= SvNumFormatType::FRACTION
;
1155 rCategory
= SvNumFormatType::LOGICAL
;
1158 rCategory
= SvNumFormatType::TEXT
;
1162 rCategory
= SvNumFormatType::ALL
;
1167 void SvxNumberFormatShell::CategoryToPos_Impl(SvNumFormatType nCategory
, sal_uInt16
& rPos
)
1169 // map category to css::form positions (->resource)
1172 case SvNumFormatType::DEFINED
:
1173 rPos
= CAT_USERDEFINED
;
1175 case SvNumFormatType::NUMBER
:
1178 case SvNumFormatType::PERCENT
:
1181 case SvNumFormatType::CURRENCY
:
1182 rPos
= CAT_CURRENCY
;
1184 case SvNumFormatType::DATETIME
:
1185 case SvNumFormatType::DATE
:
1188 case SvNumFormatType::TIME
:
1191 case SvNumFormatType::SCIENTIFIC
:
1192 rPos
= CAT_SCIENTIFIC
;
1194 case SvNumFormatType::FRACTION
:
1195 rPos
= CAT_FRACTION
;
1197 case SvNumFormatType::LOGICAL
:
1200 case SvNumFormatType::TEXT
:
1203 case SvNumFormatType::ALL
:
1210 * Function: Formats the number nValue dependent on rFormatStr
1211 * and stores the result in rPreviewStr.
1212 * Input: FormatString, color, number to format
1213 * Output: Output string rPreviewStr
1215 void SvxNumberFormatShell::MakePrevStringFromVal(const OUString
& rFormatStr
, OUString
& rPreviewStr
,
1216 const Color
*& rpFontColor
, double nValue
)
1218 rpFontColor
= nullptr;
1219 pFormatter
->GetPreviewString(rFormatStr
, nValue
, rPreviewStr
, &rpFontColor
, eCurLanguage
);
1223 * Function: Returns the comment for a given entry.
1224 * Input: Number of the entry
1225 * Output: Comment string
1227 void SvxNumberFormatShell::SetComment4Entry(short nEntry
, const OUString
& aEntStr
)
1229 SvNumberformat
* pNumEntry
;
1232 sal_uInt32 nMyNfEntry
= aCurEntryList
[nEntry
];
1233 pNumEntry
= const_cast<SvNumberformat
*>(pFormatter
->GetEntry(nMyNfEntry
));
1234 if (pNumEntry
!= nullptr)
1235 pNumEntry
->SetComment(aEntStr
);
1239 * Function: Returns the comment for a given entry.
1240 * Input: Number of the entry
1241 * Output: Comment string
1243 OUString
SvxNumberFormatShell::GetComment4Entry(short nEntry
)
1248 if (o3tl::make_unsigned(nEntry
) < aCurEntryList
.size())
1250 sal_uInt32 nMyNfEntry
= aCurEntryList
[nEntry
];
1251 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nMyNfEntry
);
1252 if (pNumEntry
!= nullptr)
1253 return pNumEntry
->GetComment();
1260 * Function: Returns the category number for a given entry.
1261 * Input: Number of the entry
1262 * Output: Category number
1264 short SvxNumberFormatShell::GetCategory4Entry(short nEntry
) const
1268 if (o3tl::make_unsigned(nEntry
) < aCurEntryList
.size())
1270 sal_uInt32 nMyNfEntry
= aCurEntryList
[nEntry
];
1272 if (nMyNfEntry
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1274 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nMyNfEntry
);
1275 if (pNumEntry
!= nullptr)
1277 SvNumFormatType nMyCat
= pNumEntry
->GetMaskedType();
1279 CategoryToPos_Impl(nMyCat
, nMyType
);
1281 return static_cast<short>(nMyType
);
1285 else if (!aCurrencyFormatList
.empty())
1287 return CAT_CURRENCY
;
1294 * Function: Returns the information about whether an entry is user-specific.
1295 * Input: Number of the entry
1296 * Output: User-specific?
1298 bool SvxNumberFormatShell::GetUserDefined4Entry(short nEntry
)
1302 if (o3tl::make_unsigned(nEntry
) < aCurEntryList
.size())
1304 sal_uInt32 nMyNfEntry
= aCurEntryList
[nEntry
];
1305 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nMyNfEntry
);
1307 if (pNumEntry
!= nullptr)
1309 if (pNumEntry
->GetType() & SvNumFormatType::DEFINED
)
1319 * Function: Returns the format string for a given entry.
1320 * Input: Number of the entry
1321 * Output: Format string
1323 OUString
SvxNumberFormatShell::GetFormat4Entry(short nEntry
)
1328 if (!aCurrencyFormatList
.empty()
1329 && (!pFormatter
->GetEntry(aCurEntryList
[nEntry
])
1330 || pFormatter
->GetEntry(aCurEntryList
[nEntry
])->GetFormatstring().indexOf("NatNum12")
1333 if (aCurrencyFormatList
.size() > o3tl::make_unsigned(nEntry
))
1334 return aCurrencyFormatList
[nEntry
];
1338 sal_uInt32 nMyNfEntry
= aCurEntryList
[nEntry
];
1339 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nMyNfEntry
);
1341 if (pNumEntry
!= nullptr)
1342 return pNumEntry
->GetFormatstring();
1348 * Function: Returns the list number for a given format index.
1349 * Input: Number of the entry
1350 * Output: Category number
1352 short SvxNumberFormatShell::GetListPos4Entry(sal_uInt32 nIdx
, std::u16string_view rFmtString
)
1354 short nSelP
= SELPOS_NONE
;
1355 if (nIdx
!= NUMBERFORMAT_ENTRY_NEW_CURRENCY
)
1357 // Check list size against return type limit.
1358 if (aCurEntryList
.size() <= o3tl::make_unsigned(::std::numeric_limits
<short>::max()))
1360 for (size_t i
= 0; i
< aCurEntryList
.size(); ++i
)
1362 if (aCurEntryList
[i
] == nIdx
)
1371 OSL_FAIL("svx::SvxNumberFormatShell::GetListPos4Entry(), list got too large!");
1376 // A second list holds the generated currency formats.
1377 for (size_t i
= 0; i
< aCurrencyFormatList
.size(); ++i
)
1379 if (rFmtString
== aCurrencyFormatList
[i
])
1381 nSelP
= static_cast<short>(i
);
1389 OUString
SvxNumberFormatShell::GetStandardName() const
1391 return pFormatter
->GetStandardName(eCurLanguage
);
1394 void SvxNumberFormatShell::GetCurrencySymbols(std::vector
<OUString
>& rList
, sal_uInt16
* pPos
)
1396 const NfCurrencyEntry
* pTmpCurrencyEntry
= SvNumberFormatter::MatchSystemCurrency();
1398 bool bFlag
= (pTmpCurrencyEntry
== nullptr);
1400 SvxCurrencyToolBoxControl::GetCurrencySymbols(rList
, bFlag
, aCurCurrencyList
);
1402 if (pPos
== nullptr)
1405 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
1406 sal_uInt16 nTableCount
= rCurrencyTable
.size();
1409 size_t nCount
= aCurCurrencyList
.size();
1414 nCurCurrencyEntryPos
= 1;
1418 for (size_t i
= 1; i
< nCount
; i
++)
1420 const sal_uInt16 j
= aCurCurrencyList
[i
];
1421 if (j
!= sal_uInt16(-1) && j
< nTableCount
&& pTmpCurrencyEntry
== &rCurrencyTable
[j
])
1423 *pPos
= static_cast<sal_uInt16
>(i
);
1424 nCurCurrencyEntryPos
= static_cast<sal_uInt16
>(i
);
1431 void SvxNumberFormatShell::SetCurrencySymbol(sal_uInt32 nPos
)
1433 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
1434 sal_uInt16 nCount
= rCurrencyTable
.size();
1436 bBankingSymbol
= (nPos
>= nCount
);
1438 if (nPos
>= aCurCurrencyList
.size())
1441 sal_uInt16 nCurrencyPos
= aCurCurrencyList
[nPos
];
1442 if (nCurrencyPos
!= sal_uInt16(-1))
1444 pCurCurrencyEntry
= const_cast<NfCurrencyEntry
*>(&rCurrencyTable
[nCurrencyPos
]);
1445 nCurCurrencyEntryPos
= nPos
;
1449 pCurCurrencyEntry
= nullptr;
1450 nCurCurrencyEntryPos
= 0;
1451 nCurFormatKey
= pFormatter
->GetFormatIndex(NF_CURRENCY_1000DEC2_RED
, eCurLanguage
);
1455 void SvxNumberFormatShell::SetCurCurrencyEntry(NfCurrencyEntry
* pCEntry
)
1457 pCurCurrencyEntry
= pCEntry
;
1460 bool SvxNumberFormatShell::IsTmpCurrencyFormat(const OUString
& rFmtString
)
1463 FindEntry(rFmtString
, &nFound
);
1464 return nFound
== NUMBERFORMAT_ENTRY_NEW_CURRENCY
;
1467 sal_uInt16
SvxNumberFormatShell::FindCurrencyFormat(const OUString
& rFmtString
)
1469 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
1470 sal_uInt16 nCount
= rCurrencyTable
.size();
1472 bool bTestBanking
= false;
1474 sal_uInt16 nPos
= FindCurrencyTableEntry(rFmtString
, bTestBanking
);
1476 if (nPos
!= sal_uInt16(-1))
1478 sal_uInt16 nStart
= 0;
1479 if (bTestBanking
&& aCurCurrencyList
.size() > nPos
)
1483 for (size_t j
= nStart
; j
< aCurCurrencyList
.size(); j
++)
1485 if (aCurCurrencyList
[j
] == nPos
)
1489 return sal_uInt16(-1);
1492 sal_uInt16
SvxNumberFormatShell::FindCurrencyTableEntry(const OUString
& rFmtString
,
1495 sal_uInt16 nPos
= sal_uInt16(-1);
1497 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
1498 sal_uInt16 nCount
= rCurrencyTable
.size();
1500 const SvNumberformat
* pFormat
;
1501 OUString aSymbol
, aExtension
;
1502 sal_uInt32 nFound
= pFormatter
->TestNewString(rFmtString
, eCurLanguage
);
1503 if (nFound
!= NUMBERFORMAT_ENTRY_NOT_FOUND
1504 && ((pFormat
= pFormatter
->GetEntry(nFound
)) != nullptr)
1505 && pFormat
->GetNewCurrencySymbol(aSymbol
, aExtension
))
1507 // eventually match with format locale
1508 const NfCurrencyEntry
* pTmpCurrencyEntry
= SvNumberFormatter::GetCurrencyEntry(
1509 bTestBanking
, aSymbol
, aExtension
, pFormat
->GetLanguage());
1510 if (pTmpCurrencyEntry
)
1512 for (sal_uInt16 i
= 0; i
< nCount
; i
++)
1514 if (pTmpCurrencyEntry
== &rCurrencyTable
[i
])
1524 // search symbol string only
1525 for (sal_uInt16 i
= 0; i
< nCount
; i
++)
1527 const NfCurrencyEntry
* pTmpCurrencyEntry
= &rCurrencyTable
[i
];
1528 OUString _aSymbol
= pTmpCurrencyEntry
->BuildSymbolString(false);
1529 OUString aBankSymbol
= pTmpCurrencyEntry
->BuildSymbolString(true);
1531 if (rFmtString
.indexOf(_aSymbol
) != -1)
1533 bTestBanking
= false;
1537 else if (rFmtString
.indexOf(aBankSymbol
) != -1)
1539 bTestBanking
= true;
1549 sal_uInt16
SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry
* pTmpCurrencyEntry
,
1552 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
1553 sal_uInt16 nCount
= rCurrencyTable
.size();
1555 sal_uInt16 nPos
= 0;
1556 for (sal_uInt16 i
= 0; i
< nCount
; i
++)
1558 if (pTmpCurrencyEntry
== &rCurrencyTable
[i
])
1565 sal_uInt16 nStart
= 0;
1566 if (bTmpBanking
&& aCurCurrencyList
.size() > nPos
)
1570 for (size_t j
= nStart
; j
< aCurCurrencyList
.size(); j
++)
1572 if (aCurCurrencyList
[j
] == nPos
)
1575 return sal_uInt16(-1);
1578 bool SvxNumberFormatShell::IsInTable(sal_uInt16
const nPos
, bool const bTmpBanking
,
1579 std::u16string_view rFmtString
) const
1583 if (nPos
!= sal_uInt16(-1))
1585 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
1587 if (nPos
< rCurrencyTable
.size())
1589 NfWSStringsDtor aWSStringsDtor
;
1590 pFormatter
->GetCurrencyFormatStrings(aWSStringsDtor
, rCurrencyTable
[nPos
], bTmpBanking
);
1592 for (const OUString
& s
: aWSStringsDtor
)
1594 if (s
== rFmtString
)
1606 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */