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>
33 #include <sfx2/IDocumentModelAccessor.hxx>
39 double GetDefaultValNum(const SvNumFormatType 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
];
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
)
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)
102 case SvxNumberValueType::String
:
105 case SvxNumberValueType::Number
:
108 nValNum
= GetDefaultValNum(pFormatter
->GetType(nCurFormatKey
));
111 case SvxNumberValueType::Undefined
:
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
)
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
141 case SvxNumberValueType::Number
:
144 case SvxNumberValueType::String
:
145 case SvxNumberValueType::Undefined
:
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.
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())
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
,
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())
233 OSL_FAIL("duplicate format!");
239 bInserted
= pFormatter
->PutEntry(rFormat
, nPos
, nCurCategory
, nAddKey
, eCurLanguage
);
240 rErrPos
= (nPos
>= 0) ? nPos
: -1;
244 // May be sorted under a different locale if LCID was parsed.
245 const SvNumberformat
* pEntry
= pFormatter
->GetEntry(nAddKey
);
248 LanguageType nLang
= pEntry
->GetLanguage();
249 if (eCurLanguage
!= nLang
)
251 // Current language's list would not show entry, adapt.
252 eCurLanguage
= nLang
;
260 nCurFormatKey
= nAddKey
;
261 DBG_ASSERT(GetAdded_Impl(nCurFormatKey
) == aAddList
.end(), "duplicate format!");
262 aAddList
.push_back(nCurFormatKey
);
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!");
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
))
293 aDelList
.push_back(nDelKey
);
295 ::std::vector
<sal_uInt32
>::iterator nAt
= GetAdded_Impl(nDelKey
);
296 if (nAt
!= aAddList
.end())
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
;
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
,
332 rFormat
= pFormatter
->GenerateFormat(nCurFormatKey
, eCurLanguage
, bThousand
, bNegRed
,
333 nPrecision
, nLeadingZeroes
);
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
);
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
)
379 rCatLbPos
= CAT_CURRENCY
;
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
,
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
)));
409 pFormatter
->GetOutputString(aValStr
, nExistingFormat
, rPreviewStr
, &rpFontColor
);
413 if (bIsDefaultValNum
)
414 nValNum
= GetDefaultValNum(pFormatter
->GetType(nExistingFormat
));
415 pFormatter
->GetOutputString(nValNum
, nExistingFormat
, rPreviewStr
, &rpFontColor
,
421 bool SvxNumberFormatShell::IsUserDefined(const OUString
& rFmtString
)
423 sal_uInt32 nFound
= pFormatter
->GetEntryKey(rFmtString
, eCurLanguage
);
426 if (nFound
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
428 bFlag
= pFormatter
->IsUserDefined(rFmtString
, eCurLanguage
);
432 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nFound
);
434 if (pNumEntry
!= nullptr && pNumEntry
->HasNewCurrency())
437 sal_uInt16 nPos
= FindCurrencyTableEntry(rFmtString
, bTestBanking
);
438 bFlag
= !IsInTable(nPos
, bTestBanking
, rFmtString
);
445 bool SvxNumberFormatShell::FindEntry(const OUString
& rFmtString
, sal_uInt32
* pAt
/* = NULL */)
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
;
473 bRes
= !IsRemoved_Impl(nFound
);
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
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
);
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);
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
;
583 case SvNumFormatType::NUMBER
:
584 eOffsetStart
= NF_NUMBER_START
;
585 eOffsetEnd
= NF_NUMBER_END
;
587 case SvNumFormatType::PERCENT
:
588 eOffsetStart
= NF_PERCENT_START
;
589 eOffsetEnd
= NF_PERCENT_END
;
591 case SvNumFormatType::CURRENCY
:
592 // Currency entries are generated and assembled, ignore
593 // bSuppressDuplicates.
594 nSelPos
= FillEListWithCurrency_Impl(rList
, nSelPos
);
596 case SvNumFormatType::DATE
:
597 eOffsetStart
= NF_DATE_START
;
598 eOffsetEnd
= NF_DATE_END
;
600 case SvNumFormatType::TIME
:
601 eOffsetStart
= NF_TIME_START
;
602 eOffsetEnd
= NF_TIME_END
;
604 case SvNumFormatType::SCIENTIFIC
:
605 eOffsetStart
= NF_SCIENTIFIC_START
;
606 eOffsetEnd
= NF_SCIENTIFIC_END
;
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);
615 = FillEListWithFormats_Impl(rList
, nSelPos
, NF_FRACTION_3D
, NF_FRACTION_100
, false);
617 case SvNumFormatType::LOGICAL
:
618 eOffsetStart
= NF_BOOLEAN
;
619 eOffsetEnd
= NF_BOOLEAN
;
621 case SvNumFormatType::TEXT
:
622 eOffsetStart
= NF_TEXT
;
623 eOffsetEnd
= NF_TEXT
;
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);
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
659 FillEListWithOneFormat_Impl(rList
, nSelPos
, bSuppressDuplicates
, NF_DATETIME_SYS_DDMMYYYY_HHMM
,
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);
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)
686 SvNumFormatType nMyCat
= pNumEntry
->GetMaskedType();
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.
700 = bSuppressIsoDateTime
&& bSuppressDuplicates
701 && (aNewFormNInfo
== "YYYY-MM-DD HH:MM:SS" || aNewFormNInfo
== "YYYY-MM-DD\"T\"HH:MM:SS");
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
)
717 const NfIndexTableOffset nIndex
= SvNumberFormatter::GetIndexTableOffset(nKey
);
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
:
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
:
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
;
752 bool bFlag
= pFormatter
->GetNewCurrencySymbolString(nCurFormatKey
, rSymbol
, &pTmpCurrencyEntry
,
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
);
765 nSelPos
= FillEListWithUserCurrencys(rList
, 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.
779 DBG_ASSERT(pCurFmtTable
!= nullptr, "unknown NumberFormat");
782 OUString aNewFormNInfo
;
784 nCurCurrencyEntryPos
= 0;
786 for (tools::Long nIndex
= NF_CURRENCY_START
; nIndex
<= NF_CURRENCY_END
; nIndex
++)
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.
796 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nNFEntry
);
798 if (pNumEntry
== nullptr)
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
;
830 pFormatter
->GetNewCurrencySymbolString(nKey
, rSymbol
, &pTmpCurrencyEntry
,
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
);
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.
861 DBG_ASSERT(pCurFmtTable
!= nullptr, "unknown NumberFormat");
863 OUString aNewFormNInfo
;
865 const NfCurrencyEntry
* pTmpCurrencyEntry
;
866 bool bTmpBanking
, bAdaptSelPos
;
868 OUString rBankSymbol
;
870 std::vector
<OUString
> aList
;
871 std::vector
<sal_uInt32
> aKeyList
;
873 pFormatter
->GetNewCurrencySymbolString(nCurFormatKey
, rSymbol
, &pTmpCurrencyEntry
,
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.
885 pCurCurrencyEntry
= const_cast<NfCurrencyEntry
*>(pTmpCurrencyEntry
);
886 bBankingSymbol
= bTmpBanking
;
887 nCurCurrencyEntryPos
= FindCurrencyFormat(pTmpCurrencyEntry
, bTmpBanking
);
891 if (pTmpCurrencyEntry
== pCurCurrencyEntry
)
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))
931 else if (aNewFormNInfo
.indexOf(rShortSymbol
) >= 0)
934 const NfCurrencyEntry
* pTstCurrencyEntry
;
937 pFormatter
->GetNewCurrencySymbolString(nKey
, rTstSymbol
, &pTstCurrencyEntry
,
940 if (pTmpCurrencyEntry
== pTstCurrencyEntry
&& bTstBanking
== bTmpBanking
)
948 aList
.push_back(aNewFormNInfo
);
949 aKeyList
.push_back(nKey
);
955 NfWSStringsDtor aWSStringsDtor
;
957 if (pTmpCurrencyEntry
&& nCurCategory
!= SvNumFormatType::ALL
)
960 = pFormatter
->GetCurrencyFormatStrings(aWSStringsDtor
, *pTmpCurrencyEntry
, bTmpBanking
);
962 pFormatter
->GetCurrencyFormatStrings(aWSStringsDtor
, *pTmpCurrencyEntry
, true);
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
)
987 OUString
aInsStr(aWSStringsDtor
[i
]);
989 for (j
= 0; j
< aList
.size(); ++j
)
991 if (aList
[j
] == aInsStr
)
999 rList
.push_back(aInsStr
);
1000 aCurEntryList
.insert(aCurEntryList
.begin() + (nPos
++), NUMBERFORMAT_ENTRY_NOT_FOUND
);
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
)
1028 if (nSelPos
== SELPOS_NONE
&& nCurCategory
!= SvNumFormatType::ALL
)
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
1073 if (pNumEntry
->HasNewCurrency())
1076 sal_uInt16 nPos
= FindCurrencyTableEntry(aNewFormNInfo
, bTestBanking
);
1077 bAdd
= !IsInTable(nPos
, bTestBanking
, aNewFormNInfo
);
1081 if (nKey
== nCurFormatKey
)
1082 nSelPos
= aCurEntryList
.size();
1083 rList
.push_back(aNewFormNInfo
);
1084 aCurEntryList
.push_back(nKey
);
1091 void SvxNumberFormatShell::GetPreviewString_Impl(OUString
& rString
, const Color
*& rpColor
)
1095 // #50441# if a string was set in addition to the value, use it for text formats
1097 = (eValType
== SvxNumberValueType::String
1098 || (!aValStr
.isEmpty() && (pFormatter
->GetType(nCurFormatKey
) & SvNumFormatType::TEXT
)));
1102 pFormatter
->GetOutputString(aValStr
, nCurFormatKey
, rString
, &rpColor
);
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)
1131 case CAT_USERDEFINED
:
1132 rCategory
= SvNumFormatType::DEFINED
;
1135 rCategory
= SvNumFormatType::NUMBER
;
1138 rCategory
= SvNumFormatType::PERCENT
;
1141 rCategory
= SvNumFormatType::CURRENCY
;
1144 rCategory
= SvNumFormatType::DATE
;
1147 rCategory
= SvNumFormatType::TIME
;
1149 case CAT_SCIENTIFIC
:
1150 rCategory
= SvNumFormatType::SCIENTIFIC
;
1153 rCategory
= SvNumFormatType::FRACTION
;
1156 rCategory
= SvNumFormatType::LOGICAL
;
1159 rCategory
= SvNumFormatType::TEXT
;
1163 rCategory
= SvNumFormatType::ALL
;
1168 void SvxNumberFormatShell::CategoryToPos_Impl(SvNumFormatType nCategory
, sal_uInt16
& rPos
)
1170 // map category to css::form positions (->resource)
1173 case SvNumFormatType::DEFINED
:
1174 rPos
= CAT_USERDEFINED
;
1176 case SvNumFormatType::NUMBER
:
1179 case SvNumFormatType::PERCENT
:
1182 case SvNumFormatType::CURRENCY
:
1183 rPos
= CAT_CURRENCY
;
1185 case SvNumFormatType::DATETIME
:
1186 case SvNumFormatType::DATE
:
1189 case SvNumFormatType::TIME
:
1192 case SvNumFormatType::SCIENTIFIC
:
1193 rPos
= CAT_SCIENTIFIC
;
1195 case SvNumFormatType::FRACTION
:
1196 rPos
= CAT_FRACTION
;
1198 case SvNumFormatType::LOGICAL
:
1201 case SvNumFormatType::TEXT
:
1204 case SvNumFormatType::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
;
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
)
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();
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
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();
1280 CategoryToPos_Impl(nMyCat
, nMyType
);
1282 return static_cast<short>(nMyType
);
1286 else if (!aCurrencyFormatList
.empty())
1288 return CAT_CURRENCY
;
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
)
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
)
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
)
1329 if (!aCurrencyFormatList
.empty()
1330 && (!pFormatter
->GetEntry(aCurEntryList
[nEntry
])
1331 || pFormatter
->GetEntry(aCurEntryList
[nEntry
])->GetFormatstring().indexOf("NatNum12")
1334 if (aCurrencyFormatList
.size() > o3tl::make_unsigned(nEntry
))
1335 return aCurrencyFormatList
[nEntry
];
1339 sal_uInt32 nMyNfEntry
= aCurEntryList
[nEntry
];
1340 const SvNumberformat
* pNumEntry
= pFormatter
->GetEntry(nMyNfEntry
);
1342 if (pNumEntry
!= nullptr)
1343 return pNumEntry
->GetFormatstring();
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
)
1372 OSL_FAIL("svx::SvxNumberFormatShell::GetListPos4Entry(), list got too large!");
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
);
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)
1408 const NfCurrencyTable
& rCurrencyTable
= SvNumberFormatter::GetTheCurrencyTable();
1409 sal_uInt16 nTableCount
= rCurrencyTable
.size();
1412 size_t nCount
= aCurCurrencyList
.size();
1417 nCurCurrencyEntryPos
= 1;
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
);
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())
1444 sal_uInt16 nCurrencyPos
= aCurCurrencyList
[nPos
];
1445 if (nCurrencyPos
!= sal_uInt16(-1))
1447 pCurCurrencyEntry
= const_cast<NfCurrencyEntry
*>(&rCurrencyTable
[nCurrencyPos
]);
1448 nCurCurrencyEntryPos
= nPos
;
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
)
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
)
1486 for (size_t j
= nStart
; j
< aCurCurrencyList
.size(); j
++)
1488 if (aCurCurrencyList
[j
] == nPos
)
1492 return sal_uInt16(-1);
1495 sal_uInt16
SvxNumberFormatShell::FindCurrencyTableEntry(const OUString
& rFmtString
,
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
])
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;
1540 else if (rFmtString
.indexOf(aBankSymbol
) != -1)
1542 bTestBanking
= true;
1552 sal_uInt16
SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry
* pTmpCurrencyEntry
,
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
])
1568 sal_uInt16 nStart
= 0;
1569 if (bTmpBanking
&& aCurCurrencyList
.size() > nPos
)
1573 for (size_t j
= nStart
; j
< aCurCurrencyList
.size(); j
++)
1575 if (aCurCurrencyList
[j
] == nPos
)
1578 return sal_uInt16(-1);
1581 bool SvxNumberFormatShell::IsInTable(sal_uInt16
const nPos
, bool const bTmpBanking
,
1582 std::u16string_view rFmtString
) const
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
)
1609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */