xref: /AOO41X/main/unotools/inc/unotools/localedatawrapper.hxx (revision bae3752ec30c258ca902793e4eea3c818b0bcaad)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _UNOTOOLS_LOCALEDATAWRAPPER_HXX
25 #define _UNOTOOLS_LOCALEDATAWRAPPER_HXX
26 
27 #include <tools/string.hxx>
28 #include <com/sun/star/i18n/XLocaleData2.hpp>
29 #include <com/sun/star/i18n/LocaleItem.hpp>
30 #include <com/sun/star/i18n/reservedWords.hpp>
31 #include <unotools/readwritemutexguard.hxx>
32 #include "unotools/unotoolsdllapi.h"
33 
34 #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
35 #include <boost/shared_ptr.hpp>
36 #endif
37 
38 
39 namespace com { namespace sun { namespace star {
40     namespace lang {
41         class XMultiServiceFactory;
42     }
43 }}}
44 class Date;
45 class Time;
46 class CalendarWrapper;
47 
48 
49 enum DateFormat {
50     MDY,
51     DMY,
52     YMD
53 };
54 
55 
56 enum MeasurementSystem {
57     MEASURE_METRIC,
58     MEASURE_US
59 };
60 
61 
62 class UNOTOOLS_DLLPUBLIC LocaleDataWrapper
63 {
64     static  sal_uInt8                nLocaleDataChecking;    // 0:=dontknow, 1:=yes, 2:=no
65 
66     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >    xSMgr;
67     ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XLocaleData2 >            xLD;
68     ::com::sun::star::lang::Locale                                                      aLocale;
69     ::boost::shared_ptr< ::com::sun::star::i18n::Calendar >                             xDefaultCalendar;
70     ::com::sun::star::i18n::LocaleDataItem                                              aLocaleDataItem;
71     ::com::sun::star::uno::Sequence< ::rtl::OUString >                                  aReservedWordSeq;
72     ::com::sun::star::uno::Sequence< sal_Int32 >                                        aGrouping;
73     // cached items
74     String                      aLocaleItem[::com::sun::star::i18n::LocaleItem::COUNT];
75     String                      aReservedWord[::com::sun::star::i18n::reservedWords::COUNT];
76     String                      aCurrSymbol;
77     String                      aCurrBankSymbol;
78     int                         nDateFormat;
79     int                         nLongDateFormat;
80     sal_uInt16                      nCurrPositiveFormat;
81     sal_uInt16                      nCurrNegativeFormat;
82     sal_uInt16                      nCurrDigits;
83     sal_Bool                        bLocaleDataItemValid;
84     sal_Bool                        bReservedWordValid;
85     mutable ::utl::ReadWriteMutex   aMutex;
86 
87     // dummies, to be implemented or provided by XML locale data
88     sal_Unicode                 cCurrZeroChar;
89 
90 
91                                 // not implemented, prevent usage
92                                 LocaleDataWrapper( const LocaleDataWrapper& );
93             LocaleDataWrapper&  operator=( const LocaleDataWrapper& );
94 
95                                 // whenever Locale changes
96             void                invalidateData();
97 
98             void                getOneLocaleItemImpl( sal_Int16 nItem );
99             const String&       getOneLocaleItem( sal_Int16 nItem ) const;
100 
101             void                getOneReservedWordImpl( sal_Int16 nWord );
102             const String&       getOneReservedWord( sal_Int16 nWord ) const;
103 
104             void                getCurrSymbolsImpl();
105             void                getCurrFormatsImpl();
106 
107             void                scanCurrFormatImpl( const String& rCode,
108                                     xub_StrLen nStart, xub_StrLen& nSign,
109                                     xub_StrLen& nPar, xub_StrLen& nNum,
110                                     xub_StrLen& nBlank, xub_StrLen& nSym );
111 
112             void                getDateFormatsImpl();
113             DateFormat          scanDateFormatImpl( const String& rCode );
114 
115             void                getDefaultCalendarImpl();
116 
117             sal_Unicode*        ImplAddFormatNum( sal_Unicode* pBuf,
118                                     sal_Int64 nNumber, sal_uInt16 nDecimals,
119                                     sal_Bool bUseThousandSep, sal_Bool bTrailingZeros ) const;
120 
121             void                getDigitGroupingImpl();
122 
123 public:
124                                 LocaleDataWrapper(
125                                     const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF,
126                                     const ::com::sun::star::lang::Locale& rLocale
127                                     );
128                                 ~LocaleDataWrapper();
129 
130     /** Get the service factory, meant to be able to create a CalendarWrapper
131         from a LocaleDataWrapper. Note that the service factory may be
132         non-existent if this LocaleDataWrapper was created without one and
133         lives "on the grassland". The CalendarWrapper ctor can handle that
134         though. */
135     const ::com::sun::star::uno::Reference<
getServiceFactory() const136         ::com::sun::star::lang::XMultiServiceFactory > & getServiceFactory()
137         const { return xSMgr; }
138 
139     /// set a new Locale to request
140             void                setLocale( const ::com::sun::star::lang::Locale& rLocale );
141 
142     /// get current requested Locale
143     const ::com::sun::star::lang::Locale& getLocale() const;
144 
145     /// get current loaded Locale, which might differ from the requested Locale
146     ::com::sun::star::lang::Locale getLoadedLocale() const;
147 
148 
149     // Wrapper implementations of service LocaleData
150 
151     ::com::sun::star::i18n::LanguageCountryInfo getLanguageCountryInfo() const;
152     ::com::sun::star::i18n::LocaleDataItem getLocaleItem() const;
153     ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar > getAllCalendars() const;
154     /// NOTE: this wraps XLocaleData2::getAllCurrencies2() in fact.
155     ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > getAllCurrencies() const;
156     ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement > getAllFormats() const;
157     ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Implementation > getCollatorImplementations() const;
158     ::com::sun::star::uno::Sequence< ::rtl::OUString > getTransliterations() const;
159     ::com::sun::star::i18n::ForbiddenCharacters getForbiddenCharacters() const;
160     ::com::sun::star::uno::Sequence< ::rtl::OUString > getReservedWord() const;
161     ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getAllInstalledLocaleNames() const;
162 
163     /// same as the wrapper implementation but static
164     static ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getInstalledLocaleNames();
165 
166     /** Get LanguageTypes for all installed locales which are unambiguous
167         convertible back and forth between locale ISO strings and MS-LCID
168         LanguageType. Upon the first time the function is called when
169         locale data checking is enabled, messages are shown for locales not
170         matching, excluding already known problems.
171         (e.g. used in number formatter dialog init)
172      */
173     static ::com::sun::star::uno::Sequence< sal_uInt16 > getInstalledLanguageTypes();
174 
175     /// maps the LocaleData string to the International enum
176             MeasurementSystem   mapMeasurementStringToEnum( const String& rMS ) const;
177 
178     /// Convenience method to obtain the default calendar.
179     const ::boost::shared_ptr< ::com::sun::star::i18n::Calendar > getDefaultCalendar() const;
180 
181     /// Convenience method to obtain the day names of the default calendar.
182     const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getDefaultCalendarDays() const;
183 
184     /// Convenience method to obtain the month names of the default calendar.
185     const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getDefaultCalendarMonths() const;
186 
187     /** Obtain digit grouping. The usually known grouping by thousands (#,###)
188         is actually only one of possible groupings. Another one, for example,
189         used in India is group by 3 and then by 2 indefinitely (#,##,###). The
190         integer sequence returned here specifies grouping from right to left
191         (!), with a 0 entry designating the end of rules and the previous value
192         to be repeated indefinitely. Hence the sequence {3,0} specifies the
193         usual grouping by thousands, whereas the sequence {3,2,0} specifies
194         Indian grouping. The sal_Int32* getConstArray() can be passed directly
195         to the ::rtl::math::doubleToString() methods as argument for the
196         pGroups parameter. */
197     const ::com::sun::star::uno::Sequence< sal_Int32 > getDigitGrouping() const;
198 
199     // Functionality of class International methods, LocaleItem
200 
getDateSep() const201     inline  const String&       getDateSep() const
202                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DATE_SEPARATOR ); }
getNumThousandSep() const203     inline  const String&       getNumThousandSep() const
204                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::THOUSAND_SEPARATOR ); }
getNumDecimalSep() const205     inline  const String&       getNumDecimalSep() const
206                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DECIMAL_SEPARATOR ); }
getTimeSep() const207     inline  const String&       getTimeSep() const
208                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_SEPARATOR ); }
getTime100SecSep() const209     inline  const String&       getTime100SecSep() const
210                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_100SEC_SEPARATOR ); }
getListSep() const211     inline  const String&       getListSep() const
212                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LIST_SEPARATOR ); }
getQuotationMarkStart() const213     inline  const String&       getQuotationMarkStart() const
214                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::SINGLE_QUOTATION_START ); }
getQuotationMarkEnd() const215     inline  const String&       getQuotationMarkEnd() const
216                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::SINGLE_QUOTATION_END ); }
getDoubleQuotationMarkStart() const217     inline  const String&       getDoubleQuotationMarkStart() const
218                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DOUBLE_QUOTATION_START ); }
getDoubleQuotationMarkEnd() const219     inline  const String&       getDoubleQuotationMarkEnd() const
220                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::DOUBLE_QUOTATION_END ); }
getMeasurementSystem() const221     inline  const String&       getMeasurementSystem() const
222                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::MEASUREMENT_SYSTEM ); }
getMeasurementSystemEnum() const223     inline  MeasurementSystem   getMeasurementSystemEnum() const
224                                     { return mapMeasurementStringToEnum( getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::MEASUREMENT_SYSTEM ) ); }
getTimeAM() const225     inline  const String&       getTimeAM() const
226                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_AM ); }
getTimePM() const227     inline  const String&       getTimePM() const
228                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::TIME_PM ); }
getLongDateDayOfWeekSep() const229     inline  const String&       getLongDateDayOfWeekSep() const
230                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_DAY_OF_WEEK_SEPARATOR ); }
getLongDateDaySep() const231     inline  const String&       getLongDateDaySep() const
232                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_DAY_SEPARATOR ); }
getLongDateMonthSep() const233     inline  const String&       getLongDateMonthSep() const
234                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_MONTH_SEPARATOR ); }
getLongDateYearSep() const235     inline  const String&       getLongDateYearSep() const
236                                     { return getOneLocaleItem( ::com::sun::star::i18n::LocaleItem::LONG_DATE_YEAR_SEPARATOR ); }
237 
238     // currency
239             const String&       getCurrSymbol() const;
240             const String&       getCurrBankSymbol() const;
241             sal_uInt16              getCurrPositiveFormat() const;
242             sal_uInt16              getCurrNegativeFormat() const;
243             sal_uInt16              getCurrDigits() const;
244 
245     // simple date and time formatting
246             DateFormat          getDateFormat() const;
247             DateFormat          getLongDateFormat() const;
248                                 /// only numerical values of Gregorian calendar
249             String              getDate( const Date& rDate ) const;
250             String              getTime( const Time& rTime, sal_Bool bSec = sal_True,
251                                     sal_Bool b100Sec = sal_False ) const;
252             String              getDuration( const Time& rTime,
253                                     sal_Bool bSec = sal_True, sal_Bool b100Sec = sal_False ) const;
254 
255                                 /** The CalendarWrapper already <b>MUST</b>
256                                     have loaded a calendar.
257                                     @param nDisplayDayOfWeek
258                                         0 := abbreviated name
259                                         1 := full name
260                                     @param bDayOfMonthWithLeadingZero
261                                         <FALSE/> := without leading zero
262                                         <TRUE/>  := with leading zero if <10
263                                     @param nDisplayMonth
264                                         0 := abbreviated name
265                                         1 := full name
266                                     @param bTwoDigitYear
267                                         <FALSE/> := full year
268                                         <TRUE/>  := year % 100
269                                  */
270             String              getLongDate( const Date& rDate,
271                                     CalendarWrapper& rCal,
272                                     sal_Int16 nDisplayDayOfWeek = 1,
273                                     sal_Bool bDayOfMonthWithLeadingZero = sal_False,
274                                     sal_Int16 nDisplayMonth = 1,
275                                     sal_Bool bTwoDigitYear = sal_False
276                                     ) const;
277 
278                                 /** Simple number formatting
279                                     @param nNumber
280                                         value * 10**nDecimals
281                                     @param bTrailingZeros
282                                     </sal_True>  := always display trailing zeros in
283                                         decimal places, even if integer value.
284                                     </sal_False> := trailing zeros are only displayed
285                                         if the value is not an integer value.
286                                  */
287             String              getNum( sal_Int64 nNumber, sal_uInt16 nDecimals,
288                                     sal_Bool bUseThousandSep = sal_True,
289                                     sal_Bool bTrailingZeros = sal_True ) const;
290 
291                                 /// "Secure" currency formatted string.
292             String              getCurr( sal_Int64 nNumber, sal_uInt16 nDecimals,
293                                     const String& rCurrencySymbol,
294                                     sal_Bool bUseThousandSep = sal_True ) const;
295                                 /** Default currency formatted string, use with
296                                     care as default currency may change in any
297                                     locale, for example, DEM -> EUR */
getCurr(sal_Int64 nNumber,sal_uInt16 nDecimals,sal_Bool bUseThousandSep=sal_True) const298             String              getCurr( sal_Int64 nNumber, sal_uInt16 nDecimals,
299                                         sal_Bool bUseThousandSep = sal_True ) const
300                                     { return getCurr( nNumber, nDecimals,
301                                         getCurrSymbol(), bUseThousandSep ); }
302 
303     // dummy returns, to be implemented
getCurrZeroChar() const304     inline  sal_Unicode         getCurrZeroChar() const
305                                     { return cCurrZeroChar; }
isNumLeadingZero() const306     inline  sal_Bool                isNumLeadingZero() const
307                                     { return sal_True; }
308                                 /// standard decimal places
getNumDigits() const309     inline  sal_uInt16              getNumDigits() const
310                                     { return 2; }
isNumTrailingZeros() const311     inline  sal_Bool                isNumTrailingZeros() const
312                                     { return sal_True; }
313 
314 
315     // reserved words
316 
getTrueWord() const317     inline  const String&       getTrueWord() const
318                                     { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::TRUE_WORD ); }
getFalseWord() const319     inline  const String&       getFalseWord() const
320                                     { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::FALSE_WORD ); }
321     /// return a quarter string matching nQuarter (0..3) => "1st quarter" .. "4th quarter"
getQuarterWord(sal_Int16 nQuarter) const322     inline  const String&       getQuarterWord( sal_Int16 nQuarter ) const
323                                     { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::QUARTER1_WORD + nQuarter ); }
getAboveWord() const324     inline  const String&       getAboveWord() const
325                                     { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::ABOVE_WORD ); }
getBelowWord() const326     inline  const String&       getBelowWord() const
327                                     { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::BELOW_WORD ); }
328     /// return a quarter abbreviation string matching nQuarter (0..3) => "Q1" .. "Q2"
getQuarterAbbreviation(sal_Int16 nQuarter) const329     inline  const String&       getQuarterAbbreviation( sal_Int16 nQuarter ) const
330                                     { return getOneReservedWord( ::com::sun::star::i18n::reservedWords::QUARTER1_ABBREVIATION + nQuarter ); }
331 
332     /** Return whether locale data checks are enabled.
333         Checks are enabled if the environment variable
334         OOO_ENABLE_LOCALE_DATA_CHECKS is set to 'Y' or 'Yes' (or any other
335         string starting with 'Y') or '1'.
336         Also used in conjunction with the number formatter. */
areChecksEnabled()337     static  inline  bool        areChecksEnabled()
338                                     {
339                                         if (nLocaleDataChecking == 0)
340                                             evaluateLocaleDataChecking();
341                                         return nLocaleDataChecking == 1;
342                                     }
343 
344     /** Append locale info to string, used with locale data checking.
345         A string similar to "de_DE requested\n en_US loaded" is appended. */
346             String&             appendLocaleInfo( String& rDebugMsg ) const;
347 
348     /** Ouput a message during locale data checking. The (UTF-8) string is
349         written to stderr and in a non-product build or if DBG_UTIL is enabled
350         also raised as an assertion message box. */
351     static  void                outputCheckMessage( const String& rMsg );
352     static  void                outputCheckMessage( const char* pStr);
353 
354 private:
355     static  void                evaluateLocaleDataChecking();
356 };
357 
358 
359 #endif // _UNOTOOLS_LOCALEDATAWRAPPER_HXX
360