From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- shell/source/backends/localebe/localebackend.cxx | 333 +++++++++++++++++++++ shell/source/backends/localebe/localebackend.hxx | 106 +++++++ shell/source/backends/localebe/localebe1.component | 26 ++ 3 files changed, 465 insertions(+) create mode 100644 shell/source/backends/localebe/localebackend.cxx create mode 100644 shell/source/backends/localebe/localebackend.hxx create mode 100644 shell/source/backends/localebe/localebe1.component (limited to 'shell/source/backends/localebe') diff --git a/shell/source/backends/localebe/localebackend.cxx b/shell/source/backends/localebe/localebackend.cxx new file mode 100644 index 000000000..558926d8f --- /dev/null +++ b/shell/source/backends/localebe/localebackend.cxx @@ -0,0 +1,333 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include +#include + +#include +#include + +#include "localebackend.hxx" +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +static css::beans::Optional ImplGetLocale(LCID lcid) +{ + WCHAR buffer[8]; + PWSTR cp = buffer; + + cp += GetLocaleInfoW( lcid, LOCALE_SISO639LANGNAME, buffer, 4 ); + if( cp > buffer ) + { + if( 0 < GetLocaleInfoW( lcid, LOCALE_SISO3166CTRYNAME, cp, buffer + 8 - cp) ) + // #i50822# minus character must be written before cp + *(cp - 1) = '-'; + + return {true, css::uno::Any(OUString(o3tl::toU(buffer)))}; + } + + return {false, {}}; +} + +#elif defined(MACOSX) + +#include +#include +#include + +#include +#include +#include +#include + +namespace /* private */ +{ + + void OUStringBufferAppendCFString(OUStringBuffer& buffer, const CFStringRef s) + { + CFIndex lstr = CFStringGetLength(s); + for (CFIndex i = 0; i < lstr; i++) + buffer.append(sal_Unicode(CFStringGetCharacterAtIndex(s, i))); + } + + template + class CFGuard + { + public: + explicit CFGuard(T& rT) : rT_(rT) {} + ~CFGuard() { if (rT_) CFRelease(rT_); } + private: + T& rT_; + }; + + typedef CFGuard CFArrayGuard; + typedef CFGuard CFStringGuard; + typedef CFGuard 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(nullptr, pref, kCFStringEncodingASCII); + CFStringGuard csRefGuard(csPref); + + CFTypeRef ref = CFPreferencesCopyAppValue(csPref, kCFPreferencesCurrentApplication); + CFTypeRefGuard refGuard(ref); + + if (ref == nullptr) + return nullptr; + + CFStringRef sref = (CFGetTypeID(ref) == CFArrayGetTypeID()) ? static_cast(CFArrayGetValueAtIndex(static_cast(ref), 0)) : static_cast(ref); + + // NOTE: this API is only available with macOS >=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 macOS versions. See also #i54337# + return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref); + } + + css::beans::Optional ImplGetLocale(const char* pref) + { + CFStringRef sref = ImplGetAppPreference(pref); + CFStringGuard srefGuard(sref); + + OUStringBuffer aLocaleBuffer; + aLocaleBuffer.append("en-US"); // initialize with fallback value + + if (sref != nullptr) + { + // split the string into substrings; the first two (if there are two) substrings + // are language and country + CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(nullptr, sref, CFSTR("_")); + CFArrayGuard subsGuard(subs); + + if (subs != nullptr) + { + aLocaleBuffer.setLength(0); // clear buffer which still contains fallback value + + CFStringRef lang = static_cast(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.append("-"); + CFStringRef country = static_cast(CFArrayGetValueAtIndex(subs, 1)); + OUStringBufferAppendCFString(aLocaleBuffer, country); + } + } + } + return {true, css::uno::Any(aLocaleBuffer.makeStringAndClear())}; + } + +} // namespace /* private */ + +#else + +#include +#include +#include + +static css::beans::Optional ImplGetLocale(char const * category) +{ + const char *locale = std::getenv("LC_ALL"); + if (locale == nullptr || *locale == '\0') { + locale = std::getenv(category); + if (locale == nullptr || *locale == '\0') { + locale = std::getenv("LANG"); + } + } + + // Return "en-US" for C locales + if( (locale == nullptr) || *locale == '\0' || std::strcmp(locale, "C") == 0 + || std::strcmp(locale, "POSIX") == 0 ) + return {true, css::uno::Any(OUString("en-US"))}; + + + const char *cp; + const char *uscore = nullptr; + const char *end = nullptr; + + // locale string have the format lang[_ctry][.encoding][@modifier] + // Let LanguageTag handle all conversion, but do a sanity and length check + // first. + // For the fallback we are only interested in the first two items, so we + // handle '.' and '@' as string end for that. + for (cp = locale; *cp; cp++) + { + if (*cp == '_' && !uscore) + uscore = cp; + if ((*cp == '.' || *cp == '@') && !end) + end = cp; + if (!rtl::isAscii(static_cast(*cp))) { + SAL_INFO("shell", "locale env var with non-ASCII content"); + return {false, {}}; + } + } + assert(cp >= locale); + if (cp - locale > std::numeric_limits::max()) { + SAL_INFO("shell", "locale env var content too long"); + return {false, {}}; + } + + // This is a tad awkward... but the easiest way to obtain what we're + // actually interested in. For example this also converts + // "ca_ES.UTF-8@valencia" to "ca-ES-valencia". + const OString aLocaleStr(locale); + const LanguageType nLang = MsLangId::convertUnxByteStringToLanguage( aLocaleStr); + if (nLang != LANGUAGE_DONTKNOW) + { + const OUString aLangTagStr( LanguageTag::convertToBcp47( nLang)); + return {true, css::uno::Any(aLangTagStr)}; + } + + // As a fallback, strip encoding and modifier and return just a + // language-country combination and let the caller handle unknowns. + OUStringBuffer aLocaleBuffer; + if (!end) + end = cp; + if( uscore != nullptr ) + { + aLocaleBuffer.appendAscii(locale, uscore++ - locale); + aLocaleBuffer.append("-"); + aLocaleBuffer.appendAscii(uscore, end - uscore); + } + else + { + aLocaleBuffer.appendAscii(locale, end - locale); + } + + return {true, css::uno::Any(aLocaleBuffer.makeStringAndClear())}; +} + +#endif + + +LocaleBackend::LocaleBackend() +{ +} + + +LocaleBackend::~LocaleBackend() +{ +} + + + +css::beans::Optional LocaleBackend::getLocale() +{ +#if defined(_WIN32) + return ImplGetLocale( GetUserDefaultLCID() ); +#elif defined (MACOSX) + return ImplGetLocale("AppleLocale"); +#else + return ImplGetLocale("LC_CTYPE"); +#endif +} + + +css::beans::Optional LocaleBackend::getUILocale() +{ +#if defined(_WIN32) + return ImplGetLocale( MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT) ); +#elif defined(MACOSX) + return ImplGetLocale("AppleLanguages"); +#else + return ImplGetLocale("LC_MESSAGES"); +#endif +} + + +css::beans::Optional LocaleBackend::getSystemLocale() +{ +// note: the implementation differs from getLocale() only on Windows +#if defined(_WIN32) + return ImplGetLocale( GetSystemDefaultLCID() ); +#else + return getLocale(); +#endif +} + + +void LocaleBackend::setPropertyValue( + OUString const &, css::uno::Any const &) +{ + throw css::lang::IllegalArgumentException( + "setPropertyValue not supported", + static_cast< cppu::OWeakObject * >(this), -1); +} + +css::uno::Any LocaleBackend::getPropertyValue( + OUString const & PropertyName) +{ + if ( PropertyName == "Locale" ) { + return css::uno::Any(getLocale()); + } else if (PropertyName == "SystemLocale") + { + return css::uno::Any(getSystemLocale()); + } else if (PropertyName == "UILocale") + { + return css::uno::Any(getUILocale()); + } else { + throw css::beans::UnknownPropertyException( + PropertyName, static_cast< cppu::OWeakObject * >(this)); + } +} + + +OUString SAL_CALL LocaleBackend::getImplementationName() +{ + return "com.sun.star.comp.configuration.backend.LocaleBackend" ; +} + +sal_Bool SAL_CALL LocaleBackend::supportsService(const OUString& aServiceName) +{ + return cppu::supportsService(this, aServiceName); +} + +uno::Sequence SAL_CALL LocaleBackend::getSupportedServiceNames() +{ + return { "com.sun.star.configuration.backend.LocaleBackend" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +shell_LocaleBackend_get_implementation( + css::uno::XComponentContext* , css::uno::Sequence const&) +{ + return cppu::acquire(new LocaleBackend()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/localebe/localebackend.hxx b/shell/source/backends/localebe/localebackend.hxx new file mode 100644 index 000000000..e2e4a0b36 --- /dev/null +++ b/shell/source/backends/localebe/localebackend.hxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SHELL_SOURCE_BACKENDS_LOCALEBE_LOCALEBACKEND_HXX +#define INCLUDED_SHELL_SOURCE_BACKENDS_LOCALEBE_LOCALEBACKEND_HXX + +#include + +#include +#include +#include +#include + + +namespace uno = css::uno ; +namespace lang = css::lang ; + +class LocaleBackend final : public ::cppu::WeakImplHelper < + css::beans::XPropertySet, + lang::XServiceInfo > +{ + + public: + + // XServiceInfo + virtual OUString SAL_CALL + getImplementationName( ) override ; + + virtual sal_Bool SAL_CALL + supportsService( const OUString& aServiceName ) override ; + + virtual uno::Sequence SAL_CALL + getSupportedServiceNames( ) override ; + + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override + { return css::uno::Reference< css::beans::XPropertySetInfo >(); } + + virtual void SAL_CALL setPropertyValue( + OUString const &, css::uno::Any const &) override; + + virtual css::uno::Any SAL_CALL getPropertyValue( + OUString const & PropertyName) override; + + virtual void SAL_CALL addPropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL removePropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL addVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + virtual void SAL_CALL removeVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + /** + Service constructor from a service factory. + + @param xContext component context + */ + LocaleBackend(); + + /** Destructor */ + virtual ~LocaleBackend() override ; + + private: + // Returns the user locale + static css::beans::Optional getLocale(); + + // Returns the user UI locale + static css::beans::Optional getUILocale(); + + // Returns the system default locale + static css::beans::Optional getSystemLocale(); +} ; + + +#endif // INCLUDED_SHELL_SOURCE_BACKENDS_LOCALEBE_LOCALEBACKEND_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/localebe/localebe1.component b/shell/source/backends/localebe/localebe1.component new file mode 100644 index 000000000..f19a3f9e8 --- /dev/null +++ b/shell/source/backends/localebe/localebe1.component @@ -0,0 +1,26 @@ + + + + + + + + -- cgit v1.2.3