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