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>
23 #include <i18nlangtag/mslangid.hxx>
24 #include <o3tl/safeint.hxx>
25 #include <svl/numformat.hxx>
26 #include <svl/zforlist.hxx>
27 #include <svl/zformat.hxx>
28 #include <svl/currencytable.hxx>
29 
30 #include <svx/numfmtsh.hxx>
31 #include <svx/flagsdef.hxx>
32 #include <svx/tbcontrl.hxx>
33 
34 #include <limits>
35 
36 namespace
37 {
38 double 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 
82 SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
83  SvxNumberValueType eNumValType, const OUString& rNumStr)
84  : pFormatter(pNumFormatter)
85  , pCurFmtTable(nullptr)
86  , eValType(eNumValType)
87  , bUndoAddList(true)
88  , nCurFormatKey(nFormatKey)
89  , nCurCategory(SvNumFormatType::ALL)
90  , eCurLanguage(LANGUAGE_NONE)
91  , pCurCurrencyEntry(nullptr)
92  , bBankingSymbol(false)
93  , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
94  , bUseStarFormat(false)
95  , bIsDefaultValNum(true)
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 
116 SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
117  SvxNumberValueType eNumValType, double nNumVal,
118  const OUString* pNumStr)
119  : pFormatter(pNumFormatter)
120  , pCurFmtTable(nullptr)
121  , eValType(eNumValType)
122  , bUndoAddList(true)
123  , nCurFormatKey(nFormatKey)
124  , nCurCategory(SvNumFormatType::ALL)
125  , eCurLanguage(LANGUAGE_NONE)
126  , pCurCurrencyEntry(nullptr)
127  , bBankingSymbol(false)
128  , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
129  , bUseStarFormat(false)
130  , bIsDefaultValNum(false)
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 
171 std::vector<sal_uInt32> const& SvxNumberFormatShell::GetUpdateData() const { return aDelList; }
172 
173 void SvxNumberFormatShell::CategoryChanged(sal_uInt16 nCatLbPos, short& rFmtSelPos,
174  std::vector<OUString>& rFmtEntries)
175 {
176  SvNumFormatType nOldCategory = nCurCategory;
177  PosToCategory_Impl(nCatLbPos, 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 
185 void SvxNumberFormatShell::LanguageChanged(LanguageType eLangType, short& rFmtSelPos,
186  std::vector<OUString>& rFmtEntries)
187 {
188  eCurLanguage = eLangType;
190  rFmtSelPos = FillEntryList_Impl(rFmtEntries);
191 }
192 
193 void 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 
215 bool 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 
281 void 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 
309 void 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 
342 sal_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 
349 void 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 
378 void 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  {
405  if (bIsDefaultValNum)
406  nValNum = GetDefaultValNum(pFormatter->GetType(nExistingFormat));
407  pFormatter->GetOutputString(nValNum, nExistingFormat, rPreviewStr, &rpFontColor,
409  }
410  }
411 }
412 
413 bool 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 
437 bool 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 
474 void 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 
492  CategoryToPos_Impl(nCurCategory, nCatLbPos);
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 
503 short 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 
558 void 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
608  = FillEListWithFormats_Impl(rList, nSelPos, NF_FRACTION_3D, NF_FRACTION_100, false);
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 
626 short 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 
644 short 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 
668 void 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:
718  case NF_TIME_HH_MMSS00:
725  return true;
726  default:
727  break;
728  }
729 
730  return nKey == pFormatter->GetStandardFormat(eType, eCurLanguage);
731 }
732 
733 short 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 
764 short 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
782  = pFormatter->GetFormatIndex(static_cast<NfIndexTableOffset>(nIndex), eCurLanguage);
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 
846 short 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 
1027 short 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 
1080 void 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  */
1205 void 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  */
1217 void 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  */
1339 short SvxNumberFormatShell::GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
1340 {
1341  short nSelP = SELPOS_NONE;
1342  if (nIdx != NUMBERFORMAT_ENTRY_NEW_CURRENCY)
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 
1381 void 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 
1392  const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
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 {
1420  const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
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]);
1432  nCurCurrencyEntryPos = nPos;
1433  }
1434  else
1435  {
1436  pCurCurrencyEntry = nullptr;
1439  }
1440 }
1441 
1442 void SvxNumberFormatShell::SetCurCurrencyEntry(NfCurrencyEntry* pCEntry)
1443 {
1444  pCurCurrencyEntry = pCEntry;
1445 }
1446 
1447 bool SvxNumberFormatShell::IsTmpCurrencyFormat(const OUString& rFmtString)
1448 {
1449  sal_uInt32 nFound;
1450  FindEntry(rFmtString, &nFound);
1451  return nFound == NUMBERFORMAT_ENTRY_NEW_CURRENCY;
1452 }
1453 
1454 sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const OUString& rFmtString)
1455 {
1456  const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
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 
1479 sal_uInt16 SvxNumberFormatShell::FindCurrencyTableEntry(const OUString& rFmtString,
1480  bool& bTestBanking)
1481 {
1482  sal_uInt16 nPos = sal_uInt16(-1);
1483 
1484  const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
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 
1536 sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry* pTmpCurrencyEntry,
1537  bool bTmpBanking)
1538 {
1539  const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
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 
1565 bool 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  {
1572  const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
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: */
sal_uInt16 GetCurrencyFormatStrings(NfWSStringsDtor &, const NfCurrencyEntry &, bool bBank) const
OUString GetComment4Entry(short nEntry)
Definition: numfmtsh.cxx:1233
SVX_DLLPRIVATE::std::vector< sal_uInt32 >::iterator GetRemoved_Impl(size_t nKey)
Definition: numfmtsh.cxx:1099
NF_DATETIME_END
std::vector< sal_uInt32 > const & GetUpdateData() const
Definition: numfmtsh.cxx:171
SvNumberFormatTable * pCurFmtTable
Definition: numfmtsh.hxx:179
bool IsInTable(sal_uInt16 nPos, bool bTmpBanking, std::u16string_view rFmtString) const
Definition: numfmtsh.cxx:1565
void FormatChanged(sal_uInt16 nFmtLbPos, OUString &rPreviewStr, const Color *&rpFontColor)
Definition: numfmtsh.cxx:193
#define LANGUAGE_NONE
SvxNumberValueType eValType
Definition: numfmtsh.hxx:180
SVX_DLLPRIVATE void GetPreviewString_Impl(OUString &rString, const Color *&rpColor)
Definition: numfmtsh.cxx:1080
SVX_DLLPRIVATE bool IsEssentialFormat_Impl(SvNumFormatType eType, sal_uInt32 nKey)
Definition: numfmtsh.cxx:705
sal_Int32 nIndex
OUString GetFormat4Entry(short nEntry)
Definition: numfmtsh.cxx:1313
#define CAT_NUMBER
Definition: numfmtsh.hxx:43
bool IsUserDefined(const OUString &rFmtString)
Definition: numfmtsh.cxx:413
NF_FRACTION_100
static const NfCurrencyEntry & GetCurrencyEntry(LanguageType)
NF_CURRENCY_START
void MakeFormat(OUString &rFormat, bool bThousand, bool bNegRed, sal_uInt16 nPrecision, sal_uInt16 nLeadingZeroes, sal_uInt16 nCurrencyEntryPos)
Definition: numfmtsh.cxx:309
NF_NUMBER_END
static SvxNumberFormatShell * Create(SvNumberFormatter *pNumFormatter, sal_uInt32 nFormatKey, SvxNumberValueType eNumValType, const OUString &rNumStr)
Definition: numfmtsh.cxx:66
sal_uInt32 GetFormatIndex(NfIndexTableOffset, LanguageType eLnge=LANGUAGE_DONTKNOW)
NF_SCIENTIFIC_START
NF_DATETIME_SYS_DDMMYYYY_HHMMSS
NF_PERCENT_END
bool GetNewCurrencySymbol(OUString &rSymbol, OUString &rExtension) const
SvNumberFormatTable & GetFirstEntryTable(SvNumFormatType &eType, sal_uInt32 &FIndex, LanguageType &rLnge)
long Long
std::vector< sal_uInt16 > aCurCurrencyList
Definition: numfmtsh.hxx:190
bool IsUserDefined(sal_uInt32 F_Index) const
std::vector< OUString > aCurrencyFormatList
Definition: numfmtsh.hxx:194
SvNumberFormatter * pFormatter
Definition: numfmtsh.hxx:178
SvNumFormatType GetType(sal_uInt32 nFIndex) const
OUString GetStandardName() const
Returns the name of Standard, General, ...
Definition: numfmtsh.cxx:1376
bool IsAdditionalBuiltin() const
NfIndexTableOffset GetIndexTableOffset(sal_uInt32 nFormat) const
SvxNumberValueType
Definition: numfmtsh.hxx:33
NF_DATETIME_ISO_YYYYMMDDTHHMMSS000
sal_uInt32 TestNewString(const OUString &sFormatString, LanguageType eLnge=LANGUAGE_DONTKNOW)
void SetComment(const OUString &rStr)
NF_TIME_HH_MMSS00
SVX_DLLPRIVATE short FillEListWithCurrency_Impl(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:733
static const NfCurrencyTable & GetTheCurrencyTable()
NF_FRACTION_END
sal_uInt16 GetFormatIntegerDigits(sal_uInt32 nFormat) const
#define CAT_FRACTION
Definition: numfmtsh.hxx:49
const OUString & GetFormatstring() const
NF_DATETIME_START
SVX_DLLPRIVATE short FillEListWithUsD_Impl(std::vector< OUString > &rList, SvNumFormatType eCategory, short Pos)
Definition: numfmtsh.cxx:1027
SVX_DLLPRIVATE::std::vector< sal_uInt32 >::iterator GetAdded_Impl(size_t nKey)
Definition: numfmtsh.cxx:1109
bool IsTmpCurrencyFormat(const OUString &rFmtString)
Definition: numfmtsh.cxx:1447
#define SELPOS_NONE
Definition: numfmtsh.hxx:53
sal_uInt16 GetFormatIntegerDigits(std::u16string_view rFormat) const
Definition: numfmtsh.cxx:342
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent=true)
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
#define CAT_TEXT
Definition: numfmtsh.hxx:51
void GetCurrencySymbols(std::vector< OUString > &rList, sal_uInt16 *pPos)
Definition: numfmtsh.cxx:1381
int nCount
NfIndexTableOffset
sal_uInt32 nCurCurrencyEntryPos
Definition: numfmtsh.hxx:193
NF_CURRENCY_END
#define CAT_PERCENT
Definition: numfmtsh.hxx:44
OUString GetStandardName(LanguageType eLnge)
NF_TIME_HH_MMSS
NF_DATE_ISO_YYYYMMDD
static LanguageType getRealLanguage(LanguageType nLang)
void GetFormatSpecialInfo(sal_uInt32 nFormat, bool &bThousand, bool &IsRed, sal_uInt16 &nPrecision, sal_uInt16 &nLeadingCnt)
NF_DATE_END
NF_PERCENT_START
DocumentType eType
SVX_DLLPRIVATE short FillEListWithSysCurrencys(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:764
SVX_DLLPRIVATE short FillEListWithFormats_Impl(std::vector< OUString > &rList, short nSelPos, NfIndexTableOffset eOffsetStart, NfIndexTableOffset eOffsetEnd, bool bSuppressDuplicates)
Definition: numfmtsh.cxx:626
static SVX_DLLPRIVATE void PosToCategory_Impl(sal_uInt16 nPos, SvNumFormatType &rCategory)
Definition: numfmtsh.cxx:1115
NF_BOOLEAN
void GetOptions(const OUString &rFormat, bool &rThousand, bool &rNegRed, sal_uInt16 &rPrecision, sal_uInt16 &rLeadingZeroes, sal_uInt16 &rCatLbPos)
Definition: numfmtsh.cxx:349
SvNumFormatType GetType() const
SvNumberFormatTable & ChangeCL(SvNumFormatType eType, sal_uInt32 &FIndex, LanguageType eLnge)
void LanguageChanged(LanguageType eLangType, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:185
#define DBG_ASSERT(sCon, aError)
int i
NF_TIME_START
SVX_DLLPRIVATE bool IsRemoved_Impl(size_t nKey)
Definition: numfmtsh.cxx:1104
void RemoveFormat(std::u16string_view rFormat, sal_uInt16 &rCatLbSelPos, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:281
bool FindEntry(const OUString &rFmtString, sal_uInt32 *pAt=nullptr)
Definition: numfmtsh.cxx:437
NF_FRACTION_3D
const o3tl::enumarray< SvxNumValCategory, double > fSvxNumValConst
Definition: flagsdef.hxx:83
#define CAT_DATE
Definition: numfmtsh.hxx:46
NF_SCIENTIFIC_END
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
static const NfCurrencyEntry * MatchSystemCurrency()
NF_DATETIME_SYS_DDMMYYYY_HHMM
SvxNumberFormatShell(SvNumberFormatter *pNumFormatter, sal_uInt32 nFormatKey, SvxNumberValueType eNumValType, const OUString &rNumStr)
Definition: numfmtsh.cxx:82
NF_TEXT
SVX_DLLPRIVATE short FillEListWithDateTime_Impl(std::vector< OUString > &rList, short nSelPos, bool bSuppressDuplicates)
Definition: numfmtsh.cxx:644
SvNumFormatType
NF_CURRENCY_1000DEC2_RED
void CategoryChanged(sal_uInt16 nCatLbPos, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:173
NF_DATE_SYS_DDMMYYYY
NF_TIME_MMSS00
#define CAT_ALL
Definition: numfmtsh.hxx:41
#define CAT_BOOLEAN
Definition: numfmtsh.hxx:50
const OUString & GetComment() const
sal_uInt32 GetEntryKey(std::u16string_view sStr, LanguageType eLnge=LANGUAGE_DONTKNOW)
void DeleteEntry(sal_uInt32 nKey)
#define CAT_CURRENCY
Definition: numfmtsh.hxx:45
std::vector< sal_uInt32 > aDelList
Definition: numfmtsh.hxx:185
SVX_DLLPRIVATE short FillEListWithUserCurrencys(std::vector< OUString > &rList, short nSelPos)
Definition: numfmtsh.cxx:846
bool GetNewCurrencySymbolString(sal_uInt32 nFormat, OUString &rSymbol, const NfCurrencyEntry **ppEntry, bool *pBank=nullptr) const
short GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
Definition: numfmtsh.cxx:1339
NF_TIME_END
sal_uInt16 FindCurrencyFormat(const OUString &rFmtString)
Definition: numfmtsh.cxx:1454
NF_DATE_START
OUString GenerateFormat(sal_uInt32 nIndex, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bThousand=false, bool IsRed=false, sal_uInt16 nPrecision=0, sal_uInt16 nLeadingCnt=1)
bool HasNewCurrency() const
const SvNumberformat * GetEntry(sal_uInt32 nKey) const
std::vector< sal_uInt32 > aAddList
Definition: numfmtsh.hxx:184
void MakePreviewString(const OUString &rFormatStr, OUString &rPreviewStr, const Color *&rpFontColor)
Definition: numfmtsh.cxx:378
#define NUMBERFORMAT_ENTRY_NEW_CURRENCY
Definition: numfmtsh.hxx:55
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
NF_FRACTION_START
#define CAT_USERDEFINED
Definition: numfmtsh.hxx:42
SvNumFormatType GetMaskedType() const
NF_DATETIME_ISO_YYYYMMDD_HHMMSS
std::vector< sal_uInt32 > aCurEntryList
Definition: numfmtsh.hxx:186
SVX_DLLPRIVATE void FillEListWithStd_Impl(std::vector< OUString > &rList, SvNumFormatType eCategory, short &Pos, bool bSuppressDuplicates=false)
Definition: numfmtsh.cxx:558
void SetCurCurrencyEntry(NfCurrencyEntry *)
Definition: numfmtsh.cxx:1442
void GetInitSettings(sal_uInt16 &nCatLbPos, LanguageType &rLangType, sal_uInt16 &nFmtLbSelPos, std::vector< OUString > &rFmtEntries, OUString &rPrevString, const Color *&rpPrevColor)
Definition: numfmtsh.cxx:474
#define CAT_TIME
Definition: numfmtsh.hxx:47
SVX_DLLPRIVATE short FillEntryList_Impl(std::vector< OUString > &rList)
Definition: numfmtsh.cxx:503
SvNumFormatType nCurCategory
Definition: numfmtsh.hxx:188
NF_DATETIME_ISO_YYYYMMDD_HHMMSS000
sal_uInt32 nCurFormatKey
Definition: numfmtsh.hxx:187
NF_DATETIME_ISO_YYYYMMDDTHHMMSS
sal_uInt16 FindCurrencyTableEntry(const OUString &rFmtString, bool &bTestBanking)
Definition: numfmtsh.cxx:1479
NfCurrencyEntry * pCurCurrencyEntry
Definition: numfmtsh.hxx:191
NF_NUMBER_START
std::vector< OUString > NfWSStringsDtor
void MakePrevStringFromVal(const OUString &rFormatStr, OUString &rPreviewStr, const Color *&rpFontColor, double nValue)
Definition: numfmtsh.cxx:1205
short GetCategory4Entry(short nEntry) const
Definition: numfmtsh.cxx:1254
void SetComment4Entry(short nEntry, const OUString &aCommentString)
Definition: numfmtsh.cxx:1217
size_t size() const
LanguageType eCurLanguage
Definition: numfmtsh.hxx:189
bool GetPreviewString(const OUString &sFormatString, double fPreviewNumber, OUString &sOutString, const Color **ppColor, LanguageType eLnge, bool bUseStarFormat=false)
SvNumberFormatTable & GetEntryTable(SvNumFormatType eType, sal_uInt32 &FIndex, LanguageType eLnge)
void SetCurrencySymbol(sal_uInt32 nPos)
Definition: numfmtsh.cxx:1418
bool AddFormat(OUString &rFormat, sal_Int32 &rErrPos, sal_uInt16 &rCatLbSelPos, short &rFmtSelPos, std::vector< OUString > &rFmtEntries)
Definition: numfmtsh.cxx:215
#define CAT_SCIENTIFIC
Definition: numfmtsh.hxx:48
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)
static SVX_DLLPRIVATE void CategoryToPos_Impl(SvNumFormatType nCategory, sal_uInt16 &rPos)
Definition: numfmtsh.cxx:1157
SVX_DLLPRIVATE void FillEListWithOneFormat_Impl(std::vector< OUString > &rList, short &nSelPos, bool bSuppressDuplicates, NfIndexTableOffset nOffset, bool bSuppressIsoDateTime)
Definition: numfmtsh.cxx:668
LanguageType GetLanguage() const
sal_uInt16 nPos
sal_Int16 nValue
Definition: fmsrccfg.cxx:81
bool GetUserDefined4Entry(short nEntry)
Definition: numfmtsh.cxx:1288