1*f8e2c85aSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*f8e2c85aSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*f8e2c85aSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*f8e2c85aSAndrew Rist  * distributed with this work for additional information
6*f8e2c85aSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*f8e2c85aSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*f8e2c85aSAndrew Rist  * "License"); you may not use this file except in compliance
9*f8e2c85aSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*f8e2c85aSAndrew Rist  *
11*f8e2c85aSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*f8e2c85aSAndrew Rist  *
13*f8e2c85aSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*f8e2c85aSAndrew Rist  * software distributed under the License is distributed on an
15*f8e2c85aSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*f8e2c85aSAndrew Rist  * KIND, either express or implied.  See the License for the
17*f8e2c85aSAndrew Rist  * specific language governing permissions and limitations
18*f8e2c85aSAndrew Rist  * under the License.
19*f8e2c85aSAndrew Rist  *
20*f8e2c85aSAndrew Rist  *************************************************************/
21*f8e2c85aSAndrew Rist 
22*f8e2c85aSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_shell.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "localebackend.hxx"
28cdf0e10cSrcweir #include <com/sun/star/beans/Optional.hpp>
29cdf0e10cSrcweir #include <osl/time.h>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <stdio.h>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
36cdf0e10cSrcweir #include <locale.h>
37cdf0e10cSrcweir #include <string.h>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir /*
40cdf0e10cSrcweir  * Note: setlocale is not at all thread safe, so is this code. It could
41cdf0e10cSrcweir  * especially interfere with the stuff VCL is doing, so make sure this
42cdf0e10cSrcweir  * is called from the main thread only.
43cdf0e10cSrcweir  */
44cdf0e10cSrcweir 
ImplGetLocale(int category)45cdf0e10cSrcweir static rtl::OUString ImplGetLocale(int category)
46cdf0e10cSrcweir {
47cdf0e10cSrcweir     const char *locale = setlocale(category, "");
48cdf0e10cSrcweir 
49cdf0e10cSrcweir     // Return "en-US" for C locales
50cdf0e10cSrcweir     if( (locale == NULL) || ( locale[0] == 'C' && locale[1] == '\0' ) )
51cdf0e10cSrcweir         return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "en-US" ) );
52cdf0e10cSrcweir 
53cdf0e10cSrcweir 
54cdf0e10cSrcweir     const char *cp;
55cdf0e10cSrcweir     const char *uscore = NULL;
56cdf0e10cSrcweir 
57cdf0e10cSrcweir     // locale string have the format lang[_ctry][.encoding][@modifier]
58cdf0e10cSrcweir     // we are only interested in the first two items, so we handle
59cdf0e10cSrcweir     // '.' and '@' as string end.
60cdf0e10cSrcweir     for (cp = locale; *cp; cp++)
61cdf0e10cSrcweir     {
62cdf0e10cSrcweir         if (*cp == '_')
63cdf0e10cSrcweir             uscore = cp;
64cdf0e10cSrcweir         if (*cp == '.' || *cp == '@')
65cdf0e10cSrcweir             break;
66cdf0e10cSrcweir     }
67cdf0e10cSrcweir 
68cdf0e10cSrcweir     rtl::OUStringBuffer aLocaleBuffer;
69cdf0e10cSrcweir     if( uscore != NULL )
70cdf0e10cSrcweir     {
71cdf0e10cSrcweir         aLocaleBuffer.appendAscii(locale, uscore++ - locale);
72cdf0e10cSrcweir         aLocaleBuffer.appendAscii("-");
73cdf0e10cSrcweir         aLocaleBuffer.appendAscii(uscore, cp - uscore);
74cdf0e10cSrcweir     }
75cdf0e10cSrcweir     else
76cdf0e10cSrcweir     {
77cdf0e10cSrcweir         aLocaleBuffer.appendAscii(locale, cp - locale);
78cdf0e10cSrcweir     }
79cdf0e10cSrcweir 
80cdf0e10cSrcweir     return aLocaleBuffer.makeStringAndClear();
81cdf0e10cSrcweir }
82cdf0e10cSrcweir 
83cdf0e10cSrcweir #elif defined(MACOSX)
84cdf0e10cSrcweir 
85cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
86cdf0e10cSrcweir #include <locale.h>
87cdf0e10cSrcweir #include <string.h>
88cdf0e10cSrcweir 
89cdf0e10cSrcweir #include <premac.h>
90cdf0e10cSrcweir #include <CoreServices/CoreServices.h>
91cdf0e10cSrcweir #include <CoreFoundation/CoreFoundation.h>
92cdf0e10cSrcweir #include <postmac.h>
93cdf0e10cSrcweir 
94cdf0e10cSrcweir namespace /* private */
95cdf0e10cSrcweir {
96cdf0e10cSrcweir 
OUStringBufferAppendCFString(rtl::OUStringBuffer & buffer,const CFStringRef s)97cdf0e10cSrcweir 	void OUStringBufferAppendCFString(rtl::OUStringBuffer& buffer, const CFStringRef s)
98cdf0e10cSrcweir 	{
99cdf0e10cSrcweir 		CFIndex lstr = CFStringGetLength(s);
100cdf0e10cSrcweir 		for (CFIndex i = 0; i < lstr; i++)
101cdf0e10cSrcweir 			buffer.append(CFStringGetCharacterAtIndex(s, i));
102cdf0e10cSrcweir 	}
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 	template <typename T>
105cdf0e10cSrcweir 	class CFGuard
106cdf0e10cSrcweir 	{
107cdf0e10cSrcweir 	public:
CFGuard(T & rT)108cdf0e10cSrcweir 		explicit CFGuard(T& rT) : rT_(rT) {}
~CFGuard()109cdf0e10cSrcweir 		~CFGuard() { if (rT_) CFRelease(rT_); }
110cdf0e10cSrcweir 	private:
111cdf0e10cSrcweir 		T& rT_;
112cdf0e10cSrcweir 	};
113cdf0e10cSrcweir 
114cdf0e10cSrcweir 	typedef CFGuard<CFArrayRef> CFArrayGuard;
115cdf0e10cSrcweir 	typedef CFGuard<CFStringRef> CFStringGuard;
116cdf0e10cSrcweir 	typedef CFGuard<CFTypeRef> CFTypeRefGuard;
117cdf0e10cSrcweir 
118cdf0e10cSrcweir 	/* For more information on the Apple locale concept please refer to
119cdf0e10cSrcweir 	http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFLocales/Articles/CFLocaleConcepts.html
120cdf0e10cSrcweir 	According to this documentation a locale identifier has the format: language[_country][_variant]*
121cdf0e10cSrcweir 	e.g. es_ES_PREEURO -> spain prior Euro support
122cdf0e10cSrcweir 	Note: The calling code should be able to handle locales with only language information e.g. 'en' for certain
123cdf0e10cSrcweir 	UI languages just the language code will be returned.
124cdf0e10cSrcweir 	*/
125cdf0e10cSrcweir 
ImplGetAppPreference(const char * pref)126cdf0e10cSrcweir 	CFStringRef ImplGetAppPreference(const char* pref)
127cdf0e10cSrcweir 	{
128cdf0e10cSrcweir 		CFStringRef csPref = CFStringCreateWithCString(NULL, pref, kCFStringEncodingASCII);
129cdf0e10cSrcweir 		CFStringGuard csRefGuard(csPref);
130cdf0e10cSrcweir 
131cdf0e10cSrcweir 		CFTypeRef ref = CFPreferencesCopyAppValue(csPref, kCFPreferencesCurrentApplication);
132cdf0e10cSrcweir 		CFTypeRefGuard refGuard(ref);
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 		if (ref == NULL)
135cdf0e10cSrcweir 			return NULL;
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 		CFStringRef sref = (CFGetTypeID(ref) == CFArrayGetTypeID()) ? (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)ref, 0) : (CFStringRef)ref;
138cdf0e10cSrcweir 
139cdf0e10cSrcweir 		// NOTE: this API is only available with Mac OS X >=10.3. We need to use it because
140cdf0e10cSrcweir 		// Apple used non-ISO values on systems <10.2 like "German" for instance but didn't
141cdf0e10cSrcweir 		// upgrade those values during upgrade to newer Mac OS X versions. See also #i54337#
142cdf0e10cSrcweir 		return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref);
143cdf0e10cSrcweir 	}
144cdf0e10cSrcweir 
ImplGetLocale(const char * pref)145cdf0e10cSrcweir 	rtl::OUString ImplGetLocale(const char* pref)
146cdf0e10cSrcweir 	{
147cdf0e10cSrcweir 		CFStringRef sref = ImplGetAppPreference(pref);
148cdf0e10cSrcweir 		CFStringGuard srefGuard(sref);
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 		rtl::OUStringBuffer aLocaleBuffer;
151cdf0e10cSrcweir 		aLocaleBuffer.appendAscii("en-US"); // initialize with fallback value
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 		if (sref != NULL)
154cdf0e10cSrcweir 		{
155cdf0e10cSrcweir 			// split the string into substrings; the first two (if there are two) substrings
156cdf0e10cSrcweir 			// are language and country
157cdf0e10cSrcweir 			CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(NULL, sref, CFSTR("_"));
158cdf0e10cSrcweir 			CFArrayGuard subsGuard(subs);
159cdf0e10cSrcweir 
160cdf0e10cSrcweir 			if (subs != NULL)
161cdf0e10cSrcweir 			{
162cdf0e10cSrcweir 				aLocaleBuffer.setLength(0); // clear buffer which still contains fallback value
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 				CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(subs, 0);
165cdf0e10cSrcweir 				OUStringBufferAppendCFString(aLocaleBuffer, lang);
166cdf0e10cSrcweir 
167cdf0e10cSrcweir 				// country also available? Assumption: if the array contains more than one
168cdf0e10cSrcweir 				// value the second value is always the country!
169cdf0e10cSrcweir 				if (CFArrayGetCount(subs) > 1)
170cdf0e10cSrcweir 				{
171cdf0e10cSrcweir 					aLocaleBuffer.appendAscii("-");
172cdf0e10cSrcweir 					CFStringRef country = (CFStringRef)CFArrayGetValueAtIndex(subs, 1);
173cdf0e10cSrcweir 					OUStringBufferAppendCFString(aLocaleBuffer, country);
174cdf0e10cSrcweir 				}
175cdf0e10cSrcweir 			}
176cdf0e10cSrcweir 		}
177cdf0e10cSrcweir 		return aLocaleBuffer.makeStringAndClear();
178cdf0e10cSrcweir 	}
179cdf0e10cSrcweir 
180cdf0e10cSrcweir } // namespace /* private */
181cdf0e10cSrcweir 
182cdf0e10cSrcweir #endif
183cdf0e10cSrcweir 
184cdf0e10cSrcweir // -------------------------------------------------------------------------------
185cdf0e10cSrcweir 
186cdf0e10cSrcweir #ifdef WNT
187cdf0e10cSrcweir 
188cdf0e10cSrcweir #ifdef WINVER
189cdf0e10cSrcweir #undef WINVER
190cdf0e10cSrcweir #endif
191cdf0e10cSrcweir #define WINVER 0x0501
192cdf0e10cSrcweir 
193cdf0e10cSrcweir #if defined _MSC_VER
194cdf0e10cSrcweir #pragma warning(push, 1)
195cdf0e10cSrcweir #endif
196cdf0e10cSrcweir #include <windows.h>
197cdf0e10cSrcweir #if defined _MSC_VER
198cdf0e10cSrcweir #pragma warning(pop)
199cdf0e10cSrcweir #endif
200cdf0e10cSrcweir 
ImplGetLocale(LCID lcid)201cdf0e10cSrcweir rtl::OUString ImplGetLocale(LCID lcid)
202cdf0e10cSrcweir {
203cdf0e10cSrcweir     TCHAR buffer[8];
204cdf0e10cSrcweir     LPTSTR cp = buffer;
205cdf0e10cSrcweir 
206cdf0e10cSrcweir     cp += GetLocaleInfo( lcid, LOCALE_SISO639LANGNAME , buffer, 4 );
207cdf0e10cSrcweir     if( cp > buffer )
208cdf0e10cSrcweir     {
209cdf0e10cSrcweir         if( 0 < GetLocaleInfo( lcid, LOCALE_SISO3166CTRYNAME, cp, buffer + 8 - cp) )
210cdf0e10cSrcweir             // #i50822# minus character must be written before cp
211cdf0e10cSrcweir             *(cp - 1) = '-';
212cdf0e10cSrcweir 
213cdf0e10cSrcweir         return rtl::OUString::createFromAscii(buffer);
214cdf0e10cSrcweir     }
215cdf0e10cSrcweir 
216cdf0e10cSrcweir     return rtl::OUString();
217cdf0e10cSrcweir }
218cdf0e10cSrcweir 
219cdf0e10cSrcweir #endif // WNT
220cdf0e10cSrcweir 
221cdf0e10cSrcweir // -------------------------------------------------------------------------------
222cdf0e10cSrcweir 
LocaleBackend()223cdf0e10cSrcweir LocaleBackend::LocaleBackend()
224cdf0e10cSrcweir {
225cdf0e10cSrcweir }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir //------------------------------------------------------------------------------
228cdf0e10cSrcweir 
~LocaleBackend(void)229cdf0e10cSrcweir LocaleBackend::~LocaleBackend(void)
230cdf0e10cSrcweir {
231cdf0e10cSrcweir }
232cdf0e10cSrcweir 
233cdf0e10cSrcweir //------------------------------------------------------------------------------
234cdf0e10cSrcweir 
createInstance()235cdf0e10cSrcweir LocaleBackend* LocaleBackend::createInstance()
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     return new LocaleBackend;
238cdf0e10cSrcweir }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir // ---------------------------------------------------------------------------------------
241cdf0e10cSrcweir 
getLocale(void)242cdf0e10cSrcweir rtl::OUString LocaleBackend::getLocale(void)
243cdf0e10cSrcweir {
244cdf0e10cSrcweir #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)
245cdf0e10cSrcweir     return ImplGetLocale(LC_CTYPE);
246cdf0e10cSrcweir #elif defined (MACOSX)
247cdf0e10cSrcweir 	return ImplGetLocale("AppleLocale");
248cdf0e10cSrcweir #elif defined WNT
249cdf0e10cSrcweir     return ImplGetLocale( GetUserDefaultLCID() );
250cdf0e10cSrcweir #endif
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir //------------------------------------------------------------------------------
254cdf0e10cSrcweir 
getUILocale(void)255cdf0e10cSrcweir rtl::OUString LocaleBackend::getUILocale(void)
256cdf0e10cSrcweir {
257cdf0e10cSrcweir #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)
258cdf0e10cSrcweir     return ImplGetLocale(LC_MESSAGES);
259cdf0e10cSrcweir #elif defined(MACOSX)
260cdf0e10cSrcweir 	return ImplGetLocale("AppleLanguages");
261cdf0e10cSrcweir #elif defined WNT
262cdf0e10cSrcweir     return ImplGetLocale( MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT) );
263cdf0e10cSrcweir #endif
264cdf0e10cSrcweir }
265cdf0e10cSrcweir 
266cdf0e10cSrcweir // ---------------------------------------------------------------------------------------
267cdf0e10cSrcweir 
getSystemLocale(void)268cdf0e10cSrcweir rtl::OUString LocaleBackend::getSystemLocale(void)
269cdf0e10cSrcweir {
270cdf0e10cSrcweir // note: the implementation differs from getLocale() only on Windows
271cdf0e10cSrcweir #if defined WNT
272cdf0e10cSrcweir     return ImplGetLocale( GetSystemDefaultLCID() );
273cdf0e10cSrcweir #else
274cdf0e10cSrcweir     return getLocale();
275cdf0e10cSrcweir #endif
276cdf0e10cSrcweir }
277cdf0e10cSrcweir //------------------------------------------------------------------------------
278cdf0e10cSrcweir 
setPropertyValue(rtl::OUString const &,css::uno::Any const &)279cdf0e10cSrcweir void LocaleBackend::setPropertyValue(
280cdf0e10cSrcweir     rtl::OUString const &, css::uno::Any const &)
281cdf0e10cSrcweir     throw (
282cdf0e10cSrcweir         css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
283cdf0e10cSrcweir         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
284cdf0e10cSrcweir         css::uno::RuntimeException)
285cdf0e10cSrcweir {
286cdf0e10cSrcweir     throw css::lang::IllegalArgumentException(
287cdf0e10cSrcweir         rtl::OUString(
288cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM("setPropertyValue not supported")),
289cdf0e10cSrcweir         static_cast< cppu::OWeakObject * >(this), -1);
290cdf0e10cSrcweir }
291cdf0e10cSrcweir 
getPropertyValue(rtl::OUString const & PropertyName)292cdf0e10cSrcweir css::uno::Any LocaleBackend::getPropertyValue(
293cdf0e10cSrcweir     rtl::OUString const & PropertyName)
294cdf0e10cSrcweir     throw (
295cdf0e10cSrcweir         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
296cdf0e10cSrcweir         css::uno::RuntimeException)
297cdf0e10cSrcweir {
298cdf0e10cSrcweir     if (PropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Locale"))) {
299cdf0e10cSrcweir         return css::uno::makeAny(
300cdf0e10cSrcweir             css::beans::Optional< css::uno::Any >(
301cdf0e10cSrcweir                 true, css::uno::makeAny(getLocale())));
302cdf0e10cSrcweir     } else if (PropertyName.equalsAsciiL(
303cdf0e10cSrcweir                    RTL_CONSTASCII_STRINGPARAM("SystemLocale")))
304cdf0e10cSrcweir     {
305cdf0e10cSrcweir         return css::uno::makeAny(
306cdf0e10cSrcweir             css::beans::Optional< css::uno::Any >(
307cdf0e10cSrcweir                 true, css::uno::makeAny(getSystemLocale())));
308cdf0e10cSrcweir     } else if (PropertyName.equalsAsciiL(
309cdf0e10cSrcweir                    RTL_CONSTASCII_STRINGPARAM("UILocale")))
310cdf0e10cSrcweir     {
311cdf0e10cSrcweir         return css::uno::makeAny(
312cdf0e10cSrcweir             css::beans::Optional< css::uno::Any >(
313cdf0e10cSrcweir                 true, css::uno::makeAny(getUILocale())));
314cdf0e10cSrcweir     } else {
315cdf0e10cSrcweir         throw css::beans::UnknownPropertyException(
316cdf0e10cSrcweir             PropertyName, static_cast< cppu::OWeakObject * >(this));
317cdf0e10cSrcweir     }
318cdf0e10cSrcweir }
319cdf0e10cSrcweir 
320cdf0e10cSrcweir //------------------------------------------------------------------------------
321cdf0e10cSrcweir 
getBackendName(void)322cdf0e10cSrcweir rtl::OUString SAL_CALL LocaleBackend::getBackendName(void) {
323cdf0e10cSrcweir 	return rtl::OUString::createFromAscii("com.sun.star.comp.configuration.backend.LocaleBackend") ;
324cdf0e10cSrcweir }
325cdf0e10cSrcweir 
326cdf0e10cSrcweir //------------------------------------------------------------------------------
327cdf0e10cSrcweir 
getImplementationName(void)328cdf0e10cSrcweir rtl::OUString SAL_CALL LocaleBackend::getImplementationName(void)
329cdf0e10cSrcweir     throw (uno::RuntimeException)
330cdf0e10cSrcweir {
331cdf0e10cSrcweir     return getBackendName() ;
332cdf0e10cSrcweir }
333cdf0e10cSrcweir 
334cdf0e10cSrcweir //------------------------------------------------------------------------------
335cdf0e10cSrcweir 
getBackendServiceNames(void)336cdf0e10cSrcweir uno::Sequence<rtl::OUString> SAL_CALL LocaleBackend::getBackendServiceNames(void)
337cdf0e10cSrcweir {
338cdf0e10cSrcweir     uno::Sequence<rtl::OUString> aServiceNameList(1);
339cdf0e10cSrcweir     aServiceNameList[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.LocaleBackend")) ;
340cdf0e10cSrcweir     return aServiceNameList ;
341cdf0e10cSrcweir }
342cdf0e10cSrcweir 
343cdf0e10cSrcweir //------------------------------------------------------------------------------
344cdf0e10cSrcweir 
supportsService(const rtl::OUString & aServiceName)345cdf0e10cSrcweir sal_Bool SAL_CALL LocaleBackend::supportsService(const rtl::OUString& aServiceName)
346cdf0e10cSrcweir     throw (uno::RuntimeException)
347cdf0e10cSrcweir {
348cdf0e10cSrcweir     uno::Sequence< rtl::OUString > const svc = getBackendServiceNames();
349cdf0e10cSrcweir 
350cdf0e10cSrcweir     for(sal_Int32 i = 0; i < svc.getLength(); ++i )
351cdf0e10cSrcweir         if(svc[i] == aServiceName)
352cdf0e10cSrcweir             return true;
353cdf0e10cSrcweir 
354cdf0e10cSrcweir     return false;
355cdf0e10cSrcweir }
356cdf0e10cSrcweir 
357cdf0e10cSrcweir //------------------------------------------------------------------------------
358cdf0e10cSrcweir 
getSupportedServiceNames(void)359cdf0e10cSrcweir uno::Sequence<rtl::OUString> SAL_CALL LocaleBackend::getSupportedServiceNames(void)
360cdf0e10cSrcweir     throw (uno::RuntimeException)
361cdf0e10cSrcweir {
362cdf0e10cSrcweir     return getBackendServiceNames() ;
363cdf0e10cSrcweir }
364