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