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