| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_shell.hxx" |
| |
| #include "localebackend.hxx" |
| #include <com/sun/star/beans/Optional.hpp> |
| #include <osl/time.h> |
| |
| #include <stdio.h> |
| |
| #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(OS2) |
| |
| #include <rtl/ustrbuf.hxx> |
| #include <locale.h> |
| #include <string.h> |
| |
| /* |
| * Note: setlocale is not at all thread safe, so is this code. It could |
| * especially interfere with the stuff VCL is doing, so make sure this |
| * is called from the main thread only. |
| */ |
| |
| static rtl::OUString ImplGetLocale(int category) |
| { |
| const char *locale = setlocale(category, ""); |
| |
| // Return "en-US" for C locales |
| if( (locale == NULL) || ( locale[0] == 'C' && locale[1] == '\0' ) ) |
| return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "en-US" ) ); |
| |
| |
| const char *cp; |
| const char *uscore = NULL; |
| |
| // locale string have the format lang[_ctry][.encoding][@modifier] |
| // we are only interested in the first two items, so we handle |
| // '.' and '@' as string end. |
| for (cp = locale; *cp; cp++) |
| { |
| if (*cp == '_') |
| uscore = cp; |
| if (*cp == '.' || *cp == '@') |
| break; |
| } |
| |
| rtl::OUStringBuffer aLocaleBuffer; |
| if( uscore != NULL ) |
| { |
| aLocaleBuffer.appendAscii(locale, uscore++ - locale); |
| aLocaleBuffer.appendAscii("-"); |
| aLocaleBuffer.appendAscii(uscore, cp - uscore); |
| } |
| else |
| { |
| aLocaleBuffer.appendAscii(locale, cp - locale); |
| } |
| |
| return aLocaleBuffer.makeStringAndClear(); |
| } |
| |
| #elif defined(MACOSX) |
| |
| #include <rtl/ustrbuf.hxx> |
| #include <locale.h> |
| #include <string.h> |
| |
| #include <premac.h> |
| #include <CoreServices/CoreServices.h> |
| #include <CoreFoundation/CoreFoundation.h> |
| #include <postmac.h> |
| |
| namespace /* private */ |
| { |
| |
| void OUStringBufferAppendCFString(rtl::OUStringBuffer& buffer, const CFStringRef s) |
| { |
| CFIndex lstr = CFStringGetLength(s); |
| for (CFIndex i = 0; i < lstr; i++) |
| buffer.append(CFStringGetCharacterAtIndex(s, i)); |
| } |
| |
| template <typename T> |
| class CFGuard |
| { |
| public: |
| explicit CFGuard(T& rT) : rT_(rT) {} |
| ~CFGuard() { if (rT_) CFRelease(rT_); } |
| private: |
| T& rT_; |
| }; |
| |
| typedef CFGuard<CFArrayRef> CFArrayGuard; |
| typedef CFGuard<CFStringRef> CFStringGuard; |
| typedef CFGuard<CFTypeRef> CFTypeRefGuard; |
| |
| /* For more information on the Apple locale concept please refer to |
| http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFLocales/Articles/CFLocaleConcepts.html |
| According to this documentation a locale identifier has the format: language[_country][_variant]* |
| e.g. es_ES_PREEURO -> spain prior Euro support |
| Note: The calling code should be able to handle locales with only language information e.g. 'en' for certain |
| UI languages just the language code will be returned. |
| */ |
| |
| CFStringRef ImplGetAppPreference(const char* pref) |
| { |
| CFStringRef csPref = CFStringCreateWithCString(NULL, pref, kCFStringEncodingASCII); |
| CFStringGuard csRefGuard(csPref); |
| |
| CFTypeRef ref = CFPreferencesCopyAppValue(csPref, kCFPreferencesCurrentApplication); |
| CFTypeRefGuard refGuard(ref); |
| |
| if (ref == NULL) |
| return NULL; |
| |
| CFStringRef sref = (CFGetTypeID(ref) == CFArrayGetTypeID()) ? (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)ref, 0) : (CFStringRef)ref; |
| |
| // NOTE: this API is only available with Mac OS X >=10.3. We need to use it because |
| // Apple used non-ISO values on systems <10.2 like "German" for instance but didn't |
| // upgrade those values during upgrade to newer Mac OS X versions. See also #i54337# |
| return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref); |
| } |
| |
| rtl::OUString ImplGetLocale(const char* pref) |
| { |
| CFStringRef sref = ImplGetAppPreference(pref); |
| CFStringGuard srefGuard(sref); |
| |
| rtl::OUStringBuffer aLocaleBuffer; |
| aLocaleBuffer.appendAscii("en-US"); // initialize with fallback value |
| |
| if (sref != NULL) |
| { |
| // split the string into substrings; the first two (if there are two) substrings |
| // are language and country |
| CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(NULL, sref, CFSTR("_")); |
| CFArrayGuard subsGuard(subs); |
| |
| if (subs != NULL) |
| { |
| aLocaleBuffer.setLength(0); // clear buffer which still contains fallback value |
| |
| CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(subs, 0); |
| OUStringBufferAppendCFString(aLocaleBuffer, lang); |
| |
| // country also available? Assumption: if the array contains more than one |
| // value the second value is always the country! |
| if (CFArrayGetCount(subs) > 1) |
| { |
| aLocaleBuffer.appendAscii("-"); |
| CFStringRef country = (CFStringRef)CFArrayGetValueAtIndex(subs, 1); |
| OUStringBufferAppendCFString(aLocaleBuffer, country); |
| } |
| } |
| } |
| return aLocaleBuffer.makeStringAndClear(); |
| } |
| |
| } // namespace /* private */ |
| |
| #endif |
| |
| // ------------------------------------------------------------------------------- |
| |
| #ifdef WNT |
| |
| #ifdef WINVER |
| #undef WINVER |
| #endif |
| #define WINVER 0x0501 |
| |
| #if defined _MSC_VER |
| #pragma warning(push, 1) |
| #endif |
| #include <windows.h> |
| #if defined _MSC_VER |
| #pragma warning(pop) |
| #endif |
| |
| rtl::OUString ImplGetLocale(LCID lcid) |
| { |
| TCHAR buffer[8]; |
| LPTSTR cp = buffer; |
| |
| cp += GetLocaleInfo( lcid, LOCALE_SISO639LANGNAME , buffer, 4 ); |
| if( cp > buffer ) |
| { |
| if( 0 < GetLocaleInfo( lcid, LOCALE_SISO3166CTRYNAME, cp, buffer + 8 - cp) ) |
| // #i50822# minus character must be written before cp |
| *(cp - 1) = '-'; |
| |
| return rtl::OUString::createFromAscii(buffer); |
| } |
| |
| return rtl::OUString(); |
| } |
| |
| #endif // WNT |
| |
| // ------------------------------------------------------------------------------- |
| |
| LocaleBackend::LocaleBackend() |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| LocaleBackend::~LocaleBackend(void) |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| LocaleBackend* LocaleBackend::createInstance() |
| { |
| return new LocaleBackend; |
| } |
| |
| // --------------------------------------------------------------------------------------- |
| |
| rtl::OUString LocaleBackend::getLocale(void) |
| { |
| #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(OS2) |
| return ImplGetLocale(LC_CTYPE); |
| #elif defined (MACOSX) |
| return ImplGetLocale("AppleLocale"); |
| #elif defined WNT |
| return ImplGetLocale( GetUserDefaultLCID() ); |
| #endif |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| rtl::OUString LocaleBackend::getUILocale(void) |
| { |
| #if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(OS2) |
| return ImplGetLocale(LC_MESSAGES); |
| #elif defined(MACOSX) |
| return ImplGetLocale("AppleLanguages"); |
| #elif defined WNT |
| return ImplGetLocale( MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT) ); |
| #endif |
| } |
| |
| // --------------------------------------------------------------------------------------- |
| |
| rtl::OUString LocaleBackend::getSystemLocale(void) |
| { |
| // note: the implementation differs from getLocale() only on Windows |
| #if defined WNT |
| return ImplGetLocale( GetSystemDefaultLCID() ); |
| #else |
| return getLocale(); |
| #endif |
| } |
| //------------------------------------------------------------------------------ |
| |
| void LocaleBackend::setPropertyValue( |
| rtl::OUString const &, css::uno::Any const &) |
| throw ( |
| css::beans::UnknownPropertyException, css::beans::PropertyVetoException, |
| css::lang::IllegalArgumentException, css::lang::WrappedTargetException, |
| css::uno::RuntimeException) |
| { |
| throw css::lang::IllegalArgumentException( |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM("setPropertyValue not supported")), |
| static_cast< cppu::OWeakObject * >(this), -1); |
| } |
| |
| css::uno::Any LocaleBackend::getPropertyValue( |
| rtl::OUString const & PropertyName) |
| throw ( |
| css::beans::UnknownPropertyException, css::lang::WrappedTargetException, |
| css::uno::RuntimeException) |
| { |
| if (PropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Locale"))) { |
| return css::uno::makeAny( |
| css::beans::Optional< css::uno::Any >( |
| true, css::uno::makeAny(getLocale()))); |
| } else if (PropertyName.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM("SystemLocale"))) |
| { |
| return css::uno::makeAny( |
| css::beans::Optional< css::uno::Any >( |
| true, css::uno::makeAny(getSystemLocale()))); |
| } else if (PropertyName.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM("UILocale"))) |
| { |
| return css::uno::makeAny( |
| css::beans::Optional< css::uno::Any >( |
| true, css::uno::makeAny(getUILocale()))); |
| } else { |
| throw css::beans::UnknownPropertyException( |
| PropertyName, static_cast< cppu::OWeakObject * >(this)); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| rtl::OUString SAL_CALL LocaleBackend::getBackendName(void) { |
| return rtl::OUString::createFromAscii("com.sun.star.comp.configuration.backend.LocaleBackend") ; |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| rtl::OUString SAL_CALL LocaleBackend::getImplementationName(void) |
| throw (uno::RuntimeException) |
| { |
| return getBackendName() ; |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| uno::Sequence<rtl::OUString> SAL_CALL LocaleBackend::getBackendServiceNames(void) |
| { |
| uno::Sequence<rtl::OUString> aServiceNameList(1); |
| aServiceNameList[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.LocaleBackend")) ; |
| return aServiceNameList ; |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL LocaleBackend::supportsService(const rtl::OUString& aServiceName) |
| throw (uno::RuntimeException) |
| { |
| uno::Sequence< rtl::OUString > const svc = getBackendServiceNames(); |
| |
| for(sal_Int32 i = 0; i < svc.getLength(); ++i ) |
| if(svc[i] == aServiceName) |
| return true; |
| |
| return false; |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| uno::Sequence<rtl::OUString> SAL_CALL LocaleBackend::getSupportedServiceNames(void) |
| throw (uno::RuntimeException) |
| { |
| return getBackendServiceNames() ; |
| } |