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
21 #include <sal/macros.h>
22 #include "lngopt.hxx"
23 #include <linguistic/misc.hxx>
24 #include <tools/debug.hxx>
25 #include <unotools/lingucfg.hxx>
26
27 #include <comphelper/sequence.hxx>
28 #include <cppuhelper/factory.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <cppuhelper/weak.hxx>
31 #include <com/sun/star/lang/Locale.hpp>
32
33 using namespace utl;
34 using namespace osl;
35 using namespace com::sun::star;
36 using namespace com::sun::star::beans;
37 using namespace com::sun::star::lang;
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::linguistic2;
40 using namespace linguistic;
41
42 using namespace com::sun::star::registry;
43
44
45 // static member initialization
46 SvtLinguOptions * LinguOptions::pData = nullptr;
47 oslInterlockedCount LinguOptions::nRefCount;
48
49
LinguOptions()50 LinguOptions::LinguOptions()
51 {
52 if (!pData)
53 {
54 pData = new SvtLinguOptions;
55 SvtLinguConfig aLinguCfg;
56 aLinguCfg.GetOptions( *pData );
57 }
58
59 osl_atomic_increment( &nRefCount );
60 }
61
62
LinguOptions(const LinguOptions &)63 LinguOptions::LinguOptions(const LinguOptions & /*rOpt*/)
64 {
65 DBG_ASSERT( pData, "lng : data missing" );
66 osl_atomic_increment( &nRefCount );
67 }
68
69
~LinguOptions()70 LinguOptions::~LinguOptions()
71 {
72 MutexGuard aGuard( GetLinguMutex() );
73
74 if ( osl_atomic_decrement( &nRefCount ) == 0 )
75 {
76 delete pData; pData = nullptr;
77 }
78 }
79
80 namespace {
81
82 struct WID_Name
83 {
84 sal_Int32 nWID;
85 const char *pPropertyName;
86 };
87
88 }
89
90 //! order of entries is import (see LinguOptions::GetName)
91 //! since the WID is used as index in this table!
92 WID_Name const aWID_Name[] =
93 {
94 { 0, nullptr },
95 { UPH_IS_USE_DICTIONARY_LIST, UPN_IS_USE_DICTIONARY_LIST },
96 { UPH_IS_IGNORE_CONTROL_CHARACTERS, UPN_IS_IGNORE_CONTROL_CHARACTERS },
97 { UPH_IS_SPELL_UPPER_CASE, UPN_IS_SPELL_UPPER_CASE },
98 { UPH_IS_SPELL_WITH_DIGITS, UPN_IS_SPELL_WITH_DIGITS },
99 { UPH_IS_SPELL_CAPITALIZATION, UPN_IS_SPELL_CAPITALIZATION },
100 { UPH_HYPH_MIN_LEADING, UPN_HYPH_MIN_LEADING },
101 { UPH_HYPH_MIN_TRAILING, UPN_HYPH_MIN_TRAILING },
102 { UPH_HYPH_MIN_WORD_LENGTH, UPN_HYPH_MIN_WORD_LENGTH },
103 { UPH_DEFAULT_LOCALE, UPN_DEFAULT_LOCALE },
104 { UPH_IS_SPELL_AUTO, UPN_IS_SPELL_AUTO },
105 { 0, nullptr },
106 { 0, nullptr },
107 { UPH_IS_SPELL_SPECIAL, UPN_IS_SPELL_SPECIAL },
108 { UPH_IS_HYPH_AUTO, UPN_IS_HYPH_AUTO },
109 { UPH_IS_HYPH_SPECIAL, UPN_IS_HYPH_SPECIAL },
110 { UPH_IS_WRAP_REVERSE, UPN_IS_WRAP_REVERSE },
111 { 0, nullptr },
112 { 0, nullptr },
113 { 0, nullptr },
114 { 0, nullptr },
115 { UPH_DEFAULT_LANGUAGE, UPN_DEFAULT_LANGUAGE },
116 { UPH_DEFAULT_LOCALE_CJK, UPN_DEFAULT_LOCALE_CJK },
117 { UPH_DEFAULT_LOCALE_CTL, UPN_DEFAULT_LOCALE_CTL }
118 };
119
120
GetName(sal_Int32 nWID)121 OUString LinguOptions::GetName( sal_Int32 nWID )
122 {
123 MutexGuard aGuard( GetLinguMutex() );
124
125 OUString aRes;
126
127 if (0 <= nWID && nWID < sal_Int32(SAL_N_ELEMENTS(aWID_Name)) && aWID_Name[ nWID ].nWID == nWID)
128 aRes = OUString::createFromAscii(aWID_Name[nWID].pPropertyName);
129 else
130 OSL_FAIL("lng : unknown WID");
131
132 return aRes;
133 }
134
135
136 //! map must be sorted by first entry in alphabetical increasing order.
lcl_GetLinguProps()137 static const SfxItemPropertyMapEntry* lcl_GetLinguProps()
138 {
139 static const SfxItemPropertyMapEntry aLinguProps[] =
140 {
141 { u"" UPN_DEFAULT_LANGUAGE, UPH_DEFAULT_LANGUAGE,
142 ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
143 { u"" UPN_DEFAULT_LOCALE, UPH_DEFAULT_LOCALE,
144 ::cppu::UnoType<Locale>::get(), 0, 0 },
145 { u"" UPN_DEFAULT_LOCALE_CJK, UPH_DEFAULT_LOCALE_CJK,
146 ::cppu::UnoType<Locale>::get(), 0, 0 },
147 { u"" UPN_DEFAULT_LOCALE_CTL, UPH_DEFAULT_LOCALE_CTL,
148 ::cppu::UnoType<Locale>::get(), 0, 0 },
149 { u"" UPN_HYPH_MIN_LEADING, UPH_HYPH_MIN_LEADING,
150 ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
151 { u"" UPN_HYPH_MIN_TRAILING, UPH_HYPH_MIN_TRAILING,
152 ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
153 { u"" UPN_HYPH_MIN_WORD_LENGTH, UPH_HYPH_MIN_WORD_LENGTH,
154 ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
155 { u"" UPN_IS_GERMAN_PRE_REFORM, UPH_IS_GERMAN_PRE_REFORM, /*! deprecated !*/
156 cppu::UnoType<bool>::get(), 0, 0 },
157 { u"" UPN_IS_HYPH_AUTO, UPH_IS_HYPH_AUTO,
158 cppu::UnoType<bool>::get(), 0, 0 },
159 { u"" UPN_IS_HYPH_SPECIAL, UPH_IS_HYPH_SPECIAL,
160 cppu::UnoType<bool>::get(), 0, 0 },
161 { u"" UPN_IS_IGNORE_CONTROL_CHARACTERS, UPH_IS_IGNORE_CONTROL_CHARACTERS,
162 cppu::UnoType<bool>::get(), 0, 0 },
163 { u"" UPN_IS_SPELL_AUTO, UPH_IS_SPELL_AUTO,
164 cppu::UnoType<bool>::get(), 0, 0 },
165 { u"" UPN_IS_SPELL_CAPITALIZATION, UPH_IS_SPELL_CAPITALIZATION,
166 cppu::UnoType<bool>::get(), 0, 0 },
167 { u"" UPN_IS_SPELL_HIDE, UPH_IS_SPELL_HIDE, /*! deprecated !*/
168 cppu::UnoType<bool>::get(), 0, 0 },
169 { u"" UPN_IS_SPELL_IN_ALL_LANGUAGES, UPH_IS_SPELL_IN_ALL_LANGUAGES, /*! deprecated !*/
170 cppu::UnoType<bool>::get(), 0, 0 },
171 { u"" UPN_IS_SPELL_SPECIAL, UPH_IS_SPELL_SPECIAL,
172 cppu::UnoType<bool>::get(), 0, 0 },
173 { u"" UPN_IS_SPELL_UPPER_CASE, UPH_IS_SPELL_UPPER_CASE,
174 cppu::UnoType<bool>::get(), 0, 0 },
175 { u"" UPN_IS_SPELL_WITH_DIGITS, UPH_IS_SPELL_WITH_DIGITS,
176 cppu::UnoType<bool>::get(), 0, 0 },
177 { u"" UPN_IS_USE_DICTIONARY_LIST, UPH_IS_USE_DICTIONARY_LIST,
178 cppu::UnoType<bool>::get(), 0, 0 },
179 { u"" UPN_IS_WRAP_REVERSE, UPH_IS_WRAP_REVERSE,
180 cppu::UnoType<bool>::get(), 0, 0 },
181 { u"", 0, css::uno::Type(), 0, 0 }
182 };
183 return aLinguProps;
184 }
LinguProps()185 LinguProps::LinguProps() :
186 aEvtListeners (GetLinguMutex()),
187 aPropListeners (GetLinguMutex()),
188 aPropertyMap(lcl_GetLinguProps())
189 {
190 bDisposing = false;
191 }
192
launchEvent(const PropertyChangeEvent & rEvt) const193 void LinguProps::launchEvent( const PropertyChangeEvent &rEvt ) const
194 {
195 cppu::OInterfaceContainerHelper *pContainer =
196 aPropListeners.getContainer( rEvt.PropertyHandle );
197 if (pContainer)
198 {
199 cppu::OInterfaceIteratorHelper aIt( *pContainer );
200 while (aIt.hasMoreElements())
201 {
202 Reference< XPropertyChangeListener > xRef( aIt.next(), UNO_QUERY );
203 if (xRef.is())
204 xRef->propertyChange( rEvt );
205 }
206 }
207 }
208
getPropertySetInfo()209 Reference< XPropertySetInfo > SAL_CALL LinguProps::getPropertySetInfo()
210 {
211 MutexGuard aGuard( GetLinguMutex() );
212
213 static Reference< XPropertySetInfo > aRef =
214 new SfxItemPropertySetInfo( aPropertyMap );
215 return aRef;
216 }
217
setPropertyValue(const OUString & rPropertyName,const Any & rValue)218 void SAL_CALL LinguProps::setPropertyValue(
219 const OUString& rPropertyName, const Any& rValue )
220 {
221 MutexGuard aGuard( GetLinguMutex() );
222
223 const SfxItemPropertyMapEntry* pCur = aPropertyMap.getByName( rPropertyName );
224 if (pCur)
225 {
226 Any aOld( aConfig.GetProperty( pCur->nWID ) );
227 if (aOld != rValue && aConfig.SetProperty( pCur->nWID, rValue ))
228 {
229 PropertyChangeEvent aChgEvt( static_cast<XPropertySet *>(this), rPropertyName,
230 false, pCur->nWID, aOld, rValue );
231 launchEvent( aChgEvt );
232 }
233 }
234 }
235
getPropertyValue(const OUString & rPropertyName)236 Any SAL_CALL LinguProps::getPropertyValue( const OUString& rPropertyName )
237 {
238 MutexGuard aGuard( GetLinguMutex() );
239
240 Any aRet;
241
242 const SfxItemPropertyMapEntry* pCur = aPropertyMap.getByName( rPropertyName );
243 if(pCur)
244 {
245 aRet = aConfig.GetProperty( pCur->nWID );
246 }
247
248 return aRet;
249 }
250
addPropertyChangeListener(const OUString & rPropertyName,const Reference<XPropertyChangeListener> & rxListener)251 void SAL_CALL LinguProps::addPropertyChangeListener(
252 const OUString& rPropertyName,
253 const Reference< XPropertyChangeListener >& rxListener )
254 {
255 MutexGuard aGuard( GetLinguMutex() );
256
257 if (!bDisposing && rxListener.is())
258 {
259 const SfxItemPropertyMapEntry* pCur = aPropertyMap.getByName( rPropertyName );
260 if(pCur)
261 aPropListeners.addInterface( pCur->nWID, rxListener );
262 }
263 }
264
removePropertyChangeListener(const OUString & rPropertyName,const Reference<XPropertyChangeListener> & rxListener)265 void SAL_CALL LinguProps::removePropertyChangeListener(
266 const OUString& rPropertyName,
267 const Reference< XPropertyChangeListener >& rxListener )
268 {
269 MutexGuard aGuard( GetLinguMutex() );
270
271 if (!bDisposing && rxListener.is())
272 {
273 const SfxItemPropertyMapEntry* pCur = aPropertyMap.getByName( rPropertyName );
274 if(pCur)
275 aPropListeners.removeInterface( pCur->nWID, rxListener );
276 }
277 }
278
addVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)279 void SAL_CALL LinguProps::addVetoableChangeListener(
280 const OUString& /*rPropertyName*/,
281 const Reference< XVetoableChangeListener >& /*xListener*/ )
282 {
283 }
284
removeVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)285 void SAL_CALL LinguProps::removeVetoableChangeListener(
286 const OUString& /*rPropertyName*/,
287 const Reference< XVetoableChangeListener >& /*xListener*/ )
288 {
289 }
290
291
setFastPropertyValue(sal_Int32 nHandle,const Any & rValue)292 void SAL_CALL LinguProps::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
293 {
294 MutexGuard aGuard( GetLinguMutex() );
295
296 Any aOld( aConfig.GetProperty( nHandle ) );
297 if (aOld != rValue && aConfig.SetProperty( nHandle, rValue ))
298 {
299 PropertyChangeEvent aChgEvt( static_cast<XPropertySet *>(this),
300 LinguOptions::GetName( nHandle ), false, nHandle, aOld, rValue );
301 launchEvent( aChgEvt );
302 }
303 }
304
305
getFastPropertyValue(sal_Int32 nHandle)306 Any SAL_CALL LinguProps::getFastPropertyValue( sal_Int32 nHandle )
307 {
308 MutexGuard aGuard( GetLinguMutex() );
309
310 Any aRes( aConfig.GetProperty( nHandle ) );
311 return aRes;
312 }
313
314
315 Sequence< PropertyValue > SAL_CALL
getPropertyValues()316 LinguProps::getPropertyValues()
317 {
318 MutexGuard aGuard( GetLinguMutex() );
319
320 std::vector<PropertyValue> aProps;
321 aProps.reserve(aPropertyMap.getPropertyEntries().size());
322 for(auto pEntry : aPropertyMap.getPropertyEntries())
323 aProps.push_back(PropertyValue(pEntry->aName, pEntry->nWID,
324 aConfig.GetProperty(pEntry->nWID),
325 css::beans::PropertyState_DIRECT_VALUE));
326 return comphelper::containerToSequence(aProps);
327 }
328
329 void SAL_CALL
setPropertyValues(const Sequence<PropertyValue> & rProps)330 LinguProps::setPropertyValues( const Sequence< PropertyValue >& rProps )
331 {
332 MutexGuard aGuard( GetLinguMutex() );
333
334 for (const PropertyValue &rVal : rProps)
335 {
336 setPropertyValue( rVal.Name, rVal.Value );
337 }
338 }
339
340 void SAL_CALL
dispose()341 LinguProps::dispose()
342 {
343 MutexGuard aGuard( GetLinguMutex() );
344
345 if (!bDisposing)
346 {
347 bDisposing = true;
348
349 //! it's too late to save the options here!
350 // (see AppExitListener for saving)
351 //aOpt.Save(); // save (possible) changes before exiting
352
353 EventObject aEvtObj( static_cast<XPropertySet *>(this) );
354 aEvtListeners.disposeAndClear( aEvtObj );
355 aPropListeners.disposeAndClear( aEvtObj );
356 }
357 }
358
359 void SAL_CALL
addEventListener(const Reference<XEventListener> & rxListener)360 LinguProps::addEventListener( const Reference< XEventListener >& rxListener )
361 {
362 MutexGuard aGuard( GetLinguMutex() );
363
364 if (!bDisposing && rxListener.is())
365 aEvtListeners.addInterface( rxListener );
366 }
367
368 void SAL_CALL
removeEventListener(const Reference<XEventListener> & rxListener)369 LinguProps::removeEventListener( const Reference< XEventListener >& rxListener )
370 {
371 MutexGuard aGuard( GetLinguMutex() );
372
373 if (!bDisposing && rxListener.is())
374 aEvtListeners.removeInterface( rxListener );
375 }
376
377
378 // Service specific part
379
380 // XServiceInfo
getImplementationName()381 OUString SAL_CALL LinguProps::getImplementationName()
382 {
383 return "com.sun.star.lingu2.LinguProps";
384 }
385
386 // XServiceInfo
supportsService(const OUString & ServiceName)387 sal_Bool SAL_CALL LinguProps::supportsService( const OUString& ServiceName )
388 {
389 return cppu::supportsService(this, ServiceName);
390 }
391
392 // XServiceInfo
getSupportedServiceNames()393 uno::Sequence< OUString > SAL_CALL LinguProps::getSupportedServiceNames()
394 {
395 return { "com.sun.star.linguistic2.LinguProperties" };
396 }
397
getPropertyBool(const OUString & aPropertyName)398 bool LinguProps::getPropertyBool(const OUString& aPropertyName)
399 {
400 uno::Any any = getPropertyValue(aPropertyName);
401 bool b = false;
402 any >>= b;
403 return b;
404 }
405
getPropertyInt16(const OUString & aPropertyName)406 sal_Int16 LinguProps::getPropertyInt16(const OUString& aPropertyName)
407 {
408 uno::Any any = getPropertyValue(aPropertyName);
409 sal_Int16 b = 0;
410 any >>= b;
411 return b;
412 }
413
getPropertyLocale(const OUString & aPropertyName)414 Locale LinguProps::getPropertyLocale(const OUString& aPropertyName)
415 {
416 uno::Any any = getPropertyValue(aPropertyName);
417 css::lang::Locale b;
418 any >>= b;
419 return b;
420 }
421
422 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
linguistic_LinguProps_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)423 linguistic_LinguProps_get_implementation(
424 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
425 {
426 return cppu::acquire(new LinguProps());
427 }
428
429
430 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
431