Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <unotools/syslocale.hxx>
21 : #include <unotools/syslocaleoptions.hxx>
22 : #include <comphelper/processfactory.hxx>
23 : #include <rtl/tencinfo.h>
24 : #include <rtl/locale.h>
25 : #include <osl/thread.h>
26 : #include <osl/nlsupport.h>
27 : #include <vector>
28 :
29 : using namespace osl;
30 : using namespace com::sun::star;
31 :
32 : SvtSysLocale_Impl* SvtSysLocale::pImpl = NULL;
33 : sal_Int32 SvtSysLocale::nRefCount = 0;
34 :
35 : class SvtSysLocale_Impl : public utl::ConfigurationListener
36 : {
37 : public:
38 : SvtSysLocaleOptions aSysLocaleOptions;
39 : LocaleDataWrapper* pLocaleData;
40 : CharClass* pCharClass;
41 :
42 : SvtSysLocale_Impl();
43 : virtual ~SvtSysLocale_Impl();
44 :
45 : CharClass* GetCharClass();
46 : virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ) SAL_OVERRIDE;
47 :
48 : private:
49 : void setDateAcceptancePatternsConfig();
50 : };
51 :
52 0 : SvtSysLocale_Impl::SvtSysLocale_Impl() : pCharClass(NULL)
53 : {
54 0 : pLocaleData = new LocaleDataWrapper( aSysLocaleOptions.GetRealLanguageTag() );
55 0 : setDateAcceptancePatternsConfig();
56 :
57 : // listen for further changes
58 0 : aSysLocaleOptions.AddListener( this );
59 0 : }
60 :
61 0 : SvtSysLocale_Impl::~SvtSysLocale_Impl()
62 : {
63 0 : aSysLocaleOptions.RemoveListener( this );
64 0 : delete pCharClass;
65 0 : delete pLocaleData;
66 0 : }
67 :
68 0 : CharClass* SvtSysLocale_Impl::GetCharClass()
69 : {
70 0 : if ( !pCharClass )
71 0 : pCharClass = new CharClass( aSysLocaleOptions.GetRealLanguageTag() );
72 0 : return pCharClass;
73 : }
74 :
75 0 : void SvtSysLocale_Impl::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 nHint )
76 : {
77 0 : MutexGuard aGuard( SvtSysLocale::GetMutex() );
78 :
79 0 : if ( nHint & SYSLOCALEOPTIONS_HINT_LOCALE )
80 : {
81 0 : const LanguageTag& rLanguageTag = aSysLocaleOptions.GetRealLanguageTag();
82 0 : pLocaleData->setLanguageTag( rLanguageTag );
83 0 : GetCharClass()->setLanguageTag( rLanguageTag );
84 : }
85 0 : if ( nHint & SYSLOCALEOPTIONS_HINT_DATEPATTERNS )
86 : {
87 0 : setDateAcceptancePatternsConfig();
88 0 : }
89 0 : }
90 :
91 0 : void SvtSysLocale_Impl::setDateAcceptancePatternsConfig()
92 : {
93 0 : OUString aStr( aSysLocaleOptions.GetDatePatternsConfigString());
94 0 : if (aStr.isEmpty())
95 0 : pLocaleData->setDateAcceptancePatterns( uno::Sequence<OUString>()); // reset
96 : else
97 : {
98 0 : ::std::vector< OUString > aVec;
99 0 : for (sal_Int32 nIndex = 0; nIndex >= 0; /*nop*/)
100 : {
101 0 : OUString aTok( aStr.getToken( 0, ';', nIndex));
102 0 : if (!aTok.isEmpty())
103 0 : aVec.push_back( aTok);
104 0 : }
105 0 : uno::Sequence< OUString > aSeq( aVec.size());
106 0 : for (sal_Int32 i=0; i < aSeq.getLength(); ++i)
107 0 : aSeq[i] = aVec[i];
108 0 : pLocaleData->setDateAcceptancePatterns( aSeq);
109 0 : }
110 0 : }
111 :
112 0 : SvtSysLocale::SvtSysLocale()
113 : {
114 0 : MutexGuard aGuard( GetMutex() );
115 0 : if ( !pImpl )
116 0 : pImpl = new SvtSysLocale_Impl;
117 0 : ++nRefCount;
118 0 : }
119 :
120 0 : SvtSysLocale::~SvtSysLocale()
121 : {
122 0 : MutexGuard aGuard( GetMutex() );
123 0 : if ( !--nRefCount )
124 : {
125 0 : delete pImpl;
126 0 : pImpl = NULL;
127 0 : }
128 0 : }
129 :
130 : // static
131 0 : Mutex& SvtSysLocale::GetMutex()
132 : {
133 : static Mutex* pMutex = NULL;
134 0 : if( !pMutex )
135 : {
136 0 : MutexGuard aGuard( Mutex::getGlobalMutex() );
137 0 : if( !pMutex )
138 : {
139 : // #i77768# Due to a static reference in the toolkit lib
140 : // we need a mutex that lives longer than the svl library.
141 : // Otherwise the dtor would use a destructed mutex!!
142 0 : pMutex = new Mutex;
143 0 : }
144 : }
145 0 : return *pMutex;
146 : }
147 :
148 0 : const LocaleDataWrapper& SvtSysLocale::GetLocaleData() const
149 : {
150 0 : return *(pImpl->pLocaleData);
151 : }
152 :
153 0 : const LocaleDataWrapper* SvtSysLocale::GetLocaleDataPtr() const
154 : {
155 0 : return pImpl->pLocaleData;
156 : }
157 :
158 0 : const CharClass& SvtSysLocale::GetCharClass() const
159 : {
160 0 : return *(pImpl->GetCharClass());
161 : }
162 :
163 0 : const CharClass* SvtSysLocale::GetCharClassPtr() const
164 : {
165 0 : return pImpl->GetCharClass();
166 : }
167 :
168 0 : SvtSysLocaleOptions& SvtSysLocale::GetOptions() const
169 : {
170 0 : return pImpl->aSysLocaleOptions;
171 : }
172 :
173 0 : const LanguageTag& SvtSysLocale::GetLanguageTag() const
174 : {
175 0 : return pImpl->aSysLocaleOptions.GetRealLanguageTag();
176 : }
177 :
178 0 : const LanguageTag& SvtSysLocale::GetUILanguageTag() const
179 : {
180 0 : return pImpl->aSysLocaleOptions.GetRealUILanguageTag();
181 : }
182 :
183 : // static
184 0 : rtl_TextEncoding SvtSysLocale::GetBestMimeEncoding()
185 : {
186 : const sal_Char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding(
187 0 : osl_getThreadTextEncoding() );
188 0 : if ( !pCharSet )
189 : {
190 : // If the system locale is unknown to us, e.g. LC_ALL=xx, match the UI
191 : // language if possible.
192 0 : SvtSysLocale aSysLocale;
193 0 : const LanguageTag& rLanguageTag = aSysLocale.GetUILanguageTag();
194 : // Converting blindly to Locale and then to rtl_Locale may feed the
195 : // 'qlt' to rtl_locale_register() and the underlying system locale
196 : // stuff, which doesn't know about it nor about BCP47 in the Variant
197 : // field. So use the real language and for non-pure ISO cases hope for
198 : // the best.. the fallback to UTF-8 should solve these cases nowadays.
199 : /* FIXME-BCP47: the script needs to go in here as well, so actually
200 : * we'd need some variant fiddling or glibc locale string and tweak
201 : * rtl_locale_register() to know about it! But then again the Windows
202 : * implementation still wouldn't know anything about it ... */
203 : SAL_WARN_IF( !rLanguageTag.isIsoLocale(), "unotools.i18n",
204 : "SvtSysLocale::GetBestMimeEncoding - non-ISO UI locale");
205 : rtl_Locale * pLocale = rtl_locale_register( rLanguageTag.getLanguage().getStr(),
206 0 : rLanguageTag.getCountry().getStr(), OUString().getStr() );
207 0 : rtl_TextEncoding nEnc = osl_getTextEncodingFromLocale( pLocale );
208 0 : pCharSet = rtl_getBestMimeCharsetFromTextEncoding( nEnc );
209 : }
210 : rtl_TextEncoding nRet;
211 0 : if ( pCharSet )
212 0 : nRet = rtl_getTextEncodingFromMimeCharset( pCharSet );
213 : else
214 0 : nRet = RTL_TEXTENCODING_UTF8;
215 0 : return nRet;
216 : }
217 :
218 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|