summaryrefslogtreecommitdiffstats
path: root/include/svl/zforlist.hxx
blob: f9edfdf783ef23272c0bbeae05ce277e35f0a014 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_SVL_ZFORLIST_HXX
#define INCLUDED_SVL_ZFORLIST_HXX

#include <config_options.h>
#include <svl/svldllapi.h>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
#include <o3tl/typed_flags_set.hxx>
#include <i18nlangtag/lang.h>
#include <com/sun/star/util/NumberFormat.hpp>
#include <unotools/localedatawrapper.hxx>

#include <map>
#include <unordered_map>

namespace com::sun::star::i18n { struct Currency; }

class SvNumberformat;

#define SV_COUNTRY_LANGUAGE_OFFSET     10000  // Max count of formats per country/language
#define SV_MAX_COUNT_STANDARD_FORMATS  100    // Max count of builtin default formats per CL

constexpr size_t NF_MAX_FORMAT_SYMBOLS = 100;

/// The built-in @ Text format, offset within a locale, key in the locale the
/// number formatter was constructed with.
constexpr sal_uInt32 NF_STANDARD_FORMAT_TEXT = SV_MAX_COUNT_STANDARD_FORMATS;

constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND  = 0xffffffff;   /// MAX_ULONG

enum class SvNumFormatType : sal_Int16
{
    /** selects all number formats.
      */
     ALL = css::util::NumberFormat::ALL, // 0
     /** selects only user-defined number formats.
      */
     DEFINED = css::util::NumberFormat::DEFINED,  // 1
     /** selects date formats.
      */
     DATE = css::util::NumberFormat::DATE, // 2
     /** selects time formats.
      */
     TIME = css::util::NumberFormat::TIME, // 4
     /** selects currency formats.
      */
     CURRENCY = css::util::NumberFormat::CURRENCY,  // 8
     /** selects decimal number formats.
      */
     NUMBER = css::util::NumberFormat::NUMBER, // 16
     /** selects scientific number formats.
      */
     SCIENTIFIC = css::util::NumberFormat::SCIENTIFIC, // 32
     /** selects number formats for fractions.
      */
     FRACTION = css::util::NumberFormat::FRACTION, // 64
     /** selects percentage number formats.
      */
     PERCENT = css::util::NumberFormat::PERCENT, // 128
     /** selects text number formats.
      */
     TEXT = css::util::NumberFormat::TEXT, // 256
     /** selects number formats which contain date and time.
      */
     DATETIME = DATE | TIME, // 6
     /** selects boolean number formats.
      */
     LOGICAL = css::util::NumberFormat::LOGICAL, // 1024
     /** is used as a return value if no format exists.
      */
     UNDEFINED = css::util::NumberFormat::UNDEFINED, // 2048
     /** @internal is used to flag an empty sub format.
         @since LibreOffice 5.1
      */
     EMPTY = css::util::NumberFormat::EMPTY, // 4096
    /** @internal selects a time duration format.
        8192 + TIME (4)
        @since LibreOffice 6.2
     */
     DURATION = css::util::NumberFormat::DURATION, // 8196
};
namespace o3tl {
    template<> struct typed_flags<SvNumFormatType> : is_typed_flags<SvNumFormatType, 0x3dff> {};
}

/** enum values for <method>SvNumberFormatter::GetFormatIndex</method>

    <p>
     Builtin standard formats, order should be also the arrangement in the
    dialog list box representation.</p>

    <p>
     Date specials:<ul>
    <li>SYSTEM: As set in System Regional Settings.
    <li>SYS: short/long defined, order and separators from System Regional Settings.
    <li>DEF: short/long and order defined, separators from System Regional Settings.
    <li>DIN: all settings hard coded as DIN (Deutsche Industrie Norm) and EN (European Norm) require.
    <li>all other: hard coded
    </ul>

    Do NOT insert any new values!
    The values here correspond with those in offapi/com/sun/star/i18n/NumberFormatIndex.idl
    You may append values though after NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS.
 */
enum NfIndexTableOffset
{
    NF_NUMERIC_START = 0,

    NF_NUMBER_START = NF_NUMERIC_START,
    NF_NUMBER_STANDARD = NF_NUMBER_START,   // Standard/General
    NF_NUMBER_INT,                          // 0
    NF_NUMBER_DEC2,                         // 0.00
    NF_NUMBER_1000INT,                      // #,##0
    NF_NUMBER_1000DEC2,                     // #,##0.00
    NF_NUMBER_SYSTEM,                       // #,##0.00 or whatever is set in System Regional Settings
    NF_NUMBER_END = NF_NUMBER_SYSTEM,

    NF_SCIENTIFIC_START,
    NF_SCIENTIFIC_000E000 = NF_SCIENTIFIC_START,    // 0.00E+000
    NF_SCIENTIFIC_000E00,                           // 0.00E+00
    NF_SCIENTIFIC_END = NF_SCIENTIFIC_000E00,

    NF_PERCENT_START,
    NF_PERCENT_INT = NF_PERCENT_START,      // 0%
    NF_PERCENT_DEC2,                        // 0.00%
    NF_PERCENT_END = NF_PERCENT_DEC2,

    NF_FRACTION_START,
    NF_FRACTION_1D = NF_FRACTION_START,      // # ?/?
    NF_FRACTION_2D,                          // # ??/??
    NF_FRACTION_END = NF_FRACTION_2D,

    NF_NUMERIC_END = NF_FRACTION_END,

    NF_CURRENCY_START,
    NF_CURRENCY_1000INT = NF_CURRENCY_START,// #,##0 DM
    NF_CURRENCY_1000DEC2,                   // #,##0.00 DM
    NF_CURRENCY_1000INT_RED,                // #,##0 DM         negative in red
    NF_CURRENCY_1000DEC2_RED,               // #,##0.00 DM      negative in red
    NF_CURRENCY_1000DEC2_CCC,               // #,##0.00 DEM     currency abbreviation
    NF_CURRENCY_1000DEC2_DASHED,            // #,##0.-- DM
    NF_CURRENCY_END = NF_CURRENCY_1000DEC2_DASHED,

    NF_DATE_START,
    NF_DATE_SYSTEM_SHORT = NF_DATE_START,   // 08.10.97
    NF_DATE_SYSTEM_LONG,                    // Wednesday, 8. October 1997
    NF_DATE_SYS_DDMMYY,                     // 08.10.97
    NF_DATE_SYS_DDMMYYYY,                   // 08.10.1997                   THE edit format, formatindex="21"
    NF_DATE_SYS_DMMMYY,                     // 8. Oct 97
    NF_DATE_SYS_DMMMYYYY,                   // 8. Oct 1997
    NF_DATE_DIN_DMMMYYYY,                   // 8. Oct. 1997                 DIN
    NF_DATE_SYS_DMMMMYYYY,                  // 8. October 1997
    NF_DATE_DIN_DMMMMYYYY,                  // 8. October 1997              DIN
    NF_DATE_SYS_NNDMMMYY,                   // Wed, 8. Okt 97
    NF_DATE_DEF_NNDDMMMYY,                  // Wed 08.Okt 97
    NF_DATE_SYS_NNDMMMMYYYY,                // Wed, 8. Oktober 1997
    NF_DATE_SYS_NNNNDMMMMYYYY,              // Wednesday, 8. Oktober 1997
    NF_DATE_DIN_MMDD,                       // 10-08                        DIN
    NF_DATE_DIN_YYMMDD,                     // 97-10-08                     DIN
    NF_DATE_DIN_YYYYMMDD,                   // 1997-10-08                   DIN
    NF_DATE_ISO_YYYYMMDD = NF_DATE_DIN_YYYYMMDD, // 1997-10-08              ISO clarify with name, formatindex="33"
    NF_DATE_SYS_MMYY,                       // 10.97
    NF_DATE_SYS_DDMMM,                      // 08.Oct
    NF_DATE_MMMM,                           // October
    NF_DATE_QQJJ,                           // 4. Quarter 97
    NF_DATE_WW,                             // week of year
    NF_DATE_END = NF_DATE_WW,

    NF_TIME_START,
    NF_TIME_HHMM = NF_TIME_START,           // HH:MM
    NF_TIME_HHMMSS,                         // HH:MM:SS
    NF_TIME_HHMMAMPM,                       // HH:MM AM/PM
    NF_TIME_HHMMSSAMPM,                     // HH:MM:SS AM/PM
    NF_TIME_HH_MMSS,                        // [HH]:MM:SS                   formatindex="43"
    NF_TIME_MMSS00,                         // MM:SS,00                     formatindex="44"
    NF_TIME_HH_MMSS00,                      // [HH]:MM:SS,00                formatindex="45"
    NF_TIME_END = NF_TIME_HH_MMSS00,

    NF_DATETIME_START,
    NF_DATETIME_SYSTEM_SHORT_HHMM = NF_DATETIME_START,  // 08.10.97 01:23
    NF_DATETIME_SYS_DDMMYYYY_HHMMSS,        // 08.10.1997 01:23:45          THE edit format, formatindex="47"
    NF_DATETIME_END = NF_DATETIME_SYS_DDMMYYYY_HHMMSS,

    NF_BOOLEAN,                             // BOOLEAN
    NF_TEXT,                                // @

    NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS,    // == 50, old number of predefined entries, i18npool locale data additions start after this

    // From here on are values of new predefined and built-in formats that are
    // not in the original NumberFormatIndex.idl

    // XXX Values appended here must also get a corresponding entry in
    // svl/source/numbers/zforlist.cxx indexTable[] in the same order.

    // XXX The dialog's number format shell assumes start/end spans
    // (NF_..._START and NF_..._END above) to fill its categories with builtin
    // formats, make new formats known to svx/source/items/numfmtsh.cxx
    // SvxNumberFormatShell::FillEListWithStd_Impl(), otherwise they will not
    // be listed at all. Yes that is ugly.
    // DATETIME formats need to be added to
    // SvxNumberFormatShell::FillEListWithDateTime_Impl().

    // New predefined format added to i18npool locale data.
    NF_DATETIME_SYS_DDMMYYYY_HHMM = NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS,  // 08.10.1997 01:23  formatindex="50"

    // No i18npool defined locale data between here and NF_INDEX_TABLE_ENTRIES.
    NF_INDEX_TABLE_RESERVED_START,

    NF_FRACTION_3D = NF_INDEX_TABLE_RESERVED_START,  // # ???/???
    NF_FRACTION_2,                          // # ?/2
    NF_FRACTION_4,                          // # ?/4
    NF_FRACTION_8,                          // # ?/8
    NF_FRACTION_16,                         // # ??/16
    NF_FRACTION_10,                         // # ??/10
    NF_FRACTION_100,                        // # ??/100

    NF_DATETIME_ISO_YYYYMMDD_HHMMSS,        // 1997-10-08 01:23:45          ISO (with blank instead of T)
    NF_DATETIME_ISO_YYYYMMDD_HHMMSS000,     // 1997-10-08 01:23:45.678      not quite ISO with locale's separator
    NF_DATETIME_ISO_YYYYMMDDTHHMMSS,        // 1997-10-08T01:23:45          ISO
    NF_DATETIME_ISO_YYYYMMDDTHHMMSS000,     // 1997-10-08T01:23:45,678      ISO with milliseconds and ',' or '.'

    // XXX When adding values here, follow the comment above about
    // svx/source/items/numfmtsh.cxx

    NF_INDEX_TABLE_ENTRIES                  // == 62, reserved to not be used in i18npool locale data.

    // XXX Adding values above may increment the reserved area that can't be
    // used by i18npool's locale data FormatCode definitions, see the
    // description at i18npool/source/localedata/data/locale.dtd for ELEMENT
    // FormatCode what the current convention's value is. In that case, the
    // used formatIndex values in i18npool/source/localedata/data/*.xml will
    // have to be adjusted.
    // Overlapping the area will bail out with a check in
    // SvNumberFormatter::ImpInsertFormat() in debug builds.
};


// #45717# IsNumberFormat( "98-10-24", 30, x ), YMD Format set with DMY
// International settings doesn't recognize the string as a date.
/** enum values for <method>SvNumberFormatter::SetEvalDateFormat</method>

    <p>How <method>ImpSvNumberInputScan::GetDateRef</method> shall take the
     DateFormat order (YMD,DMY,MDY) into account, if called from IsNumberFormat
    with a date format to match against.
 */
enum NfEvalDateFormat
{
    /** DateFormat only from International, default. */
    NF_EVALDATEFORMAT_INTL,

    /** DateFormat only from date format passed to function (if any).
        If no date format is passed then the DateFormat is taken from International. */
    NF_EVALDATEFORMAT_FORMAT,

    /** First try the DateFormat from International. If it doesn't match a
         valid date try the DateFormat from the date format passed. */
    NF_EVALDATEFORMAT_INTL_FORMAT,

    /** First try the DateFormat from the date format passed. If it doesn't
        match a valid date try the DateFormat from International. */
    NF_EVALDATEFORMAT_FORMAT_INTL
};


/// This table is std::map because it needs to preserve insertion order,
/// because the formats are roughly ordered from most to least common, and some
/// parts of the UI want to show them in that order.
typedef std::map<sal_uInt32, SvNumberformat*> SvNumberFormatTable;
typedef std::unordered_map<sal_uInt16, sal_uInt32> SvNumberFormatterIndexTable;
typedef std::unordered_map< sal_uInt32, sal_uInt32> SvNumberFormatterMergeMap;


/** Language/country dependent currency entries
 */
class UNLESS_MERGELIBS(SVL_DLLPUBLIC) NfCurrencyEntry final
{
    OUString        aSymbol;            /// currency symbol
    OUString        aBankSymbol;        /// currency abbreviation
    LanguageType    eLanguage;          /// language/country value
    sal_uInt16      nPositiveFormat;    /// position of symbol
    sal_uInt16      nNegativeFormat;    /// position of symbol and type and position of negative sign
    sal_uInt16      nDigits;            /// count of decimal digits
    sal_Unicode     cZeroChar;          /// which character is used for zeros as last decimal digits

private:

                        // nDecimalFormat := 0, 1, 2
                        // #,##0 or #,##0.00 or #,##0.-- is returned
    SVL_DLLPRIVATE OUString Impl_BuildFormatStringNumChars( const LocaleDataWrapper&, sal_uInt16 nDecimalFormat) const;

public:

    NfCurrencyEntry( const LocaleDataWrapper& rLocaleData,
                     LanguageType eLang );
    NfCurrencyEntry( const css::i18n::Currency & rCurr,
                     const LocaleDataWrapper& rLocaleData,
                     LanguageType eLang );

                        /// Symbols and language identical
    bool                operator==( const NfCurrencyEntry& r ) const;

    const OUString&     GetSymbol() const           { return aSymbol; }
    const OUString&     GetBankSymbol() const       { return aBankSymbol; }
    LanguageType        GetLanguage() const         { return eLanguage; }
    sal_uInt16          GetPositiveFormat() const   { return nPositiveFormat; }
    sal_uInt16          GetNegativeFormat() const   { return nNegativeFormat; }
    sal_uInt16          GetDigits() const           { return nDigits; }

                        /** Only to resolve system locale for currency list. */
    void                SetLanguage( LanguageType nLang ) { eLanguage = nLang; }

                        /** [$DM-407] (bBank==false) or [$DEM] (bBank==true)
                            is returned. If bBank==false and
                            bWithoutExtension==true only [$DM] */
    OUString            BuildSymbolString(bool bBank, bool bWithoutExtension = false) const;

                        /** #,##0.00 [$DM-407] is returned, separators
                              from rLoc,    incl. minus sign but without [RED] */
    OUString            BuildPositiveFormatString(bool bBank, const LocaleDataWrapper&,
                                                  sal_uInt16 nDecimalFormat = 1) const;
    OUString            BuildNegativeFormatString(bool bBank, const LocaleDataWrapper&,
                                                  sal_uInt16 nDecimalFormat = 1) const;

                        /** [$DM-407] (or [$DEM] if bBank==true)
                            is appended/prepended to rStr, incl. minus sign */
    void                CompletePositiveFormatString(OUStringBuffer& rStr, bool bBank,
                                                     sal_uInt16 nPosiFormat) const;
    void                CompleteNegativeFormatString(OUStringBuffer& rStr, bool bBank,
                                                     sal_uInt16 nNegaFormat) const;

                        /// rSymStr is appended/prepended to rStr, incl. minus sign
    static  void        CompletePositiveFormatString(OUStringBuffer& rStr,
                                                     std::u16string_view rSymStr, sal_uInt16 nPosiFormat);
    static  void        CompleteNegativeFormatString(OUStringBuffer& rStr,
                                                     std::u16string_view rSymStr, sal_uInt16 nNegaFormat);

                        /** Representation of a currency (symbol position and
                             negative sign) in other locales */
    static  sal_uInt16  GetEffectivePositiveFormat( sal_uInt16 nIntlFormat,
                                                    sal_uInt16 nCurrFormat, bool bBank );
    static  sal_uInt16  GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat,
                                                    sal_uInt16 nCurrFormat, bool bBank );

    /// General Unicode Euro symbol
    static sal_Unicode   GetEuroSymbol() { return u'\x20AC'; }
};

typedef std::vector< OUString > NfWSStringsDtor;

/** Input options to be used with IsNumberFormat() */
enum class SvNumInputOptions : sal_uInt16
{
    NONE = 0,
    LAX_TIME = 1    ///< allow input of minutes or seconds >59
};
namespace o3tl {
    template<> struct typed_flags<SvNumInputOptions> : is_typed_flags<SvNumInputOptions, 0x0001> {};
}


#endif // INCLUDED_SVL_ZFORLIST_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */