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