/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: */ |