summaryrefslogtreecommitdiffstats
path: root/unotools/source/misc/syslocale.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--unotools/source/misc/syslocale.cxx212
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: */