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