diff options
Diffstat (limited to 'unotools/source/misc/syslocale.cxx')
-rw-r--r-- | unotools/source/misc/syslocale.cxx | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/unotools/source/misc/syslocale.cxx b/unotools/source/misc/syslocale.cxx new file mode 100644 index 000000000..a1325958a --- /dev/null +++ b/unotools/source/misc/syslocale.cxx @@ -0,0 +1,212 @@ +/* -*- 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 <sal/config.h> + +#include <sal/log.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/charclass.hxx> +#include <unotools/syslocale.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <comphelper/lok.hxx> +#include <rtl/tencinfo.h> +#include <rtl/locale.h> +#include <osl/thread.h> +#include <osl/nlsupport.h> + +#include <memory> +#include <mutex> +#include <optional> +#include <vector> + +using namespace osl; +using namespace com::sun::star; + +namespace { + +std::weak_ptr<SvtSysLocale_Impl> g_pSysLocale; + +// static +std::mutex& GetMutex() +{ + // #i77768# Due to a static reference in the toolkit lib + // we need a mutex that lives longer than the svl library. + // Otherwise the dtor would use a destructed mutex!! + static std::mutex* persistentMutex(new std::mutex); + + return *persistentMutex; +} + + +} + +class SvtSysLocale_Impl : public utl::ConfigurationListener +{ +public: + SvtSysLocaleOptions aSysLocaleOptions; + std::optional<LocaleDataWrapper> moLocaleData; + std::optional<CharClass> moCharClass; + + SvtSysLocale_Impl(); + virtual ~SvtSysLocale_Impl() override; + + CharClass& GetCharClass(); + virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints ) override; + +private: + std::vector<OUString> getDateAcceptancePatternsConfig() const; +}; + +SvtSysLocale_Impl::SvtSysLocale_Impl() +{ + moLocaleData.emplace( + aSysLocaleOptions.GetRealLanguageTag(), + getDateAcceptancePatternsConfig() ); + + // listen for further changes + aSysLocaleOptions.AddListener( this ); +} + +SvtSysLocale_Impl::~SvtSysLocale_Impl() +{ + aSysLocaleOptions.RemoveListener( this ); +} + +CharClass& SvtSysLocale_Impl::GetCharClass() +{ + if ( !moCharClass ) + moCharClass.emplace( aSysLocaleOptions.GetRealLanguageTag() ); + return *moCharClass; +} + +void SvtSysLocale_Impl::ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints nHint ) +{ + if ( !(nHint & ConfigurationHints::Locale) && + !(nHint & ConfigurationHints::DatePatterns) ) + return; + + std::unique_lock aGuard( GetMutex() ); + + const LanguageTag& rLanguageTag = aSysLocaleOptions.GetRealLanguageTag(); + if ( nHint & ConfigurationHints::Locale ) + { + moCharClass.emplace( rLanguageTag ); + } + moLocaleData.emplace(rLanguageTag, getDateAcceptancePatternsConfig()); +} + +std::vector<OUString> SvtSysLocale_Impl::getDateAcceptancePatternsConfig() const +{ + OUString aStr( aSysLocaleOptions.GetDatePatternsConfigString()); + if (aStr.isEmpty()) + return {}; // reset + ::std::vector< OUString > aVec; + for (sal_Int32 nIndex = 0; nIndex >= 0; /*nop*/) + { + OUString aTok( aStr.getToken( 0, ';', nIndex)); + if (!aTok.isEmpty()) + aVec.push_back( aTok); + } + return aVec; +} + +SvtSysLocale::SvtSysLocale() +{ + std::unique_lock aGuard( GetMutex() ); + pImpl = g_pSysLocale.lock(); + if ( !pImpl ) + { + pImpl = std::make_shared<SvtSysLocale_Impl>(); + g_pSysLocale = pImpl; + } +} + +SvtSysLocale::~SvtSysLocale() +{ + std::unique_lock aGuard( GetMutex() ); + pImpl.reset(); +} + +const LocaleDataWrapper& SvtSysLocale::GetLocaleData() const +{ + return *(pImpl->moLocaleData); +} + +const CharClass& SvtSysLocale::GetCharClass() const +{ + return pImpl->GetCharClass(); +} + +SvtSysLocaleOptions& SvtSysLocale::GetOptions() const +{ + return pImpl->aSysLocaleOptions; +} + +const LanguageTag& SvtSysLocale::GetLanguageTag() const +{ + if (comphelper::LibreOfficeKit::isActive()) + return comphelper::LibreOfficeKit::getLocale(); + + return pImpl->aSysLocaleOptions.GetRealLanguageTag(); +} + +const LanguageTag& SvtSysLocale::GetUILanguageTag() const +{ + if (comphelper::LibreOfficeKit::isActive()) + return comphelper::LibreOfficeKit::getLanguageTag(); + + return pImpl->aSysLocaleOptions.GetRealUILanguageTag(); +} + +// static +rtl_TextEncoding SvtSysLocale::GetBestMimeEncoding() +{ + const char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding( + osl_getThreadTextEncoding() ); + if ( !pCharSet ) + { + // If the system locale is unknown to us, e.g. LC_ALL=xx, match the UI + // language if possible. + SvtSysLocale aSysLocale; + const LanguageTag& rLanguageTag = aSysLocale.GetUILanguageTag(); + // Converting blindly to Locale and then to rtl_Locale may feed the + // 'qlt' to rtl_locale_register() and the underlying system locale + // stuff, which doesn't know about it nor about BCP47 in the Variant + // field. So use the real language and for non-pure ISO cases hope for + // the best... the fallback to UTF-8 should solve these cases nowadays. + /* FIXME-BCP47: the script needs to go in here as well, so actually + * we'd need some variant fiddling or glibc locale string and tweak + * rtl_locale_register() to know about it! But then again the Windows + * implementation still wouldn't know anything about it ... */ + SAL_WARN_IF( !rLanguageTag.isIsoLocale(), "unotools.i18n", + "SvtSysLocale::GetBestMimeEncoding - non-ISO UI locale"); + rtl_Locale * pLocale = rtl_locale_register( rLanguageTag.getLanguage().getStr(), + rLanguageTag.getCountry().getStr(), OUString().getStr() ); + rtl_TextEncoding nEnc = osl_getTextEncodingFromLocale( pLocale ); + pCharSet = rtl_getBestMimeCharsetFromTextEncoding( nEnc ); + } + rtl_TextEncoding nRet; + if ( pCharSet ) + nRet = rtl_getTextEncodingFromMimeCharset( pCharSet ); + else + nRet = RTL_TEXTENCODING_UTF8; + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |