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