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 : :
21 : : #include <string.h> // memcpy()
22 : : #include <stdio.h> // fprintf(), stderr
23 : :
24 : : #include <unotools/localedatawrapper.hxx>
25 : : #include <unotools/numberformatcodewrapper.hxx>
26 : : #include <unotools/calendarwrapper.hxx>
27 : : #include <unotools/digitgroupingiterator.hxx>
28 : : #include <tools/string.hxx>
29 : : #include <tools/debug.hxx>
30 : : #include <i18npool/mslangid.hxx>
31 : :
32 : : #include "instance.hxx"
33 : : #include <com/sun/star/i18n/KNumberFormatUsage.hpp>
34 : : #include <com/sun/star/i18n/KNumberFormatType.hpp>
35 : : #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
36 : : #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
37 : :
38 : : #include <com/sun/star/i18n/NumberFormatIndex.hpp>
39 : : #include <rtl/instance.hxx>
40 : : #include <rtl/ustrbuf.hxx>
41 : : #include <sal/macros.h>
42 : :
43 : : static const int nDateFormatInvalid = -1;
44 : : static const sal_uInt16 nCurrFormatInvalid = 0xffff;
45 : : static const sal_uInt16 nCurrFormatDefault = 0;
46 : :
47 : : using namespace ::com::sun::star;
48 : : using namespace ::com::sun::star::i18n;
49 : : using namespace ::com::sun::star::uno;
50 : :
51 : : namespace
52 : : {
53 : : struct InstalledLocales
54 : : : public rtl::Static<
55 : : uno::Sequence< lang::Locale >, InstalledLocales >
56 : : {};
57 : :
58 : : struct InstalledLanguageTypes
59 : : : public rtl::Static<
60 : : uno::Sequence< sal_uInt16 >, InstalledLanguageTypes >
61 : : {};
62 : : }
63 : :
64 : : sal_uInt8 LocaleDataWrapper::nLocaleDataChecking = 0;
65 : :
66 : 23318 : LocaleDataWrapper::LocaleDataWrapper(
67 : : const Reference< lang::XMultiServiceFactory > & xSF,
68 : : const lang::Locale& rLocale
69 : : )
70 : : :
71 : : xSMgr( xSF ),
72 : : bLocaleDataItemValid( sal_False ),
73 [ + - ][ + - ]: 699540 : bReservedWordValid( sal_False )
[ + - ][ + + ]
[ + + ][ + - ]
74 : : {
75 [ + - ]: 23318 : setLocale( rLocale );
76 : : xLD = Reference< XLocaleData4 > (
77 : : intl_createInstance( xSMgr, "com.sun.star.i18n.LocaleData",
78 [ + - ][ + - ]: 23318 : "LocaleDataWrapper" ), uno::UNO_QUERY );
[ + - ]
79 [ # # # # : 23318 : }
# # # # ]
80 : :
81 : :
82 [ + - ][ + - ]: 719355 : LocaleDataWrapper::~LocaleDataWrapper()
[ + - ][ + - ]
83 : : {
84 [ + + ][ + - ]: 719355 : }
[ + + # #
# # # # #
# ][ + - ]
85 : :
86 : :
87 : 30778 : void LocaleDataWrapper::setLocale( const ::com::sun::star::lang::Locale& rLocale )
88 : : {
89 [ + - ]: 30778 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nCriticalChange );
90 : 30778 : aLocale = rLocale;
91 [ + - ][ + - ]: 30778 : invalidateData();
92 : 30778 : }
93 : :
94 : :
95 : 129105 : const ::com::sun::star::lang::Locale& LocaleDataWrapper::getLocale() const
96 : : {
97 [ + - ]: 129105 : ::utl::ReadWriteGuard aGuard( aMutex );
98 [ + - ]: 129105 : return aLocale;
99 : : }
100 : :
101 : :
102 : 30778 : void LocaleDataWrapper::invalidateData()
103 : : {
104 : 30778 : aCurrSymbol = rtl::OUString();
105 : 30778 : aCurrBankSymbol = rtl::OUString();
106 : 30778 : nDateFormat = nLongDateFormat = nDateFormatInvalid;
107 : 30778 : nCurrPositiveFormat = nCurrNegativeFormat = nCurrDigits = nCurrFormatInvalid;
108 [ + + ]: 30778 : if ( bLocaleDataItemValid )
109 : : {
110 [ + + ]: 6624 : for (sal_Int32 j=0; j<LocaleItem::COUNT; ++j)
111 : 6256 : aLocaleItem[j] = rtl::OUString();
112 : 368 : bLocaleDataItemValid = sal_False;
113 : : }
114 [ + + ]: 30778 : if ( bReservedWordValid )
115 : : {
116 [ + + ]: 78 : for ( sal_Int16 j=0; j<reservedWords::COUNT; ++j )
117 : 72 : aReservedWord[j] = rtl::OUString();
118 : 6 : bReservedWordValid = sal_False;
119 : : }
120 : 30778 : xDefaultCalendar.reset();
121 [ + + ]: 30778 : if (aGrouping.getLength())
122 : 6 : aGrouping[0] = 0;
123 : : // dummies
124 : 30778 : cCurrZeroChar = '0';
125 : 30778 : }
126 : :
127 : :
128 : 75149 : ::com::sun::star::i18n::LanguageCountryInfo LocaleDataWrapper::getLanguageCountryInfo() const
129 : : {
130 : : try
131 : : {
132 [ + - ]: 75149 : if ( xLD.is() )
133 [ + - ][ + - ]: 75149 : return xLD->getLanguageCountryInfo( getLocale() );
[ + - ]
134 : : }
135 : 0 : catch (const Exception& e)
136 : : {
137 : : SAL_WARN( "unotools.i18n", "getLanguageCountryInfo: Exception caught " << e.Message );
138 : : }
139 [ # # ]: 75149 : return ::com::sun::star::i18n::LanguageCountryInfo();
140 : : }
141 : :
142 : :
143 : 3738 : ::com::sun::star::i18n::LocaleDataItem LocaleDataWrapper::getLocaleItem() const
144 : : {
145 : : try
146 : : {
147 [ + - ]: 3738 : if ( xLD.is() )
148 [ + - ][ + - ]: 3738 : return xLD->getLocaleItem( getLocale() );
[ + - ]
149 : : }
150 : 0 : catch (const Exception& e)
151 : : {
152 : : SAL_WARN( "unotools.i18n", "getLocaleItem: Exception caught " << e.Message );
153 : : }
154 [ # # ]: 3738 : return ::com::sun::star::i18n::LocaleDataItem();
155 : : }
156 : :
157 : :
158 : 21618 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > LocaleDataWrapper::getAllCurrencies() const
159 : : {
160 : : try
161 : : {
162 [ + - ]: 21618 : if ( xLD.is() )
163 [ + - ][ + - ]: 21618 : return xLD->getAllCurrencies2( getLocale() );
[ + - ]
164 : : }
165 : 0 : catch (const Exception& e)
166 : : {
167 : : SAL_WARN( "unotools.i18n", "getAllCurrencies: Exception caught " << e.Message );
168 : : }
169 [ # # ]: 21618 : return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 >(0);
170 : : }
171 : :
172 : :
173 : 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement > LocaleDataWrapper::getAllFormats() const
174 : : {
175 : : try
176 : : {
177 [ # # ]: 0 : if ( xLD.is() )
178 [ # # ][ # # ]: 0 : return xLD->getAllFormats( getLocale() );
[ # # ]
179 : : }
180 : 0 : catch (const Exception& e)
181 : : {
182 : : SAL_WARN( "unotools.i18n", "getAllFormats: Exception caught " << e.Message );
183 : : }
184 [ # # ]: 0 : return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement >(0);
185 : : }
186 : :
187 : :
188 : 16729 : ::com::sun::star::i18n::ForbiddenCharacters LocaleDataWrapper::getForbiddenCharacters() const
189 : : {
190 : : try
191 : : {
192 [ + - ]: 16729 : if ( xLD.is() )
193 [ + - ][ + - ]: 16729 : return xLD->getForbiddenCharacters( getLocale() );
[ + - ]
194 : : }
195 : 0 : catch (const Exception& e)
196 : : {
197 : : SAL_WARN( "unotools.i18n", "getForbiddenCharacters: Exception caught " << e.Message );
198 : : }
199 [ # # ]: 16729 : return ::com::sun::star::i18n::ForbiddenCharacters();
200 : : }
201 : :
202 : :
203 : 684 : ::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getReservedWord() const
204 : : {
205 : : try
206 : : {
207 [ + - ]: 684 : if ( xLD.is() )
208 [ + - ][ + - ]: 684 : return xLD->getReservedWord( getLocale() );
[ + - ]
209 : : }
210 : 0 : catch ( const Exception& e )
211 : : {
212 : : SAL_WARN( "unotools.i18n", "getReservedWord: Exception caught " << e.Message );
213 : : }
214 [ # # ]: 684 : return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0);
215 : : }
216 : :
217 : :
218 : 36 : ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > LocaleDataWrapper::getAllInstalledLocaleNames() const
219 : : {
220 : 36 : uno::Sequence< lang::Locale > &rInstalledLocales = InstalledLocales::get();
221 : :
222 [ - + ]: 36 : if ( rInstalledLocales.getLength() )
223 : 0 : return rInstalledLocales;
224 : :
225 : : try
226 : : {
227 [ + - ]: 36 : if ( xLD.is() )
228 [ + - ][ + - ]: 36 : rInstalledLocales = xLD->getAllInstalledLocaleNames();
[ + - ][ + - ]
[ # # ]
229 : : }
230 : 0 : catch ( const Exception& e )
231 : : {
232 : : SAL_WARN( "unotools.i18n", "getAllInstalledLocaleNames: Exception caught " << e.Message );
233 : : }
234 : 36 : return rInstalledLocales;
235 : : }
236 : :
237 : :
238 : : // --- Impl and helpers ----------------------------------------------------
239 : :
240 : : // static
241 : 36 : ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > LocaleDataWrapper::getInstalledLocaleNames()
242 : : {
243 : : const uno::Sequence< lang::Locale > &rInstalledLocales =
244 : 36 : InstalledLocales::get();
245 : :
246 [ + - ]: 36 : if ( !rInstalledLocales.getLength() )
247 : : {
248 [ + - ][ + - ]: 36 : LocaleDataWrapper aLDW( ::comphelper::getProcessServiceFactory(), lang::Locale() );
249 [ + - ][ + - ]: 36 : aLDW.getAllInstalledLocaleNames();
[ + - ]
250 : : }
251 : 36 : return rInstalledLocales;
252 : : }
253 : :
254 : : // static
255 : 0 : ::com::sun::star::uno::Sequence< sal_uInt16 > LocaleDataWrapper::getInstalledLanguageTypes()
256 : : {
257 : : uno::Sequence< sal_uInt16 > &rInstalledLanguageTypes =
258 [ # # ]: 0 : InstalledLanguageTypes::get();
259 : :
260 [ # # ]: 0 : if ( rInstalledLanguageTypes.getLength() )
261 [ # # ]: 0 : return rInstalledLanguageTypes;
262 : :
263 : : ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > xLoc =
264 [ # # ]: 0 : getInstalledLocaleNames();
265 : 0 : sal_Int32 nCount = xLoc.getLength();
266 [ # # ]: 0 : ::com::sun::star::uno::Sequence< sal_uInt16 > xLang( nCount );
267 : 0 : sal_Int32 nLanguages = 0;
268 [ # # ]: 0 : for ( sal_Int32 i=0; i<nCount; i++ )
269 : : {
270 [ # # ]: 0 : String aDebugLocale;
271 [ # # ][ # # ]: 0 : if (areChecksEnabled())
272 : : {
273 [ # # ][ # # ]: 0 : aDebugLocale = xLoc[i].Language;
274 [ # # ][ # # ]: 0 : if ( !xLoc[i].Country.isEmpty() )
275 : : {
276 [ # # ]: 0 : aDebugLocale += '_';
277 [ # # ][ # # ]: 0 : aDebugLocale += String( xLoc[i].Country);
[ # # ][ # # ]
278 [ # # ][ # # ]: 0 : if ( !xLoc[i].Variant.isEmpty() )
279 : : {
280 [ # # ]: 0 : aDebugLocale += '_';
281 [ # # ][ # # ]: 0 : aDebugLocale += String( xLoc[i].Variant);
[ # # ][ # # ]
282 : : }
283 : : }
284 : : }
285 : :
286 [ # # ][ # # ]: 0 : if ( !xLoc[i].Variant.isEmpty() )
287 : : {
288 [ # # ][ # # ]: 0 : if (areChecksEnabled())
289 : : {
290 : 0 : rtl::OUStringBuffer aMsg("LocaleDataWrapper::getInstalledLanguageTypes: Variants not supported, locale\n");
291 [ # # ][ # # ]: 0 : aMsg.append(aDebugLocale);
292 [ # # ][ # # ]: 0 : outputCheckMessage(aMsg.makeStringAndClear());
293 : : }
294 : 0 : continue;
295 : : }
296 [ # # ][ # # ]: 0 : LanguageType eLang = MsLangId::convertLocaleToLanguage( xLoc[i] );
297 : :
298 : : // In checks, exclude known problems because no MS-LCID defined.
299 [ # # ][ # # ]: 0 : if (areChecksEnabled() && eLang == LANGUAGE_DONTKNOW)
[ # # ][ # # ]
300 : : {
301 : 0 : rtl::OUStringBuffer aMsg("ConvertIsoNamesToLanguage: unknown MS-LCID for locale\n");
302 [ # # ][ # # ]: 0 : aMsg.append(aDebugLocale);
303 [ # # ][ # # ]: 0 : outputCheckMessage(aMsg.makeStringAndClear());
304 : : }
305 : :
306 [ # # ]: 0 : switch ( eLang )
307 : : {
308 : : case LANGUAGE_NORWEGIAN : // no_NO, not Bokmal (nb_NO), not Nynorsk (nn_NO)
309 : 0 : eLang = LANGUAGE_DONTKNOW; // don't offer "Unknown" language
310 : 0 : break;
311 : : }
312 [ # # ]: 0 : if ( eLang != LANGUAGE_DONTKNOW )
313 : : {
314 : 0 : rtl::OUString aLanguage, aCountry;
315 [ # # ]: 0 : MsLangId::convertLanguageToIsoNames( eLang, aLanguage, aCountry );
316 [ # # ]: 0 : if ( xLoc[i].Language != aLanguage ||
[ # # # # ]
[ # # ]
317 [ # # ]: 0 : xLoc[i].Country != aCountry )
318 : : {
319 : : // In checks, exclude known problems because no MS-LCID defined
320 : : // and default for Language found.
321 [ # # ][ # # ]: 0 : if ( areChecksEnabled()
[ # # ][ # # ]
[ # # ]
322 [ # # ]: 0 : && !aDebugLocale.EqualsAscii( "ar_SD" ) // Sudan/ar
323 [ # # ]: 0 : && !aDebugLocale.EqualsAscii( "en_CB" ) // Carribean is not a country
324 : : // && !aDebugLocale.EqualsAscii( "en_BG" ) // ?!? Bulgaria/en
325 : : // && !aDebugLocale.EqualsAscii( "es_BR" ) // ?!? Brazil/es
326 : : )
327 : : {
328 : 0 : rtl::OUStringBuffer aMsg;
329 : : aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM(
330 [ # # ]: 0 : "ConvertIsoNamesToLanguage/ConvertLanguageToIsoNames: ambiguous locale (MS-LCID?)\n"));
331 [ # # ][ # # ]: 0 : aMsg.append(aDebugLocale);
332 [ # # ]: 0 : aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM( " -> 0x"));
333 [ # # ]: 0 : aMsg.append(static_cast<sal_Int32>(eLang), 16);
334 [ # # ]: 0 : aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM( " -> "));
335 [ # # ]: 0 : aMsg.append(aLanguage);
336 [ # # ]: 0 : if ( !aCountry.isEmpty() )
337 : : {
338 [ # # ]: 0 : aMsg.append('_');
339 [ # # ]: 0 : aMsg.append(aCountry);
340 : : }
341 [ # # ][ # # ]: 0 : outputCheckMessage( aMsg.makeStringAndClear() );
342 : : }
343 : 0 : eLang = LANGUAGE_DONTKNOW;
344 : 0 : }
345 : : }
346 [ # # ]: 0 : if ( eLang != LANGUAGE_DONTKNOW )
347 [ # # ]: 0 : xLang[ nLanguages++ ] = eLang;
348 [ # # ][ # # ]: 0 : }
349 [ # # ]: 0 : if ( nLanguages < nCount )
350 [ # # ]: 0 : xLang.realloc( nLanguages );
351 [ # # ]: 0 : rInstalledLanguageTypes = xLang;
352 : :
353 [ # # ][ # # ]: 0 : return rInstalledLanguageTypes;
[ # # ]
354 : : }
355 : :
356 : 2003439 : const rtl::OUString& LocaleDataWrapper::getOneLocaleItem( sal_Int16 nItem ) const
357 : : {
358 [ + - ]: 2003439 : ::utl::ReadWriteGuard aGuard( aMutex );
359 [ - + ]: 2003439 : if ( nItem >= LocaleItem::COUNT )
360 : : {
361 : : SAL_WARN( "unotools", "getOneLocaleItem: bounds" );
362 : 0 : return aLocaleItem[0];
363 : : }
364 [ + + ]: 2003439 : if (aLocaleItem[nItem].isEmpty())
365 : : { // no cached content
366 [ + - ]: 7158 : aGuard.changeReadToWrite();
367 [ + - ]: 7158 : ((LocaleDataWrapper*)this)->getOneLocaleItemImpl( nItem );
368 : : }
369 [ + - ]: 2003439 : return aLocaleItem[nItem];
370 : : }
371 : :
372 : :
373 : 7158 : void LocaleDataWrapper::getOneLocaleItemImpl( sal_Int16 nItem )
374 : : {
375 [ + + ]: 7158 : if ( !bLocaleDataItemValid )
376 : : {
377 : 2766 : aLocaleDataItem = getLocaleItem();
378 : 2766 : bLocaleDataItemValid = sal_True;
379 : : }
380 [ + + + + : 7158 : switch ( nItem )
+ + - + -
- + + + +
+ + - - ]
381 : : {
382 : : case LocaleItem::DATE_SEPARATOR :
383 : 738 : aLocaleItem[nItem] = aLocaleDataItem.dateSeparator;
384 : 738 : break;
385 : : case LocaleItem::THOUSAND_SEPARATOR :
386 : 2492 : aLocaleItem[nItem] = aLocaleDataItem.thousandSeparator;
387 : 2492 : break;
388 : : case LocaleItem::DECIMAL_SEPARATOR :
389 : 2175 : aLocaleItem[nItem] = aLocaleDataItem.decimalSeparator;
390 : 2175 : break;
391 : : case LocaleItem::TIME_SEPARATOR :
392 : 715 : aLocaleItem[nItem] = aLocaleDataItem.timeSeparator;
393 : 715 : break;
394 : : case LocaleItem::TIME_100SEC_SEPARATOR :
395 : 685 : aLocaleItem[nItem] = aLocaleDataItem.time100SecSeparator;
396 : 685 : break;
397 : : case LocaleItem::LIST_SEPARATOR :
398 : 51 : aLocaleItem[nItem] = aLocaleDataItem.listSeparator;
399 : 51 : break;
400 : : case LocaleItem::SINGLE_QUOTATION_START :
401 : 0 : aLocaleItem[nItem] = aLocaleDataItem.quotationStart;
402 : 0 : break;
403 : : case LocaleItem::SINGLE_QUOTATION_END :
404 : 40 : aLocaleItem[nItem] = aLocaleDataItem.quotationEnd;
405 : 40 : break;
406 : : case LocaleItem::DOUBLE_QUOTATION_START :
407 : 0 : aLocaleItem[nItem] = aLocaleDataItem.doubleQuotationStart;
408 : 0 : break;
409 : : case LocaleItem::DOUBLE_QUOTATION_END :
410 : 0 : aLocaleItem[nItem] = aLocaleDataItem.doubleQuotationEnd;
411 : 0 : break;
412 : : case LocaleItem::MEASUREMENT_SYSTEM :
413 : 135 : aLocaleItem[nItem] = aLocaleDataItem.measurementSystem;
414 : 135 : break;
415 : : case LocaleItem::TIME_AM :
416 : 35 : aLocaleItem[nItem] = aLocaleDataItem.timeAM;
417 : 35 : break;
418 : : case LocaleItem::TIME_PM :
419 : 35 : aLocaleItem[nItem] = aLocaleDataItem.timePM;
420 : 35 : break;
421 : : case LocaleItem::LONG_DATE_DAY_OF_WEEK_SEPARATOR :
422 : 19 : aLocaleItem[nItem] = aLocaleDataItem.LongDateDayOfWeekSeparator;
423 : 19 : break;
424 : : case LocaleItem::LONG_DATE_DAY_SEPARATOR :
425 : 19 : aLocaleItem[nItem] = aLocaleDataItem.LongDateDaySeparator;
426 : 19 : break;
427 : : case LocaleItem::LONG_DATE_MONTH_SEPARATOR :
428 : 19 : aLocaleItem[nItem] = aLocaleDataItem.LongDateMonthSeparator;
429 : 19 : break;
430 : : case LocaleItem::LONG_DATE_YEAR_SEPARATOR :
431 : 0 : aLocaleItem[nItem] = aLocaleDataItem.LongDateYearSeparator;
432 : 0 : break;
433 : : default:
434 : : SAL_WARN( "unotools", "getOneLocaleItemImpl: which one?" );
435 : : }
436 : 7158 : }
437 : :
438 : :
439 : 1377 : void LocaleDataWrapper::getOneReservedWordImpl( sal_Int16 nWord )
440 : : {
441 [ + + ]: 1377 : if ( !bReservedWordValid )
442 : : {
443 [ + - ]: 684 : aReservedWordSeq = getReservedWord();
444 : 684 : bReservedWordValid = sal_True;
445 : : }
446 : : DBG_ASSERT( nWord < aReservedWordSeq.getLength(), "getOneReservedWordImpl: which one?" );
447 [ + - ]: 1377 : if ( nWord < aReservedWordSeq.getLength() )
448 : 1377 : aReservedWord[nWord] = aReservedWordSeq[nWord];
449 : 1377 : }
450 : :
451 : :
452 : 14722 : const rtl::OUString& LocaleDataWrapper::getOneReservedWord( sal_Int16 nWord ) const
453 : : {
454 [ + - ]: 14722 : ::utl::ReadWriteGuard aGuard( aMutex );
455 [ + - ][ - + ]: 14722 : if ( nWord < 0 || nWord >= reservedWords::COUNT )
456 : : {
457 : : SAL_WARN( "unotools", "getOneReservedWord: bounds" );
458 : 0 : nWord = reservedWords::FALSE_WORD;
459 : : }
460 [ + + ]: 14722 : if (aReservedWord[nWord].isEmpty())
461 : : { // no cached content
462 [ + - ]: 1377 : aGuard.changeReadToWrite();
463 [ + - ]: 1377 : ((LocaleDataWrapper*)this)->getOneReservedWordImpl( nWord );
464 : : }
465 [ + - ]: 14722 : return aReservedWord[nWord];
466 : : }
467 : :
468 : :
469 : 8422 : MeasurementSystem LocaleDataWrapper::mapMeasurementStringToEnum( const rtl::OUString& rMS ) const
470 : : {
471 : : //! TODO: could be cached too
472 [ - + ]: 8422 : if ( rMS.equalsIgnoreAsciiCase( "metric" ) )
473 : 0 : return MEASURE_METRIC;
474 : : //! TODO: other measurement systems? => extend enum MeasurementSystem
475 : 8422 : return MEASURE_US;
476 : : }
477 : :
478 : :
479 : 0 : void LocaleDataWrapper::getDefaultCalendarImpl()
480 : : {
481 [ # # ]: 0 : if (!xDefaultCalendar)
482 : : {
483 [ # # ]: 0 : Sequence< Calendar2 > xCals = getAllCalendars();
484 : 0 : sal_Int32 nCount = xCals.getLength();
485 : 0 : sal_Int32 nDef = 0;
486 [ # # ]: 0 : if (nCount > 1)
487 : : {
488 [ # # ]: 0 : const Calendar2* pArr = xCals.getArray();
489 [ # # ]: 0 : for (sal_Int32 i=0; i<nCount; ++i)
490 : : {
491 [ # # ]: 0 : if (pArr[i].Default)
492 : : {
493 : 0 : nDef = i;
494 : 0 : break;
495 : : }
496 : : }
497 : : }
498 [ # # ][ # # ]: 0 : xDefaultCalendar.reset( new Calendar2( xCals[nDef]));
[ # # ][ # # ]
[ # # ]
499 : : }
500 : 0 : }
501 : :
502 : :
503 : 0 : const ::boost::shared_ptr< ::com::sun::star::i18n::Calendar2 > LocaleDataWrapper::getDefaultCalendar() const
504 : : {
505 [ # # ]: 0 : ::utl::ReadWriteGuard aGuard( aMutex );
506 [ # # ]: 0 : if (!xDefaultCalendar)
507 : : { // no cached content
508 [ # # ]: 0 : aGuard.changeReadToWrite();
509 [ # # ]: 0 : ((LocaleDataWrapper*)this)->getDefaultCalendarImpl();
510 : : }
511 [ # # ][ # # ]: 0 : return xDefaultCalendar;
512 : : }
513 : :
514 : :
515 : 0 : const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > LocaleDataWrapper::getDefaultCalendarDays() const
516 : : {
517 [ # # ]: 0 : return getDefaultCalendar()->Days;
518 : : }
519 : :
520 : :
521 : 0 : const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > LocaleDataWrapper::getDefaultCalendarMonths() const
522 : : {
523 [ # # ]: 0 : return getDefaultCalendar()->Months;
524 : : }
525 : :
526 : :
527 : : // --- currencies -----------------------------------------------------
528 : :
529 : 7335 : const rtl::OUString& LocaleDataWrapper::getCurrSymbol() const
530 : : {
531 [ + - ]: 7335 : ::utl::ReadWriteGuard aGuard( aMutex );
532 [ + + ]: 7335 : if (aCurrSymbol.isEmpty())
533 : : {
534 [ + - ]: 7201 : aGuard.changeReadToWrite();
535 [ + - ]: 7201 : ((LocaleDataWrapper*)this)->getCurrSymbolsImpl();
536 : : }
537 [ + - ]: 7335 : return aCurrSymbol;
538 : : }
539 : :
540 : :
541 : 65 : const rtl::OUString& LocaleDataWrapper::getCurrBankSymbol() const
542 : : {
543 [ + - ]: 65 : ::utl::ReadWriteGuard aGuard( aMutex );
544 [ + + ]: 65 : if (aCurrBankSymbol.isEmpty())
545 : : {
546 [ + - ]: 29 : aGuard.changeReadToWrite();
547 [ + - ]: 29 : ((LocaleDataWrapper*)this)->getCurrSymbolsImpl();
548 : : }
549 [ + - ]: 65 : return aCurrBankSymbol;
550 : : }
551 : :
552 : :
553 : 10854 : sal_uInt16 LocaleDataWrapper::getCurrPositiveFormat() const
554 : : {
555 [ + - ]: 10854 : ::utl::ReadWriteGuard aGuard( aMutex );
556 [ + + ]: 10854 : if ( nCurrPositiveFormat == nCurrFormatInvalid )
557 : : {
558 [ + - ]: 7193 : aGuard.changeReadToWrite();
559 [ + - ]: 7193 : ((LocaleDataWrapper*)this)->getCurrFormatsImpl();
560 : : }
561 [ + - ]: 10854 : return nCurrPositiveFormat;
562 : : }
563 : :
564 : :
565 : 10835 : sal_uInt16 LocaleDataWrapper::getCurrNegativeFormat() const
566 : : {
567 [ + - ]: 10835 : ::utl::ReadWriteGuard aGuard( aMutex );
568 [ - + ]: 10835 : if ( nCurrNegativeFormat == nCurrFormatInvalid )
569 : : {
570 [ # # ]: 0 : aGuard.changeReadToWrite();
571 [ # # ]: 0 : ((LocaleDataWrapper*)this)->getCurrFormatsImpl();
572 : : }
573 [ + - ]: 10835 : return nCurrNegativeFormat;
574 : : }
575 : :
576 : :
577 : 36 : sal_uInt16 LocaleDataWrapper::getCurrDigits() const
578 : : {
579 [ + - ]: 36 : ::utl::ReadWriteGuard aGuard( aMutex );
580 [ - + ]: 36 : if ( nCurrDigits == nCurrFormatInvalid )
581 : : {
582 [ # # ]: 0 : aGuard.changeReadToWrite();
583 [ # # ]: 0 : ((LocaleDataWrapper*)this)->getCurrSymbolsImpl();
584 : : }
585 [ + - ]: 36 : return nCurrDigits;
586 : : }
587 : :
588 : :
589 : 7230 : void LocaleDataWrapper::getCurrSymbolsImpl()
590 : : {
591 [ + - ]: 7230 : Sequence< Currency2 > aCurrSeq = getAllCurrencies();
592 : 7230 : sal_Int32 nCnt = aCurrSeq.getLength();
593 [ + - ]: 7230 : Currency2 const * const pCurrArr = aCurrSeq.getArray();
594 : : sal_Int32 nElem;
595 [ + - ]: 7626 : for ( nElem = 0; nElem < nCnt; nElem++ )
596 : : {
597 [ + + ]: 7626 : if ( pCurrArr[nElem].Default )
598 : 7230 : break;
599 : : }
600 [ - + ]: 7230 : if ( nElem >= nCnt )
601 : : {
602 [ # # ][ # # ]: 0 : if (areChecksEnabled())
603 : : {
604 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
605 [ # # ]: 0 : "LocaleDataWrapper::getCurrSymbolsImpl: no default currency"));
606 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
607 : : }
608 : 0 : nElem = 0;
609 [ # # ]: 0 : if ( nElem >= nCnt )
610 : : {
611 [ # # ][ # # ]: 0 : if (areChecksEnabled())
612 [ # # ]: 0 : outputCheckMessage(rtl::OUString("LocaleDataWrapper::getCurrSymbolsImpl: no currency at all, using ShellsAndPebbles"));
613 : 0 : aCurrSymbol = rtl::OUString("ShellsAndPebbles");
614 : 0 : aCurrBankSymbol = aCurrSymbol;
615 : 0 : nCurrPositiveFormat = nCurrNegativeFormat = nCurrFormatDefault;
616 : 0 : nCurrDigits = 2;
617 : 7230 : return ;
618 : : }
619 : : }
620 : 7230 : aCurrSymbol = pCurrArr[nElem].Symbol;
621 : 7230 : aCurrBankSymbol = pCurrArr[nElem].BankSymbol;
622 [ + - ][ + - ]: 7230 : nCurrDigits = pCurrArr[nElem].DecimalPlaces;
623 : : }
624 : :
625 : :
626 : 14386 : void LocaleDataWrapper::scanCurrFormatImpl( const rtl::OUString& rCode,
627 : : sal_Int32 nStart, sal_Int32& nSign, sal_Int32& nPar,
628 : : sal_Int32& nNum, sal_Int32& nBlank, sal_Int32& nSym )
629 : : {
630 : 14386 : nSign = nPar = nNum = nBlank = nSym = -1;
631 : 14386 : const sal_Unicode* const pStr = rCode.getStr();
632 : 14386 : const sal_Unicode* const pStop = pStr + rCode.getLength();
633 : 14386 : const sal_Unicode* p = pStr + nStart;
634 : 14386 : int nInSection = 0;
635 : 14386 : sal_Bool bQuote = sal_False;
636 [ + + ]: 315325 : while ( p < pStop )
637 : : {
638 [ - + ]: 300939 : if ( bQuote )
639 : : {
640 [ # # ][ # # ]: 0 : if ( *p == '"' && *(p-1) != '\\' )
641 : 0 : bQuote = sal_False;
642 : : }
643 : : else
644 : : {
645 [ - + + + : 300939 : switch ( *p )
+ + + +
+ ]
646 : : {
647 : : case '"' :
648 [ # # ][ # # ]: 0 : if ( pStr == p || *(p-1) != '\\' )
649 : 0 : bQuote = sal_True;
650 : 0 : break;
651 : : case '-' :
652 [ + + ][ + - ]: 21111 : if (!nInSection && nSign == -1)
653 : 6725 : nSign = p - pStr;
654 : 21111 : break;
655 : : case '(' :
656 [ + - ][ + - ]: 468 : if (!nInSection && nPar == -1)
657 : 468 : nPar = p - pStr;
658 : 468 : break;
659 : : case '0' :
660 : : case '#' :
661 [ + + ][ + + ]: 90406 : if (!nInSection && nNum == -1)
662 : 14386 : nNum = p - pStr;
663 : 90406 : break;
664 : : case '[' :
665 : 21615 : nInSection++;
666 : 21615 : break;
667 : : case ']' :
668 [ + - ]: 21615 : if ( nInSection )
669 : : {
670 : 21615 : nInSection--;
671 [ + - ][ + + ]: 21615 : if (!nInSection && nBlank == -1
[ + + ][ + + ]
[ + + ]
672 : 20456 : && nSym != -1 && p < pStop-1 && *(p+1) == ' ' )
673 : 3024 : nBlank = p - pStr + 1;
674 : : }
675 : 21615 : break;
676 : : case '$' :
677 [ + + ][ + - ]: 16676 : if (nSym == -1 && nInSection && *(p-1) == '[')
[ + - ]
678 : : {
679 : 14386 : nSym = p - pStr + 1;
680 [ + + ][ + + ]: 14386 : if (nNum != -1 && *(p-2) == ' ')
681 : 3852 : nBlank = p - pStr - 2;
682 : : }
683 : 16676 : break;
684 : : case ';' :
685 [ + - ]: 7193 : if ( !nInSection )
686 : 7193 : p = pStop;
687 : 7193 : break;
688 : : default:
689 [ + + ][ + + ]: 121855 : if (!nInSection && nSym == -1 && String(rCode).Equals( aCurrSymbol, (xub_StrLen)(p-pStr), aCurrSymbol.getLength()))
[ + - ][ + - ]
[ + - ][ - + ]
[ + + ][ + - ]
[ + + ][ - +
# # # # ]
690 : : { // currency symbol not surrounded by [$...]
691 : 0 : nSym = p - pStr;
692 [ # # ][ # # ]: 0 : if (nBlank == -1 && pStr < p && *(p-1) == ' ')
[ # # ]
693 : 0 : nBlank = p - pStr - 1;
694 : 0 : p += aCurrSymbol.getLength() - 1;
695 [ # # ][ # # ]: 0 : if (nBlank == -1 && p < pStop-2 && *(p+2) == ' ')
[ # # ]
696 : 0 : nBlank = p - pStr + 2;
697 : : }
698 : : }
699 : : }
700 : 300939 : p++;
701 : : }
702 : 14386 : }
703 : :
704 : 7193 : void LocaleDataWrapper::getCurrFormatsImpl()
705 : : {
706 [ + - ][ + - ]: 7193 : NumberFormatCodeWrapper aNumberFormatCode( xSMgr, getLocale() );
707 : : uno::Sequence< NumberFormatCode > aFormatSeq
708 [ + - ]: 7193 : = aNumberFormatCode.getAllFormatCode( KNumberFormatUsage::CURRENCY );
709 : 7193 : sal_Int32 nCnt = aFormatSeq.getLength();
710 [ - + ]: 7193 : if ( !nCnt )
711 : : { // bad luck
712 [ # # ][ # # ]: 0 : if (areChecksEnabled())
713 : : {
714 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
715 [ # # ]: 0 : "LocaleDataWrapper::getCurrFormatsImpl: no currency formats"));
716 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
717 : : }
718 : 0 : nCurrPositiveFormat = nCurrNegativeFormat = nCurrFormatDefault;
719 : 7193 : return ;
720 : : }
721 : : // find a negative code (medium preferred) and a default (medium preferred) (not necessarily the same)
722 [ + - ]: 7193 : NumberFormatCode const * const pFormatArr = aFormatSeq.getArray();
723 : : sal_Int32 nElem, nDef, nNeg, nMedium;
724 : 7193 : nDef = nNeg = nMedium = -1;
725 [ + + ]: 51071 : for ( nElem = 0; nElem < nCnt; nElem++ )
726 : : {
727 [ + + ]: 43878 : if ( pFormatArr[nElem].Type == KNumberFormatType::MEDIUM )
728 : : {
729 [ + + ]: 36541 : if ( pFormatArr[nElem].Default )
730 : : {
731 : 7193 : nDef = nElem;
732 : 7193 : nMedium = nElem;
733 [ + - ]: 7193 : if ( pFormatArr[nElem].Code.indexOf( ';' ) >= 0 )
734 : 7193 : nNeg = nElem;
735 : : }
736 : : else
737 : : {
738 [ + + ][ + + ]: 29348 : if ( (nNeg == -1 || nMedium == -1) && pFormatArr[nElem].Code.indexOf( ';' ) >= 0 )
[ + - ][ + + ]
739 : 7013 : nNeg = nElem;
740 [ + + ]: 29348 : if ( nMedium == -1 )
741 : 7013 : nMedium = nElem;
742 : : }
743 : : }
744 : : else
745 : : {
746 [ + + ][ + - ]: 7337 : if ( nDef == -1 && pFormatArr[nElem].Default )
747 : 6941 : nDef = nElem;
748 [ + + ][ + - ]: 7337 : if ( nNeg == -1 && pFormatArr[nElem].Code.indexOf( ';' ) >= 0 )
[ + + ]
749 : 6941 : nNeg = nElem;
750 : : }
751 : : }
752 : :
753 : : // make sure it's loaded
754 [ + - ]: 7193 : getCurrSymbol();
755 : :
756 : : sal_Int32 nSign, nPar, nNum, nBlank, nSym;
757 : :
758 : : // positive format
759 [ - + ]: 7193 : nElem = (nDef >= 0 ? nDef : (nNeg >= 0 ? nNeg : 0));
760 [ + - ]: 7193 : scanCurrFormatImpl( pFormatArr[nElem].Code, 0, nSign, nPar, nNum, nBlank, nSym );
761 [ + - ][ - + ]: 7193 : if (areChecksEnabled() && (nNum == -1 || nSym == -1))
[ # # ][ # # ]
[ - + ]
762 : : {
763 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
764 [ # # ]: 0 : "LocaleDataWrapper::getCurrFormatsImpl: CurrPositiveFormat?"));
765 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
766 : : }
767 [ + + ]: 7193 : if (nBlank == -1)
768 : : {
769 [ + + ]: 3521 : if ( nSym < nNum )
770 : 2909 : nCurrPositiveFormat = 0; // $1
771 : : else
772 : 612 : nCurrPositiveFormat = 1; // 1$
773 : : }
774 : : else
775 : : {
776 [ + + ]: 3672 : if ( nSym < nNum )
777 : 1764 : nCurrPositiveFormat = 2; // $ 1
778 : : else
779 : 1908 : nCurrPositiveFormat = 3; // 1 $
780 : : }
781 : :
782 : : // negative format
783 [ - + ]: 7193 : if ( nNeg < 0 )
784 : 0 : nCurrNegativeFormat = nCurrFormatDefault;
785 : : else
786 : : {
787 : 7193 : const ::rtl::OUString& rCode = pFormatArr[nNeg].Code;
788 : 7193 : sal_Int32 nDelim = rCode.indexOf(';');
789 [ + - ]: 7193 : scanCurrFormatImpl( rCode, nDelim+1, nSign, nPar, nNum, nBlank, nSym );
790 [ + - ][ - + ]: 7193 : if (areChecksEnabled() && (nNum == -1 || nSym == -1 || (nPar == -1 && nSign == -1)))
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ]
791 : : {
792 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
793 [ # # ]: 0 : "LocaleDataWrapper::getCurrFormatsImpl: CurrNegativeFormat?"));
794 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
795 : : }
796 : : // NOTE: one of nPar or nSign are allowed to be -1
797 [ + + ]: 7193 : if (nBlank == -1)
798 : : {
799 [ + + ]: 3989 : if ( nSym < nNum )
800 : : {
801 [ + + ][ + - ]: 3377 : if ( -1 < nPar && nPar < nSym )
802 : 396 : nCurrNegativeFormat = 0; // ($1)
803 [ + - ][ + + ]: 2981 : else if ( -1 < nSign && nSign < nSym )
804 : 2261 : nCurrNegativeFormat = 1; // -$1
805 [ - + ]: 720 : else if ( nNum < nSign )
806 : 0 : nCurrNegativeFormat = 3; // $1-
807 : : else
808 : 3377 : nCurrNegativeFormat = 2; // $-1
809 : : }
810 : : else
811 : : {
812 [ - + ][ # # ]: 612 : if ( -1 < nPar && nPar < nNum )
813 : 0 : nCurrNegativeFormat = 4; // (1$)
814 [ + - ][ + - ]: 612 : else if ( -1 < nSign && nSign < nNum )
815 : 612 : nCurrNegativeFormat = 5; // -1$
816 [ # # ]: 0 : else if ( nSym < nSign )
817 : 0 : nCurrNegativeFormat = 7; // 1$-
818 : : else
819 : 3989 : nCurrNegativeFormat = 6; // 1-$
820 : : }
821 : : }
822 : : else
823 : : {
824 [ + + ]: 3204 : if ( nSym < nNum )
825 : : {
826 [ + + ][ + - ]: 1260 : if ( -1 < nPar && nPar < nSym )
827 : 72 : nCurrNegativeFormat = 14; // ($ 1)
828 [ + - ][ + + ]: 1188 : else if ( -1 < nSign && nSign < nSym )
829 : 576 : nCurrNegativeFormat = 9; // -$ 1
830 [ + + ]: 612 : else if ( nNum < nSign )
831 : 252 : nCurrNegativeFormat = 12; // $ 1-
832 : : else
833 : 1260 : nCurrNegativeFormat = 11; // $ -1
834 : : }
835 : : else
836 : : {
837 [ - + ][ # # ]: 1944 : if ( -1 < nPar && nPar < nNum )
838 : 0 : nCurrNegativeFormat = 15; // (1 $)
839 [ + - ][ + - ]: 1944 : else if ( -1 < nSign && nSign < nNum )
840 : 1944 : nCurrNegativeFormat = 8; // -1 $
841 [ # # ]: 0 : else if ( nSym < nSign )
842 : 0 : nCurrNegativeFormat = 10; // 1 $-
843 : : else
844 : 7193 : nCurrNegativeFormat = 13; // 1- $
845 : : }
846 : : }
847 [ + - ][ - + ]: 7193 : }
[ + - ][ + - ]
848 : : }
849 : :
850 : :
851 : : // --- date -----------------------------------------------------------
852 : :
853 : 1283 : DateFormat LocaleDataWrapper::getDateFormat() const
854 : : {
855 [ + - ]: 1283 : ::utl::ReadWriteGuard aGuard( aMutex );
856 [ + + ]: 1283 : if ( nDateFormat == nDateFormatInvalid )
857 : : {
858 [ + - ]: 74 : aGuard.changeReadToWrite();
859 [ + - ]: 74 : ((LocaleDataWrapper*)this)->getDateFormatsImpl();
860 : : }
861 [ + - ]: 1283 : return (DateFormat) nDateFormat;
862 : : }
863 : :
864 : :
865 : 299 : DateFormat LocaleDataWrapper::getLongDateFormat() const
866 : : {
867 [ + - ]: 299 : ::utl::ReadWriteGuard aGuard( aMutex );
868 [ - + ]: 299 : if ( nLongDateFormat == nDateFormatInvalid )
869 : : {
870 [ # # ]: 0 : aGuard.changeReadToWrite();
871 [ # # ]: 0 : ((LocaleDataWrapper*)this)->getDateFormatsImpl();
872 : : }
873 [ + - ]: 299 : return (DateFormat) nLongDateFormat;
874 : : }
875 : :
876 : :
877 : 148 : DateFormat LocaleDataWrapper::scanDateFormatImpl( const rtl::OUString& rCode )
878 : : {
879 : : // Only some european versions were translated, the ones with different
880 : : // keyword combinations are:
881 : : // English DMY, German TMJ, Spanish DMA, French JMA, Italian GMA,
882 : : // Dutch DMJ, Finnish PKV
883 : :
884 : : // default is English keywords for every other language
885 : 148 : sal_Int32 nDay = rCode.indexOf('D');
886 : 148 : sal_Int32 nMonth = rCode.indexOf('M');
887 : 148 : sal_Int32 nYear = rCode.indexOf('Y');
888 [ + - ][ - + ]: 148 : if (nDay == -1 || nMonth == -1 || nYear == -1)
[ + - ]
889 : : { // This algorithm assumes that all three parts (DMY) are present
890 [ # # ]: 0 : if (nMonth == -1)
891 : : { // only Finnish has something else than 'M' for month
892 : 0 : nMonth = rCode.indexOf('K');
893 [ # # ]: 0 : if (nMonth != -1)
894 : : {
895 : 0 : nDay = rCode.indexOf('P');
896 : 0 : nYear = rCode.indexOf('V');
897 : : }
898 : : }
899 [ # # ]: 0 : else if (nDay == -1)
900 : : { // We have a month 'M' if we reach this branch.
901 : : // Possible languages containing 'M' but no 'D':
902 : : // German, French, Italian
903 : 0 : nDay = rCode.indexOf('T'); // German
904 [ # # ]: 0 : if (nDay != -1)
905 : 0 : nYear = rCode.indexOf('J');
906 : : else
907 : : {
908 : 0 : nYear = rCode.indexOf('A'); // French, Italian
909 [ # # ]: 0 : if (nYear != -1)
910 : : {
911 : 0 : nDay = rCode.indexOf('J'); // French
912 [ # # ]: 0 : if (nDay == -1)
913 : 0 : nDay = rCode.indexOf('G'); // Italian
914 : : }
915 : : }
916 : : }
917 : : else
918 : : { // We have a month 'M' and a day 'D'.
919 : : // Possible languages containing 'D' and 'M' but not 'Y':
920 : : // Spanish, Dutch
921 : 0 : nYear = rCode.indexOf('A'); // Spanish
922 [ # # ]: 0 : if (nYear == -1)
923 : 0 : nYear = rCode.indexOf('J'); // Dutch
924 : : }
925 [ # # ][ # # ]: 0 : if (nDay == -1 || nMonth == -1 || nYear == -1)
[ # # ]
926 : : {
927 [ # # ]: 0 : if (areChecksEnabled())
928 : : {
929 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
930 [ # # ]: 0 : "LocaleDataWrapper::scanDateFormat: not all DMY present"));
931 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
932 : : }
933 [ # # ]: 0 : if (nDay == -1)
934 : 0 : nDay = rCode.getLength();
935 [ # # ]: 0 : if (nMonth == -1)
936 : 0 : nMonth = rCode.getLength();
937 [ # # ]: 0 : if (nYear == -1)
938 : 0 : nYear = rCode.getLength();
939 : : }
940 : : }
941 : : // compare with <= because each position may equal rCode.getLength()
942 [ - + ][ # # ]: 148 : if ( nDay <= nMonth && nMonth <= nYear )
943 : 0 : return DMY; // also if every position equals rCode.getLength()
944 [ + - ][ + - ]: 148 : else if ( nMonth <= nDay && nDay <= nYear )
945 : 148 : return MDY;
946 [ # # ][ # # ]: 0 : else if ( nYear <= nMonth && nMonth <= nDay )
947 : 0 : return YMD;
948 : : else
949 : : {
950 [ # # ]: 0 : if (areChecksEnabled())
951 : : {
952 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
953 [ # # ]: 0 : "LocaleDataWrapper::scanDateFormat: no magic applyable"));
954 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
955 : : }
956 : 148 : return DMY;
957 : : }
958 : : }
959 : :
960 : :
961 : 74 : void LocaleDataWrapper::getDateFormatsImpl()
962 : : {
963 [ + - ][ + - ]: 74 : NumberFormatCodeWrapper aNumberFormatCode( xSMgr, getLocale() );
964 : : uno::Sequence< NumberFormatCode > aFormatSeq
965 [ + - ]: 74 : = aNumberFormatCode.getAllFormatCode( KNumberFormatUsage::DATE );
966 : 74 : sal_Int32 nCnt = aFormatSeq.getLength();
967 [ - + ]: 74 : if ( !nCnt )
968 : : { // bad luck
969 [ # # ][ # # ]: 0 : if (areChecksEnabled())
970 : : {
971 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
972 [ # # ]: 0 : "LocaleDataWrapper::getDateFormatsImpl: no date formats"));
973 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
974 : : }
975 : 0 : nDateFormat = nLongDateFormat = DMY;
976 : 74 : return ;
977 : : }
978 : : // find the edit (21), a default (medium preferred),
979 : : // a medium (default preferred), and a long (default preferred)
980 [ + - ]: 74 : NumberFormatCode const * const pFormatArr = aFormatSeq.getArray();
981 : : sal_Int32 nElem, nEdit, nDef, nMedium, nLong;
982 : 74 : nEdit = nDef = nMedium = nLong = -1;
983 [ + + ]: 2368 : for ( nElem = 0; nElem < nCnt; nElem++ )
984 : : {
985 [ + + ][ + + ]: 2294 : if ( nEdit == -1 && pFormatArr[nElem].Index == NumberFormatIndex::DATE_SYS_DDMMYYYY )
986 : 74 : nEdit = nElem;
987 [ + + ][ + - ]: 2294 : if ( nDef == -1 && pFormatArr[nElem].Default )
988 : 74 : nDef = nElem;
989 [ + + + ]: 2294 : switch ( pFormatArr[nElem].Type )
990 : : {
991 : : case KNumberFormatType::MEDIUM :
992 : : {
993 [ + + ]: 1110 : if ( pFormatArr[nElem].Default )
994 : : {
995 : 74 : nDef = nElem;
996 : 74 : nMedium = nElem;
997 : : }
998 [ - + ]: 1036 : else if ( nMedium == -1 )
999 : 0 : nMedium = nElem;
1000 : : }
1001 : 1110 : break;
1002 : : case KNumberFormatType::LONG :
1003 : : {
1004 [ + + ]: 1036 : if ( pFormatArr[nElem].Default )
1005 : 74 : nLong = nElem;
1006 [ - + ]: 962 : else if ( nLong == -1 )
1007 : 0 : nLong = nElem;
1008 : : }
1009 : 1036 : break;
1010 : : }
1011 : : }
1012 [ - + ]: 74 : if ( nEdit == -1 )
1013 : : {
1014 [ # # ][ # # ]: 0 : if (areChecksEnabled())
1015 : : {
1016 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
1017 [ # # ]: 0 : "LocaleDataWrapper::getDateFormatsImpl: no edit"));
1018 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
1019 : : }
1020 [ # # ]: 0 : if ( nDef == -1 )
1021 : : {
1022 [ # # ][ # # ]: 0 : if (areChecksEnabled())
1023 : : {
1024 : : rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
1025 [ # # ]: 0 : "LocaleDataWrapper::getDateFormatsImpl: no default"));
1026 [ # # ][ # # ]: 0 : outputCheckMessage( appendLocaleInfo( aMsg ) );
1027 : : }
1028 [ # # ]: 0 : if ( nMedium != -1 )
1029 : 0 : nDef = nMedium;
1030 [ # # ]: 0 : else if ( nLong != -1 )
1031 : 0 : nDef = nLong;
1032 : : else
1033 : 0 : nDef = 0;
1034 : : }
1035 : 0 : nEdit = nDef;
1036 : : }
1037 [ + - ]: 74 : DateFormat nDF = scanDateFormatImpl( pFormatArr[nEdit].Code );
1038 [ - + ]: 74 : if ( pFormatArr[nEdit].Type == KNumberFormatType::LONG )
1039 : : { // normally this is not the case
1040 : 0 : nLongDateFormat = nDateFormat = nDF;
1041 : : }
1042 : : else
1043 : : {
1044 : 74 : nDateFormat = nDF;
1045 [ - + ]: 74 : if ( nLong == -1 )
1046 : 0 : nLongDateFormat = nDF;
1047 : : else
1048 [ + - ]: 74 : nLongDateFormat = scanDateFormatImpl( pFormatArr[nLong].Code );
1049 [ + - ][ - + ]: 74 : }
[ + - ][ + - ]
1050 : : }
1051 : :
1052 : :
1053 : : // --- digit grouping -------------------------------------------------
1054 : :
1055 : 1832 : void LocaleDataWrapper::getDigitGroupingImpl()
1056 : : {
1057 : : /* TODO: This is a very simplified grouping setup that only serves its
1058 : : * current purpose for Indian locales. A free-form flexible one would
1059 : : * obtain grouping from locale data where it could be specified using, for
1060 : : * example, codes like #,### and #,##,### that would generate the integer
1061 : : * sequence. Needed additional API and a locale data element.
1062 : : */
1063 : :
1064 [ + - ]: 1832 : if (!aGrouping.getLength())
1065 : : {
1066 : 1832 : aGrouping.realloc(3); // room for {3,2,0}
1067 : 1832 : aGrouping[0] = 0; // invalidate
1068 : : }
1069 [ + - ]: 1832 : if (!aGrouping[0])
1070 : : {
1071 [ + - ]: 1832 : i18n::LanguageCountryInfo aLCInfo( getLanguageCountryInfo());
1072 [ + - - + ]: 3664 : if (aLCInfo.Country.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("IN")) || // India
[ - + ]
1073 : 1832 : aLCInfo.Country.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("BT")) ) // Bhutan
1074 : : {
1075 [ # # ]: 0 : aGrouping[0] = 3;
1076 [ # # ]: 0 : aGrouping[1] = 2;
1077 [ # # ]: 0 : aGrouping[2] = 0;
1078 : : }
1079 : : else
1080 : : {
1081 [ + - ]: 1832 : aGrouping[0] = 3;
1082 [ + - ]: 1832 : aGrouping[1] = 0;
1083 : 1832 : }
1084 : : }
1085 : 1832 : }
1086 : :
1087 : :
1088 : 110114 : const ::com::sun::star::uno::Sequence< sal_Int32 > LocaleDataWrapper::getDigitGrouping() const
1089 : : {
1090 [ + - ]: 110114 : ::utl::ReadWriteGuard aGuard( aMutex );
1091 [ + + ][ - + ]: 110114 : if (!aGrouping.getLength() || aGrouping[0] == 0)
[ + + ]
1092 : : { // no cached content
1093 [ + - ]: 1832 : aGuard.changeReadToWrite();
1094 [ + - ]: 1832 : ((LocaleDataWrapper*)this)->getDigitGroupingImpl();
1095 : : }
1096 [ + - ][ + - ]: 110114 : return aGrouping;
1097 : : }
1098 : :
1099 : :
1100 : : // --- simple number formatting helpers -------------------------------
1101 : :
1102 : : // The ImplAdd... methods are taken from class International and modified to
1103 : : // suit the needs.
1104 : :
1105 : 38440 : static sal_Unicode* ImplAddUNum( sal_Unicode* pBuf, sal_uInt64 nNumber )
1106 : : {
1107 : : // fill temp buffer with digits
1108 : : sal_Unicode aTempBuf[64];
1109 : 38440 : sal_Unicode* pTempBuf = aTempBuf;
1110 [ + + ]: 98934 : do
1111 : : {
1112 : 98934 : *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
1113 : 98934 : pTempBuf++;
1114 : 98934 : nNumber /= 10;
1115 : : }
1116 : : while ( nNumber );
1117 : :
1118 : : // copy temp buffer to buffer passed
1119 [ + + ]: 98934 : do
1120 : : {
1121 : 98934 : pTempBuf--;
1122 : 98934 : *pBuf = *pTempBuf;
1123 : 98934 : pBuf++;
1124 : : }
1125 : : while ( pTempBuf != aTempBuf );
1126 : :
1127 : 38440 : return pBuf;
1128 : : }
1129 : :
1130 : :
1131 : 119 : static sal_Unicode* ImplAddUNum( sal_Unicode* pBuf, sal_uInt64 nNumber, int nMinLen )
1132 : : {
1133 : : // fill temp buffer with digits
1134 : : sal_Unicode aTempBuf[64];
1135 : 119 : sal_Unicode* pTempBuf = aTempBuf;
1136 [ + + ]: 218 : do
1137 : : {
1138 : 218 : *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
1139 : 218 : pTempBuf++;
1140 : 218 : nNumber /= 10;
1141 : 218 : nMinLen--;
1142 : : }
1143 : : while ( nNumber );
1144 : :
1145 : : // fill with zeros up to the minimal length
1146 [ + + ]: 353 : while ( nMinLen > 0 )
1147 : : {
1148 : 234 : *pBuf = '0';
1149 : 234 : pBuf++;
1150 : 234 : nMinLen--;
1151 : : }
1152 : :
1153 : : // copy temp buffer to real buffer
1154 [ + + ]: 218 : do
1155 : : {
1156 : 218 : pTempBuf--;
1157 : 218 : *pBuf = *pTempBuf;
1158 : 218 : pBuf++;
1159 : : }
1160 : : while ( pTempBuf != aTempBuf );
1161 : :
1162 : 119 : return pBuf;
1163 : : }
1164 : :
1165 : :
1166 : 1353 : static sal_Unicode* ImplAdd2UNum( sal_Unicode* pBuf, sal_uInt16 nNumber, int bLeading )
1167 : : {
1168 : : DBG_ASSERT( nNumber < 100, "ImplAdd2UNum() - Number >= 100" );
1169 : :
1170 [ + + ]: 1353 : if ( nNumber < 10 )
1171 : : {
1172 [ + - ]: 1192 : if ( bLeading )
1173 : : {
1174 : 1192 : *pBuf = '0';
1175 : 1192 : pBuf++;
1176 : : }
1177 : 1192 : *pBuf = nNumber + '0';
1178 : : }
1179 : : else
1180 : : {
1181 : 161 : sal_uInt16 nTemp = nNumber % 10;
1182 : 161 : nNumber /= 10;
1183 : 161 : *pBuf = nNumber + '0';
1184 : 161 : pBuf++;
1185 : 161 : *pBuf = nTemp + '0';
1186 : : }
1187 : :
1188 : 1353 : pBuf++;
1189 : 1353 : return pBuf;
1190 : : }
1191 : :
1192 : :
1193 : 35448 : inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, const rtl::OUString& rStr )
1194 : : {
1195 [ + - ]: 35448 : if ( rStr.getLength() == 1 )
1196 : 35448 : *pBuf++ = rStr[0];
1197 [ # # ]: 0 : else if (rStr.isEmpty())
1198 : : ;
1199 : : else
1200 : : {
1201 : 0 : memcpy( pBuf, rStr.getStr(), rStr.getLength() * sizeof(sal_Unicode) );
1202 : 0 : pBuf += rStr.getLength();
1203 : : }
1204 : 35448 : return pBuf;
1205 : : }
1206 : :
1207 : :
1208 : 0 : inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, sal_Unicode c )
1209 : : {
1210 : 0 : *pBuf = c;
1211 : 0 : pBuf++;
1212 : 0 : return pBuf;
1213 : : }
1214 : :
1215 : :
1216 : 0 : inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, const sal_Unicode* pCopyBuf, xub_StrLen nLen )
1217 : : {
1218 : 0 : memcpy( pBuf, pCopyBuf, nLen * sizeof(sal_Unicode) );
1219 : 0 : return pBuf + nLen;
1220 : : }
1221 : :
1222 : :
1223 : 38345 : sal_Unicode* LocaleDataWrapper::ImplAddFormatNum( sal_Unicode* pBuf,
1224 : : sal_Int64 nNumber, sal_uInt16 nDecimals, sal_Bool bUseThousandSep,
1225 : : sal_Bool bTrailingZeros ) const
1226 : : {
1227 : : sal_Unicode aNumBuf[64];
1228 : : sal_Unicode* pNumBuf;
1229 : : sal_uInt16 nNumLen;
1230 : 38345 : sal_uInt16 i = 0;
1231 : :
1232 : : // negative number
1233 [ - + ]: 38345 : if ( nNumber < 0 )
1234 : : {
1235 : 0 : nNumber *= -1;
1236 : 0 : *pBuf = '-';
1237 : 0 : pBuf++;
1238 : : }
1239 : :
1240 : : // convert number
1241 : 38345 : pNumBuf = ImplAddUNum( aNumBuf, (sal_uInt64)nNumber );
1242 : 38345 : nNumLen = (sal_uInt16)(sal_uLong)(pNumBuf-aNumBuf);
1243 : 38345 : pNumBuf = aNumBuf;
1244 : :
1245 [ + + ]: 38345 : if ( nNumLen <= nDecimals )
1246 : : {
1247 : : // strip .0 in decimals?
1248 [ + - ][ + + ]: 2122 : if ( !nNumber && !bTrailingZeros )
1249 : : {
1250 : 961 : *pBuf = '0';
1251 : 961 : pBuf++;
1252 : : }
1253 : : else
1254 : : {
1255 : : // LeadingZero, insert 0
1256 [ + - ]: 1161 : if ( isNumLeadingZero() )
1257 : : {
1258 : 1161 : *pBuf = '0';
1259 : 1161 : pBuf++;
1260 : : }
1261 : :
1262 : : // append decimal separator
1263 [ + - ]: 1161 : pBuf = ImplAddString( pBuf, getNumDecimalSep() );
1264 : :
1265 : : // fill with zeros
1266 [ + + ]: 2322 : while ( i < (nDecimals-nNumLen) )
1267 : : {
1268 : 1161 : *pBuf = '0';
1269 : 1161 : pBuf++;
1270 : 1161 : i++;
1271 : : }
1272 : :
1273 : : // append decimals
1274 [ + + ]: 3283 : while ( nNumLen )
1275 : : {
1276 : 1161 : *pBuf = *pNumBuf;
1277 : 1161 : pBuf++;
1278 : 1161 : pNumBuf++;
1279 : 1161 : nNumLen--;
1280 : : }
1281 : : }
1282 : : }
1283 : : else
1284 : : {
1285 [ + - ]: 36223 : const rtl::OUString& rThoSep = getNumThousandSep();
1286 : :
1287 : : // copy number to buffer (excluding decimals)
1288 : 36223 : sal_uInt16 nNumLen2 = nNumLen-nDecimals;
1289 [ + - ]: 36223 : uno::Sequence< sal_Bool > aGroupPos;
1290 [ + - ]: 36223 : if (bUseThousandSep)
1291 : : aGroupPos = utl::DigitGroupingIterator::createForwardSequence(
1292 [ + - ][ + - ]: 36223 : nNumLen2, getDigitGrouping());
[ + - ][ + - ]
[ + - ]
1293 [ + + ]: 99284 : for ( ; i < nNumLen2; ++i )
1294 : : {
1295 : 63061 : *pBuf = *pNumBuf;
1296 : 63061 : pBuf++;
1297 : 63061 : pNumBuf++;
1298 : :
1299 : : // add thousand separator?
1300 [ + - ][ + - ]: 63061 : if ( bUseThousandSep && aGroupPos[i] )
[ - + ][ - + ]
1301 : 0 : pBuf = ImplAddString( pBuf, rThoSep );
1302 : : }
1303 : :
1304 : : // append decimals
1305 [ + + ]: 36223 : if ( nDecimals )
1306 : : {
1307 [ + - ]: 33479 : pBuf = ImplAddString( pBuf, getNumDecimalSep() );
1308 : :
1309 : 33479 : sal_Bool bNullEnd = sal_True;
1310 [ + + ]: 66958 : while ( i < nNumLen )
1311 : : {
1312 [ + + ]: 33479 : if ( *pNumBuf != '0' )
1313 : 940 : bNullEnd = sal_False;
1314 : :
1315 : 33479 : *pBuf = *pNumBuf;
1316 : 33479 : pBuf++;
1317 : 33479 : pNumBuf++;
1318 : 33479 : i++;
1319 : : }
1320 : :
1321 : : // strip .0 in decimals?
1322 [ + + ][ + - ]: 33479 : if ( bNullEnd && !bTrailingZeros )
1323 : 32539 : pBuf -= nDecimals+1;
1324 [ + - ]: 36223 : }
1325 : : }
1326 : :
1327 : 38345 : return pBuf;
1328 : : }
1329 : :
1330 : :
1331 : : // --- simple date and time formatting --------------------------------
1332 : :
1333 : 107 : rtl::OUString LocaleDataWrapper::getDate( const Date& rDate ) const
1334 : : {
1335 [ + - ]: 107 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
1336 : : //!TODO: leading zeros et al
1337 : : sal_Unicode aBuf[128];
1338 : 107 : sal_Unicode* pBuf = aBuf;
1339 : 107 : sal_uInt16 nDay = rDate.GetDay();
1340 : 107 : sal_uInt16 nMonth = rDate.GetMonth();
1341 : 107 : sal_uInt16 nYear = rDate.GetYear();
1342 : : sal_uInt16 nYearLen;
1343 : :
1344 : : if ( sal_True /* IsDateCentury() */ )
1345 : 107 : nYearLen = 4;
1346 : : else
1347 : : {
1348 : : nYearLen = 2;
1349 : : nYear %= 100;
1350 : : }
1351 : :
1352 [ - + - ]: 107 : switch ( getDateFormat() )
[ + - ]
1353 : : {
1354 : : case DMY :
1355 : 0 : pBuf = ImplAdd2UNum( pBuf, nDay, sal_True /* IsDateDayLeadingZero() */ );
1356 [ # # ]: 0 : pBuf = ImplAddString( pBuf, getDateSep() );
1357 : 0 : pBuf = ImplAdd2UNum( pBuf, nMonth, sal_True /* IsDateMonthLeadingZero() */ );
1358 [ # # ]: 0 : pBuf = ImplAddString( pBuf, getDateSep() );
1359 : 0 : pBuf = ImplAddUNum( pBuf, nYear, nYearLen );
1360 : 0 : break;
1361 : : case MDY :
1362 : 107 : pBuf = ImplAdd2UNum( pBuf, nMonth, sal_True /* IsDateMonthLeadingZero() */ );
1363 [ + - ]: 107 : pBuf = ImplAddString( pBuf, getDateSep() );
1364 : 107 : pBuf = ImplAdd2UNum( pBuf, nDay, sal_True /* IsDateDayLeadingZero() */ );
1365 [ + - ]: 107 : pBuf = ImplAddString( pBuf, getDateSep() );
1366 : 107 : pBuf = ImplAddUNum( pBuf, nYear, nYearLen );
1367 : 107 : break;
1368 : : default:
1369 : 0 : pBuf = ImplAddUNum( pBuf, nYear, nYearLen );
1370 [ # # ]: 0 : pBuf = ImplAddString( pBuf, getDateSep() );
1371 : 0 : pBuf = ImplAdd2UNum( pBuf, nMonth, sal_True /* IsDateMonthLeadingZero() */ );
1372 [ # # ]: 0 : pBuf = ImplAddString( pBuf, getDateSep() );
1373 : 0 : pBuf = ImplAdd2UNum( pBuf, nDay, sal_True /* IsDateDayLeadingZero() */ );
1374 : : }
1375 : :
1376 [ + - ]: 107 : return rtl::OUString(aBuf, pBuf-aBuf);
1377 : : }
1378 : :
1379 : :
1380 : 450 : rtl::OUString LocaleDataWrapper::getTime( const Time& rTime, sal_Bool bSec, sal_Bool b100Sec ) const
1381 : : {
1382 [ + - ]: 450 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
1383 : : //!TODO: leading zeros et al
1384 : : sal_Unicode aBuf[128];
1385 : 450 : sal_Unicode* pBuf = aBuf;
1386 : 450 : sal_uInt16 nHour = rTime.GetHour();
1387 : 450 : sal_Bool bHour12 = sal_False; //!TODO: AM/PM from default time format code
1388 : :
1389 [ - + ]: 450 : if ( bHour12 )
1390 : : {
1391 : 0 : nHour %= 12;
1392 : : // 0:00 -> 12:00
1393 [ # # ]: 0 : if ( !nHour )
1394 : 0 : nHour = 12;
1395 : : }
1396 : : else
1397 : 450 : nHour %= 24;
1398 : :
1399 : 450 : pBuf = ImplAdd2UNum( pBuf, nHour, sal_True /* IsTimeLeadingZero() */ );
1400 [ + - ]: 450 : pBuf = ImplAddString( pBuf, getTimeSep() );
1401 : 450 : pBuf = ImplAdd2UNum( pBuf, rTime.GetMin(), sal_True );
1402 [ + + ]: 450 : if ( bSec )
1403 : : {
1404 [ + - ]: 130 : pBuf = ImplAddString( pBuf, getTimeSep() );
1405 : 130 : pBuf = ImplAdd2UNum( pBuf, rTime.GetSec(), sal_True );
1406 : :
1407 [ - + ]: 130 : if ( b100Sec )
1408 : : {
1409 [ # # ]: 0 : pBuf = ImplAddString( pBuf, getTime100SecSep() );
1410 : 0 : pBuf = ImplAdd2UNum( pBuf, rTime.Get100Sec(), sal_True );
1411 : : }
1412 : : }
1413 : :
1414 : 450 : rtl::OUString aStr(aBuf, pBuf - aBuf);
1415 : :
1416 [ - + ]: 450 : if ( bHour12 )
1417 : : {
1418 [ # # ]: 0 : if ( (rTime.GetHour() % 24) >= 12 )
1419 [ # # ]: 0 : aStr += getTimePM();
1420 : : else
1421 [ # # ]: 0 : aStr += getTimeAM();
1422 : : }
1423 : :
1424 [ + - ]: 450 : return aStr;
1425 : : }
1426 : :
1427 : :
1428 : 95 : rtl::OUString LocaleDataWrapper::getLongDate( const Date& rDate, CalendarWrapper& rCal,
1429 : : sal_Int16 nDisplayDayOfWeek, sal_Bool bDayOfMonthWithLeadingZero,
1430 : : sal_Int16 nDisplayMonth, sal_Bool bTwoDigitYear ) const
1431 : : {
1432 [ + - ]: 95 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
1433 : : using namespace ::com::sun::star::i18n;
1434 : : sal_Unicode aBuf[20];
1435 : : sal_Unicode* pBuf;
1436 [ + - ]: 95 : String aStr;
1437 : : sal_Int16 nVal;
1438 [ + - ]: 95 : rCal.setGregorianDateTime( rDate );
1439 : : // day of week
1440 [ + - ]: 95 : nVal = rCal.getValue( CalendarFieldIndex::DAY_OF_WEEK );
1441 [ + - ][ + - ]: 95 : aStr += rCal.getDisplayName( CalendarDisplayIndex::DAY, nVal, nDisplayDayOfWeek );
[ + - ]
1442 [ + - ][ + - ]: 95 : aStr += getLongDateDayOfWeekSep();
1443 : : // day of month
1444 [ + - ]: 95 : nVal = rCal.getValue( CalendarFieldIndex::DAY_OF_MONTH );
1445 : 95 : pBuf = ImplAdd2UNum( aBuf, nVal, bDayOfMonthWithLeadingZero );
1446 : 95 : rtl::OUString aDay(aBuf, pBuf-aBuf);
1447 : : // month of year
1448 [ + - ]: 95 : nVal = rCal.getValue( CalendarFieldIndex::MONTH );
1449 [ + - ][ + - ]: 95 : rtl::OUString aMonth( rCal.getDisplayName( CalendarDisplayIndex::MONTH, nVal, nDisplayMonth ) );
[ + - ]
1450 : : // year
1451 [ + - ]: 95 : nVal = rCal.getValue( CalendarFieldIndex::YEAR );
1452 [ - + ]: 95 : if ( bTwoDigitYear )
1453 : 0 : pBuf = ImplAddUNum( aBuf, nVal % 100, 2 );
1454 : : else
1455 : 95 : pBuf = ImplAddUNum( aBuf, nVal );
1456 : 95 : rtl::OUString aYear(aBuf, pBuf-aBuf);
1457 : : // concatenate
1458 [ - + - ]: 95 : switch ( getLongDateFormat() )
[ + - ]
1459 : : {
1460 : : case DMY :
1461 [ # # ]: 0 : aStr += aDay;
1462 [ # # ][ # # ]: 0 : aStr += getLongDateDaySep();
1463 [ # # ]: 0 : aStr += aMonth;
1464 [ # # ][ # # ]: 0 : aStr += getLongDateMonthSep();
1465 [ # # ]: 0 : aStr += aYear;
1466 : 0 : break;
1467 : : case MDY :
1468 [ + - ]: 95 : aStr += aMonth;
1469 [ + - ][ + - ]: 95 : aStr += getLongDateMonthSep();
1470 [ + - ]: 95 : aStr += aDay;
1471 [ + - ][ + - ]: 95 : aStr += getLongDateDaySep();
1472 [ + - ]: 95 : aStr += aYear;
1473 : 95 : break;
1474 : : default: // YMD
1475 [ # # ]: 0 : aStr += aYear;
1476 [ # # ][ # # ]: 0 : aStr += getLongDateYearSep();
1477 [ # # ]: 0 : aStr += aMonth;
1478 [ # # ][ # # ]: 0 : aStr += getLongDateMonthSep();
1479 [ # # ]: 0 : aStr += aDay;
1480 : : }
1481 [ + - ][ + - ]: 95 : return aStr;
[ + - ]
1482 : : }
1483 : :
1484 : :
1485 : 12 : rtl::OUString LocaleDataWrapper::getDuration( const Time& rTime, sal_Bool bSec, sal_Bool b100Sec ) const
1486 : : {
1487 [ + - ]: 12 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
1488 : : sal_Unicode aBuf[128];
1489 : 12 : sal_Unicode* pBuf = aBuf;
1490 : :
1491 [ - + ]: 12 : if ( rTime < Time( 0 ) )
1492 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1493 : :
1494 : : if ( sal_True /* IsTimeLeadingZero() */ )
1495 : 12 : pBuf = ImplAddUNum( pBuf, rTime.GetHour(), 2 );
1496 : : else
1497 : : pBuf = ImplAddUNum( pBuf, rTime.GetHour() );
1498 [ + - ]: 12 : pBuf = ImplAddString( pBuf, getTimeSep() );
1499 : 12 : pBuf = ImplAdd2UNum( pBuf, rTime.GetMin(), sal_True );
1500 [ + + ]: 12 : if ( bSec )
1501 : : {
1502 [ + - ]: 2 : pBuf = ImplAddString( pBuf, getTimeSep() );
1503 : 2 : pBuf = ImplAdd2UNum( pBuf, rTime.GetSec(), sal_True );
1504 : :
1505 [ - + ]: 2 : if ( b100Sec )
1506 : : {
1507 [ # # ]: 0 : pBuf = ImplAddString( pBuf, getTime100SecSep() );
1508 : 0 : pBuf = ImplAdd2UNum( pBuf, rTime.Get100Sec(), sal_True );
1509 : : }
1510 : : }
1511 : :
1512 [ + - ]: 12 : return rtl::OUString(aBuf, pBuf-aBuf);
1513 : : }
1514 : :
1515 : :
1516 : : // --- simple number formatting ---------------------------------------
1517 : :
1518 : 38345 : inline size_t ImplGetNumberStringLengthGuess( const LocaleDataWrapper& rLoc, sal_uInt16 nDecimals )
1519 : : {
1520 : : // approximately 3.2 bits per digit
1521 : 38345 : const size_t nDig = ((sizeof(sal_Int64) * 8) / 3) + 1;
1522 : : // digits, separators (pessimized for insane "every digit may be grouped"), leading zero, sign
1523 : : size_t nGuess = ((nDecimals < nDig) ?
1524 : 38345 : (((nDig - nDecimals) * rLoc.getNumThousandSep().getLength()) + nDig) :
1525 [ + - ]: 76690 : nDecimals) + rLoc.getNumDecimalSep().getLength() + 3;
1526 : 38345 : return nGuess;
1527 : : }
1528 : :
1529 : :
1530 : 38345 : rtl::OUString LocaleDataWrapper::getNum( sal_Int64 nNumber, sal_uInt16 nDecimals,
1531 : : sal_Bool bUseThousandSep, sal_Bool bTrailingZeros ) const
1532 : : {
1533 [ + - ]: 38345 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
1534 : : sal_Unicode aBuf[128]; // big enough for 64-bit long and crazy grouping
1535 : : // check if digits and separators will fit into fixed buffer or allocate
1536 [ + - ]: 38345 : size_t nGuess = ImplGetNumberStringLengthGuess( *this, nDecimals );
1537 : : sal_Unicode* const pBuffer = (nGuess < 118 ? aBuf :
1538 [ + - ][ # # ]: 38345 : new sal_Unicode[nGuess + 16]);
1539 : :
1540 : : sal_Unicode* pBuf = ImplAddFormatNum( pBuffer, nNumber, nDecimals,
1541 [ + - ]: 38345 : bUseThousandSep, bTrailingZeros );
1542 : 38345 : rtl::OUString aStr(pBuffer, pBuf-pBuffer);
1543 : :
1544 [ - + ]: 38345 : if ( pBuffer != aBuf )
1545 [ # # ]: 0 : delete [] pBuffer;
1546 [ + - ]: 38345 : return aStr;
1547 : : }
1548 : :
1549 : 0 : rtl::OUString LocaleDataWrapper::getCurr( sal_Int64 nNumber, sal_uInt16 nDecimals,
1550 : : const rtl::OUString& rCurrencySymbol, sal_Bool bUseThousandSep ) const
1551 : : {
1552 [ # # ]: 0 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
1553 : : sal_Unicode aBuf[192];
1554 : : sal_Unicode aNumBuf[128]; // big enough for 64-bit long and crazy grouping
1555 : 0 : sal_Unicode cZeroChar = getCurrZeroChar();
1556 : :
1557 : : // check if digits and separators will fit into fixed buffer or allocate
1558 [ # # ]: 0 : size_t nGuess = ImplGetNumberStringLengthGuess( *this, nDecimals );
1559 : : sal_Unicode* const pNumBuffer = (nGuess < 118 ? aNumBuf :
1560 [ # # ][ # # ]: 0 : new sal_Unicode[nGuess + 16]);
1561 : :
1562 : : sal_Unicode* const pBuffer =
1563 : 0 : ((size_t(rCurrencySymbol.getLength()) + nGuess + 20) < SAL_N_ELEMENTS(aBuf) ? aBuf :
1564 [ # # ][ # # ]: 0 : new sal_Unicode[ rCurrencySymbol.getLength() + nGuess + 20 ]);
1565 : 0 : sal_Unicode* pBuf = pBuffer;
1566 : :
1567 : : sal_Bool bNeg;
1568 [ # # ]: 0 : if ( nNumber < 0 )
1569 : : {
1570 : 0 : bNeg = sal_True;
1571 : 0 : nNumber *= -1;
1572 : : }
1573 : : else
1574 : 0 : bNeg = sal_False;
1575 : :
1576 : : // convert number
1577 : : sal_Unicode* pEndNumBuf = ImplAddFormatNum( pNumBuffer, nNumber, nDecimals,
1578 [ # # ]: 0 : bUseThousandSep, sal_True );
1579 : 0 : xub_StrLen nNumLen = (xub_StrLen)(sal_uLong)(pEndNumBuf-pNumBuffer);
1580 : :
1581 : : // replace zeros with zero character
1582 [ # # ][ # # ]: 0 : if ( (cZeroChar != '0') && nDecimals /* && IsNumTrailingZeros() */ )
1583 : : {
1584 : : sal_Unicode* pTempBuf;
1585 : : sal_uInt16 i;
1586 : 0 : sal_Bool bZero = sal_True;
1587 : :
1588 : 0 : pTempBuf = pNumBuffer+nNumLen-nDecimals;
1589 : 0 : i = 0;
1590 [ # # ]: 0 : do
1591 : : {
1592 [ # # ]: 0 : if ( *pTempBuf != '0' )
1593 : : {
1594 : 0 : bZero = sal_False;
1595 : 0 : break;
1596 : : }
1597 : :
1598 : 0 : pTempBuf++;
1599 : 0 : i++;
1600 : : }
1601 : : while ( i < nDecimals );
1602 : :
1603 [ # # ]: 0 : if ( bZero )
1604 : : {
1605 : 0 : pTempBuf = pNumBuffer+nNumLen-nDecimals;
1606 : 0 : i = 0;
1607 [ # # ]: 0 : do
1608 : : {
1609 : 0 : *pTempBuf = cZeroChar;
1610 : 0 : pTempBuf++;
1611 : 0 : i++;
1612 : : }
1613 : : while ( i < nDecimals );
1614 : : }
1615 : : }
1616 : :
1617 [ # # ]: 0 : if ( !bNeg )
1618 : : {
1619 [ # # ][ # # : 0 : switch( getCurrPositiveFormat() )
# # # ]
1620 : : {
1621 : : case 0:
1622 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1623 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1624 : 0 : break;
1625 : : case 1:
1626 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1627 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1628 : 0 : break;
1629 : : case 2:
1630 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1631 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1632 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1633 : 0 : break;
1634 : : case 3:
1635 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1636 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1637 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1638 : 0 : break;
1639 : : }
1640 : : }
1641 : : else
1642 : : {
1643 [ # # ][ # # : 0 : switch( getCurrNegativeFormat() )
# # # # #
# # # # #
# # # #
# ]
1644 : : {
1645 : : case 0:
1646 : 0 : pBuf = ImplAddString( pBuf, '(' );
1647 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1648 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1649 : 0 : pBuf = ImplAddString( pBuf, ')' );
1650 : 0 : break;
1651 : : case 1:
1652 : 0 : pBuf = ImplAddString( pBuf, '-' );
1653 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1654 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1655 : 0 : break;
1656 : : case 2:
1657 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1658 : 0 : pBuf = ImplAddString( pBuf, '-' );
1659 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1660 : 0 : break;
1661 : : case 3:
1662 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1663 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1664 : 0 : pBuf = ImplAddString( pBuf, '-' );
1665 : 0 : break;
1666 : : case 4:
1667 : 0 : pBuf = ImplAddString( pBuf, '(' );
1668 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1669 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1670 : 0 : pBuf = ImplAddString( pBuf, ')' );
1671 : 0 : break;
1672 : : case 5:
1673 : 0 : pBuf = ImplAddString( pBuf, '-' );
1674 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1675 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1676 : 0 : break;
1677 : : case 6:
1678 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1679 : 0 : pBuf = ImplAddString( pBuf, '-' );
1680 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1681 : 0 : break;
1682 : : case 7:
1683 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1684 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1685 : 0 : pBuf = ImplAddString( pBuf, '-' );
1686 : 0 : break;
1687 : : case 8:
1688 : 0 : pBuf = ImplAddString( pBuf, '-' );
1689 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1690 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1691 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1692 : 0 : break;
1693 : : case 9:
1694 : 0 : pBuf = ImplAddString( pBuf, '-' );
1695 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1696 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1697 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1698 : 0 : break;
1699 : : case 10:
1700 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1701 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1702 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1703 : 0 : pBuf = ImplAddString( pBuf, '-' );
1704 : 0 : break;
1705 : : case 11:
1706 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1707 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1708 : 0 : pBuf = ImplAddString( pBuf, '-' );
1709 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1710 : 0 : break;
1711 : : case 12:
1712 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1713 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1714 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1715 : 0 : pBuf = ImplAddString( pBuf, '-' );
1716 : 0 : break;
1717 : : case 13:
1718 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1719 : 0 : pBuf = ImplAddString( pBuf, '-' );
1720 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1721 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1722 : 0 : break;
1723 : : case 14:
1724 : 0 : pBuf = ImplAddString( pBuf, '(' );
1725 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1726 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1727 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1728 : 0 : pBuf = ImplAddString( pBuf, ')' );
1729 : 0 : break;
1730 : : case 15:
1731 : 0 : pBuf = ImplAddString( pBuf, '(' );
1732 : 0 : pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
1733 : 0 : pBuf = ImplAddString( pBuf, ' ' );
1734 : 0 : pBuf = ImplAddString( pBuf, rCurrencySymbol );
1735 : 0 : pBuf = ImplAddString( pBuf, ')' );
1736 : 0 : break;
1737 : : }
1738 : : }
1739 : :
1740 : 0 : rtl::OUString aNumber(pBuffer, pBuf-pBuffer);
1741 : :
1742 [ # # ]: 0 : if ( pBuffer != aBuf )
1743 [ # # ]: 0 : delete [] pBuffer;
1744 [ # # ]: 0 : if ( pNumBuffer != aNumBuf )
1745 [ # # ]: 0 : delete [] pNumBuffer;
1746 : :
1747 [ # # ]: 0 : return aNumber;
1748 : : }
1749 : :
1750 : :
1751 : : // --- mixed ----------------------------------------------------------
1752 : :
1753 : 73317 : ::com::sun::star::lang::Locale LocaleDataWrapper::getLoadedLocale() const
1754 : : {
1755 [ + - ]: 73317 : LanguageCountryInfo aLCInfo = getLanguageCountryInfo();
1756 : 73317 : return lang::Locale( aLCInfo.Language, aLCInfo.Country, aLCInfo.Variant );
1757 : : }
1758 : :
1759 : :
1760 : 0 : rtl::OUString LocaleDataWrapper::appendLocaleInfo(const rtl::OUString& rDebugMsg) const
1761 : : {
1762 [ # # ]: 0 : ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
1763 [ # # ]: 0 : rtl::OUStringBuffer aDebugMsg(rDebugMsg);
1764 [ # # ]: 0 : aDebugMsg.append(static_cast<sal_Unicode>('\n'));
1765 [ # # ]: 0 : aDebugMsg.append(aLocale.Language);
1766 [ # # ]: 0 : aDebugMsg.append(static_cast<sal_Unicode>('_'));
1767 [ # # ]: 0 : aDebugMsg.append(aLocale.Country);
1768 [ # # ]: 0 : aDebugMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM(" requested\n"));
1769 [ # # ]: 0 : lang::Locale aLoaded = getLoadedLocale();
1770 [ # # ]: 0 : aDebugMsg.append(aLoaded.Language);
1771 [ # # ]: 0 : aDebugMsg.append(static_cast<sal_Unicode>('_'));
1772 [ # # ]: 0 : aDebugMsg.append(aLoaded.Country);
1773 [ # # ]: 0 : aDebugMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM(" loaded"));
1774 [ # # ][ # # ]: 0 : return aDebugMsg.makeStringAndClear();
1775 : : }
1776 : :
1777 : :
1778 : : // static
1779 : 0 : void LocaleDataWrapper::outputCheckMessage( const rtl::OUString& rMsg )
1780 : : {
1781 [ # # ]: 0 : outputCheckMessage(rtl::OUStringToOString(rMsg, RTL_TEXTENCODING_UTF8).getStr());
1782 : 0 : }
1783 : :
1784 : :
1785 : : // static
1786 : 0 : void LocaleDataWrapper::outputCheckMessage( const char* pStr )
1787 : : {
1788 : 0 : fprintf( stderr, "\n%s\n", pStr);
1789 : 0 : fflush( stderr);
1790 : : OSL_TRACE("%s", pStr);
1791 : 0 : }
1792 : :
1793 : :
1794 : : // static
1795 : 123 : void LocaleDataWrapper::evaluateLocaleDataChecking()
1796 : : {
1797 : : // Using the rtl_Instance template here wouldn't solve all threaded write
1798 : : // accesses, since we want to assign the result to the static member
1799 : : // variable and would need to dereference the pointer returned and assign
1800 : : // the value unguarded. This is the same pattern manually coded.
1801 : 123 : sal_uInt8 nCheck = nLocaleDataChecking;
1802 [ + - ]: 123 : if (!nCheck)
1803 : : {
1804 [ + - ][ + - ]: 123 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex());
1805 : 123 : nCheck = nLocaleDataChecking;
1806 [ + - ]: 123 : if (!nCheck)
1807 : : {
1808 : : #ifdef DBG_UTIL
1809 : : nCheck = 1;
1810 : : #else
1811 : 123 : const char* pEnv = getenv( "OOO_ENABLE_LOCALE_DATA_CHECKS");
1812 [ # # ][ # # ]: 123 : if (pEnv && (pEnv[0] == 'Y' || pEnv[0] == 'y' || pEnv[0] == '1'))
[ # # ][ - + ]
1813 : 0 : nCheck = 1;
1814 : : else
1815 : 123 : nCheck = 2;
1816 : : #endif
1817 : : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
1818 : 123 : nLocaleDataChecking = nCheck;
1819 [ + - ]: 123 : }
1820 : : }
1821 : : else {
1822 : : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
1823 : : }
1824 : 123 : }
1825 : :
1826 : :
1827 : : // --- XLocaleData3 ----------------------------------------------------------
1828 : :
1829 : 51 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar2 > LocaleDataWrapper::getAllCalendars() const
1830 : : {
1831 : : try
1832 : : {
1833 [ + - ]: 51 : if ( xLD.is() )
1834 [ + - ][ + - ]: 51 : return xLD->getAllCalendars2( getLocale() );
[ + - ]
1835 : : }
1836 : 0 : catch (const Exception& e)
1837 : : {
1838 : : SAL_WARN( "unotools.i18n", "getAllCalendars: Exception caught " << e.Message );
1839 : : }
1840 [ # # ]: 51 : return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar2 >(0);
1841 : : }
1842 : :
1843 : :
1844 : : // --- XLocaleData4 ----------------------------------------------------------
1845 : :
1846 : 54 : ::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getDateAcceptancePatterns() const
1847 : : {
1848 : : try
1849 : : {
1850 [ + - ]: 54 : if ( xLD.is() )
1851 [ + - ][ + - ]: 54 : return xLD->getDateAcceptancePatterns( getLocale() );
[ + - ]
1852 : : }
1853 : 0 : catch (const Exception& e)
1854 : : {
1855 : : SAL_WARN( "unotools.i18n", "getDateAcceptancePatterns: Exception caught " << e.Message );
1856 : : }
1857 [ # # ]: 54 : return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0);
1858 : : }
1859 : :
1860 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|