Update ooo320-m1
[ooovba.git] / shell / source / backends / localebe / localebackend.cxx
blob56094892f0337121dec51c1ad0d5d69581cc82fe
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: localebackend.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_shell.hxx"
34 #include "localebackend.hxx"
35 #include "localelayer.hxx"
36 #include <com/sun/star/configuration/backend/ComponentChangeEvent.hpp>
37 #include <uno/current_context.hxx>
38 #include <osl/time.h>
40 #include <stdio.h>
42 #if defined(LINUX) || defined(SOLARIS) || defined(IRIX) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)
44 #include <rtl/ustrbuf.hxx>
45 #include <locale.h>
46 #include <string.h>
49 * Note: setlocale is not at all thread safe, so is this code. It could
50 * especially interfere with the stuff VCL is doing, so make sure this
51 * is called from the main thread only.
54 static rtl::OUString ImplGetLocale(int category)
56 const char *locale = setlocale(category, "");
58 // Return "en-US" for C locales
59 if( (locale == NULL) || ( locale[0] == 'C' && locale[1] == '\0' ) )
60 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "en-US" ) );
63 const char *cp;
64 const char *uscore = NULL;
66 // locale string have the format lang[_ctry][.encoding][@modifier]
67 // we are only interested in the first two items, so we handle
68 // '.' and '@' as string end.
69 for (cp = locale; *cp; cp++)
71 if (*cp == '_')
72 uscore = cp;
73 if (*cp == '.' || *cp == '@')
74 break;
77 rtl::OUStringBuffer aLocaleBuffer;
78 if( uscore != NULL )
80 aLocaleBuffer.appendAscii(locale, uscore++ - locale);
81 aLocaleBuffer.appendAscii("-");
82 aLocaleBuffer.appendAscii(uscore, cp - uscore);
84 else
86 aLocaleBuffer.appendAscii(locale, cp - locale);
89 return aLocaleBuffer.makeStringAndClear();
92 #elif defined(MACOSX)
94 #include <rtl/ustrbuf.hxx>
95 #include <locale.h>
96 #include <string.h>
98 #include <premac.h>
99 #include <CoreServices/CoreServices.h>
100 #include <CoreFoundation/CoreFoundation.h>
101 #include <postmac.h>
103 namespace /* private */
106 void OUStringBufferAppendCFString(rtl::OUStringBuffer& buffer, const CFStringRef s)
108 CFIndex lstr = CFStringGetLength(s);
109 for (CFIndex i = 0; i < lstr; i++)
110 buffer.append(CFStringGetCharacterAtIndex(s, i));
113 template <typename T>
114 class CFGuard
116 public:
117 explicit CFGuard(T& rT) : rT_(rT) {}
118 ~CFGuard() { if (rT_) CFRelease(rT_); }
119 private:
120 T& rT_;
123 typedef CFGuard<CFArrayRef> CFArrayGuard;
124 typedef CFGuard<CFStringRef> CFStringGuard;
125 typedef CFGuard<CFTypeRef> CFTypeRefGuard;
127 /* For more information on the Apple locale concept please refer to
128 http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFLocales/Articles/CFLocaleConcepts.html
129 According to this documentation a locale identifier has the format: language[_country][_variant]*
130 e.g. es_ES_PREEURO -> spain prior Euro support
131 Note: The calling code should be able to handle locales with only language information e.g. 'en' for certain
132 UI languages just the language code will be returned.
135 CFStringRef ImplGetAppPreference(const char* pref)
137 CFStringRef csPref = CFStringCreateWithCString(NULL, pref, kCFStringEncodingASCII);
138 CFStringGuard csRefGuard(csPref);
140 CFTypeRef ref = CFPreferencesCopyAppValue(csPref, kCFPreferencesCurrentApplication);
141 CFTypeRefGuard refGuard(ref);
143 if (ref == NULL)
144 return NULL;
146 CFStringRef sref = (CFGetTypeID(ref) == CFArrayGetTypeID()) ? (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)ref, 0) : (CFStringRef)ref;
148 // NOTE: this API is only available with Mac OS X >=10.3. We need to use it because
149 // Apple used non-ISO values on systems <10.2 like "German" for instance but didn't
150 // upgrade those values during upgrade to newer Mac OS X versions. See also #i54337#
151 return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref);
154 rtl::OUString ImplGetLocale(const char* pref)
156 CFStringRef sref = ImplGetAppPreference(pref);
157 CFStringGuard srefGuard(sref);
159 rtl::OUStringBuffer aLocaleBuffer;
160 aLocaleBuffer.appendAscii("en-US"); // initialize with fallback value
162 if (sref != NULL)
164 // split the string into substrings; the first two (if there are two) substrings
165 // are language and country
166 CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(NULL, sref, CFSTR("_"));
167 CFArrayGuard subsGuard(subs);
169 if (subs != NULL)
171 aLocaleBuffer.setLength(0); // clear buffer which still contains fallback value
173 CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(subs, 0);
174 OUStringBufferAppendCFString(aLocaleBuffer, lang);
176 // country also available? Assumption: if the array contains more than one
177 // value the second value is always the country!
178 if (CFArrayGetCount(subs) > 1)
180 aLocaleBuffer.appendAscii("-");
181 CFStringRef country = (CFStringRef)CFArrayGetValueAtIndex(subs, 1);
182 OUStringBufferAppendCFString(aLocaleBuffer, country);
186 return aLocaleBuffer.makeStringAndClear();
189 } // namespace /* private */
191 #endif
193 // -------------------------------------------------------------------------------
195 #ifdef WNT
197 #ifdef WINVER
198 #undef WINVER
199 #endif
200 #define WINVER 0x0501
202 #if defined _MSC_VER
203 #pragma warning(push, 1)
204 #endif
205 #include <windows.h>
206 #if defined _MSC_VER
207 #pragma warning(pop)
208 #endif
210 rtl::OUString ImplGetLocale(LCID lcid)
212 TCHAR buffer[8];
213 LPTSTR cp = buffer;
215 cp += GetLocaleInfo( lcid, LOCALE_SISO639LANGNAME , buffer, 4 );
216 if( cp > buffer )
218 if( 0 < GetLocaleInfo( lcid, LOCALE_SISO3166CTRYNAME, cp, buffer + 8 - cp) )
219 // #i50822# minus character must be written before cp
220 *(cp - 1) = '-';
222 return rtl::OUString::createFromAscii(buffer);
225 return rtl::OUString();
228 #endif // WNT
230 // -------------------------------------------------------------------------------
232 LocaleBackend::LocaleBackend(const uno::Reference<uno::XComponentContext>& xContext)
233 throw (backend::BackendAccessException) :
234 ::cppu::WeakImplHelper2 < backend::XSingleLayerStratum, lang::XServiceInfo > (),
235 m_xContext(xContext)
240 //------------------------------------------------------------------------------
242 LocaleBackend::~LocaleBackend(void)
246 //------------------------------------------------------------------------------
248 LocaleBackend* LocaleBackend::createInstance(
249 const uno::Reference<uno::XComponentContext>& xContext
252 return new LocaleBackend(xContext);
255 // ---------------------------------------------------------------------------------------
257 rtl::OUString LocaleBackend::getLocale(void)
259 #if defined(LINUX) || defined(SOLARIS) || defined(IRIX) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)
260 return ImplGetLocale(LC_CTYPE);
261 #elif defined (MACOSX)
262 return ImplGetLocale("AppleLocale");
263 #elif defined WNT
264 return ImplGetLocale( GetUserDefaultLCID() );
265 #endif
268 //------------------------------------------------------------------------------
270 rtl::OUString LocaleBackend::getUILocale(void)
272 #if defined(LINUX) || defined(SOLARIS) || defined(IRIX) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)
273 return ImplGetLocale(LC_MESSAGES);
274 #elif defined(MACOSX)
275 return ImplGetLocale("AppleLanguages");
276 #elif defined WNT
277 return ImplGetLocale( MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT) );
278 #endif
281 // ---------------------------------------------------------------------------------------
283 rtl::OUString LocaleBackend::getSystemLocale(void)
285 // note: the implementation differs from getLocale() only on Windows
286 #if defined WNT
287 return ImplGetLocale( GetSystemDefaultLCID() );
288 #else
289 return getLocale();
290 #endif
292 //------------------------------------------------------------------------------
294 rtl::OUString LocaleBackend::createTimeStamp()
296 // the time stamp is free text, so just returning the values here.
297 return getLocale() + getUILocale() + getSystemLocale();
300 //------------------------------------------------------------------------------
302 uno::Reference<backend::XLayer> SAL_CALL LocaleBackend::getLayer(
303 const rtl::OUString& aComponent, const rtl::OUString& /*aTimestamp*/)
304 throw (backend::BackendAccessException, lang::IllegalArgumentException)
307 uno::Sequence<rtl::OUString> aComps( getSupportedComponents() );
308 if( aComponent.equals( aComps[0]) )
310 if( ! m_xSystemLayer.is() )
312 uno::Sequence<backend::PropertyInfo> aPropInfoList(3);
314 aPropInfoList[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.System/L10N/UILocale") );
315 aPropInfoList[0].Type = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "string" ) );
316 aPropInfoList[0].Protected = sal_False;
317 aPropInfoList[0].Value = uno::makeAny( getUILocale() );
319 aPropInfoList[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("org.openoffice.System/L10N/Locale") );
320 aPropInfoList[1].Type = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "string" ));
321 aPropInfoList[1].Protected = sal_False;
322 aPropInfoList[1].Value = uno::makeAny( getLocale() );
324 aPropInfoList[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("org.openoffice.System/L10N/SystemLocale") );
325 aPropInfoList[2].Type = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "string" ));
326 aPropInfoList[2].Protected = sal_False;
327 aPropInfoList[2].Value = uno::makeAny( getSystemLocale() );
329 m_xSystemLayer = new LocaleLayer(aPropInfoList, createTimeStamp(), m_xContext);
332 return m_xSystemLayer;
335 return uno::Reference<backend::XLayer>();
338 //------------------------------------------------------------------------------
340 uno::Reference<backend::XUpdatableLayer> SAL_CALL
341 LocaleBackend::getUpdatableLayer(const rtl::OUString& /*aComponent*/)
342 throw (backend::BackendAccessException,lang::NoSupportException,
343 lang::IllegalArgumentException)
345 throw lang::NoSupportException(
346 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
347 "LocaleBackend: No Update Operation allowed, Read Only access") ),
348 *this) ;
351 //------------------------------------------------------------------------------
353 rtl::OUString SAL_CALL LocaleBackend::getBackendName(void) {
354 return rtl::OUString::createFromAscii("com.sun.star.comp.configuration.backend.LocaleBackend") ;
357 //------------------------------------------------------------------------------
359 rtl::OUString SAL_CALL LocaleBackend::getImplementationName(void)
360 throw (uno::RuntimeException)
362 return getBackendName() ;
365 //------------------------------------------------------------------------------
367 uno::Sequence<rtl::OUString> SAL_CALL LocaleBackend::getBackendServiceNames(void)
369 uno::Sequence<rtl::OUString> aServiceNameList(2);
370 aServiceNameList[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.LocaleBackend")) ;
371 aServiceNameList[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.PlatformBackend")) ;
373 return aServiceNameList ;
376 //------------------------------------------------------------------------------
378 sal_Bool SAL_CALL LocaleBackend::supportsService(const rtl::OUString& aServiceName)
379 throw (uno::RuntimeException)
381 uno::Sequence< rtl::OUString > const svc = getBackendServiceNames();
383 for(sal_Int32 i = 0; i < svc.getLength(); ++i )
384 if(svc[i] == aServiceName)
385 return true;
387 return false;
390 //------------------------------------------------------------------------------
392 uno::Sequence<rtl::OUString> SAL_CALL LocaleBackend::getSupportedServiceNames(void)
393 throw (uno::RuntimeException)
395 return getBackendServiceNames() ;
398 // ---------------------------------------------------------------------------------------
400 uno::Sequence<rtl::OUString> SAL_CALL LocaleBackend::getSupportedComponents(void)
402 uno::Sequence<rtl::OUString> aSupportedComponentList(1);
403 aSupportedComponentList[0] = rtl::OUString(
404 RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.System" )
407 return aSupportedComponentList;