1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "localebackend.hxx"
22 #include <com/sun/star/beans/Optional.hpp>
23 #include <cppuhelper/supportsservice.hxx>
30 #pragma warning(push, 1)
37 OUString
ImplGetLocale(LCID lcid
)
42 cp
+= GetLocaleInfo( lcid
, LOCALE_SISO639LANGNAME
, buffer
, 4 );
45 if( 0 < GetLocaleInfo( lcid
, LOCALE_SISO3166CTRYNAME
, cp
, buffer
+ 8 - cp
) )
46 // #i50822# minus character must be written before cp
49 return OUString::createFromAscii(buffer
);
57 #include <rtl/ustrbuf.hxx>
62 #include <CoreServices/CoreServices.h>
63 #include <CoreFoundation/CoreFoundation.h>
66 namespace /* private */
69 void OUStringBufferAppendCFString(OUStringBuffer
& buffer
, const CFStringRef s
)
71 CFIndex lstr
= CFStringGetLength(s
);
72 for (CFIndex i
= 0; i
< lstr
; i
++)
73 buffer
.append(CFStringGetCharacterAtIndex(s
, i
));
80 explicit CFGuard(T
& rT
) : rT_(rT
) {}
81 ~CFGuard() { if (rT_
) CFRelease(rT_
); }
86 typedef CFGuard
<CFArrayRef
> CFArrayGuard
;
87 typedef CFGuard
<CFStringRef
> CFStringGuard
;
88 typedef CFGuard
<CFTypeRef
> CFTypeRefGuard
;
90 /* For more information on the Apple locale concept please refer to
91 http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFLocales/Articles/CFLocaleConcepts.html
92 According to this documentation a locale identifier has the format: language[_country][_variant]*
93 e.g. es_ES_PREEURO -> spain prior Euro support
94 Note: The calling code should be able to handle locales with only language information e.g. 'en' for certain
95 UI languages just the language code will be returned.
98 CFStringRef
ImplGetAppPreference(const char* pref
)
100 CFStringRef csPref
= CFStringCreateWithCString(NULL
, pref
, kCFStringEncodingASCII
);
101 CFStringGuard
csRefGuard(csPref
);
103 CFTypeRef ref
= CFPreferencesCopyAppValue(csPref
, kCFPreferencesCurrentApplication
);
104 CFTypeRefGuard
refGuard(ref
);
109 CFStringRef sref
= (CFGetTypeID(ref
) == CFArrayGetTypeID()) ? static_cast<CFStringRef
>(CFArrayGetValueAtIndex(static_cast<CFArrayRef
>(ref
), 0)) : static_cast<CFStringRef
>(ref
);
111 // NOTE: this API is only available with Mac OS X >=10.3. We need to use it because
112 // Apple used non-ISO values on systems <10.2 like "German" for instance but didn't
113 // upgrade those values during upgrade to newer Mac OS X versions. See also #i54337#
114 return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault
, sref
);
117 OUString
ImplGetLocale(const char* pref
)
119 CFStringRef sref
= ImplGetAppPreference(pref
);
120 CFStringGuard
srefGuard(sref
);
122 OUStringBuffer aLocaleBuffer
;
123 aLocaleBuffer
.appendAscii("en-US"); // initialize with fallback value
127 // split the string into substrings; the first two (if there are two) substrings
128 // are language and country
129 CFArrayRef subs
= CFStringCreateArrayBySeparatingStrings(NULL
, sref
, CFSTR("_"));
130 CFArrayGuard
subsGuard(subs
);
134 aLocaleBuffer
.setLength(0); // clear buffer which still contains fallback value
136 CFStringRef lang
= static_cast<CFStringRef
>(CFArrayGetValueAtIndex(subs
, 0));
137 OUStringBufferAppendCFString(aLocaleBuffer
, lang
);
139 // country also available? Assumption: if the array contains more than one
140 // value the second value is always the country!
141 if (CFArrayGetCount(subs
) > 1)
143 aLocaleBuffer
.appendAscii("-");
144 CFStringRef country
= static_cast<CFStringRef
>(CFArrayGetValueAtIndex(subs
, 1));
145 OUStringBufferAppendCFString(aLocaleBuffer
, country
);
149 return aLocaleBuffer
.makeStringAndClear();
152 } // namespace /* private */
156 #include <rtl/ustrbuf.hxx>
161 * Note: setlocale is not at all thread safe, so is this code. It could
162 * especially interfere with the stuff VCL is doing, so make sure this
163 * is called from the main thread only.
166 static OUString
ImplGetLocale(int category
)
168 const char *locale
= setlocale(category
, "");
170 // Return "en-US" for C locales
171 if( (locale
== NULL
) || ( locale
[0] == 'C' && locale
[1] == '\0' ) )
172 return OUString( "en-US" );
176 const char *uscore
= NULL
;
178 // locale string have the format lang[_ctry][.encoding][@modifier]
179 // we are only interested in the first two items, so we handle
180 // '.' and '@' as string end.
181 for (cp
= locale
; *cp
; cp
++)
185 if (*cp
== '.' || *cp
== '@')
189 OUStringBuffer aLocaleBuffer
;
192 aLocaleBuffer
.appendAscii(locale
, uscore
++ - locale
);
193 aLocaleBuffer
.appendAscii("-");
194 aLocaleBuffer
.appendAscii(uscore
, cp
- uscore
);
198 aLocaleBuffer
.appendAscii(locale
, cp
- locale
);
201 return aLocaleBuffer
.makeStringAndClear();
208 LocaleBackend::LocaleBackend()
214 LocaleBackend::~LocaleBackend()
220 LocaleBackend
* LocaleBackend::createInstance()
222 return new LocaleBackend
;
227 OUString
LocaleBackend::getLocale()
230 return ImplGetLocale( GetUserDefaultLCID() );
231 #elif defined (MACOSX)
232 return ImplGetLocale("AppleLocale");
234 return ImplGetLocale(LC_CTYPE
);
240 OUString
LocaleBackend::getUILocale()
243 return ImplGetLocale( MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT
) );
244 #elif defined(MACOSX)
245 return ImplGetLocale("AppleLanguages");
247 return ImplGetLocale(LC_MESSAGES
);
253 OUString
LocaleBackend::getSystemLocale()
255 // note: the implementation differs from getLocale() only on Windows
257 return ImplGetLocale( GetSystemDefaultLCID() );
264 void LocaleBackend::setPropertyValue(
265 OUString
const &, css::uno::Any
const &)
267 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
268 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
269 css::uno::RuntimeException
, std::exception
)
271 throw css::lang::IllegalArgumentException(
273 "setPropertyValue not supported"),
274 static_cast< cppu::OWeakObject
* >(this), -1);
277 css::uno::Any
LocaleBackend::getPropertyValue(
278 OUString
const & PropertyName
)
280 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
281 css::uno::RuntimeException
, std::exception
)
283 if ( PropertyName
== "Locale" ) {
284 return css::uno::makeAny(
285 css::beans::Optional
< css::uno::Any
>(
286 true, css::uno::makeAny(getLocale())));
287 } else if (PropertyName
== "SystemLocale")
289 return css::uno::makeAny(
290 css::beans::Optional
< css::uno::Any
>(
291 true, css::uno::makeAny(getSystemLocale())));
292 } else if (PropertyName
== "UILocale")
294 return css::uno::makeAny(
295 css::beans::Optional
< css::uno::Any
>(
296 true, css::uno::makeAny(getUILocale())));
298 throw css::beans::UnknownPropertyException(
299 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
305 OUString SAL_CALL
LocaleBackend::getBackendName() {
306 return OUString("com.sun.star.comp.configuration.backend.LocaleBackend") ;
309 OUString SAL_CALL
LocaleBackend::getImplementationName()
310 throw (uno::RuntimeException
, std::exception
)
312 return getBackendName() ;
315 uno::Sequence
<OUString
> SAL_CALL
LocaleBackend::getBackendServiceNames()
317 uno::Sequence
<OUString
> aServiceNameList(1);
318 aServiceNameList
[0] = "com.sun.star.configuration.backend.LocaleBackend";
319 return aServiceNameList
;
322 sal_Bool SAL_CALL
LocaleBackend::supportsService(const OUString
& aServiceName
)
323 throw (uno::RuntimeException
, std::exception
)
325 return cppu::supportsService(this, aServiceName
);
328 uno::Sequence
<OUString
> SAL_CALL
LocaleBackend::getSupportedServiceNames()
329 throw (uno::RuntimeException
, std::exception
)
331 return getBackendServiceNames() ;
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */