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