1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_UNOTOOLS_LOCALEDATAWRAPPER_HXX
21 #define INCLUDED_UNOTOOLS_LOCALEDATAWRAPPER_HXX
23 #include <com/sun/star/i18n/XLocaleData4.hpp>
24 #include <com/sun/star/i18n/LocaleItem.hpp>
25 #include <com/sun/star/i18n/reservedWords.hpp>
26 #include <rtl/ustring.hxx>
27 #include <i18nlangtag/languagetag.hxx>
28 #include <unotools/readwritemutexguard.hxx>
29 #include <unotools/unotoolsdllapi.h>
33 namespace com
{ namespace sun
{ namespace star
{
35 class XComponentContext
;
39 namespace tools
{ class Time
; }
40 class CalendarWrapper
;
48 enum MeasurementSystem
{
53 class UNOTOOLS_DLLPUBLIC LocaleDataWrapper
55 static sal_uInt8 nLocaleDataChecking
; // 0:=dontknow, 1:=yes, 2:=no
57 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
58 css::uno::Reference
< css::i18n::XLocaleData4
> xLD
;
59 LanguageTag maLanguageTag
;
60 std::shared_ptr
< css::i18n::Calendar2
> xDefaultCalendar
;
61 std::shared_ptr
< css::i18n::Calendar2
> xSecondaryCalendar
;
62 css::i18n::LocaleDataItem aLocaleDataItem
;
63 css::uno::Sequence
< OUString
> aReservedWordSeq
;
64 css::uno::Sequence
< OUString
> aDateAcceptancePatterns
;
65 css::uno::Sequence
< sal_Int32
> aGrouping
;
67 OUString aLocaleItem
[css::i18n::LocaleItem::COUNT
];
68 OUString aReservedWord
[css::i18n::reservedWords::COUNT
];
70 OUString aCurrBankSymbol
;
73 sal_uInt16 nCurrPositiveFormat
;
74 sal_uInt16 nCurrNegativeFormat
;
75 sal_uInt16 nCurrDigits
;
76 bool bLocaleDataItemValid
;
77 bool bReservedWordValid
;
78 bool bSecondaryCalendarValid
;
79 mutable ::utl::ReadWriteMutex aMutex
;
82 bool operator()(const css::lang::Locale
& rLocale1
, const css::lang::Locale
& rLocale2
) const;
84 mutable std::map
<css::lang::Locale
, css::i18n::LocaleDataItem
, Locale_Compare
> maDataItemCache
;
86 // dummies, to be implemented or provided by XML locale data
87 sal_Unicode cCurrZeroChar
;
89 // whenever Locale changes
90 void invalidateData();
92 void getOneLocaleItemImpl( sal_Int16 nItem
);
93 const OUString
& getOneLocaleItem( sal_Int16 nItem
) const;
95 void getOneReservedWordImpl( sal_Int16 nWord
);
96 const OUString
& getOneReservedWord( sal_Int16 nWord
) const;
98 void getCurrSymbolsImpl();
99 void getCurrFormatsImpl();
101 void scanCurrFormatImpl( const OUString
& rCode
,
102 sal_Int32 nStart
, sal_Int32
& nSign
,
103 sal_Int32
& nPar
, sal_Int32
& nNum
,
104 sal_Int32
& nBlank
, sal_Int32
& nSym
);
106 void getDateFormatsImpl();
107 DateFormat
scanDateFormatImpl( const OUString
& rCode
);
109 void getDefaultCalendarImpl();
110 void getSecondaryCalendarImpl();
112 sal_Unicode
* ImplAddFormatNum( sal_Unicode
* pBuf
,
113 sal_Int64 nNumber
, sal_uInt16 nDecimals
,
114 bool bUseThousandSep
, bool bTrailingZeros
) const;
116 void getDigitGroupingImpl();
120 const css::uno::Reference
< css::uno::XComponentContext
> & rxContext
,
121 const LanguageTag
& rLanguageTag
124 const LanguageTag
& rLanguageTag
126 ~LocaleDataWrapper();
128 /** Get the service factory, meant to be able to create a CalendarWrapper
129 from a LocaleDataWrapper. Note that the service factory may be
130 non-existent if this LocaleDataWrapper was created without one and
131 lives "on the grassland". The CalendarWrapper ctor can handle that
133 const css::uno::Reference
<
134 css::uno::XComponentContext
> & getComponentContext()
135 const { return m_xContext
; }
137 /// set a new Locale to request
138 void setLanguageTag( const LanguageTag
& rLanguageTag
);
140 /// get current requested Locale
141 const LanguageTag
& getLanguageTag() const;
143 /// get current loaded Locale, which might differ from the requested Locale
144 LanguageTag
getLoadedLanguageTag() const;
146 // Wrapper implementations of service LocaleData
148 css::i18n::LanguageCountryInfo
getLanguageCountryInfo() const;
149 const css::i18n::LocaleDataItem
& getLocaleItem() const;
150 /// NOTE: this wraps XLocaleData3::getAllCalendars2() in fact.
151 css::uno::Sequence
< css::i18n::Calendar2
> getAllCalendars() const;
152 /// NOTE: this wraps XLocaleData2::getAllCurrencies2() in fact.
153 css::uno::Sequence
< css::i18n::Currency2
> getAllCurrencies() const;
154 css::uno::Sequence
< css::i18n::FormatElement
> getAllFormats() const;
155 css::i18n::ForbiddenCharacters
getForbiddenCharacters() const;
156 css::uno::Sequence
< OUString
> getReservedWord() const;
157 css::uno::Sequence
< css::lang::Locale
> getAllInstalledLocaleNames() const;
158 css::uno::Sequence
< OUString
> getDateAcceptancePatterns() const;
160 /** Override locale's date acceptance patterns.
161 An empty sequence resets the patterns to the locale's pattern sequence.
163 void setDateAcceptancePatterns( const css::uno::Sequence
< OUString
> & rPatterns
);
165 /// same as the wrapper implementation but static
166 static css::uno::Sequence
< css::lang::Locale
> getInstalledLocaleNames();
168 /** Get LanguageTypes for all installed locales which are unambiguous
169 convertible back and forth between locale ISO strings and MS-LCID
170 LanguageType. Upon the first time the function is called when
171 locale data checking is enabled, messages are shown for locales not
172 matching, excluding already known problems.
173 (e.g. used in number formatter dialog init)
175 static css::uno::Sequence
< sal_uInt16
> getInstalledLanguageTypes();
177 /// maps the LocaleData string to the International enum
178 MeasurementSystem
mapMeasurementStringToEnum( const OUString
& rMS
) const;
180 /// Convenience method to obtain the default calendar.
181 const std::shared_ptr
< css::i18n::Calendar2
>& getDefaultCalendar() const;
183 /// Convenience method to obtain the day names of the default calendar.
184 const css::uno::Sequence
< css::i18n::CalendarItem2
> getDefaultCalendarDays() const;
186 /// Convenience method to obtain the month names of the default calendar.
187 const css::uno::Sequence
< css::i18n::CalendarItem2
> getDefaultCalendarMonths() const;
189 /** If the secondary calendar, if any, is of the name passed AND number
190 formats using it usually use the E or EE keyword (EC|EEC). */
191 bool doesSecondaryCalendarUseEC( const OUString
& rName
) const;
193 /** Obtain digit grouping. The usually known grouping by thousands (#,###)
194 is actually only one of possible groupings. Another one, for example,
195 used in India is group by 3 and then by 2 indefinitely (#,##,###). The
196 integer sequence returned here specifies grouping from right to left
197 (!), with a 0 entry designating the end of rules and the previous value
198 to be repeated indefinitely. Hence the sequence {3,0} specifies the
199 usual grouping by thousands, whereas the sequence {3,2,0} specifies
200 Indian grouping. The sal_Int32* getConstArray() can be passed directly
201 to the ::rtl::math::doubleToString() methods as argument for the
202 pGroups parameter. */
203 const css::uno::Sequence
< sal_Int32
> getDigitGrouping() const;
205 // Functionality of class International methods, LocaleItem
207 const OUString
& getDateSep() const
208 { return getOneLocaleItem( css::i18n::LocaleItem::DATE_SEPARATOR
); }
209 const OUString
& getNumThousandSep() const
210 { return getOneLocaleItem( css::i18n::LocaleItem::THOUSAND_SEPARATOR
); }
211 const OUString
& getNumDecimalSep() const
212 { return getOneLocaleItem( css::i18n::LocaleItem::DECIMAL_SEPARATOR
); }
213 const OUString
& getTimeSep() const
214 { return getOneLocaleItem( css::i18n::LocaleItem::TIME_SEPARATOR
); }
215 const OUString
& getTime100SecSep() const
216 { return getOneLocaleItem( css::i18n::LocaleItem::TIME_100SEC_SEPARATOR
); }
217 const OUString
& getListSep() const
218 { return getOneLocaleItem( css::i18n::LocaleItem::LIST_SEPARATOR
); }
219 const OUString
& getQuotationMarkStart() const
220 { return getOneLocaleItem( css::i18n::LocaleItem::SINGLE_QUOTATION_START
); }
221 const OUString
& getQuotationMarkEnd() const
222 { return getOneLocaleItem( css::i18n::LocaleItem::SINGLE_QUOTATION_END
); }
223 const OUString
& getDoubleQuotationMarkStart() const
224 { return getOneLocaleItem( css::i18n::LocaleItem::DOUBLE_QUOTATION_START
); }
225 const OUString
& getDoubleQuotationMarkEnd() const
226 { return getOneLocaleItem( css::i18n::LocaleItem::DOUBLE_QUOTATION_END
); }
227 MeasurementSystem
getMeasurementSystemEnum() const
228 { return mapMeasurementStringToEnum( getOneLocaleItem( css::i18n::LocaleItem::MEASUREMENT_SYSTEM
) ); }
229 const OUString
& getTimeAM() const
230 { return getOneLocaleItem( css::i18n::LocaleItem::TIME_AM
); }
231 const OUString
& getTimePM() const
232 { return getOneLocaleItem( css::i18n::LocaleItem::TIME_PM
); }
233 const OUString
& getLongDateDayOfWeekSep() const
234 { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_DAY_OF_WEEK_SEPARATOR
); }
235 const OUString
& getLongDateDaySep() const
236 { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_DAY_SEPARATOR
); }
237 const OUString
& getLongDateMonthSep() const
238 { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_MONTH_SEPARATOR
); }
239 const OUString
& getLongDateYearSep() const
240 { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_YEAR_SEPARATOR
); }
243 const OUString
& getCurrSymbol() const;
244 const OUString
& getCurrBankSymbol() const;
245 sal_uInt16
getCurrPositiveFormat() const;
246 sal_uInt16
getCurrNegativeFormat() const;
247 sal_uInt16
getCurrDigits() const;
249 // simple date and time formatting
250 DateFormat
getDateFormat() const;
251 DateFormat
getLongDateFormat() const;
252 /// only numerical values of Gregorian calendar
253 OUString
getDate( const Date
& rDate
) const;
254 OUString
getTime( const tools::Time
& rTime
, bool bSec
= true,
255 bool b100Sec
= false ) const;
256 OUString
getDuration( const tools::Time
& rTime
,
257 bool bSec
= true, bool b100Sec
= false ) const;
259 /** The CalendarWrapper already <b>MUST</b>
260 have loaded a calendar.
262 <FALSE/> := full year
263 <TRUE/> := year % 100
265 OUString
getLongDate( const Date
& rDate
,
266 CalendarWrapper
& rCal
,
270 /** Simple number formatting
272 value * 10**nDecimals
273 @param bTrailingZeros
274 </sal_True> := always display trailing zeros in
275 decimal places, even if integer value.
276 </sal_False> := trailing zeros are only displayed
277 if the value is not an integer value.
279 OUString
getNum( sal_Int64 nNumber
, sal_uInt16 nDecimals
,
280 bool bUseThousandSep
= true,
281 bool bTrailingZeros
= true ) const;
283 /// "Secure" currency formatted string.
284 OUString
getCurr( sal_Int64 nNumber
, sal_uInt16 nDecimals
,
285 const OUString
& rCurrencySymbol
,
286 bool bUseThousandSep
= true ) const;
288 // dummy returns, to be implemented
289 inline sal_Unicode
getCurrZeroChar() const
290 { return cCurrZeroChar
; }
291 static inline bool isNumLeadingZero()
293 /// standard decimal places
294 static inline sal_uInt16
getNumDigits()
296 static inline bool isNumTrailingZeros()
301 const OUString
& getTrueWord() const
302 { return getOneReservedWord( css::i18n::reservedWords::TRUE_WORD
); }
303 const OUString
& getFalseWord() const
304 { return getOneReservedWord( css::i18n::reservedWords::FALSE_WORD
); }
305 const OUString
& getAboveWord() const
306 { return getOneReservedWord( css::i18n::reservedWords::ABOVE_WORD
); }
307 const OUString
& getBelowWord() const
308 { return getOneReservedWord( css::i18n::reservedWords::BELOW_WORD
); }
309 /// return a quarter abbreviation string matching nQuarter (0..3) => "Q1" .. "Q2"
310 const OUString
& getQuarterAbbreviation( sal_Int16 nQuarter
) const
311 { return getOneReservedWord( css::i18n::reservedWords::QUARTER1_ABBREVIATION
+ nQuarter
); }
313 /** Return whether locale data checks are enabled.
314 Checks are enabled if the environment variable
315 OOO_ENABLE_LOCALE_DATA_CHECKS is set to 'Y' or 'Yes' (or any other
316 string starting with 'Y') or '1'.
317 Also used in conjunction with the number formatter. */
318 static inline bool areChecksEnabled()
320 if (nLocaleDataChecking
== 0)
321 evaluateLocaleDataChecking();
322 return nLocaleDataChecking
== 1;
325 /** Append locale info to string, used with locale data checking.
326 A string similar to "de_DE requested\n en_US loaded" is appended. */
327 OUString
appendLocaleInfo(const OUString
& rDebugMsg
) const;
329 /** Ouput a message during locale data checking. The (UTF-8) string is
330 written to stderr and in a non-product build or if DBG_UTIL is enabled
331 also raised as an assertion message box. */
332 static void outputCheckMessage( const OUString
& rMsg
);
333 static void outputCheckMessage( const char* pStr
);
335 LocaleDataWrapper(const LocaleDataWrapper
&) = delete;
336 LocaleDataWrapper
& operator=(const LocaleDataWrapper
&) = delete;
340 const css::lang::Locale
& getMyLocale() const;
342 static void evaluateLocaleDataChecking();
345 #endif // INCLUDED_UNOTOOLS_LOCALEDATAWRAPPER_HXX
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */