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 :
21 : #include <sal/macros.h>
22 : #include "lngopt.hxx"
23 : #include "linguistic/lngprops.hxx"
24 : #include "linguistic/misc.hxx"
25 : #include <tools/debug.hxx>
26 : #include <unotools/lingucfg.hxx>
27 :
28 : #include <uno/lbnames.h> // CPPU_CURRENT_LANGUAGE_BINDING_NAME macro, which specify the environment type
29 : #include <cppuhelper/implbase1.hxx> // helper for implementations
30 :
31 : #include <cppuhelper/factory.hxx> // helper for factories
32 : #include <com/sun/star/container/XNameAccess.hpp>
33 : #include <com/sun/star/registry/XSimpleRegistry.hpp>
34 : #include <com/sun/star/registry/XRegistryKey.hpp>
35 : #include <com/sun/star/lang/Locale.hpp>
36 : #include <com/sun/star/i18n/ScriptType.hpp>
37 : #include <i18nlangtag/mslangid.hxx>
38 :
39 : using namespace utl;
40 : using namespace osl;
41 : using namespace com::sun::star;
42 : using namespace com::sun::star::container;
43 : using namespace com::sun::star::beans;
44 : using namespace com::sun::star::lang;
45 : using namespace com::sun::star::uno;
46 : using namespace com::sun::star::linguistic2;
47 : using namespace linguistic;
48 :
49 : using namespace com::sun::star::registry;
50 :
51 :
52 :
53 :
54 : // static member intialization
55 : SvtLinguOptions * LinguOptions::pData = NULL;
56 : oslInterlockedCount LinguOptions::nRefCount;
57 :
58 :
59 57 : LinguOptions::LinguOptions()
60 : {
61 57 : if (!pData)
62 : {
63 33 : pData = new SvtLinguOptions;
64 33 : SvtLinguConfig aLinguCfg;
65 33 : aLinguCfg.GetOptions( *pData );
66 : }
67 :
68 57 : osl_atomic_increment( &nRefCount );
69 57 : }
70 :
71 :
72 0 : LinguOptions::LinguOptions(const LinguOptions & /*rOpt*/)
73 : {
74 : DBG_ASSERT( pData, "lng : data missing" );
75 0 : osl_atomic_increment( &nRefCount );
76 0 : }
77 :
78 :
79 56 : LinguOptions::~LinguOptions()
80 : {
81 56 : MutexGuard aGuard( GetLinguMutex() );
82 :
83 56 : if ( osl_atomic_decrement( &nRefCount ) == 0 )
84 : {
85 32 : delete pData; pData = NULL;
86 56 : }
87 56 : }
88 :
89 : struct WID_Name
90 : {
91 : sal_Int32 nWID;
92 : const char *pPropertyName;
93 : };
94 :
95 : //! order of entries is import (see LinguOptions::GetName)
96 : //! since the WID is used as index in this table!
97 : WID_Name aWID_Name[] =
98 : {
99 : { 0, 0 },
100 : { WID_IS_USE_DICTIONARY_LIST, UPN_IS_USE_DICTIONARY_LIST },
101 : { WID_IS_IGNORE_CONTROL_CHARACTERS, UPN_IS_IGNORE_CONTROL_CHARACTERS },
102 : { WID_IS_SPELL_UPPER_CASE, UPN_IS_SPELL_UPPER_CASE },
103 : { WID_IS_SPELL_WITH_DIGITS, UPN_IS_SPELL_WITH_DIGITS },
104 : { WID_IS_SPELL_CAPITALIZATION, UPN_IS_SPELL_CAPITALIZATION },
105 : { WID_HYPH_MIN_LEADING, UPN_HYPH_MIN_LEADING },
106 : { WID_HYPH_MIN_TRAILING, UPN_HYPH_MIN_TRAILING },
107 : { WID_HYPH_MIN_WORD_LENGTH, UPN_HYPH_MIN_WORD_LENGTH },
108 : { WID_DEFAULT_LOCALE, UPN_DEFAULT_LOCALE },
109 : { WID_IS_SPELL_AUTO, UPN_IS_SPELL_AUTO },
110 : { 0, 0 },
111 : { 0, 0 },
112 : { WID_IS_SPELL_SPECIAL, UPN_IS_SPELL_SPECIAL },
113 : { WID_IS_HYPH_AUTO, UPN_IS_HYPH_AUTO },
114 : { WID_IS_HYPH_SPECIAL, UPN_IS_HYPH_SPECIAL },
115 : { WID_IS_WRAP_REVERSE, UPN_IS_WRAP_REVERSE },
116 : { 0, 0 },
117 : { 0, 0 },
118 : { 0, 0 },
119 : { 0, 0 },
120 : { WID_DEFAULT_LANGUAGE, UPN_DEFAULT_LANGUAGE },
121 : { WID_DEFAULT_LOCALE_CJK, UPN_DEFAULT_LOCALE_CJK },
122 : { WID_DEFAULT_LOCALE_CTL, UPN_DEFAULT_LOCALE_CTL }
123 : };
124 :
125 :
126 31 : OUString LinguOptions::GetName( sal_Int32 nWID )
127 : {
128 31 : MutexGuard aGuard( GetLinguMutex() );
129 :
130 31 : OUString aRes;
131 :
132 31 : sal_Int32 nLen = sizeof (aWID_Name) / sizeof (aWID_Name[0]);
133 31 : if (0 <= nWID && nWID < nLen && aWID_Name[ nWID ].nWID == nWID)
134 31 : aRes = OUString::createFromAscii(aWID_Name[nWID].pPropertyName);
135 : else
136 : OSL_FAIL("lng : unknown WID");
137 :
138 31 : return aRes;
139 : }
140 :
141 :
142 :
143 : //! map must be sorted by first entry in alphabetical increasing order.
144 27 : static const SfxItemPropertyMapEntry* lcl_GetLinguProps()
145 : {
146 : static const SfxItemPropertyMapEntry aLinguProps[] =
147 : {
148 : { MAP_CHAR_LEN(UPN_DEFAULT_LANGUAGE), WID_DEFAULT_LANGUAGE,
149 27 : &::getCppuType( (sal_Int16*)0 ), 0, 0 },
150 : { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE), WID_DEFAULT_LOCALE,
151 27 : &::getCppuType( (Locale* )0), 0, 0 },
152 : { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE_CJK), WID_DEFAULT_LOCALE_CJK,
153 27 : &::getCppuType( (Locale* )0), 0, 0 },
154 : { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE_CTL), WID_DEFAULT_LOCALE_CTL,
155 27 : &::getCppuType( (Locale* )0), 0, 0 },
156 : { MAP_CHAR_LEN(UPN_HYPH_MIN_LEADING), WID_HYPH_MIN_LEADING,
157 27 : &::getCppuType( (sal_Int16*)0 ), 0, 0 },
158 : { MAP_CHAR_LEN(UPN_HYPH_MIN_TRAILING), WID_HYPH_MIN_TRAILING,
159 27 : &::getCppuType( (sal_Int16*)0 ), 0, 0 },
160 : { MAP_CHAR_LEN(UPN_HYPH_MIN_WORD_LENGTH), WID_HYPH_MIN_WORD_LENGTH,
161 27 : &::getCppuType( (sal_Int16*)0 ), 0, 0 },
162 : { MAP_CHAR_LEN(UPN_IS_GERMAN_PRE_REFORM), WID_IS_GERMAN_PRE_REFORM, /*! deprecated !*/
163 27 : &::getBooleanCppuType(), 0, 0 },
164 : { MAP_CHAR_LEN(UPN_IS_HYPH_AUTO), WID_IS_HYPH_AUTO,
165 27 : &::getBooleanCppuType(), 0, 0 },
166 : { MAP_CHAR_LEN(UPN_IS_HYPH_SPECIAL), WID_IS_HYPH_SPECIAL,
167 27 : &::getBooleanCppuType(), 0, 0 },
168 : { MAP_CHAR_LEN(UPN_IS_IGNORE_CONTROL_CHARACTERS), WID_IS_IGNORE_CONTROL_CHARACTERS,
169 27 : &::getBooleanCppuType(), 0, 0 },
170 : { MAP_CHAR_LEN(UPN_IS_SPELL_AUTO), WID_IS_SPELL_AUTO,
171 27 : &::getBooleanCppuType(), 0, 0 },
172 : { MAP_CHAR_LEN(UPN_IS_SPELL_CAPITALIZATION), WID_IS_SPELL_CAPITALIZATION,
173 27 : &::getBooleanCppuType(), 0, 0 },
174 : { MAP_CHAR_LEN(UPN_IS_SPELL_HIDE), WID_IS_SPELL_HIDE, /*! deprecated !*/
175 27 : &::getBooleanCppuType(), 0, 0 },
176 : { MAP_CHAR_LEN(UPN_IS_SPELL_IN_ALL_LANGUAGES), WID_IS_SPELL_IN_ALL_LANGUAGES, /*! deprecated !*/
177 27 : &::getBooleanCppuType(), 0, 0 },
178 : { MAP_CHAR_LEN(UPN_IS_SPELL_SPECIAL), WID_IS_SPELL_SPECIAL,
179 27 : &::getBooleanCppuType(), 0, 0 },
180 : { MAP_CHAR_LEN(UPN_IS_SPELL_UPPER_CASE), WID_IS_SPELL_UPPER_CASE,
181 27 : &::getBooleanCppuType(), 0, 0 },
182 : { MAP_CHAR_LEN(UPN_IS_SPELL_WITH_DIGITS), WID_IS_SPELL_WITH_DIGITS,
183 27 : &::getBooleanCppuType(), 0, 0 },
184 : { MAP_CHAR_LEN(UPN_IS_USE_DICTIONARY_LIST), WID_IS_USE_DICTIONARY_LIST,
185 27 : &::getBooleanCppuType(), 0, 0 },
186 : { MAP_CHAR_LEN(UPN_IS_WRAP_REVERSE), WID_IS_WRAP_REVERSE,
187 27 : &::getBooleanCppuType(), 0, 0 },
188 : { 0,0,0,0,0,0 }
189 567 : };
190 27 : return aLinguProps;
191 : }
192 27 : LinguProps::LinguProps() :
193 27 : aEvtListeners (GetLinguMutex()),
194 27 : aPropListeners (GetLinguMutex()),
195 81 : aPropertyMap(lcl_GetLinguProps())
196 : {
197 27 : bDisposing = sal_False;
198 27 : }
199 :
200 63 : void LinguProps::launchEvent( const PropertyChangeEvent &rEvt ) const
201 : {
202 : cppu::OInterfaceContainerHelper *pContainer =
203 63 : aPropListeners.getContainer( rEvt.PropertyHandle );
204 63 : if (pContainer)
205 : {
206 0 : cppu::OInterfaceIteratorHelper aIt( *pContainer );
207 0 : while (aIt.hasMoreElements())
208 : {
209 0 : Reference< XPropertyChangeListener > xRef( aIt.next(), UNO_QUERY );
210 0 : if (xRef.is())
211 0 : xRef->propertyChange( rEvt );
212 0 : }
213 : }
214 63 : }
215 :
216 27 : Reference< XInterface > SAL_CALL LinguProps_CreateInstance(
217 : const Reference< XMultiServiceFactory > & /*rSMgr*/ )
218 : throw(Exception)
219 : {
220 27 : Reference< XInterface > xService = (cppu::OWeakObject*)new LinguProps;
221 27 : return xService;
222 : }
223 :
224 3 : Reference< XPropertySetInfo > SAL_CALL LinguProps::getPropertySetInfo()
225 : throw(RuntimeException)
226 : {
227 3 : MutexGuard aGuard( GetLinguMutex() );
228 :
229 : static Reference< XPropertySetInfo > aRef =
230 3 : new SfxItemPropertySetInfo( aPropertyMap );
231 3 : return aRef;
232 : }
233 :
234 34 : void SAL_CALL LinguProps::setPropertyValue(
235 : const OUString& rPropertyName, const Any& rValue )
236 : throw(UnknownPropertyException, PropertyVetoException,
237 : IllegalArgumentException, WrappedTargetException, RuntimeException)
238 : {
239 34 : MutexGuard aGuard( GetLinguMutex() );
240 :
241 34 : const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
242 34 : if (pCur)
243 : {
244 34 : Any aOld( aConfig.GetProperty( pCur->nWID ) );
245 34 : if (aOld != rValue && aConfig.SetProperty( pCur->nWID, rValue ))
246 : {
247 : PropertyChangeEvent aChgEvt( (XPropertySet *) this, rPropertyName,
248 32 : sal_False, pCur->nWID, aOld, rValue );
249 32 : launchEvent( aChgEvt );
250 34 : }
251 34 : }
252 34 : }
253 :
254 245 : Any SAL_CALL LinguProps::getPropertyValue( const OUString& rPropertyName )
255 : throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
256 : {
257 245 : MutexGuard aGuard( GetLinguMutex() );
258 :
259 245 : Any aRet;
260 :
261 245 : const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
262 245 : if(pCur)
263 : {
264 245 : aRet = aConfig.GetProperty( pCur->nWID );
265 : }
266 :
267 245 : return aRet;
268 : }
269 :
270 244 : void SAL_CALL LinguProps::addPropertyChangeListener(
271 : const OUString& rPropertyName,
272 : const Reference< XPropertyChangeListener >& rxListener )
273 : throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
274 : {
275 244 : MutexGuard aGuard( GetLinguMutex() );
276 :
277 244 : if (!bDisposing && rxListener.is())
278 : {
279 244 : const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
280 244 : if(pCur)
281 225 : aPropListeners.addInterface( pCur->nWID, rxListener );
282 244 : }
283 244 : }
284 :
285 244 : void SAL_CALL LinguProps::removePropertyChangeListener(
286 : const OUString& rPropertyName,
287 : const Reference< XPropertyChangeListener >& rxListener )
288 : throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
289 : {
290 244 : MutexGuard aGuard( GetLinguMutex() );
291 :
292 244 : if (!bDisposing && rxListener.is())
293 : {
294 130 : const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
295 130 : if(pCur)
296 130 : aPropListeners.removeInterface( pCur->nWID, rxListener );
297 244 : }
298 244 : }
299 :
300 0 : void SAL_CALL LinguProps::addVetoableChangeListener(
301 : const OUString& /*rPropertyName*/,
302 : const Reference< XVetoableChangeListener >& /*xListener*/ )
303 : throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
304 : {
305 0 : }
306 :
307 0 : void SAL_CALL LinguProps::removeVetoableChangeListener(
308 : const OUString& /*rPropertyName*/,
309 : const Reference< XVetoableChangeListener >& /*xListener*/ )
310 : throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
311 : {
312 0 : }
313 :
314 :
315 35 : void SAL_CALL LinguProps::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
316 : throw(UnknownPropertyException, PropertyVetoException,
317 : IllegalArgumentException, WrappedTargetException, RuntimeException)
318 : {
319 35 : MutexGuard aGuard( GetLinguMutex() );
320 :
321 70 : Any aOld( aConfig.GetProperty( nHandle ) );
322 35 : if (aOld != rValue && aConfig.SetProperty( nHandle, rValue ))
323 : {
324 : PropertyChangeEvent aChgEvt( (XPropertySet *) this,
325 31 : LinguOptions::GetName( nHandle ), sal_False, nHandle, aOld, rValue );
326 31 : launchEvent( aChgEvt );
327 35 : }
328 35 : }
329 :
330 :
331 66803 : Any SAL_CALL LinguProps::getFastPropertyValue( sal_Int32 nHandle )
332 : throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
333 : {
334 66803 : MutexGuard aGuard( GetLinguMutex() );
335 :
336 66803 : Any aRes( aConfig.GetProperty( nHandle ) );
337 66803 : return aRes;
338 : }
339 :
340 :
341 : Sequence< PropertyValue > SAL_CALL
342 0 : LinguProps::getPropertyValues()
343 : throw(RuntimeException)
344 : {
345 0 : MutexGuard aGuard( GetLinguMutex() );
346 :
347 0 : sal_Int32 nLen = aPropertyMap.getSize();
348 0 : Sequence< PropertyValue > aProps( nLen );
349 0 : PropertyValue *pProp = aProps.getArray();
350 0 : PropertyEntryVector_t aPropEntries = aPropertyMap.getPropertyEntries();
351 0 : PropertyEntryVector_t::const_iterator aIt = aPropEntries.begin();
352 0 : for (sal_Int32 i = 0; i < nLen; ++i, ++aIt)
353 : {
354 0 : PropertyValue &rVal = pProp[i];
355 0 : Any aAny( aConfig.GetProperty( aIt->nWID ) );
356 :
357 0 : rVal.Name = aIt->sName;
358 0 : rVal.Handle = aIt->nWID;
359 0 : rVal.Value = aAny;
360 0 : rVal.State = PropertyState_DIRECT_VALUE ;
361 0 : }
362 0 : return aProps;
363 : }
364 :
365 : void SAL_CALL
366 0 : LinguProps::setPropertyValues( const Sequence< PropertyValue >& rProps )
367 : throw(UnknownPropertyException, PropertyVetoException,
368 : IllegalArgumentException, WrappedTargetException, RuntimeException)
369 : {
370 0 : MutexGuard aGuard( GetLinguMutex() );
371 :
372 0 : sal_Int32 nLen = rProps.getLength();
373 0 : const PropertyValue *pVal = rProps.getConstArray();
374 0 : for (sal_Int32 i = 0; i < nLen; ++i)
375 : {
376 0 : const PropertyValue &rVal = pVal[i];
377 0 : setPropertyValue( rVal.Name, rVal.Value );
378 0 : }
379 0 : }
380 :
381 : void SAL_CALL
382 28 : LinguProps::dispose()
383 : throw(RuntimeException)
384 : {
385 28 : MutexGuard aGuard( GetLinguMutex() );
386 :
387 28 : if (!bDisposing)
388 : {
389 27 : bDisposing = sal_True;
390 :
391 : //! its too late to save the options here!
392 : // (see AppExitListener for saving)
393 : //aOpt.Save(); // save (possible) changes before exiting
394 :
395 27 : EventObject aEvtObj( (XPropertySet *) this );
396 27 : aEvtListeners.disposeAndClear( aEvtObj );
397 27 : aPropListeners.disposeAndClear( aEvtObj );
398 28 : }
399 28 : }
400 :
401 : void SAL_CALL
402 2 : LinguProps::addEventListener( const Reference< XEventListener >& rxListener )
403 : throw(RuntimeException)
404 : {
405 2 : MutexGuard aGuard( GetLinguMutex() );
406 :
407 2 : if (!bDisposing && rxListener.is())
408 2 : aEvtListeners.addInterface( rxListener );
409 2 : }
410 :
411 : void SAL_CALL
412 1 : LinguProps::removeEventListener( const Reference< XEventListener >& rxListener )
413 : throw(RuntimeException)
414 : {
415 1 : MutexGuard aGuard( GetLinguMutex() );
416 :
417 1 : if (!bDisposing && rxListener.is())
418 1 : aEvtListeners.removeInterface( rxListener );
419 1 : }
420 :
421 :
422 : // Service specific part
423 :
424 : // XServiceInfo
425 3 : OUString SAL_CALL LinguProps::getImplementationName()
426 : throw(RuntimeException)
427 : {
428 3 : MutexGuard aGuard( GetLinguMutex() );
429 3 : return getImplementationName_Static();
430 : }
431 :
432 : // XServiceInfo
433 1 : sal_Bool SAL_CALL LinguProps::supportsService( const OUString& ServiceName )
434 : throw(RuntimeException)
435 : {
436 1 : MutexGuard aGuard( GetLinguMutex() );
437 :
438 2 : uno::Sequence< OUString > aSNL = getSupportedServiceNames();
439 1 : const OUString * pArray = aSNL.getConstArray();
440 1 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
441 1 : if( pArray[i] == ServiceName )
442 1 : return sal_True;
443 1 : return sal_False;
444 : }
445 :
446 : // XServiceInfo
447 3 : uno::Sequence< OUString > SAL_CALL LinguProps::getSupportedServiceNames()
448 : throw(RuntimeException)
449 : {
450 3 : MutexGuard aGuard( GetLinguMutex() );
451 3 : return getSupportedServiceNames_Static();
452 : }
453 :
454 : // ORegistryServiceManager_Static
455 30 : uno::Sequence< OUString > LinguProps::getSupportedServiceNames_Static()
456 : throw()
457 : {
458 30 : MutexGuard aGuard( GetLinguMutex() );
459 :
460 30 : uno::Sequence< OUString > aSNS( 1 ); // more than 1 service possible
461 30 : aSNS.getArray()[0] = "com.sun.star.linguistic2.LinguProperties";
462 30 : return aSNS;
463 : }
464 :
465 27 : sal_Bool LinguProps::getPropertyBool(const OUString& aPropertyName) throw (css::uno::RuntimeException)
466 : {
467 27 : uno::Any any = getPropertyValue(aPropertyName);
468 27 : sal_Bool b = sal_False;
469 27 : any >>= b;
470 27 : return b;
471 : }
472 :
473 0 : sal_Int16 LinguProps::getPropertyInt16(const OUString& aPropertyName) throw (css::uno::RuntimeException)
474 : {
475 0 : uno::Any any = getPropertyValue(aPropertyName);
476 0 : sal_Int16 b = sal_False;
477 0 : any >>= b;
478 0 : return b;
479 : }
480 :
481 0 : Locale LinguProps::getPropertyLocale(const OUString& aPropertyName) throw (css::uno::RuntimeException)
482 : {
483 0 : uno::Any any = getPropertyValue(aPropertyName);
484 0 : css::lang::Locale b;
485 0 : any >>= b;
486 0 : return b;
487 : }
488 :
489 56 : void * SAL_CALL LinguProps_getFactory( const sal_Char * pImplName,
490 : XMultiServiceFactory *pServiceManager, void * )
491 : {
492 56 : void * pRet = 0;
493 56 : if ( !LinguProps::getImplementationName_Static().compareToAscii( pImplName ) )
494 : {
495 : Reference< XSingleServiceFactory > xFactory =
496 : cppu::createOneInstanceFactory(
497 : pServiceManager,
498 : LinguProps::getImplementationName_Static(),
499 : LinguProps_CreateInstance,
500 27 : LinguProps::getSupportedServiceNames_Static());
501 : // acquire, because we return an interface pointer instead of a reference
502 27 : xFactory->acquire();
503 27 : pRet = xFactory.get();
504 : }
505 56 : return pRet;
506 : }
507 :
508 :
509 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|