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