Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/svl/zforlist.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
#ifndef INCLUDED_SVL_ZFORLIST_HXX
20
#define INCLUDED_SVL_ZFORLIST_HXX
21
22
#include <config_options.h>
23
#include <svl/svldllapi.h>
24
#include <rtl/ustrbuf.hxx>
25
#include <rtl/ustring.hxx>
26
#include <o3tl/typed_flags_set.hxx>
27
#include <i18nlangtag/lang.h>
28
#include <com/sun/star/util/NumberFormat.hpp>
29
30
#include <map>
31
#include <unordered_map>
32
#include <vector>
33
34
namespace com::sun::star::i18n { struct Currency; }
35
36
class LocaleDataWrapper;
37
class SvNumberformat;
38
39
342M
#define SV_COUNTRY_LANGUAGE_OFFSET     10000  // Max count of formats per country/language
40
1.91M
#define SV_MAX_COUNT_STANDARD_FORMATS  100    // Max count of builtin default formats per CL
41
42
constexpr size_t NF_MAX_FORMAT_SYMBOLS = 100;
43
44
/// The built-in @ Text format, offset within a locale, key in the locale the
45
/// number formatter was constructed with.
46
constexpr sal_uInt32 NF_STANDARD_FORMAT_TEXT = SV_MAX_COUNT_STANDARD_FORMATS;
47
48
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND  = 0xffffffff;   /// MAX_ULONG
49
50
enum class SvNumFormatType : sal_Int16
51
{
52
    /** selects all number formats.
53
      */
54
     ALL = css::util::NumberFormat::ALL, // 0
55
     /** selects only user-defined number formats.
56
      */
57
     DEFINED = css::util::NumberFormat::DEFINED,  // 1
58
     /** selects date formats.
59
      */
60
     DATE = css::util::NumberFormat::DATE, // 2
61
     /** selects time formats.
62
      */
63
     TIME = css::util::NumberFormat::TIME, // 4
64
     /** selects currency formats.
65
      */
66
     CURRENCY = css::util::NumberFormat::CURRENCY,  // 8
67
     /** selects decimal number formats.
68
      */
69
     NUMBER = css::util::NumberFormat::NUMBER, // 16
70
     /** selects scientific number formats.
71
      */
72
     SCIENTIFIC = css::util::NumberFormat::SCIENTIFIC, // 32
73
     /** selects number formats for fractions.
74
      */
75
     FRACTION = css::util::NumberFormat::FRACTION, // 64
76
     /** selects percentage number formats.
77
      */
78
     PERCENT = css::util::NumberFormat::PERCENT, // 128
79
     /** selects text number formats.
80
      */
81
     TEXT = css::util::NumberFormat::TEXT, // 256
82
     /** selects number formats which contain date and time.
83
      */
84
     DATETIME = DATE | TIME, // 6
85
     /** selects boolean number formats.
86
      */
87
     LOGICAL = css::util::NumberFormat::LOGICAL, // 1024
88
     /** is used as a return value if no format exists.
89
      */
90
     UNDEFINED = css::util::NumberFormat::UNDEFINED, // 2048
91
     /** @internal is used to flag an empty sub format.
92
         @since LibreOffice 5.1
93
      */
94
     EMPTY = css::util::NumberFormat::EMPTY, // 4096
95
    /** @internal selects a time duration format.
96
        8192 + TIME (4)
97
        @since LibreOffice 6.2
98
     */
99
     DURATION = css::util::NumberFormat::DURATION, // 8196
100
};
101
namespace o3tl {
102
    template<> struct typed_flags<SvNumFormatType> : is_typed_flags<SvNumFormatType, 0x3dff> {};
103
}
104
105
/** enum values for <method>SvNumberFormatter::GetFormatIndex</method>
106
107
    <p>
108
     Builtin standard formats, order should be also the arrangement in the
109
    dialog list box representation.</p>
110
111
    <p>
112
     Date specials:<ul>
113
    <li>SYSTEM: As set in System Regional Settings.
114
    <li>SYS: short/long defined, order and separators from System Regional Settings.
115
    <li>DEF: short/long and order defined, separators from System Regional Settings.
116
    <li>DIN: all settings hard coded as DIN (Deutsche Industrie Norm) and EN (European Norm) require.
117
    <li>all other: hard coded
118
    </ul>
119
120
    Do NOT insert any new values!
121
    The values here correspond with those in offapi/com/sun/star/i18n/NumberFormatIndex.idl
122
    You may append values though after NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS.
123
 */
124
enum NfIndexTableOffset
125
{
126
    NF_NUMERIC_START = 0,
127
128
    NF_NUMBER_START = NF_NUMERIC_START,
129
    NF_NUMBER_STANDARD = NF_NUMBER_START,   // Standard/General
130
    NF_NUMBER_INT,                          // 0
131
    NF_NUMBER_DEC2,                         // 0.00
132
    NF_NUMBER_1000INT,                      // #,##0
133
    NF_NUMBER_1000DEC2,                     // #,##0.00
134
    NF_NUMBER_SYSTEM,                       // #,##0.00 or whatever is set in System Regional Settings
135
    NF_NUMBER_END = NF_NUMBER_SYSTEM,
136
137
    NF_SCIENTIFIC_START,
138
    NF_SCIENTIFIC_000E000 = NF_SCIENTIFIC_START,    // 0.00E+000
139
    NF_SCIENTIFIC_000E00,                           // 0.00E+00
140
    NF_SCIENTIFIC_END = NF_SCIENTIFIC_000E00,
141
142
    NF_PERCENT_START,
143
    NF_PERCENT_INT = NF_PERCENT_START,      // 0%
144
    NF_PERCENT_DEC2,                        // 0.00%
145
    NF_PERCENT_END = NF_PERCENT_DEC2,
146
147
    NF_FRACTION_START,
148
    NF_FRACTION_1D = NF_FRACTION_START,      // # ?/?
149
    NF_FRACTION_2D,                          // # ??/??
150
    NF_FRACTION_END = NF_FRACTION_2D,
151
152
    NF_NUMERIC_END = NF_FRACTION_END,
153
154
    NF_CURRENCY_START,
155
    NF_CURRENCY_1000INT = NF_CURRENCY_START,// #,##0 DM
156
    NF_CURRENCY_1000DEC2,                   // #,##0.00 DM
157
    NF_CURRENCY_1000INT_RED,                // #,##0 DM         negative in red
158
    NF_CURRENCY_1000DEC2_RED,               // #,##0.00 DM      negative in red
159
    NF_CURRENCY_1000DEC2_CCC,               // #,##0.00 DEM     currency abbreviation
160
    NF_CURRENCY_1000DEC2_DASHED,            // #,##0.-- DM
161
    NF_CURRENCY_END = NF_CURRENCY_1000DEC2_DASHED,
162
163
    NF_DATE_START,
164
    NF_DATE_SYSTEM_SHORT = NF_DATE_START,   // 08.10.97
165
    NF_DATE_SYSTEM_LONG,                    // Wednesday, 8. October 1997
166
    NF_DATE_SYS_DDMMYY,                     // 08.10.97
167
    NF_DATE_SYS_DDMMYYYY,                   // 08.10.1997                   THE edit format, formatindex="21"
168
    NF_DATE_SYS_DMMMYY,                     // 8. Oct 97
169
    NF_DATE_SYS_DMMMYYYY,                   // 8. Oct 1997
170
    NF_DATE_DIN_DMMMYYYY,                   // 8. Oct. 1997                 DIN
171
    NF_DATE_SYS_DMMMMYYYY,                  // 8. October 1997
172
    NF_DATE_DIN_DMMMMYYYY,                  // 8. October 1997              DIN
173
    NF_DATE_SYS_NNDMMMYY,                   // Wed, 8. Okt 97
174
    NF_DATE_DEF_NNDDMMMYY,                  // Wed 08.Okt 97
175
    NF_DATE_SYS_NNDMMMMYYYY,                // Wed, 8. Oktober 1997
176
    NF_DATE_SYS_NNNNDMMMMYYYY,              // Wednesday, 8. Oktober 1997
177
    NF_DATE_DIN_MMDD,                       // 10-08                        DIN
178
    NF_DATE_DIN_YYMMDD,                     // 97-10-08                     DIN
179
    NF_DATE_DIN_YYYYMMDD,                   // 1997-10-08                   DIN
180
    NF_DATE_ISO_YYYYMMDD = NF_DATE_DIN_YYYYMMDD, // 1997-10-08              ISO clarify with name, formatindex="33"
181
    NF_DATE_SYS_MMYY,                       // 10.97
182
    NF_DATE_SYS_DDMMM,                      // 08.Oct
183
    NF_DATE_MMMM,                           // October
184
    NF_DATE_QQJJ,                           // 4. Quarter 97
185
    NF_DATE_WW,                             // week of year
186
    NF_DATE_END = NF_DATE_WW,
187
188
    NF_TIME_START,
189
    NF_TIME_HHMM = NF_TIME_START,           // HH:MM
190
    NF_TIME_HHMMSS,                         // HH:MM:SS
191
    NF_TIME_HHMMAMPM,                       // HH:MM AM/PM
192
    NF_TIME_HHMMSSAMPM,                     // HH:MM:SS AM/PM
193
    NF_TIME_HH_MMSS,                        // [HH]:MM:SS                   formatindex="43"
194
    NF_TIME_MMSS00,                         // MM:SS,00                     formatindex="44"
195
    NF_TIME_HH_MMSS00,                      // [HH]:MM:SS,00                formatindex="45"
196
    NF_TIME_END = NF_TIME_HH_MMSS00,
197
198
    NF_DATETIME_START,
199
    NF_DATETIME_SYSTEM_SHORT_HHMM = NF_DATETIME_START,  // 08.10.97 01:23
200
    NF_DATETIME_SYS_DDMMYYYY_HHMMSS,        // 08.10.1997 01:23:45          THE edit format, formatindex="47"
201
    NF_DATETIME_END = NF_DATETIME_SYS_DDMMYYYY_HHMMSS,
202
203
    NF_BOOLEAN,                             // BOOLEAN
204
    NF_TEXT,                                // @
205
206
    NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS,    // == 50, old number of predefined entries, i18npool locale data additions start after this
207
208
    // From here on are values of new predefined and built-in formats that are
209
    // not in the original NumberFormatIndex.idl
210
211
    // XXX Values appended here must also get a corresponding entry in
212
    // svl/source/numbers/zforlist.cxx indexTable[] in the same order.
213
214
    // XXX The dialog's number format shell assumes start/end spans
215
    // (NF_..._START and NF_..._END above) to fill its categories with builtin
216
    // formats, make new formats known to svx/source/items/numfmtsh.cxx
217
    // SvxNumberFormatShell::FillEListWithStd_Impl(), otherwise they will not
218
    // be listed at all. Yes that is ugly.
219
    // DATETIME formats need to be added to
220
    // SvxNumberFormatShell::FillEListWithDateTime_Impl().
221
222
    // New predefined format added to i18npool locale data.
223
    NF_DATETIME_SYS_DDMMYYYY_HHMM = NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS,  // 08.10.1997 01:23  formatindex="50"
224
225
    // No i18npool defined locale data between here and NF_INDEX_TABLE_ENTRIES.
226
    NF_INDEX_TABLE_RESERVED_START,
227
228
    NF_FRACTION_3D = NF_INDEX_TABLE_RESERVED_START,  // # ???/???
229
    NF_FRACTION_2,                          // # ?/2
230
    NF_FRACTION_4,                          // # ?/4
231
    NF_FRACTION_8,                          // # ?/8
232
    NF_FRACTION_16,                         // # ??/16
233
    NF_FRACTION_10,                         // # ??/10
234
    NF_FRACTION_100,                        // # ??/100
235
236
    NF_DATETIME_ISO_YYYYMMDD_HHMMSS,        // 1997-10-08 01:23:45          ISO (with blank instead of T)
237
    NF_DATETIME_ISO_YYYYMMDD_HHMMSS000,     // 1997-10-08 01:23:45.678      not quite ISO with locale's separator
238
    NF_DATETIME_ISO_YYYYMMDDTHHMMSS,        // 1997-10-08T01:23:45          ISO
239
    NF_DATETIME_ISO_YYYYMMDDTHHMMSS000,     // 1997-10-08T01:23:45,678      ISO with milliseconds and ',' or '.'
240
241
    // XXX When adding values here, follow the comment above about
242
    // svx/source/items/numfmtsh.cxx
243
244
    NF_INDEX_TABLE_ENTRIES                  // == 62, reserved to not be used in i18npool locale data.
245
246
    // XXX Adding values above may increment the reserved area that can't be
247
    // used by i18npool's locale data FormatCode definitions, see the
248
    // description at i18npool/source/localedata/data/locale.dtd for ELEMENT
249
    // FormatCode what the current convention's value is. In that case, the
250
    // used formatIndex values in i18npool/source/localedata/data/*.xml will
251
    // have to be adjusted.
252
    // Overlapping the area will bail out with a check in
253
    // SvNumberFormatter::ImpInsertFormat() in debug builds.
254
};
255
256
257
// #45717# IsNumberFormat( "98-10-24", 30, x ), YMD Format set with DMY
258
// International settings doesn't recognize the string as a date.
259
/** enum values for <method>SvNumberFormatter::SetEvalDateFormat</method>
260
261
    <p>How <method>ImpSvNumberInputScan::GetDateRef</method> shall take the
262
     DateFormat order (YMD,DMY,MDY) into account, if called from IsNumberFormat
263
    with a date format to match against.
264
 */
265
enum class NfEvalDateFormat
266
{
267
    /** DateFormat only from International, default. */
268
    International,
269
270
    /** DateFormat only from date format passed to function (if any).
271
        If no date format is passed then the DateFormat is taken from International. */
272
    Format,
273
274
    /** First try the DateFormat from International. If it doesn't match a
275
         valid date try the DateFormat from the date format passed. */
276
    InternationalThenFormat,
277
278
    /** First try the DateFormat from the date format passed. If it doesn't
279
        match a valid date try the DateFormat from International. */
280
    FormatThenInternational
281
};
282
283
284
/// This table is std::map because it needs to preserve insertion order,
285
/// because the formats are roughly ordered from most to least common, and some
286
/// parts of the UI want to show them in that order.
287
typedef std::map<sal_uInt32, SvNumberformat*> SvNumberFormatTable;
288
typedef std::unordered_map<sal_uInt16, sal_uInt32> SvNumberFormatterIndexTable;
289
typedef std::unordered_map< sal_uInt32, sal_uInt32> SvNumberFormatterMergeMap;
290
291
292
/** Language/country dependent currency entries
293
 */
294
class UNLESS_MERGELIBS(SVL_DLLPUBLIC) NfCurrencyEntry final
295
{
296
    OUString        aSymbol;            /// currency symbol
297
    OUString        aBankSymbol;        /// currency abbreviation
298
    LanguageType    eLanguage;          /// language/country value
299
    sal_uInt16      nPositiveFormat;    /// position of symbol
300
    sal_uInt16      nNegativeFormat;    /// position of symbol and type and position of negative sign
301
    sal_uInt16      nDigits;            /// count of decimal digits
302
    sal_Unicode     cZeroChar;          /// which character is used for zeros as last decimal digits
303
304
private:
305
306
                        // nDecimalFormat := 0, 1, 2
307
                        // #,##0 or #,##0.00 or #,##0.-- is returned
308
    SVL_DLLPRIVATE OUString Impl_BuildFormatStringNumChars( const LocaleDataWrapper&, sal_uInt16 nDecimalFormat) const;
309
310
public:
311
312
    NfCurrencyEntry( const LocaleDataWrapper& rLocaleData,
313
                     LanguageType eLang );
314
    NfCurrencyEntry( const css::i18n::Currency & rCurr,
315
                     const LocaleDataWrapper& rLocaleData,
316
                     LanguageType eLang );
317
318
                        /// Symbols and language identical
319
    bool                operator==( const NfCurrencyEntry& r ) const;
320
321
137k
    const OUString&     GetSymbol() const           { return aSymbol; }
322
0
    const OUString&     GetBankSymbol() const       { return aBankSymbol; }
323
4.22M
    LanguageType        GetLanguage() const         { return eLanguage; }
324
4.85k
    sal_uInt16          GetPositiveFormat() const   { return nPositiveFormat; }
325
4.85k
    sal_uInt16          GetNegativeFormat() const   { return nNegativeFormat; }
326
232k
    sal_uInt16          GetDigits() const           { return nDigits; }
327
328
                        /** Only to resolve system locale for currency list. */
329
0
    void                SetLanguage( LanguageType nLang ) { eLanguage = nLang; }
330
331
                        /** [$DM-407] (bBank==false) or [$DEM] (bBank==true)
332
                            is returned. If bBank==false and
333
                            bWithoutExtension==true only [$DM] */
334
    OUString            BuildSymbolString(bool bBank, bool bWithoutExtension = false) const;
335
336
                        /** #,##0.00 [$DM-407] is returned, separators
337
                              from rLoc,    incl. minus sign but without [RED] */
338
    OUString            BuildPositiveFormatString(bool bBank, const LocaleDataWrapper&,
339
                                                  sal_uInt16 nDecimalFormat = 1) const;
340
    OUString            BuildNegativeFormatString(bool bBank, const LocaleDataWrapper&,
341
                                                  sal_uInt16 nDecimalFormat = 1) const;
342
343
                        /** [$DM-407] (or [$DEM] if bBank==true)
344
                            is appended/prepended to rStr, incl. minus sign */
345
    void                CompletePositiveFormatString(OUStringBuffer& rStr, bool bBank,
346
                                                     sal_uInt16 nPosiFormat) const;
347
    void                CompleteNegativeFormatString(OUStringBuffer& rStr, bool bBank,
348
                                                     sal_uInt16 nNegaFormat) const;
349
350
                        /// rSymStr is appended/prepended to rStr, incl. minus sign
351
    static  void        CompletePositiveFormatString(OUStringBuffer& rStr,
352
                                                     std::u16string_view rSymStr, sal_uInt16 nPosiFormat);
353
    static  void        CompleteNegativeFormatString(OUStringBuffer& rStr,
354
                                                     std::u16string_view rSymStr, sal_uInt16 nNegaFormat);
355
356
                        /** Representation of a currency (symbol position and
357
                             negative sign) in other locales */
358
    static  sal_uInt16  GetEffectivePositiveFormat( sal_uInt16 nIntlFormat,
359
                                                    sal_uInt16 nCurrFormat, bool bBank );
360
    static  sal_uInt16  GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat,
361
                                                    sal_uInt16 nCurrFormat, bool bBank );
362
363
    /// General Unicode Euro symbol
364
0
    static sal_Unicode   GetEuroSymbol() { return u'\x20AC'; }
365
};
366
367
typedef std::vector< OUString > NfWSStringsDtor;
368
369
/** Input options to be used with IsNumberFormat() */
370
enum class SvNumInputOptions : sal_uInt16
371
{
372
    NONE = 0,
373
    LAX_TIME = 1    ///< allow input of minutes or seconds >59
374
};
375
namespace o3tl {
376
    template<> struct typed_flags<SvNumInputOptions> : is_typed_flags<SvNumInputOptions, 0x0001> {};
377
}
378
379
380
#endif // INCLUDED_SVL_ZFORLIST_HXX
381
382
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */