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
349void SvxNumberFormatShell::GetOptions(const OUString& rFormat, bool& rThousand, bool& rNegRed,
350 sal_uInt16& rPrecision, sal_uInt16& rLeadingZeroes,
351 sal_uInt16& rCatLbPos)
352{
353 sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);
354
355 if (nFmtKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
356 {
357 pFormatter->GetFormatSpecialInfo(nFmtKey, rThousand, rNegRed, rPrecision, rLeadingZeroes);
358
359 CategoryToPos_Impl(pFormatter->GetType(nFmtKey), rCatLbPos);
360 }
361 else
362 {
363 bool bTestBanking = false;
364 sal_uInt16 nPos = FindCurrencyTableEntry(rFormat, bTestBanking);
365
366 if (IsInTable(nPos, bTestBanking, rFormat)
367 && pFormatter->GetFormatSpecialInfo(rFormat, rThousand, rNegRed, rPrecision,
368 rLeadingZeroes, eCurLanguage)
369 == 0)
370 {
371 rCatLbPos = CAT_CURRENCY;
372 }
373 else
374 rCatLbPos = CAT_USERDEFINED;
375 }
376}
377
378void SvxNumberFormatShell::MakePreviewString(const OUString& rFormatStr, OUString& rPreviewStr,
379 const Color*& rpFontColor)
380{
381 rpFontColor = nullptr;
382
383 sal_uInt32 nExistingFormat = pFormatter->GetEntryKey(rFormatStr, eCurLanguage);
384 if (nExistingFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
385 {
386 // real preview - not implemented in NumberFormatter for text formats
387 pFormatter->GetPreviewString(rFormatStr, nValNum, rPreviewStr, &rpFontColor, eCurLanguage,
389 }
390 else
391 {
392 // format exists
393
394 // #50441# if a string was set in addition to the value, use it for text formats
395 bool bUseText = (eValType == SvxNumberValueType::String
396 || (!aValStr.isEmpty()
397 && (pFormatter->GetType(nExistingFormat) & SvNumFormatType::TEXT)));
398
399 if (bUseText)
400 {
401 pFormatter->GetOutputString(aValStr, nExistingFormat, rPreviewStr, &rpFontColor);
402 }
403 else
404 {
406 nValNum = GetDefaultValNum(pFormatter->GetType(nExistingFormat));
407 pFormatter->GetOutputString(nValNum, nExistingFormat, rPreviewStr, &rpFontColor,
409 }
410 }
411}
412
413bool SvxNumberFormatShell::IsUserDefined(const OUString& rFmtString)
414{
415 sal_uInt32 nFound = pFormatter->GetEntryKey(rFmtString, eCurLanguage);
416
417 bool bFlag = false;
418 if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND)
419 {
420 bFlag = pFormatter->IsUserDefined(rFmtString, eCurLanguage);
421
422 if (bFlag)
423 {
424 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nFound);
425
426 if (pNumEntry != nullptr && pNumEntry->HasNewCurrency())
427 {
428 bool bTestBanking;
429 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
430 bFlag = !IsInTable(nPos, bTestBanking, rFmtString);
431 }
432 }
433 }
434 return bFlag;
435}
436
437bool SvxNumberFormatShell::FindEntry(const OUString& rFmtString, sal_uInt32* pAt /* = NULL */)
438{
439 bool bRes = false;
440
441 sal_uInt32 nFound = NUMBERFORMAT_ENTRY_NOT_FOUND;
442 // There may be multiple builtin entries with the same format code, first
443 // try if the current key matches.
445 if (pEntry && pEntry->GetLanguage() == eCurLanguage && pEntry->GetFormatstring() == rFmtString)
446 nFound = nCurFormatKey;
447
448 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
449 // Find the first matching format code.
450 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
451
452 if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
453 {
454 bool bTestBanking = false;
455 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
456
457 if (IsInTable(nPos, bTestBanking, rFmtString))
458 {
460 bRes = true;
461 }
462 }
463 else
464 {
465 bRes = !IsRemoved_Impl(nFound);
466 }
467
468 if (pAt)
469 *pAt = nFound;
470
471 return bRes;
472}
473
474void SvxNumberFormatShell::GetInitSettings(sal_uInt16& nCatLbPos, LanguageType& rLangType,
475 sal_uInt16& nFmtLbSelPos,
476 std::vector<OUString>& rFmtEntries,
477 OUString& rPrevString, const Color*& rpPrevColor)
478{
479 // precondition: number formater found
480 DBG_ASSERT(pFormatter != nullptr, "Number formatter not found!");
481
482 short nSelPos = SELPOS_NONE;
483
484 // special treatment for undefined number format:
486 PosToCategory_Impl(CAT_ALL, nCurCategory); // category = all
487 else
488 nCurCategory = SvNumFormatType::UNDEFINED; // category = undefined
489
491
493 rLangType = eCurLanguage;
494
495 nSelPos = FillEntryList_Impl(rFmtEntries);
496
497 DBG_ASSERT(nSelPos != SELPOS_NONE, "Leere Formatliste!");
498
499 nFmtLbSelPos = (nSelPos != SELPOS_NONE) ? static_cast<sal_uInt16>(nSelPos) : 0;
500 GetPreviewString_Impl(rPrevString, rpPrevColor);
501}
502
503short SvxNumberFormatShell::FillEntryList_Impl(std::vector<OUString>& rList)
504{
505 /* Create a current list of format entries. The return value is
506 * the list position of the current format. If the list is empty
507 * or if there is no current format, SELPOS_NONE is delivered.
508 */
509 short nSelPos = SELPOS_NONE;
510
511 aCurEntryList.clear();
512
513 if (nCurCategory == SvNumFormatType::ALL)
514 {
515 FillEListWithStd_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
516 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
517
518 FillEListWithStd_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
519 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
520
521 FillEListWithStd_Impl(rList, SvNumFormatType::CURRENCY, nSelPos);
522 // No FillEListWithUsD_Impl() here, user defined currency formats
523 // were already added.
524
525 FillEListWithStd_Impl(rList, SvNumFormatType::DATE, nSelPos);
526 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATE, nSelPos);
527
528 FillEListWithStd_Impl(rList, SvNumFormatType::TIME, nSelPos);
529 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TIME, nSelPos);
530
531 nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, false);
532 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATETIME, nSelPos);
533
534 FillEListWithStd_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
535 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
536
537 FillEListWithStd_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
538 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
539
540 FillEListWithStd_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
541 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
542
543 FillEListWithStd_Impl(rList, SvNumFormatType::TEXT, nSelPos);
544 nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TEXT, nSelPos);
545 }
546 else
547 {
548 FillEListWithStd_Impl(rList, nCurCategory, nSelPos, true);
549 if (nCurCategory != SvNumFormatType::CURRENCY)
550 nSelPos = FillEListWithUsD_Impl(rList, nCurCategory, nSelPos);
551 if (nCurCategory == SvNumFormatType::DATE || nCurCategory == SvNumFormatType::TIME)
552 nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, true);
553 }
554
555 return nSelPos;
556}
557
558void SvxNumberFormatShell::FillEListWithStd_Impl(std::vector<OUString>& rList,
559 SvNumFormatType eCategory, short& nSelPos,
560 bool bSuppressDuplicates)
561{
562 /* Create a current list of format entries. The return value is
563 * the list position of the current format. If the list is empty
564 * or if there is no current format, SELPOS_NONE is delivered.
565 */
566
567 assert(pCurFmtTable != nullptr);
568
569 aCurrencyFormatList.clear();
570
571 NfIndexTableOffset eOffsetStart;
572 NfIndexTableOffset eOffsetEnd;
573
574 switch (eCategory)
575 {
576 case SvNumFormatType::NUMBER:
577 eOffsetStart = NF_NUMBER_START;
578 eOffsetEnd = NF_NUMBER_END;
579 break;
580 case SvNumFormatType::PERCENT:
581 eOffsetStart = NF_PERCENT_START;
582 eOffsetEnd = NF_PERCENT_END;
583 break;
584 case SvNumFormatType::CURRENCY:
585 // Currency entries are generated and assembled, ignore
586 // bSuppressDuplicates.
587 nSelPos = FillEListWithCurrency_Impl(rList, nSelPos);
588 return;
589 case SvNumFormatType::DATE:
590 eOffsetStart = NF_DATE_START;
591 eOffsetEnd = NF_DATE_END;
592 break;
593 case SvNumFormatType::TIME:
594 eOffsetStart = NF_TIME_START;
595 eOffsetEnd = NF_TIME_END;
596 break;
597 case SvNumFormatType::SCIENTIFIC:
598 eOffsetStart = NF_SCIENTIFIC_START;
599 eOffsetEnd = NF_SCIENTIFIC_END;
600 break;
601 case SvNumFormatType::FRACTION:
602 eOffsetStart = NF_FRACTION_START;
603 eOffsetEnd = NF_FRACTION_END;
604 // Fraction formats are internally generated by the number
605 // formatter and are not supposed to contain duplicates anyway.
606 nSelPos = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, false);
607 nSelPos
609 return;
610 case SvNumFormatType::LOGICAL:
611 eOffsetStart = NF_BOOLEAN;
612 eOffsetEnd = NF_BOOLEAN;
613 break;
614 case SvNumFormatType::TEXT:
615 eOffsetStart = NF_TEXT;
616 eOffsetEnd = NF_TEXT;
617 break;
618 default:
619 return;
620 }
621
622 nSelPos
623 = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, bSuppressDuplicates);
624}
625
626short SvxNumberFormatShell::FillEListWithFormats_Impl(std::vector<OUString>& rList, short nSelPos,
627 NfIndexTableOffset eOffsetStart,
628 NfIndexTableOffset eOffsetEnd,
629 bool bSuppressDuplicates)
630{
631 /* Create a current list of format entries. The return value is
632 * the list position of the current format. If the list is empty
633 * or if there is no current format, SELPOS_NONE is delivered.
634 */
635 for (tools::Long nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex)
636 {
637 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
638 static_cast<NfIndexTableOffset>(nIndex), false);
639 }
640
641 return nSelPos;
642}
643
644short SvxNumberFormatShell::FillEListWithDateTime_Impl(std::vector<OUString>& rList, short nSelPos,
645 bool bSuppressDuplicates)
646{
647 // Append a list of date+time formats.
648
649 // Add first, so a NF_DATETIME_SYSTEM_SHORT_HHMM may be suppressed in
650 // locales that do not use 2-digit years there and this here is the
651 // default.
652 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates, NF_DATETIME_SYS_DDMMYYYY_HHMM,
653 true);
654
656 {
657 FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
658 static_cast<NfIndexTableOffset>(nIndex), true);
659 }
660
661 // Always add the internally generated ISO formats.
664
665 return nSelPos;
666}
667
668void SvxNumberFormatShell::FillEListWithOneFormat_Impl(std::vector<OUString>& rList, short& nSelPos,
669 bool bSuppressDuplicates,
670 NfIndexTableOffset nOffset,
671 bool bSuppressIsoDateTime)
672{
673 sal_uInt32 nNFEntry = pFormatter->GetFormatIndex(nOffset, eCurLanguage);
674
675 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
676 if (pNumEntry == nullptr)
677 return;
678
679 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
680 sal_uInt16 nMyType;
681 CategoryToPos_Impl(nMyCat, nMyType);
682 OUString aNewFormNInfo = pNumEntry->GetFormatstring();
683
684 if (nNFEntry == nCurFormatKey)
685 {
686 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
687 }
688
689 // Ugly hack to suppress an ISO date+time format that is the default
690 // date+time format of the locale and identical to the internally generated
691 // one always to be added after/below.
692 const bool bSupIso
693 = bSuppressIsoDateTime && bSuppressDuplicates
694 && (aNewFormNInfo == "YYYY-MM-DD HH:MM:SS" || aNewFormNInfo == "YYYY-MM-DD\"T\"HH:MM:SS");
695
696 if (!bSupIso
697 && (!bSuppressDuplicates || IsEssentialFormat_Impl(nMyCat, nNFEntry)
698 || std::find(rList.begin(), rList.end(), aNewFormNInfo) == rList.end()))
699 {
700 rList.push_back(aNewFormNInfo);
701 aCurEntryList.push_back(nNFEntry);
702 }
703}
704
706{
707 if (nKey == nCurFormatKey)
708 return true;
709
711 switch (nIndex)
712 {
713 // These are preferred or edit formats.
716 case NF_TIME_HH_MMSS:
717 case NF_TIME_MMSS00:
725 return true;
726 default:
727 break;
728 }
729
731}
732
733short SvxNumberFormatShell::FillEListWithCurrency_Impl(std::vector<OUString>& rList, short nSelPos)
734{
735 /* Create a current list of format entries. The return value is
736 * the list position of the current format. If the list is empty
737 * or if there is no current format, SELPOS_NONE is delivered.
738 */
739 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
740
741 const NfCurrencyEntry* pTmpCurrencyEntry;
742 bool bTmpBanking;
743 OUString rSymbol;
744
745 bool bFlag = pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
746 &bTmpBanking);
747
748 if ((!bFlag && pCurCurrencyEntry == nullptr)
749 || (bFlag && pTmpCurrencyEntry == nullptr && rSymbol.isEmpty())
750 || (nCurCategory == SvNumFormatType::ALL))
751 {
752 if (nCurCategory == SvNumFormatType::ALL)
753 FillEListWithUserCurrencys(rList, nSelPos);
754 nSelPos = FillEListWithSysCurrencys(rList, nSelPos);
755 }
756 else
757 {
758 nSelPos = FillEListWithUserCurrencys(rList, nSelPos);
759 }
760
761 return nSelPos;
762}
763
764short SvxNumberFormatShell::FillEListWithSysCurrencys(std::vector<OUString>& rList, short nSelPos)
765{
766 /* Create a current list of format entries. The return value is
767 * the list position of the current format. If the list is empty
768 * or if there is no current format, SELPOS_NONE is delivered.
769 */
770 sal_uInt16 nMyType;
771
772 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
773
774 sal_uInt32 nNFEntry;
775 OUString aNewFormNInfo;
776
778
780 {
781 nNFEntry
783
784 if (nCurCategory == SvNumFormatType::ALL && nNFEntry != nCurFormatKey)
785 // Deprecated old currency entries, for ALL add only if used as
786 // current format key.
787 continue;
788
789 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
790
791 if (pNumEntry == nullptr)
792 continue;
793
794 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
795 CategoryToPos_Impl(nMyCat, nMyType);
796 aNewFormNInfo = pNumEntry->GetFormatstring();
797
798 if (nNFEntry == nCurFormatKey)
799 {
800 nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
801 }
802
803 rList.push_back(aNewFormNInfo);
804 aCurEntryList.push_back(nNFEntry);
805 }
806
807 if (nCurCategory != SvNumFormatType::ALL)
808 {
809 for (const auto& rEntry : *pCurFmtTable)
810 {
811 sal_uInt32 nKey = rEntry.first;
812 const SvNumberformat* pNumEntry = rEntry.second;
813
814 if (!IsRemoved_Impl(nKey))
815 {
816 bool bUserNewCurrency = false;
817 if (pNumEntry->HasNewCurrency())
818 {
819 const NfCurrencyEntry* pTmpCurrencyEntry;
820 bool bTmpBanking;
821 OUString rSymbol;
822
823 pFormatter->GetNewCurrencySymbolString(nKey, rSymbol, &pTmpCurrencyEntry,
824 &bTmpBanking);
825
826 bUserNewCurrency = (pTmpCurrencyEntry != nullptr);
827 }
828
829 if (!bUserNewCurrency && (pNumEntry->GetType() & SvNumFormatType::DEFINED))
830 {
831 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
832 CategoryToPos_Impl(nMyCat, nMyType);
833 aNewFormNInfo = pNumEntry->GetFormatstring();
834
835 if (nKey == nCurFormatKey)
836 nSelPos = aCurEntryList.size();
837 rList.push_back(aNewFormNInfo);
838 aCurEntryList.push_back(nKey);
839 }
840 }
841 }
842 }
843 return nSelPos;
844}
845
846short SvxNumberFormatShell::FillEListWithUserCurrencys(std::vector<OUString>& rList, short nSelPos)
847{
848 /* Create a current list of format entries. The return value is
849 * the list position of the current format. If the list is empty
850 * or if there is no current format, SELPOS_NONE is delivered.
851 */
852 sal_uInt16 nMyType;
853
854 DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
855
856 OUString aNewFormNInfo;
857
858 const NfCurrencyEntry* pTmpCurrencyEntry;
859 bool bTmpBanking, bAdaptSelPos;
860 OUString rSymbol;
861 OUString rBankSymbol;
862
863 std::vector<OUString> aList;
864 std::vector<sal_uInt32> aKeyList;
865
866 pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
867 &bTmpBanking);
868
869 OUString rShortSymbol;
870
871 if (pCurCurrencyEntry == nullptr)
872 {
873 // #110398# If no currency format was previously selected (we're not
874 // about to add another currency), try to select the initial currency
875 // format (nCurFormatKey) that was set in FormatChanged() after
876 // matching the format string entered in the dialog.
877 bAdaptSelPos = true;
878 pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(pTmpCurrencyEntry);
879 bBankingSymbol = bTmpBanking;
880 nCurCurrencyEntryPos = FindCurrencyFormat(pTmpCurrencyEntry, bTmpBanking);
881 }
882 else
883 {
884 if (pTmpCurrencyEntry == pCurCurrencyEntry)
885 bAdaptSelPos = true;
886 else
887 {
888 bAdaptSelPos = false;
889 pTmpCurrencyEntry = pCurCurrencyEntry;
890 }
891 bTmpBanking = bBankingSymbol;
892 }
893
894 if (pTmpCurrencyEntry != nullptr)
895 {
896 rSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
897 rBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
898 rShortSymbol = pTmpCurrencyEntry->BuildSymbolString(bTmpBanking, true);
899 }
900
901 for (const auto& rEntry : *pCurFmtTable)
902 {
903 sal_uInt32 nKey = rEntry.first;
904 const SvNumberformat* pNumEntry = rEntry.second;
905
906 if (!IsRemoved_Impl(nKey))
907 {
908 if (pNumEntry->GetType() & SvNumFormatType::DEFINED || pNumEntry->IsAdditionalBuiltin())
909 {
910 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
911 CategoryToPos_Impl(nMyCat, nMyType);
912 aNewFormNInfo = pNumEntry->GetFormatstring();
913
914 bool bInsFlag = false;
915 if (pNumEntry->HasNewCurrency())
916 {
917 bInsFlag = true; // merge locale formats into currency selection
918 }
919 else if ((!bTmpBanking && aNewFormNInfo.indexOf(rSymbol) >= 0)
920 || (bTmpBanking && aNewFormNInfo.indexOf(rBankSymbol) >= 0))
921 {
922 bInsFlag = true;
923 }
924 else if (aNewFormNInfo.indexOf(rShortSymbol) >= 0)
925 {
926 OUString rTstSymbol;
927 const NfCurrencyEntry* pTstCurrencyEntry;
928 bool bTstBanking;
929
930 pFormatter->GetNewCurrencySymbolString(nKey, rTstSymbol, &pTstCurrencyEntry,
931 &bTstBanking);
932
933 if (pTmpCurrencyEntry == pTstCurrencyEntry && bTstBanking == bTmpBanking)
934 {
935 bInsFlag = true;
936 }
937 }
938
939 if (bInsFlag)
940 {
941 aList.push_back(aNewFormNInfo);
942 aKeyList.push_back(nKey);
943 }
944 }
945 }
946 }
947
948 NfWSStringsDtor aWSStringsDtor;
949 sal_uInt16 nDefault;
950 if (pTmpCurrencyEntry && nCurCategory != SvNumFormatType::ALL)
951 {
952 nDefault
953 = pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, bTmpBanking);
954 if (!bTmpBanking)
955 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, true);
956 }
957 else
958 nDefault = 0;
959 if (!bTmpBanking && nCurCategory != SvNumFormatType::ALL)
960 {
961 // append formats for all currencies defined in the current I18N locale
963 sal_uInt16 nCurrCount = rCurrencyTable.size();
965 for (sal_uInt16 i = 0; i < nCurrCount; ++i)
966 {
967 const NfCurrencyEntry* pCurr = &rCurrencyTable[i];
968 if (pCurr->GetLanguage() == eLang && pTmpCurrencyEntry != pCurr)
969 {
970 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, false);
971 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, true);
972 }
973 }
974 }
975
976 size_t nOldListCount = rList.size();
977 for (size_t i = 0, nPos = nOldListCount; i < aWSStringsDtor.size(); ++i)
978 {
979 bool bFlag = true;
980 OUString aInsStr(aWSStringsDtor[i]);
981 size_t j;
982 for (j = 0; j < aList.size(); ++j)
983 {
984 if (aList[j] == aInsStr)
985 {
986 bFlag = false;
987 break;
988 }
989 }
990 if (bFlag)
991 {
992 rList.push_back(aInsStr);
994 }
995 else
996 {
997 rList.push_back(aList[j]);
998 aList.erase(aList.begin() + j);
999 aCurEntryList.insert(aCurEntryList.begin() + (nPos++), aKeyList[j]);
1000 aKeyList.erase(aKeyList.begin() + j);
1001 }
1002 }
1003
1004 for (size_t i = 0; i < aKeyList.size(); ++i)
1005 {
1006 if (aKeyList[i] != NUMBERFORMAT_ENTRY_NOT_FOUND)
1007 {
1008 rList.push_back(aList[i]);
1009 aCurEntryList.push_back(aKeyList[i]);
1010 }
1011 }
1012
1013 for (size_t i = nOldListCount; i < rList.size(); ++i)
1014 {
1015 aCurrencyFormatList.push_back(rList[i]);
1016
1017 if (nSelPos == SELPOS_NONE && bAdaptSelPos && aCurEntryList[i] == nCurFormatKey)
1018 nSelPos = i;
1019 }
1020
1021 if (nSelPos == SELPOS_NONE && nCurCategory != SvNumFormatType::ALL)
1022 nSelPos = nDefault;
1023
1024 return nSelPos;
1025}
1026
1027short SvxNumberFormatShell::FillEListWithUsD_Impl(std::vector<OUString>& rList,
1028 SvNumFormatType eCategory, short nSelPos)
1029{
1030 /* Create a current list of format entries. The return value is
1031 * the list position of the current format. If the list is empty
1032 * or if there is no current format, SELPOS_NONE is delivered.
1033 */
1034
1035 assert(pCurFmtTable != nullptr);
1036
1037 OUString aNewFormNInfo;
1038
1039 const bool bCatDefined = (eCategory == SvNumFormatType::DEFINED);
1040 const bool bCategoryMatch = (eCategory != SvNumFormatType::ALL && !bCatDefined);
1041
1042 for (const auto& rEntry : *pCurFmtTable)
1043 {
1044 const SvNumberformat* pNumEntry = rEntry.second;
1045
1046 if (bCategoryMatch && (pNumEntry->GetMaskedType() & eCategory) != eCategory)
1047 continue; // for; type does not match category if not ALL
1048
1049 const bool bUserDefined = bool(pNumEntry->GetType() & SvNumFormatType::DEFINED);
1050 if (!bUserDefined && bCatDefined)
1051 continue; // for; not user defined in DEFINED category
1052
1053 if (!(bUserDefined || (!bCatDefined && pNumEntry->IsAdditionalBuiltin())))
1054 continue; // for; does not match criteria at all
1055
1056 const sal_uInt32 nKey = rEntry.first;
1057 if (!IsRemoved_Impl(nKey))
1058 {
1059 aNewFormNInfo = pNumEntry->GetFormatstring();
1060
1061 bool bAdd = true;
1062 if (pNumEntry->HasNewCurrency())
1063 {
1064 bool bTestBanking;
1065 sal_uInt16 nPos = FindCurrencyTableEntry(aNewFormNInfo, bTestBanking);
1066 bAdd = !IsInTable(nPos, bTestBanking, aNewFormNInfo);
1067 }
1068 if (bAdd)
1069 {
1070 if (nKey == nCurFormatKey)
1071 nSelPos = aCurEntryList.size();
1072 rList.push_back(aNewFormNInfo);
1073 aCurEntryList.push_back(nKey);
1074 }
1075 }
1076 }
1077 return nSelPos;
1078}
1079
1080void SvxNumberFormatShell::GetPreviewString_Impl(OUString& rString, const Color*& rpColor)
1081{
1082 rpColor = nullptr;
1083
1084 // #50441# if a string was set in addition to the value, use it for text formats
1085 bool bUseText
1087 || (!aValStr.isEmpty() && (pFormatter->GetType(nCurFormatKey) & SvNumFormatType::TEXT)));
1088
1089 if (bUseText)
1090 {
1091 pFormatter->GetOutputString(aValStr, nCurFormatKey, rString, &rpColor);
1092 }
1093 else
1094 {
1096 }
1097}
1098
1099::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetRemoved_Impl(size_t nKey)
1100{
1101 return ::std::find(aDelList.begin(), aDelList.end(), nKey);
1102}
1103
1105{
1106 return GetRemoved_Impl(nKey) != aDelList.end();
1107}
1108
1109::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetAdded_Impl(size_t nKey)
1110{
1111 return ::std::find(aAddList.begin(), aAddList.end(), nKey);
1112}
1113
1114// Conversion routines:
1116{
1117 // map category css::form positions (->resource)
1118 switch (nPos)
1119 {
1120 case CAT_USERDEFINED:
1121 rCategory = SvNumFormatType::DEFINED;
1122 break;
1123 case CAT_NUMBER:
1124 rCategory = SvNumFormatType::NUMBER;
1125 break;
1126 case CAT_PERCENT:
1127 rCategory = SvNumFormatType::PERCENT;
1128 break;
1129 case CAT_CURRENCY:
1130 rCategory = SvNumFormatType::CURRENCY;
1131 break;
1132 case CAT_DATE:
1133 rCategory = SvNumFormatType::DATE;
1134 break;
1135 case CAT_TIME:
1136 rCategory = SvNumFormatType::TIME;
1137 break;
1138 case CAT_SCIENTIFIC:
1139 rCategory = SvNumFormatType::SCIENTIFIC;
1140 break;
1141 case CAT_FRACTION:
1142 rCategory = SvNumFormatType::FRACTION;
1143 break;
1144 case CAT_BOOLEAN:
1145 rCategory = SvNumFormatType::LOGICAL;
1146 break;
1147 case CAT_TEXT:
1148 rCategory = SvNumFormatType::TEXT;
1149 break;
1150 case CAT_ALL:
1151 default:
1152 rCategory = SvNumFormatType::ALL;
1153 break;
1154 }
1155}
1156
1158{
1159 // map category to css::form positions (->resource)
1160 switch (nCategory)
1161 {
1162 case SvNumFormatType::DEFINED:
1163 rPos = CAT_USERDEFINED;
1164 break;
1165 case SvNumFormatType::NUMBER:
1166 rPos = CAT_NUMBER;
1167 break;
1168 case SvNumFormatType::PERCENT:
1169 rPos = CAT_PERCENT;
1170 break;
1171 case SvNumFormatType::CURRENCY:
1172 rPos = CAT_CURRENCY;
1173 break;
1174 case SvNumFormatType::DATETIME:
1175 case SvNumFormatType::DATE:
1176 rPos = CAT_DATE;
1177 break;
1178 case SvNumFormatType::TIME:
1179 rPos = CAT_TIME;
1180 break;
1181 case SvNumFormatType::SCIENTIFIC:
1182 rPos = CAT_SCIENTIFIC;
1183 break;
1184 case SvNumFormatType::FRACTION:
1185 rPos = CAT_FRACTION;
1186 break;
1187 case SvNumFormatType::LOGICAL:
1188 rPos = CAT_BOOLEAN;
1189 break;
1190 case SvNumFormatType::TEXT:
1191 rPos = CAT_TEXT;
1192 break;
1193 case SvNumFormatType::ALL:
1194 default:
1195 rPos = CAT_ALL;
1196 }
1197}
1198
1199/*
1200 * Function: Formats the number nValue dependent on rFormatStr
1201 * and stores the result in rPreviewStr.
1202 * Input: FormatString, color, number to format
1203 * Output: Output string rPreviewStr
1204 */
1205void SvxNumberFormatShell::MakePrevStringFromVal(const OUString& rFormatStr, OUString& rPreviewStr,
1206 const Color*& rpFontColor, double nValue)
1207{
1208 rpFontColor = nullptr;
1209 pFormatter->GetPreviewString(rFormatStr, nValue, rPreviewStr, &rpFontColor, eCurLanguage);
1210}
1211
1212/*
1213 * Function: Returns the comment for a given entry.
1214 * Input: Number of the entry
1215 * Output: Comment string
1216 */
1217void SvxNumberFormatShell::SetComment4Entry(short nEntry, const OUString& aEntStr)
1218{
1219 SvNumberformat* pNumEntry;
1220 if (nEntry < 0)
1221 return;
1222 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1223 pNumEntry = const_cast<SvNumberformat*>(pFormatter->GetEntry(nMyNfEntry));
1224 if (pNumEntry != nullptr)
1225 pNumEntry->SetComment(aEntStr);
1226}
1227
1228/*
1229 * Function: Returns the comment for a given entry.
1230 * Input: Number of the entry
1231 * Output: Comment string
1232 */
1234{
1235 if (nEntry < 0)
1236 return OUString();
1237
1238 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1239 {
1240 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1241 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1242 if (pNumEntry != nullptr)
1243 return pNumEntry->GetComment();
1244 }
1245
1246 return OUString();
1247}
1248
1249/*
1250 * Function: Returns the category number for a given entry.
1251 * Input: Number of the entry
1252 * Output: Category number
1253 */
1255{
1256 if (nEntry < 0)
1257 return 0;
1258 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1259 {
1260 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1261
1262 if (nMyNfEntry != NUMBERFORMAT_ENTRY_NOT_FOUND)
1263 {
1264 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1265 if (pNumEntry != nullptr)
1266 {
1267 SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
1268 sal_uInt16 nMyType;
1269 CategoryToPos_Impl(nMyCat, nMyType);
1270
1271 return static_cast<short>(nMyType);
1272 }
1273 return 0;
1274 }
1275 else if (!aCurrencyFormatList.empty())
1276 {
1277 return CAT_CURRENCY;
1278 }
1279 }
1280 return 0;
1281}
1282
1283/*
1284 * Function: Returns the information about whether an entry is user-specific.
1285 * Input: Number of the entry
1286 * Output: User-specific?
1287 */
1289{
1290 if (nEntry < 0)
1291 return false;
1292 if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
1293 {
1294 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1295 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1296
1297 if (pNumEntry != nullptr)
1298 {
1299 if (pNumEntry->GetType() & SvNumFormatType::DEFINED)
1300 {
1301 return true;
1302 }
1303 }
1304 }
1305 return false;
1306}
1307
1308/*
1309 * Function: Returns the format string for a given entry.
1310 * Input: Number of the entry
1311 * Output: Format string
1312 */
1314{
1315 if (nEntry < 0)
1316 return OUString();
1317
1318 if (!aCurrencyFormatList.empty())
1319 {
1320 if (aCurrencyFormatList.size() > o3tl::make_unsigned(nEntry))
1321 return aCurrencyFormatList[nEntry];
1322 }
1323 else
1324 {
1325 sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
1326 const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
1327
1328 if (pNumEntry != nullptr)
1329 return pNumEntry->GetFormatstring();
1330 }
1331 return OUString();
1332}
1333
1334/*
1335 * Function: Returns the list number for a given format index.
1336 * Input: Number of the entry
1337 * Output: Category number
1338 */
1339short SvxNumberFormatShell::GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
1340{
1341 short nSelP = SELPOS_NONE;
1343 {
1344 // Check list size against return type limit.
1345 if (aCurEntryList.size() <= o3tl::make_unsigned(::std::numeric_limits<short>::max()))
1346 {
1347 for (size_t i = 0; i < aCurEntryList.size(); ++i)
1348 {
1349 if (aCurEntryList[i] == nIdx)
1350 {
1351 nSelP = i;
1352 break;
1353 }
1354 }
1355 }
1356 else
1357 {
1358 OSL_FAIL("svx::SvxNumberFormatShell::GetListPos4Entry(), list got too large!");
1359 }
1360 }
1361 else
1362 {
1363 // A second list holds the generated currency formats.
1364 for (size_t i = 0; i < aCurrencyFormatList.size(); ++i)
1365 {
1366 if (rFmtString == aCurrencyFormatList[i])
1367 {
1368 nSelP = static_cast<short>(i);
1369 break;
1370 }
1371 }
1372 }
1373 return nSelP;
1374}
1375
1377{
1379}
1380
1381void SvxNumberFormatShell::GetCurrencySymbols(std::vector<OUString>& rList, sal_uInt16* pPos)
1382{
1383 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::MatchSystemCurrency();
1384
1385 bool bFlag = (pTmpCurrencyEntry == nullptr);
1386
1387 SvxCurrencyToolBoxControl::GetCurrencySymbols(rList, bFlag, aCurCurrencyList);
1388
1389 if (pPos == nullptr)
1390 return;
1391
1393 sal_uInt16 nTableCount = rCurrencyTable.size();
1394
1395 *pPos = 0;
1396 size_t nCount = aCurCurrencyList.size();
1397
1398 if (bFlag)
1399 {
1400 *pPos = 1;
1402 }
1403 else
1404 {
1405 for (size_t i = 1; i < nCount; i++)
1406 {
1407 const sal_uInt16 j = aCurCurrencyList[i];
1408 if (j != sal_uInt16(-1) && j < nTableCount && pTmpCurrencyEntry == &rCurrencyTable[j])
1409 {
1410 *pPos = static_cast<sal_uInt16>(i);
1411 nCurCurrencyEntryPos = static_cast<sal_uInt16>(i);
1412 break;
1413 }
1414 }
1415 }
1416}
1417
1419{
1421 sal_uInt16 nCount = rCurrencyTable.size();
1422
1423 bBankingSymbol = (nPos >= nCount);
1424
1425 if (nPos >= aCurCurrencyList.size())
1426 return;
1427
1428 sal_uInt16 nCurrencyPos = aCurCurrencyList[nPos];
1429 if (nCurrencyPos != sal_uInt16(-1))
1430 {
1431 pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(&rCurrencyTable[nCurrencyPos]);
1433 }
1434 else
1435 {
1436 pCurCurrencyEntry = nullptr;
1439 }
1440}
1441
1442void SvxNumberFormatShell::SetCurCurrencyEntry(NfCurrencyEntry* pCEntry)
1443{
1444 pCurCurrencyEntry = pCEntry;
1445}
1446
1447bool SvxNumberFormatShell::IsTmpCurrencyFormat(const OUString& rFmtString)
1448{
1449 sal_uInt32 nFound;
1450 FindEntry(rFmtString, &nFound);
1451 return nFound == NUMBERFORMAT_ENTRY_NEW_CURRENCY;
1452}
1453
1454sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const OUString& rFmtString)
1455{
1457 sal_uInt16 nCount = rCurrencyTable.size();
1458
1459 bool bTestBanking = false;
1460
1461 sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
1462
1463 if (nPos != sal_uInt16(-1))
1464 {
1465 sal_uInt16 nStart = 0;
1466 if (bTestBanking && aCurCurrencyList.size() > nPos)
1467 {
1468 nStart = nCount;
1469 }
1470 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1471 {
1472 if (aCurCurrencyList[j] == nPos)
1473 return j;
1474 }
1475 }
1476 return sal_uInt16(-1);
1477}
1478
1479sal_uInt16 SvxNumberFormatShell::FindCurrencyTableEntry(const OUString& rFmtString,
1480 bool& bTestBanking)
1481{
1482 sal_uInt16 nPos = sal_uInt16(-1);
1483
1485 sal_uInt16 nCount = rCurrencyTable.size();
1486
1487 const SvNumberformat* pFormat;
1488 OUString aSymbol, aExtension;
1489 sal_uInt32 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
1490 if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND
1491 && ((pFormat = pFormatter->GetEntry(nFound)) != nullptr)
1492 && pFormat->GetNewCurrencySymbol(aSymbol, aExtension))
1493 {
1494 // eventually match with format locale
1495 const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::GetCurrencyEntry(
1496 bTestBanking, aSymbol, aExtension, pFormat->GetLanguage());
1497 if (pTmpCurrencyEntry)
1498 {
1499 for (sal_uInt16 i = 0; i < nCount; i++)
1500 {
1501 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1502 {
1503 nPos = i;
1504 break;
1505 }
1506 }
1507 }
1508 }
1509 else
1510 {
1511 // search symbol string only
1512 for (sal_uInt16 i = 0; i < nCount; i++)
1513 {
1514 const NfCurrencyEntry* pTmpCurrencyEntry = &rCurrencyTable[i];
1515 OUString _aSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
1516 OUString aBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
1517
1518 if (rFmtString.indexOf(_aSymbol) != -1)
1519 {
1520 bTestBanking = false;
1521 nPos = i;
1522 break;
1523 }
1524 else if (rFmtString.indexOf(aBankSymbol) != -1)
1525 {
1526 bTestBanking = true;
1527 nPos = i;
1528 break;
1529 }
1530 }
1531 }
1532
1533 return nPos;
1534}
1535
1536sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry* pTmpCurrencyEntry,
1537 bool bTmpBanking)
1538{
1540 sal_uInt16 nCount = rCurrencyTable.size();
1541
1542 sal_uInt16 nPos = 0;
1543 for (sal_uInt16 i = 0; i < nCount; i++)
1544 {
1545 if (pTmpCurrencyEntry == &rCurrencyTable[i])
1546 {
1547 nPos = i;
1548 break;
1549 }
1550 }
1551
1552 sal_uInt16 nStart = 0;
1553 if (bTmpBanking && aCurCurrencyList.size() > nPos)
1554 {
1555 nStart = nCount;
1556 }
1557 for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
1558 {
1559 if (aCurCurrencyList[j] == nPos)
1560 return j;
1561 }
1562 return sal_uInt16(-1);
1563}
1564
1565bool SvxNumberFormatShell::IsInTable(sal_uInt16 const nPos, bool const bTmpBanking,
1566 std::u16string_view rFmtString) const
1567{
1568 bool bFlag = false;
1569
1570 if (nPos != sal_uInt16(-1))
1571 {
1573
1574 if (nPos < rCurrencyTable.size())
1575 {
1576 NfWSStringsDtor aWSStringsDtor;
1577 pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, rCurrencyTable[nPos], bTmpBanking);
1578
1579 for (const OUString& s : aWSStringsDtor)
1580 {
1581 if (s == rFmtString)
1582 {
1583 bFlag = true;
1584 break;
1585 }
1586 }
1587 }
1588 }
1589
1590 return bFlag;
1591}
1592
1593/* 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()
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:1313
SVX_DLLPRIVATE::std::vector< sal_uInt32 >::iterator GetAdded_Impl(size_t nKey)
Definition: numfmtsh.cxx:1109
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:1080
SvxNumberValueType eValType
Definition: numfmtsh.hxx:180
sal_uInt32 nCurFormatKey
Definition: numfmtsh.hxx:187
bool IsUserDefined(const OUString &rFmtString)
Definition: numfmtsh.cxx:413
void SetComment4Entry(short nEntry, const OUString &aCommentString)
Definition: numfmtsh.cxx:1217
LanguageType eCurLanguage
Definition: numfmtsh.hxx:189
SVX_DLLPRIVATE short FillEListWithDateTime_Impl(std::vector< OUString > &rList, short nSelPos, bool bSuppressDuplicates)
Definition: numfmtsh.cxx:644
void GetOptions(const OUString &rFormat, bool &rThousand, bool &rNegRed, sal_uInt16 &rPrecision, sal_uInt16 &rLeadingZeroes, sal_uInt16 &rCatLbPos)
Definition: numfmtsh.cxx:349
void SetCurrencySymbol(sal_uInt32 nPos)
Definition: numfmtsh.cxx:1418
short GetCategory4Entry(short nEntry) const
Definition: numfmtsh.cxx:1254
SVX_DLLPRIVATE short FillEListWithCurrency_Impl(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:733
SVX_DLLPRIVATE short FillEListWithUsD_Impl(std::vector< OUString > &rList, SvNumFormatType eCategory, short Pos)
Definition: numfmtsh.cxx:1027
std::vector< sal_uInt32 > const & GetUpdateData() const
Definition: numfmtsh.cxx:171
SVX_DLLPRIVATE bool IsEssentialFormat_Impl(SvNumFormatType eType, sal_uInt32 nKey)
Definition: numfmtsh.cxx:705
void SetCurCurrencyEntry(NfCurrencyEntry *)
Definition: numfmtsh.cxx:1442
SVX_DLLPRIVATE short FillEntryList_Impl(std::vector< OUString > &rList)
Definition: numfmtsh.cxx:503
std::vector< sal_uInt16 > aCurCurrencyList
Definition: numfmtsh.hxx:190
sal_uInt16 FindCurrencyTableEntry(const OUString &rFmtString, bool &bTestBanking)
Definition: numfmtsh.cxx:1479
std::vector< sal_uInt32 > aCurEntryList
Definition: numfmtsh.hxx:186
SVX_DLLPRIVATE short FillEListWithUserCurrencys(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:846
std::vector< sal_uInt32 > aAddList
Definition: numfmtsh.hxx:184
std::vector< OUString > aCurrencyFormatList
Definition: numfmtsh.hxx:194
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:1104
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:1447
sal_uInt32 nCurCurrencyEntryPos
Definition: numfmtsh.hxx:193
SVX_DLLPRIVATE void FillEListWithStd_Impl(std::vector< OUString > &rList, SvNumFormatType eCategory, short &Pos, bool bSuppressDuplicates=false)
Definition: numfmtsh.cxx:558
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:1205
OUString GetStandardName() const
Returns the name of Standard, General, ... for the current language.
Definition: numfmtsh.cxx:1376
bool FindEntry(const OUString &rFmtString, sal_uInt32 *pAt=nullptr)
Definition: numfmtsh.cxx:437
SvNumberFormatter * pFormatter
Definition: numfmtsh.hxx:178
OUString GetComment4Entry(short nEntry)
Definition: numfmtsh.cxx:1233
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:1115
NfCurrencyEntry * pCurCurrencyEntry
Definition: numfmtsh.hxx:191
SVX_DLLPRIVATE short FillEListWithFormats_Impl(std::vector< OUString > &rList, short nSelPos, NfIndexTableOffset eOffsetStart, NfIndexTableOffset eOffsetEnd, bool bSuppressDuplicates)
Definition: numfmtsh.cxx:626
bool IsInTable(sal_uInt16 nPos, bool bTmpBanking, std::u16string_view rFmtString) const
Definition: numfmtsh.cxx:1565
std::vector< sal_uInt32 > aDelList
Definition: numfmtsh.hxx:185
sal_uInt16 FindCurrencyFormat(const OUString &rFmtString)
Definition: numfmtsh.cxx:1454
SVX_DLLPRIVATE void FillEListWithOneFormat_Impl(std::vector< OUString > &rList, short &nSelPos, bool bSuppressDuplicates, NfIndexTableOffset nOffset, bool bSuppressIsoDateTime)
Definition: numfmtsh.cxx:668
SVX_DLLPRIVATE short FillEListWithSysCurrencys(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:764
void GetCurrencySymbols(std::vector< OUString > &rList, sal_uInt16 *pPos)
Definition: numfmtsh.cxx:1381
static SVX_DLLPRIVATE void CategoryToPos_Impl(SvNumFormatType nCategory, sal_uInt16 &rPos)
Definition: numfmtsh.cxx:1157
void GetInitSettings(sal_uInt16 &nCatLbPos, LanguageType &rLangType, sal_uInt16 &nFmtLbSelPos, std::vector< OUString > &rFmtEntries, OUString &rPrevString, const Color *&rpPrevColor)
Definition: numfmtsh.cxx:474
SvNumberFormatTable * pCurFmtTable
Definition: numfmtsh.hxx:179
void MakePreviewString(const OUString &rFormatStr, OUString &rPreviewStr, const Color *&rpFontColor)
Definition: numfmtsh.cxx:378
SvNumFormatType nCurCategory
Definition: numfmtsh.hxx:188
short GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
Definition: numfmtsh.cxx:1339
SVX_DLLPRIVATE::std::vector< sal_uInt32 >::iterator GetRemoved_Impl(size_t nKey)
Definition: numfmtsh.cxx:1099
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:1288
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
#define CAT_ALL
Definition: numfmtsh.hxx:41
#define CAT_FRACTION
Definition: numfmtsh.hxx:49
#define SELPOS_NONE
Definition: numfmtsh.hxx:53
#define CAT_TEXT
Definition: numfmtsh.hxx:51
SvxNumberValueType
Definition: numfmtsh.hxx:34
#define CAT_DATE
Definition: numfmtsh.hxx:46
#define CAT_PERCENT
Definition: numfmtsh.hxx:44
#define NUMBERFORMAT_ENTRY_NEW_CURRENCY
Definition: numfmtsh.hxx:55
#define CAT_TIME
Definition: numfmtsh.hxx:47
#define CAT_NUMBER
Definition: numfmtsh.hxx:43
#define CAT_SCIENTIFIC
Definition: numfmtsh.hxx:48
#define CAT_CURRENCY
Definition: numfmtsh.hxx:45
#define CAT_USERDEFINED
Definition: numfmtsh.hxx:42
#define CAT_BOOLEAN
Definition: numfmtsh.hxx:50
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