Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/svl/numformat.hxx
Line
Count
Source
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
#pragma once
20
21
#include <svl/svldllapi.h>
22
23
#include <svl/nfengine.hxx>
24
#include <svl/nfkeytab.hxx>
25
#include <tools/link.hxx>
26
27
class SvNumberFormatterRegistry_Impl;
28
class NfCurrencyTable;
29
30
class SVL_DLLPUBLIC SvNumberFormatter
31
{
32
    friend class SvNumberFormatterRegistry_Impl;
33
34
public:
35
    /**
36
     * We can't technically have an "infinite" value, so we use an arbitrary
37
     * upper precision threshold to represent the "unlimited" precision.
38
     */
39
    static const sal_uInt16 UNLIMITED_PRECISION;
40
41
    /**
42
     * Precision suitable for numbers displayed in input bar, for instance
43
     * Calc's formula input bar.
44
     */
45
    static const sal_uInt16 INPUTSTRING_PRECISION;
46
47
    /// ctor with service manager and language/country enum
48
    SvNumberFormatter(const css::uno::Reference<css::uno::XComponentContext>& rxContext,
49
                      LanguageType eLang);
50
51
    ~SvNumberFormatter();
52
53
    /// Set CallBack to ColorTable
54
    void SetColorLink(const Link<sal_uInt16, Color*>& rColorTableCallBack);
55
    /// Do the CallBack to ColorTable
56
    Color* GetUserDefColor(sal_uInt16 nIndex) const;
57
58
    /// Change language/country, also input and format scanner
59
    void ChangeIntl(LanguageType eLnge);
60
    /// Change the reference null date
61
    void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear);
62
    /// Change standard precision
63
    void ChangeStandardPrec(short nPrec);
64
    /// Set zero value suppression
65
    void SetNoZero(bool bNZ);
66
67
    /** The language with which the formatter was initialized (system setting),
68
        NOT the current language after a ChangeIntl() */
69
    LanguageType GetLanguage() const;
70
71
    // Determine whether two format types are input compatible or not
72
    static bool IsCompatible(SvNumFormatType eOldType, SvNumFormatType eNewType);
73
74
    /** Get table of formats of a specific type of a locale. A format FIndex is
75
        tested whether it has the type and locale requested, if it doesn't
76
        match FIndex returns the default format for the type/locale. If no
77
        specific format is to be selected FIndex may be initialized to 0. */
78
    SvNumberFormatTable& GetEntryTable(SvNumFormatType eType, sal_uInt32& FIndex,
79
                                       LanguageType eLnge);
80
81
    /** Get table of formats of a specific type of a language/country.
82
        FIndex returns the default format of that type.
83
        If the language/country was never touched before new entries are generated */
84
    SvNumberFormatTable& ChangeCL(SvNumFormatType eType, sal_uInt32& FIndex, LanguageType eLnge);
85
86
    /** Get table of formats of the same type as FIndex; eType and rLnge are
87
        set accordingly. An unknown format is set to Standard/General */
88
    SvNumberFormatTable& GetFirstEntryTable(SvNumFormatType& eType, sal_uInt32& FIndex,
89
                                            LanguageType& rLnge);
90
91
    /// Delete an entry including the format it is referring to
92
    void DeleteEntry(sal_uInt32 nKey);
93
94
    /** Create new entry of a format code string for language/country.
95
        @return
96
            <TRUE/> if string new and ok and inserted.
97
             <FALSE/> if string already exists or an unresolvable parse error
98
             occurred, in which case nCheckPos is the error position within rString.
99
            If the error occurs at position 0 or rString is empty nCheckPos
100
            will be 1, so an error in the string is always indicated by
101
             nCheckPos not being zero.
102
            The content of the rString variable can be changed and corrected
103
             by the method.
104
            nType contains the type of the format.
105
            nKey contains the index key of the format.
106
     */
107
    bool PutEntry(OUString& rString, sal_Int32& nCheckPos, SvNumFormatType& nType, sal_uInt32& nKey,
108
                  LanguageType eLnge = LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent = true);
109
110
    /** Same as <method>PutEntry</method> but the format code string is
111
         considered to be of language/country eLnge and is converted to
112
        language/country eNewLnge */
113
    bool PutandConvertEntry(OUString& rString, sal_Int32& nCheckPos, SvNumFormatType& nType,
114
                            sal_uInt32& nKey, LanguageType eLnge, LanguageType eNewLnge,
115
                            bool bConvertDateOrder, bool bReplaceBooleanEquivalent = true);
116
117
    /** Same as <method>PutandConvertEntry</method> but the format code string
118
         is considered to be of the System language/country eLnge and is
119
        converted to another System language/country eNewLnge. In this case
120
         the automatic currency is converted too. */
121
    bool PutandConvertEntrySystem(OUString& rString, sal_Int32& nCheckPos, SvNumFormatType& nType,
122
                                  sal_uInt32& nKey, LanguageType eLnge, LanguageType eNewLnge);
123
124
    /** Similar to <method>PutEntry</method> and
125
        <method>PutandConvertEntry</method> or
126
        <method>PutandConvertEntrySystem</method>, the format code string
127
        passed is considered to be of language/country eLnge. If
128
        eLnge==LANGUAGE_SYSTEM the format code has to match eSysLnge, and if
129
        eSysLnge is not the current application locale the format code is
130
        converted to the current locale. Additionally, if the format code
131
        represents an old "automatic" currency format, it is converted to the
132
        new default currency format of the eLnge locale. The rString format
133
        code passed as an argument may get adapted in case eLnge was used (or
134
        is LANGUAGE_SYSTEM and eSysLnge is identical); in case it wasn't the
135
        method works on a copy instead, otherwise the resulting string would
136
        not match eSysLnge anymore.
137
138
        <p> This method was introduced to handle the legacy currency formats of
139
        the "autotbl.fmt" file used by Calc and Writer and convert them to
140
        fixed currency codes of the actual currency. Note that in the case of
141
        legacy currency formats no special attribution is converted, only the
142
        default currency format of the locale is chosen, and that new fixed
143
        currency codes are of course not converted to other currencies. The
144
        method may also be used as a general method taking, converting and
145
        inserting almost arbitrary format codes. To insert or use, for example,
146
        the default currency format code matching the current locale, the
147
        method could be called with<br/>
148
149
        <code>
150
        GetIndexPuttingAndConverting( "0 $", LANGUAGE_SYSTEM, LANGUAGE_ENGLISH_US, ...);
151
        </code>
152
153
        @return
154
            The index key of the resulting number format. If the format code
155
            was empty, could not be converted or has errors, the eLnge locale's
156
            standard number format is chosen instead. The index key is
157
            guaranteed to represent some valid number format. If
158
            rNewInserted==false and rCheckPos>0 the format code has errors
159
            and/or could not be converted.
160
     */
161
    sal_uInt32 GetIndexPuttingAndConverting(OUString& rString, LanguageType eLnge,
162
                                            LanguageType eSysLnge, SvNumFormatType& rType,
163
                                            bool& rNewInserted, sal_Int32& rCheckPos);
164
165
    /** Create a format code string using format nIndex as a template and
166
        applying other settings (passed from the dialog) */
167
    OUString GenerateFormat(sal_uInt32 nIndex, LanguageType eLnge = LANGUAGE_DONTKNOW,
168
                            bool bThousand = false, bool IsRed = false, sal_uInt16 nPrecision = 0,
169
                            sal_uInt16 nLeadingCnt = 1);
170
171
    /** Analyze an input string
172
        @return
173
            <TRUE/> if input is a number or is matching a format F_Index
174
                F_Index is set to a matching format if number, the value is
175
                returned in fOutNumber
176
            <FALSE/> if input is not a number
177
     */
178
    bool IsNumberFormat(const OUString& sString, sal_uInt32& F_Index, double& fOutNumber,
179
                        SvNumInputOptions eInputOptions = SvNumInputOptions::NONE);
180
181
    /// Format a number according to a format index, return string and color
182
    void GetOutputString(const double& fOutNumber, sal_uInt32 nFIndex, OUString& sOutString,
183
                         const Color** ppColor, bool bUseStarFormat = false);
184
185
    /** Format a string according to a format index, return string and color.
186
        Formats only if the format code is of type text or the 4th subcode
187
        of a format code is specified, otherwise sOutString will be == "" */
188
    void GetOutputString(const OUString& sString, sal_uInt32 nFIndex, OUString& sOutString,
189
                         const Color** ppColor, bool bUseStarFormat = false);
190
191
    /** Format a number according to the standard default format matching
192
        the given format index. rOutString will be the real cell string (e.g.
193
        a number rounded by the cell format, which rounded value is used
194
        in the filtering condition now), instead of the EditFormat string
195
        (e.g a not rounded value, which is visible during editing).*/
196
    OUString GetInputLineString(const double& fOutNumber, sal_uInt32 nFIndex,
197
                                bool bFiltering = false, bool bForceSystemLocale = false);
198
199
    /** Format a number according to a format code string to be scanned.
200
        @return
201
            <FALSE/> if format code contains an error
202
            <TRUE/> else, in which case the string and color are returned.
203
     */
204
    bool GetPreviewString(const OUString& sFormatString, double fPreviewNumber,
205
                          OUString& sOutString, const Color** ppColor, LanguageType eLnge,
206
                          bool bUseStarFormat = false);
207
208
    /** Same as <method>GetPreviewString</method> but the format code string
209
        may be either language/country eLnge or en_US english US */
210
    bool GetPreviewStringGuess(const OUString& sFormatString, double fPreviewNumber,
211
                               OUString& sOutString, const Color** ppColor,
212
                               LanguageType eLnge = LANGUAGE_DONTKNOW);
213
214
    /** Format a string according to a format code string to be scanned.
215
        @return
216
            <FALSE/> if format code contains an error
217
            <TRUE/> else, in which case the string and color are returned.
218
     */
219
    bool GetPreviewString(const OUString& sFormatString, const OUString& sPreviewString,
220
                          OUString& sOutString, const Color** ppColor,
221
                          LanguageType eLnge = LANGUAGE_DONTKNOW);
222
223
    /** Test whether the format code string is already present in container
224
        @return
225
            NUMBERFORMAT_ENTRY_NOT_FOUND if not found, else the format index.
226
     */
227
    sal_uInt32 TestNewString(const OUString& sFormatString, LanguageType eLnge = LANGUAGE_DONTKNOW);
228
229
    /// Whether format index nFIndex is of type text or not
230
    bool IsTextFormat(sal_uInt32 nFIndex) const;
231
232
    /// Whether format index nFIndex has NatNum12 modifier
233
    bool IsNatNum12(sal_uInt32 nFIndex) const;
234
235
    /// Get additional info of a format index, e.g. for dialog box
236
    void GetFormatSpecialInfo(sal_uInt32 nFormat, bool& bThousand, bool& IsRed,
237
                              sal_uInt16& nPrecision, sal_uInt16& nLeadingCnt);
238
239
    /// Count of decimals
240
    sal_uInt16 GetFormatPrecision(sal_uInt32 nFormat);
241
242
    /// Count of integer digits
243
    sal_uInt16 GetFormatIntegerDigits(sal_uInt32 nFormat) const;
244
245
    /** Get additional info of a format code string, e.g. for dialog box.
246
        Uses a temporary parse, if possible use only if format code is not
247
        present in container yet, otherwise ineffective.
248
        @return
249
            0 if format code string parsed without errors, otherwise error
250
            position (like nCheckPos on <method>PutEntry</method>)
251
     */
252
    sal_uInt32 GetFormatSpecialInfo(const OUString&, bool& bThousand, bool& IsRed,
253
                                    sal_uInt16& nPrecision, sal_uInt16& nLeadingCnt,
254
                                    LanguageType eLnge = LANGUAGE_DONTKNOW);
255
256
    /// Get return string for Calc CELL() function, "G", "D1", ...
257
    OUString GetCalcCellReturn(sal_uInt32 nFormat) const;
258
259
    bool IsUserDefined(sal_uInt32 F_Index) const;
260
261
    /// Check if format code string may be deleted by user
262
    bool IsUserDefined(std::u16string_view sStr, LanguageType eLnge = LANGUAGE_DONTKNOW);
263
264
    /** Return the format index of the format code string for language/country,
265
        or NUMBERFORMAT_ENTRY_NOT_FOUND */
266
    sal_uInt32 GetEntryKey(std::u16string_view sStr, LanguageType eLnge = LANGUAGE_DONTKNOW);
267
268
    /// Return the format for a format index
269
    const SvNumberformat* GetEntry(sal_uInt32 nKey) const;
270
271
    /// Obtain substituted GetFormatEntry(), i.e. system formats.
272
    const SvNumberformat* GetSubstitutedEntry(sal_uInt32 nKey, sal_uInt32& o_rNewKey);
273
274
    /// Return the format index of the standard default number format for language/country
275
    sal_uInt32 GetStandardIndex(LanguageType eLnge = LANGUAGE_DONTKNOW);
276
277
    /// Return the format index of the default format of a type for language/country
278
    sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge = LANGUAGE_DONTKNOW);
279
280
    /** Return the format index of the default format of a type for language/country.
281
        Maybe not the default format but a special builtin format, e.g. for
282
        NF_TIME_HH_MMSS00, if that format is passed in nFIndex. */
283
    sal_uInt32 GetStandardFormat(sal_uInt32 nFIndex, SvNumFormatType eType, LanguageType eLnge);
284
285
    /** Return the format index of the default format of a type for language/country.
286
        Maybe not the default format but a special builtin format, e.g. for
287
        NF_TIME_HH_MMSS00, or NF_TIME_HH_MMSS if fNumber >= 1.0  */
288
    sal_uInt32 GetStandardFormat(double fNumber, sal_uInt32 nFIndex, SvNumFormatType eType,
289
                                 LanguageType eLnge);
290
291
    /** Return a time format that best matches fNumber. */
292
    sal_uInt32 GetTimeFormat(double fNumber, LanguageType eLnge, bool bForceDuration);
293
294
    /** Return a format and type that best matches the value of fNumber if
295
        fNumber is assumed to be a date, time or datetime value, but unknown
296
        which. Originally introduced for Chart databrowser editor, probably
297
        should not be used otherwise. */
298
    sal_uInt32 GuessDateTimeFormat(SvNumFormatType& rType, double fNumber, LanguageType eLnge);
299
300
    /** Return the corresponding edit format of a format.
301
302
        nFIndex, eType and pFormat (if not nullptr) are assumed to match each
303
        other / be of one format. The locale to use is obtained from pFormat,
304
        if nullptr then LANGUAGE_SYSTEM is used. This can be overridden by
305
        specifying eForLocale other than LANGUAGE_DONTKNOW.
306
     */
307
    sal_uInt32 GetEditFormat(double fNumber, sal_uInt32 nFIndex, SvNumFormatType eType,
308
                             SvNumberformat const* pFormat,
309
                             LanguageType eForLocale = LANGUAGE_DONTKNOW);
310
311
    /// Return the reference date
312
    const Date& GetNullDate() const;
313
    /// Return the standard decimal precision
314
    sal_uInt16 GetStandardPrec() const;
315
    /// Return whether zero suppression is switched on
316
    bool GetNoZero() const;
317
    /** Get the type of a format (or css::util::NumberFormat::UNDEFINED if no entry),
318
         but with css::util::NumberFormat::DEFINED masked out */
319
    SvNumFormatType GetType(sal_uInt32 nFIndex) const;
320
321
    /// As the name says
322
    void ClearMergeTable();
323
    /// Merge in all new entries from rNewTable and return a table of resulting new format indices
324
    SvNumberFormatterIndexTable* MergeFormatter(SvNumberFormatter& rNewTable);
325
326
    /// Whether a merge table is present or not
327
    bool HasMergeFormatTable() const;
328
    /// Return the new format index for an old format index, if a merge table exists
329
    sal_uInt32 GetMergeFormatIndex(sal_uInt32 nOldFmt) const;
330
331
    /** Convert the ugly old tools' Table type bloated with new'ed sal_uInt32
332
        entries merge table to ::std::map with old index key and new index key.
333
        @ATTENTION! Also clears the old table using ClearMergeTable() */
334
    SvNumberFormatterMergeMap ConvertMergeTableToMap();
335
336
    /** Return the format index of a builtin format for a specific language/country.
337
        If nFormat is not a builtin format nFormat is returned. */
338
    sal_uInt32 GetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat,
339
                                             LanguageType eLnge = LANGUAGE_DONTKNOW);
340
341
    /** Return the format index for a builtin format of a specific language
342
        @see NfIndexTableOffset
343
     */
344
    sal_uInt32 GetFormatIndex(NfIndexTableOffset, LanguageType eLnge = LANGUAGE_DONTKNOW);
345
346
    /** Return enum index of a format index of a builtin format,
347
        NF_INDEX_TABLE_ENTRIES if it's not a builtin format.
348
        @see NfIndexTableOffset
349
     */
350
    static NfIndexTableOffset GetIndexTableOffset(sal_uInt32 nFormat);
351
352
    /** Set evaluation type and order of input date strings
353
        @see NfEvalDateFormat
354
     */
355
    void SetEvalDateFormat(NfEvalDateFormat eEDF);
356
    NfEvalDateFormat GetEvalDateFormat() const;
357
358
    /** Set TwoDigitYearStart, how the input string scanner handles a two digit year.
359
        Default from VCL: 1930, 30-99 19xx, 00-29 20xx
360
361
        <p> Historically (prior to src513e) it was a two digit number determining
362
        until which number the string scanner recognizes a year to be 20xx,
363
        default <= 29 is used by SFX/OfaMiscCfg.
364
        The name Year2000 is kept although the actual functionality is now a
365
        TwoDigitYearStart which might be in any century.
366
     */
367
    void SetYear2000(sal_uInt16 nVal);
368
    sal_uInt16 GetYear2000() const;
369
    static sal_uInt16 GetYear2000Default();
370
371
    sal_uInt16 ExpandTwoDigitYear(sal_uInt16 nYear) const;
372
    static sal_uInt16 ExpandTwoDigitYear(sal_uInt16 nYear, sal_uInt16 nTwoDigitYearStart);
373
374
    /// Return the decimal separator matching the locale of the given format
375
    OUString GetFormatDecimalSep(sal_uInt32 nFormat);
376
377
    static void resetTheCurrencyTable();
378
379
    /// Return a NfCurrencyTable with pointers to <type>NfCurrencyEntry</type> entries
380
    static const NfCurrencyTable& GetTheCurrencyTable();
381
382
    /** Searches, according to the default locale currency, an entry of the
383
        CurrencyTable which is <bold>not</bold> the first (LANGUAGE_SYSTEM) entry.
384
        @return
385
            <NULL/> if not found
386
            else pointer to NfCurrencyEntry
387
     */
388
    static const NfCurrencyEntry* MatchSystemCurrency();
389
390
    /** Return a NfCurrencyEntry matching a language/country.
391
        If language/country is LANGUAGE_SYSTEM a <method>MatchSystemCurrency</method>
392
        call is tried to get an entry. If that fails or the corresponding
393
        language/country is not present the entry for LANGUAGE_SYSTEM is returned.
394
     */
395
    static const NfCurrencyEntry& GetCurrencyEntry(LanguageType);
396
397
    /** Return a NfCurrencyEntry pointer matching a language/country
398
        and currency abbreviation (AKA banking symbol).
399
        This method is meant for the configuration of the default currency.
400
        @return
401
            <NULL/> if not found
402
            else pointer to NfCurrencyEntry
403
     */
404
    static const NfCurrencyEntry* GetCurrencyEntry(std::u16string_view rAbbrev, LanguageType eLang);
405
406
    /** Return a NfCurrencyEntry pointer matching the symbol
407
        combination of a LegacyOnly currency. Note that this means only that
408
        the currency matching both symbols was once used in the Office, but is
409
        not offered in dialogs anymore. It doesn't even mean that the currency
410
        symbol combination is valid, since the reason for removing it may have
411
        been just that. #i61657#
412
        @return
413
            A matching entry, or else <NULL/>.
414
     */
415
    static const NfCurrencyEntry* GetLegacyOnlyCurrencyEntry(std::u16string_view rSymbol,
416
                                                             std::u16string_view rAbbrev);
417
418
    /** Set the default system currency. The combination of abbreviation and
419
        language must match an existent element of theCurrencyTable. If not,
420
        the SYSTEM (current locale) entry becomes the default.
421
        This method is meant for the configuration of the default currency.
422
     */
423
    static void SetDefaultSystemCurrency(std::u16string_view rAbbrev, LanguageType eLang);
424
425
    /** Get all standard formats for a specific currency, formats are
426
        appended to the NfWSStringsDtor list.
427
        @param bBank
428
            <TRUE/>: generate only format strings with currency abbreviation
429
            <FALSE/>: mixed format strings
430
        @return
431
            position of default format
432
     */
433
    sal_uInt16 GetCurrencyFormatStrings(NfWSStringsDtor&, const NfCurrencyEntry&, bool bBank) const;
434
435
    /** Whether nFormat is of type css::util::NumberFormat::CURRENCY and the format code
436
        contains a new SYMBOLTYPE_CURRENCY and if so which one [$xxx-nnn].
437
        If ppEntry is not NULL and exactly one entry is found, a [$xxx-nnn] is
438
        returned, even if the format code only contains [$xxx] !
439
     */
440
    bool GetNewCurrencySymbolString(sal_uInt32 nFormat, OUString& rSymbol,
441
                                    const NfCurrencyEntry** ppEntry, bool* pBank = nullptr) const;
442
443
    /** Look up the corresponding NfCurrencyEntry matching
444
        rSymbol (may be CurrencySymbol or CurrencyAbbreviation) and possibly
445
        a rExtension (being yyy of [$xxx-yyy]) or a given language/country
446
        value. Tries to match a rSymbol with rExtension first, then with
447
         eFormatLanguage, then rSymbol only. This is because a currency entry
448
        might have been constructed using I18N locale data where a used locale
449
        of a currency format code must not necessarily match the locale of
450
        the locale data itself, e.g. [$HK$-40C] (being "zh_HK" locale) in
451
        zh_CN locale data. Here the rExtension would have the value 0x40c but
452
         eFormatLanguage of the number format would have the value of zh_CN
453
         locale, the value with which the corresponding CurrencyEntry is
454
        constructed.
455
456
        @param bFoundBank
457
            Only used for output.
458
             If the return value is not <NULL/> this value is set to <TRUE/> if
459
             the matching entry was found by comparing rSymbol against the
460
             CurrencyAbbreviation (AKA BankSymbol).
461
             If the return value is <NULL/> the value of bFoundBank is undefined.
462
        @param rSymbol
463
            Currency symbol, preferably obtained of a format by a call to
464
            <method>SvNumberformat::GetNewCurrencySymbol()</method>
465
        @param rExtension
466
            Currency extension, preferably obtained of a format by a call to
467
            <method>SvNumberformat::GetNewCurrencySymbol()</method>
468
        @param eFormatLanguage
469
            The language/country value of the format of which rSymbol and
470
            rExtension are obtained (<method>SvNumberformat::GetLanguage()</method>).
471
        @param bOnlyStringLanguage
472
            If <TRUE/> only entries with language/country of rExtension are
473
            checked, no match on eFormatLanguage. If rExtension is empty all
474
             entries are checked.
475
        @return
476
            The matching entry if unique (in which case bFoundBank is set),
477
             else <NULL/>.
478
     */
479
    static const NfCurrencyEntry* GetCurrencyEntry(bool& bFoundBank, std::u16string_view rSymbol,
480
                                                   std::u16string_view rExtension,
481
                                                   LanguageType eFormatLanguage,
482
                                                   bool bOnlyStringLanguage = false);
483
484
    /// Get compatibility ("automatic" old style) currency from I18N locale data
485
    void GetCompatibilityCurrency(OUString& rSymbol, OUString& rAbbrev) const;
486
487
    /// Fill rList with the language/country codes that have been allocated
488
    void GetUsedLanguages(std::vector<LanguageType>& rList);
489
490
    /// Fill a NfKeywordIndex table with keywords of a language/country
491
    void FillKeywordTable(NfKeywordTable& rKeywords, LanguageType eLang);
492
493
    /** Fill a NfKeywordIndex table with keywords usable in Excel export with
494
        GetFormatStringForExcel() or SvNumberformat::GetMappedFormatstring() */
495
    void FillKeywordTableForExcel(NfKeywordTable& rKeywords);
496
497
    /** Return a format code string suitable for Excel export.
498
499
        @param  rTempFormatter
500
                SvNumberFormatter to use if a non-en-US format code needs to be
501
                converted and put, should not be the same formatter to not
502
                pollute the entries of this one here.
503
     */
504
    OUString GetFormatStringForExcel(sal_uInt32 nKey, const NfKeywordTable& rKeywords,
505
                                     SvNumberFormatter& rTempFormatter) const;
506
507
    /** Return a keyword for a language/country and NfKeywordIndex
508
        for XML import, to generate number format strings. */
509
    OUString GetKeyword(LanguageType eLnge, sal_uInt16 nIndex);
510
511
    /** Return the GENERAL keyword in proper case ("General") for a
512
        language/country, used in XML import */
513
    OUString GetStandardName(LanguageType eLnge);
514
515
    void MergeDefaultFormatKeys(const SvNFFormatData::DefaultFormatKeysMap& rDefaultFormatKeys);
516
517
    /** Check if a specific locale has supported locale data. */
518
    static bool IsLocaleInstalled(LanguageType eLang);
519
520
    /** Obtain NfKeywordTable used with a format, possibly localized.
521
522
        XXX NOTE: the content (actual keywords) is only valid as long as the
523
        locale context of the associated ImpSvNumberformatScan instance does
524
        not change to a locale with different keywords, which may happen
525
        anytime with a call (implicit or explicit) to
526
        SvNumberFormatter::ChangeIntl(). If needed longer, copy-create another
527
        NfKeywordTable instance or copy individual elements.
528
529
        If the format specified with nKey does not exist, the content of the
530
        NfKeywordTable matches the locale with which the SvNumberFormatter
531
        instance was created and initialized.
532
533
        This function preliminary exists for unit tests and otherwise is
534
        pretty much useless.
535
     */
536
    const NfKeywordTable& GetKeywords(sal_uInt32 nKey);
537
538
    /** Access for unit tests. */
539
    static const NfKeywordTable& GetEnglishKeywords();
540
541
    /** Access for unit tests. */
542
    static const std::vector<Color>& GetStandardColors();
543
544
    /** Access for unit tests. */
545
    static size_t GetMaxDefaultColors();
546
547
private:
548
    mutable ::osl::Mutex m_aMutex;
549
    css::uno::Reference<css::uno::XComponentContext> m_xContext;
550
    const LanguageType IniLnge; // Initialized setting language/country
551
    SvNFFormatData m_aFormatData;
552
    SvNFEngine::Accessor m_aRWPolicy;
553
    std::unique_ptr<SvNumberFormatTable> pFormatTable; // For the UI dialog
554
    std::unique_ptr<SvNumberFormatterIndexTable>
555
        pMergeTable; // List of indices for merging two formatters
556
    SvNFLanguageData m_aCurrentLanguage;
557
    OnDemandNativeNumberWrapper m_xNatNum; // Native number service loaded on demand
558
    Link<sal_uInt16, Color*> aColorLink; // User defined color table CallBack
559
560
    SVL_DLLPRIVATE static sal_uInt16 nSystemCurrencyPosition;
561
    SVL_DLLPRIVATE static SvNumberFormatterRegistry_Impl* pFormatterRegistry;
562
563
    // get the registry, create one if none exists
564
    SVL_DLLPRIVATE static SvNumberFormatterRegistry_Impl& GetFormatterRegistry();
565
566
    // Generate additional formats provided by i18n
567
    SVL_DLLPRIVATE void ImpGenerateAdditionalFormats(
568
        sal_uInt32 CLOffset,
569
        css::uno::Reference<css::i18n::XNumberFormatCode> const& rNumberFormatCode);
570
571
    // Test whether format code already exists, then return index key,
572
    // otherwise NUMBERFORMAT_ENTRY_NOT_FOUND
573
    SVL_DLLPRIVATE sal_uInt32 ImpIsEntry(std::u16string_view rString, sal_uInt32 CLOffset,
574
                                         LanguageType eLnge) const;
575
576
    // Create theCurrencyTable with all <type>NfCurrencyEntry</type>
577
    SVL_DLLPRIVATE static void ImpInitCurrencyTable();
578
579
    // used as a loop body inside of GetNewCurrencySymbolString() and GetCurrencyEntry()
580
    static bool ImpLookupCurrencyEntryLoopBody(const NfCurrencyEntry*& pFoundEntry,
581
                                               bool& bFoundBank, const NfCurrencyEntry* pData,
582
                                               sal_uInt16 nPos, std::u16string_view rSymbol);
583
584
    // called by SvNumberFormatterRegistry_Impl::Notify if the default system currency changes
585
    SVL_DLLPRIVATE void ResetDefaultSystemCurrency();
586
587
    // link to be set at <method>SvtSysLocaleOptions::SetCurrencyChangeLink()</method>
588
    DECL_DLLPRIVATE_STATIC_LINK(SvNumberFormatter, CurrencyChangeLink, LinkParamNone*, void);
589
590
    // Substitute a format during GetFormatEntry(), i.e. system formats.
591
    SVL_DLLPRIVATE const SvNumberformat* ImpSubstituteEntry(const SvNumberformat* pFormat,
592
                                                            sal_uInt32* o_pRealKey = nullptr);
593
594
    // Whether nFIndex is a special builtin format
595
    SVL_DLLPRIVATE bool ImpIsSpecialStandardFormat(sal_uInt32 nFIndex, LanguageType eLnge);
596
597
    // Replace the SYSTEM language/country format codes. Called upon change of
598
    // the user configurable locale.
599
    // Old compatibility codes are replaced, user defined are converted, and
600
    // new format codes are appended.
601
    SVL_DLLPRIVATE void ReplaceSystemCL(LanguageType eOldLanguage);
602
603
    // own mutex, may also be used by internal class SvNumberFormatterRegistry_Impl
604
    static ::osl::Mutex& GetGlobalMutex();
605
112M
    ::osl::Mutex& GetInstanceMutex() const { return m_aMutex; }
606
607
public:
608
    // Called by SvNumberFormatterRegistry_Impl::Notify if the system locale's
609
    // date acceptance patterns change.
610
    void InvalidateDateAcceptancePatterns();
611
612
    //! The following methods are not to be used from outside but must be
613
    //! public for the InputScanner and FormatScanner.
614
615
    // return current (!) Locale
616
0
    const LanguageTag& GetLanguageTag() const { return m_aCurrentLanguage.GetLanguageTag(); }
617
618
    // return the corresponding CharacterClassification wrapper
619
0
    const CharClass* GetCharClass() const { return m_aCurrentLanguage.GetCharClass(); }
620
621
    // return the corresponding LocaleData wrapper
622
0
    const LocaleDataWrapper* GetLocaleData() const { return m_aCurrentLanguage.GetLocaleData(); }
623
624
    // return the corresponding Calendar wrapper
625
0
    CalendarWrapper* GetCalendar() const { return m_aCurrentLanguage.GetCalendar(); }
626
627
    // return the corresponding NativeNumberSupplier wrapper
628
    const NativeNumberWrapper& GetNatNum() const;
629
630
    // cached locale data items
631
632
    // return the corresponding decimal separator
633
168
    const OUString& GetNumDecimalSep() const { return m_aCurrentLanguage.GetNumDecimalSep(); }
634
635
    // return the corresponding date separator
636
1.09k
    const OUString& GetDateSep() const { return m_aCurrentLanguage.GetDateSep(); }
637
638
    void PrepForRoMode();
639
78.8k
    const SvNFFormatData& GetROFormatData() const { return m_aFormatData; }
640
78.8k
    const SvNFLanguageData& GetROLanguageData() const { return m_aCurrentLanguage; }
641
};
642
643
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */