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