Line data Source code
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 :
20 : #ifndef INCLUDED_UNOTOOLS_LOCALEDATAWRAPPER_HXX
21 : #define INCLUDED_UNOTOOLS_LOCALEDATAWRAPPER_HXX
22 :
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>
30 : #include <memory>
31 :
32 : namespace com { namespace sun { namespace star {
33 : namespace uno {
34 : class XComponentContext;
35 : }
36 : }}}
37 : class Date;
38 : namespace tools { class Time; }
39 : class CalendarWrapper;
40 :
41 : enum DateFormat {
42 : MDY,
43 : DMY,
44 : YMD
45 : };
46 :
47 : enum MeasurementSystem {
48 : MEASURE_METRIC,
49 : MEASURE_US
50 : };
51 :
52 : class UNOTOOLS_DLLPUBLIC LocaleDataWrapper
53 : {
54 : static sal_uInt8 nLocaleDataChecking; // 0:=dontknow, 1:=yes, 2:=no
55 :
56 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext;
57 : ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XLocaleData4 > xLD;
58 : LanguageTag maLanguageTag;
59 : std::shared_ptr< ::com::sun::star::i18n::Calendar2 > xDefaultCalendar;
60 : ::com::sun::star::i18n::LocaleDataItem aLocaleDataItem;
61 : ::com::sun::star::uno::Sequence< OUString > aReservedWordSeq;
62 : ::com::sun::star::uno::Sequence< OUString > aDateAcceptancePatterns;
63 : ::com::sun::star::uno::Sequence< sal_Int32 > aGrouping;
64 : // cached items
65 : OUString aLocaleItem[::com::sun::star::i18n::LocaleItem::COUNT];
66 : OUString aReservedWord[::com::sun::star::i18n::reservedWords::COUNT];
67 : OUString aCurrSymbol;
68 : OUString aCurrBankSymbol;
69 : int nDateFormat;
70 : int nLongDateFormat;
71 : sal_uInt16 nCurrPositiveFormat;
72 : sal_uInt16 nCurrNegativeFormat;
73 : sal_uInt16 nCurrDigits;
74 : bool bLocaleDataItemValid;
75 : bool bReservedWordValid;
76 : mutable ::utl::ReadWriteMutex aMutex;
77 :
78 : // dummies, to be implemented or provided by XML locale data
79 : sal_Unicode cCurrZeroChar;
80 :
81 : // whenever Locale changes
82 : void invalidateData();
83 :
84 : void getOneLocaleItemImpl( sal_Int16 nItem );
85 : const OUString& getOneLocaleItem( sal_Int16 nItem ) const;
86 :
87 : void getOneReservedWordImpl( sal_Int16 nWord );
88 : const OUString& getOneReservedWord( sal_Int16 nWord ) const;
89 :
90 : void getCurrSymbolsImpl();
91 : void getCurrFormatsImpl();
92 :
93 : void scanCurrFormatImpl( const OUString& rCode,
94 : sal_Int32 nStart, sal_Int32& nSign,
95 : sal_Int32& nPar, sal_Int32& nNum,
96 : sal_Int32& nBlank, sal_Int32& nSym );
97 :
98 : void getDateFormatsImpl();
99 : DateFormat scanDateFormatImpl( const OUString& rCode );
100 :
101 : void getDefaultCalendarImpl();
102 :
103 : sal_Unicode* ImplAddFormatNum( sal_Unicode* pBuf,
104 : sal_Int64 nNumber, sal_uInt16 nDecimals,
105 : bool bUseThousandSep, bool bTrailingZeros ) const;
106 :
107 : void getDigitGroupingImpl();
108 :
109 : public:
110 : LocaleDataWrapper(
111 : const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & rxContext,
112 : const LanguageTag& rLanguageTag
113 : );
114 : LocaleDataWrapper(
115 : const LanguageTag& rLanguageTag
116 : );
117 : ~LocaleDataWrapper();
118 :
119 : /** Get the service factory, meant to be able to create a CalendarWrapper
120 : from a LocaleDataWrapper. Note that the service factory may be
121 : non-existent if this LocaleDataWrapper was created without one and
122 : lives "on the grassland". The CalendarWrapper ctor can handle that
123 : though. */
124 : const ::com::sun::star::uno::Reference<
125 0 : ::com::sun::star::uno::XComponentContext > & getComponentContext()
126 0 : const { return m_xContext; }
127 :
128 : /// set a new Locale to request
129 : void setLanguageTag( const LanguageTag& rLanguageTag );
130 :
131 : /// get current requested Locale
132 : const LanguageTag& getLanguageTag() const;
133 :
134 : /// get current loaded Locale, which might differ from the requested Locale
135 : LanguageTag getLoadedLanguageTag() const;
136 :
137 : // Wrapper implementations of service LocaleData
138 :
139 : ::com::sun::star::i18n::LanguageCountryInfo getLanguageCountryInfo() const;
140 : ::com::sun::star::i18n::LocaleDataItem getLocaleItem() const;
141 : /// NOTE: this wraps XLocaleData3::getAllCalendars2() in fact.
142 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar2 > getAllCalendars() const;
143 : /// NOTE: this wraps XLocaleData2::getAllCurrencies2() in fact.
144 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > getAllCurrencies() const;
145 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement > getAllFormats() const;
146 : ::com::sun::star::i18n::ForbiddenCharacters getForbiddenCharacters() const;
147 : ::com::sun::star::uno::Sequence< OUString > getReservedWord() const;
148 : ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getAllInstalledLocaleNames() const;
149 : ::com::sun::star::uno::Sequence< OUString > getDateAcceptancePatterns() const;
150 :
151 : /** Override locale's date acceptance patterns.
152 : An empty sequence resets the patterns to the locale's pattern sequence.
153 : */
154 : void setDateAcceptancePatterns( const ::com::sun::star::uno::Sequence< OUString > & rPatterns );
155 :
156 : /// same as the wrapper implementation but static
157 : static ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getInstalledLocaleNames();
158 :
159 : /** Get LanguageTypes for all installed locales which are unambiguous
160 : convertible back and forth between locale ISO strings and MS-LCID
161 : LanguageType. Upon the first time the function is called when
162 : locale data checking is enabled, messages are shown for locales not
163 : matching, excluding already known problems.
164 : (e.g. used in number formatter dialog init)
165 : */
166 : static ::com::sun::star::uno::Sequence< sal_uInt16 > getInstalledLanguageTypes();
167 :
168 : /// maps the LocaleData string to the International enum
169 : MeasurementSystem mapMeasurementStringToEnum( const OUString& rMS ) const;
170 :
171 : /// Convenience method to obtain the default calendar.
172 : const std::shared_ptr< ::com::sun::star::i18n::Calendar2 > getDefaultCalendar() const;
173 :
174 : /// Convenience method to obtain the day names of the default calendar.
175 : const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > getDefaultCalendarDays() const;
176 :
177 : /// Convenience method to obtain the month names of the default calendar.
178 : const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > getDefaultCalendarMonths() const;
179 :
180 : /** Obtain digit grouping. The usually known grouping by thousands (#,###)
181 : is actually only one of possible groupings. Another one, for example,
182 : used in India is group by 3 and then by 2 indefinitely (#,##,###). The
183 : integer sequence returned here specifies grouping from right to left
184 : (!), with a 0 entry designating the end of rules and the previous value
185 : to be repeated indefinitely. Hence the sequence {3,0} specifies the
186 : usual grouping by thousands, whereas the sequence {3,2,0} specifies
187 : Indian grouping. The sal_Int32* getConstArray() can be passed directly
188 : to the ::rtl::math::doubleToString() methods as argument for the
189 : pGroups parameter. */
190 : const ::com::sun::star::uno::Sequence< sal_Int32 > getDigitGrouping() const;
191 :
192 : // Functionality of class International methods, LocaleItem
193 :
194 22083 : const OUString& getDateSep() const
195 22083 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DATE_SEPARATOR ); }
196 163947 : const OUString& getNumThousandSep() const
197 163947 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::THOUSAND_SEPARATOR ); }
198 224049 : const OUString& getNumDecimalSep() const
199 224049 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DECIMAL_SEPARATOR ); }
200 1525319 : const OUString& getTimeSep() const
201 1525319 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_SEPARATOR ); }
202 2318650 : const OUString& getTime100SecSep() const
203 2318650 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_100SEC_SEPARATOR ); }
204 54 : const OUString& getListSep() const
205 54 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LIST_SEPARATOR ); }
206 0 : const OUString& getQuotationMarkStart() const
207 0 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::SINGLE_QUOTATION_START ); }
208 85382539 : const OUString& getQuotationMarkEnd() const
209 85382539 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::SINGLE_QUOTATION_END ); }
210 0 : const OUString& getDoubleQuotationMarkStart() const
211 0 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DOUBLE_QUOTATION_START ); }
212 0 : const OUString& getDoubleQuotationMarkEnd() const
213 0 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DOUBLE_QUOTATION_END ); }
214 : const OUString& getMeasurementSystem() const
215 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::MEASUREMENT_SYSTEM ); }
216 79300 : MeasurementSystem getMeasurementSystemEnum() const
217 79300 : { return mapMeasurementStringToEnum( getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::MEASUREMENT_SYSTEM ) ); }
218 858 : const OUString& getTimeAM() const
219 858 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_AM ); }
220 844 : const OUString& getTimePM() const
221 844 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_PM ); }
222 482 : const OUString& getLongDateDayOfWeekSep() const
223 482 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_DAY_OF_WEEK_SEPARATOR ); }
224 39 : const OUString& getLongDateDaySep() const
225 39 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_DAY_SEPARATOR ); }
226 477 : const OUString& getLongDateMonthSep() const
227 477 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_MONTH_SEPARATOR ); }
228 0 : const OUString& getLongDateYearSep() const
229 0 : { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_YEAR_SEPARATOR ); }
230 :
231 : // currency
232 : const OUString& getCurrSymbol() const;
233 : const OUString& getCurrBankSymbol() const;
234 : sal_uInt16 getCurrPositiveFormat() const;
235 : sal_uInt16 getCurrNegativeFormat() const;
236 : sal_uInt16 getCurrDigits() const;
237 :
238 : // simple date and time formatting
239 : DateFormat getDateFormat() const;
240 : DateFormat getLongDateFormat() const;
241 : /// only numerical values of Gregorian calendar
242 : OUString getDate( const Date& rDate ) const;
243 : OUString getTime( const tools::Time& rTime, bool bSec = true,
244 : bool b100Sec = false ) const;
245 : OUString getDuration( const tools::Time& rTime,
246 : bool bSec = true, bool b100Sec = false ) const;
247 :
248 : /** The CalendarWrapper already <b>MUST</b>
249 : have loaded a calendar.
250 : @param nDisplayDayOfWeek
251 : 0 := abbreviated name
252 : 1 := full name
253 : @param bDayOfMonthWithLeadingZero
254 : <FALSE/> := without leading zero
255 : <TRUE/> := with leading zero if <10
256 : @param nDisplayMonth
257 : 0 := abbreviated name
258 : 1 := full name
259 : @param bTwoDigitYear
260 : <FALSE/> := full year
261 : <TRUE/> := year % 100
262 : */
263 : OUString getLongDate( const Date& rDate,
264 : CalendarWrapper& rCal,
265 : sal_Int16 nDisplayDayOfWeek = 1,
266 : bool bDayOfMonthWithLeadingZero = false,
267 : sal_Int16 nDisplayMonth = 1,
268 : bool bTwoDigitYear = false
269 : ) const;
270 :
271 : /** Simple number formatting
272 : @param nNumber
273 : value * 10**nDecimals
274 : @param bTrailingZeros
275 : </sal_True> := always display trailing zeros in
276 : decimal places, even if integer value.
277 : </sal_False> := trailing zeros are only displayed
278 : if the value is not an integer value.
279 : */
280 : OUString getNum( sal_Int64 nNumber, sal_uInt16 nDecimals,
281 : bool bUseThousandSep = true,
282 : bool bTrailingZeros = true ) const;
283 :
284 : /// "Secure" currency formatted string.
285 : OUString getCurr( sal_Int64 nNumber, sal_uInt16 nDecimals,
286 : const OUString& rCurrencySymbol,
287 : bool bUseThousandSep = true ) const;
288 : /** Default currency formatted string, use with
289 : care as default currency may change in any
290 : locale, for example, DEM -> EUR */
291 : OUString getCurr( sal_Int64 nNumber, sal_uInt16 nDecimals,
292 : bool bUseThousandSep = true ) const
293 : { return getCurr( nNumber, nDecimals,
294 : getCurrSymbol(), bUseThousandSep ); }
295 :
296 : // dummy returns, to be implemented
297 14964 : inline sal_Unicode getCurrZeroChar() const
298 14964 : { return cCurrZeroChar; }
299 23805 : static inline bool isNumLeadingZero()
300 23805 : { return true; }
301 : /// standard decimal places
302 0 : static inline sal_uInt16 getNumDigits()
303 0 : { return 2; }
304 117 : static inline bool isNumTrailingZeros()
305 117 : { return true; }
306 :
307 : // reserved words
308 :
309 17752 : const OUString& getTrueWord() const
310 17752 : { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::TRUE_WORD ); }
311 17745 : const OUString& getFalseWord() const
312 17745 : { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::FALSE_WORD ); }
313 : /// return a quarter string matching nQuarter (0..3) => "1st quarter" .. "4th quarter"
314 : const OUString& getQuarterWord( sal_Int16 nQuarter ) const
315 : { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::QUARTER1_WORD + nQuarter ); }
316 0 : const OUString& getAboveWord() const
317 0 : { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::ABOVE_WORD ); }
318 2 : const OUString& getBelowWord() const
319 2 : { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::BELOW_WORD ); }
320 : /// return a quarter abbreviation string matching nQuarter (0..3) => "Q1" .. "Q2"
321 12 : const OUString& getQuarterAbbreviation( sal_Int16 nQuarter ) const
322 12 : { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::QUARTER1_ABBREVIATION + nQuarter ); }
323 :
324 : /** Return whether locale data checks are enabled.
325 : Checks are enabled if the environment variable
326 : OOO_ENABLE_LOCALE_DATA_CHECKS is set to 'Y' or 'Yes' (or any other
327 : string starting with 'Y') or '1'.
328 : Also used in conjunction with the number formatter. */
329 75697 : static inline bool areChecksEnabled()
330 : {
331 75697 : if (nLocaleDataChecking == 0)
332 119 : evaluateLocaleDataChecking();
333 75697 : return nLocaleDataChecking == 1;
334 : }
335 :
336 : /** Append locale info to string, used with locale data checking.
337 : A string similar to "de_DE requested\n en_US loaded" is appended. */
338 : OUString appendLocaleInfo(const OUString& rDebugMsg) const;
339 :
340 : /** Ouput a message during locale data checking. The (UTF-8) string is
341 : written to stderr and in a non-product build or if DBG_UTIL is enabled
342 : also raised as an assertion message box. */
343 : static void outputCheckMessage( const OUString& rMsg );
344 : static void outputCheckMessage( const char* pStr);
345 :
346 : LocaleDataWrapper(const LocaleDataWrapper&) SAL_DELETED_FUNCTION;
347 : LocaleDataWrapper& operator=(const LocaleDataWrapper&) SAL_DELETED_FUNCTION;
348 :
349 : private:
350 :
351 : const ::com::sun::star::lang::Locale & getMyLocale() const;
352 :
353 : static void evaluateLocaleDataChecking();
354 : };
355 :
356 : #endif // INCLUDED_UNOTOOLS_LOCALEDATAWRAPPER_HXX
357 :
358 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|