xref: /trunk/main/linguistic/source/lngopt.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_linguistic.hxx"
30 
31 #include "lngopt.hxx"
32 #include "linguistic/lngprops.hxx"
33 #include "linguistic/misc.hxx"
34 #include <tools/debug.hxx>
35 #include <unotools/lingucfg.hxx>
36 
37 #include <uno/lbnames.h>            // CPPU_CURRENT_LANGUAGE_BINDING_NAME macro, which specify the environment type
38 #include <cppuhelper/implbase1.hxx> // helper for implementations
39 
40 #include <cppuhelper/factory.hxx>   // helper for factories
41 #include <com/sun/star/container/XNameAccess.hpp>
42 #include <com/sun/star/registry/XSimpleRegistry.hpp>
43 #include <com/sun/star/registry/XRegistryKey.hpp>
44 #include <com/sun/star/lang/Locale.hpp>
45 #include <com/sun/star/i18n/ScriptType.hpp>
46 #include <unotools/processfactory.hxx>
47 #include <i18npool/mslangid.hxx>
48 
49 using namespace utl;
50 using namespace osl;
51 using namespace rtl;
52 using namespace com::sun::star;
53 using namespace com::sun::star::container;
54 using namespace com::sun::star::beans;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::uno;
57 using namespace com::sun::star::linguistic2;
58 using namespace linguistic;
59 
60 using namespace com::sun::star::registry;
61 
62 ///////////////////////////////////////////////////////////////////////////
63 
64 
65 // static member intialization
66 SvtLinguOptions *   LinguOptions::pData = NULL;
67 vos::ORefCount      LinguOptions::aRefCount;
68 
69 
70 LinguOptions::LinguOptions()
71 {
72     if (!pData)
73     {
74         pData = new SvtLinguOptions;
75         SvtLinguConfig aLinguCfg;
76         aLinguCfg.GetOptions( *pData );
77     }
78 
79     ++aRefCount;
80 }
81 
82 
83 LinguOptions::LinguOptions(const LinguOptions & /*rOpt*/)
84 {
85     DBG_ASSERT( pData, "lng : data missing" );
86     ++aRefCount;
87 }
88 
89 
90 LinguOptions::~LinguOptions()
91 {
92     MutexGuard  aGuard( GetLinguMutex() );
93 
94     if (--aRefCount == 0)
95     {
96         delete pData;   pData  = NULL;
97     }
98 }
99 
100 
101 sal_Bool LinguOptions::SetLocale_Impl( sal_Int16 &rLanguage, Any &rOld, const Any &rVal, sal_Int16 nType)
102 {
103     sal_Bool bRes = sal_False;
104 
105     Locale  aNew;
106     rVal >>= aNew;
107         sal_Int16 nNew = MsLangId::resolveSystemLanguageByScriptType(MsLangId::convertLocaleToLanguage(aNew), nType);
108     if (nNew != rLanguage)
109     {
110         Locale  aLocale( CreateLocale( rLanguage ) );
111         rOld.setValue( &aLocale, ::getCppuType((Locale*)0 ));
112         rLanguage = nNew;
113         bRes = sal_True;
114     }
115 
116     return bRes;
117 }
118 
119 
120 sal_Bool LinguOptions::SetValue( Any &rOld, const Any &rVal, sal_Int32 nWID )
121 {
122     MutexGuard  aGuard( GetLinguMutex() );
123 
124     sal_Bool bRes = sal_False;
125 
126     sal_Int16 *pnVal = 0;
127     sal_Bool  *pbVal = 0;
128 
129     switch( nWID )
130     {
131         case WID_IS_GERMAN_PRE_REFORM :     /*! deprecated !*/ break;
132         case WID_IS_USE_DICTIONARY_LIST :   pbVal = &pData->bIsUseDictionaryList;   break;
133         case WID_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &pData->bIsIgnoreControlCharacters; break;
134         case WID_IS_HYPH_AUTO :             pbVal = &pData->bIsHyphAuto;    break;
135         case WID_IS_HYPH_SPECIAL :          pbVal = &pData->bIsHyphSpecial; break;
136         case WID_IS_SPELL_AUTO :            pbVal = &pData->bIsSpellAuto;   break;
137         case WID_IS_SPELL_HIDE :            /*! deprecated !*/ break;
138         case WID_IS_SPELL_IN_ALL_LANGUAGES :/*! deprecated !*/ break;
139         case WID_IS_SPELL_SPECIAL :         pbVal = &pData->bIsSpellSpecial;    break;
140         case WID_IS_WRAP_REVERSE :          pbVal = &pData->bIsSpellReverse;    break;
141         case WID_DEFAULT_LANGUAGE :         pnVal = &pData->nDefaultLanguage;   break;
142         case WID_IS_SPELL_CAPITALIZATION :  pbVal = &pData->bIsSpellCapitalization;     break;
143         case WID_IS_SPELL_WITH_DIGITS :     pbVal = &pData->bIsSpellWithDigits; break;
144         case WID_IS_SPELL_UPPER_CASE :      pbVal = &pData->bIsSpellUpperCase;      break;
145         case WID_HYPH_MIN_LEADING :         pnVal = &pData->nHyphMinLeading;        break;
146         case WID_HYPH_MIN_TRAILING :        pnVal = &pData->nHyphMinTrailing;   break;
147         case WID_HYPH_MIN_WORD_LENGTH :     pnVal = &pData->nHyphMinWordLength; break;
148         case WID_DEFAULT_LOCALE :
149         {
150             bRes = SetLocale_Impl( pData->nDefaultLanguage, rOld, rVal, ::com::sun::star::i18n::ScriptType::LATIN );
151             break;
152         }
153         case WID_DEFAULT_LOCALE_CJK :
154         {
155             bRes = SetLocale_Impl( pData->nDefaultLanguage_CJK, rOld, rVal, ::com::sun::star::i18n::ScriptType::ASIAN );
156             break;
157         }
158         case WID_DEFAULT_LOCALE_CTL :
159         {
160             bRes = SetLocale_Impl( pData->nDefaultLanguage_CTL, rOld, rVal, ::com::sun::star::i18n::ScriptType::COMPLEX );
161             break;
162         }
163         default :
164         {
165             DBG_ASSERT( 0,"lng : unknown WID");
166             bRes = sal_False;
167         }
168     }
169 
170     if (pbVal)
171     {
172         sal_Bool bNew = sal_False;
173         rVal >>= bNew;
174         if (bNew != *pbVal)
175         {
176             rOld <<= *pbVal;
177             *pbVal = bNew;
178             bRes = sal_True;
179         }
180     }
181     if (pnVal)
182     {
183         sal_Int16 nNew = 0;
184         rVal >>= nNew;
185         if (nNew != *pnVal)
186         {
187             rOld <<= *pnVal;
188             *pnVal = nNew;
189             bRes = sal_True;
190         }
191     }
192 
193 //  if (bRes)
194 //      pData->SetModified();
195 
196     return bRes;
197 }
198 
199 void LinguOptions::GetValue( Any &rVal, sal_Int32 nWID ) const
200 {
201     MutexGuard  aGuard( GetLinguMutex() );
202 
203     sal_Int16 *pnVal = 0;
204     sal_Bool  *pbVal = 0;
205     sal_Bool  bDummy = sal_False;
206 
207     switch( nWID )
208     {
209         case WID_IS_GERMAN_PRE_REFORM :     pbVal = &bDummy; /*! deprecated !*/ break;
210         case WID_IS_USE_DICTIONARY_LIST :   pbVal = &pData->bIsUseDictionaryList;   break;
211         case WID_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &pData->bIsIgnoreControlCharacters; break;
212         case WID_IS_HYPH_AUTO :             pbVal = &pData->bIsHyphAuto;    break;
213         case WID_IS_HYPH_SPECIAL :          pbVal = &pData->bIsHyphSpecial; break;
214         case WID_IS_SPELL_AUTO :            pbVal = &pData->bIsSpellAuto;   break;
215         case WID_IS_SPELL_HIDE :            pbVal = &bDummy; /*! deprecated !*/ break;
216         case WID_IS_SPELL_IN_ALL_LANGUAGES :pbVal = &bDummy; /*! deprecated !*/ break;
217         case WID_IS_SPELL_SPECIAL :         pbVal = &pData->bIsSpellSpecial;    break;
218         case WID_IS_WRAP_REVERSE :          pbVal = &pData->bIsSpellReverse;    break;
219         case WID_DEFAULT_LANGUAGE :         pnVal = &pData->nDefaultLanguage;   break;
220         case WID_IS_SPELL_CAPITALIZATION :  pbVal = &pData->bIsSpellCapitalization;     break;
221         case WID_IS_SPELL_WITH_DIGITS :     pbVal = &pData->bIsSpellWithDigits; break;
222         case WID_IS_SPELL_UPPER_CASE :      pbVal = &pData->bIsSpellUpperCase;      break;
223         case WID_HYPH_MIN_LEADING :         pnVal = &pData->nHyphMinLeading;        break;
224         case WID_HYPH_MIN_TRAILING :        pnVal = &pData->nHyphMinTrailing;   break;
225         case WID_HYPH_MIN_WORD_LENGTH :     pnVal = &pData->nHyphMinWordLength; break;
226         case WID_DEFAULT_LOCALE :
227         {
228             Locale aLocale( MsLangId::convertLanguageToLocale( pData->nDefaultLanguage ) );
229             rVal.setValue( &aLocale, ::getCppuType((Locale*)0 ));
230             break;
231         }
232         case WID_DEFAULT_LOCALE_CJK :
233         {
234             Locale aLocale( MsLangId::convertLanguageToLocale( pData->nDefaultLanguage_CJK ) );
235             rVal.setValue( &aLocale, ::getCppuType((Locale*)0 ));
236             break;
237         }
238         case WID_DEFAULT_LOCALE_CTL :
239         {
240             Locale aLocale( MsLangId::convertLanguageToLocale( pData->nDefaultLanguage_CTL ) );
241             rVal.setValue( &aLocale, ::getCppuType((Locale*)0 ));
242             break;
243         }
244         default :
245         {
246             DBG_ASSERT( 0,"lng : unknown WID");
247         }
248     }
249 
250     if (pbVal)
251         rVal <<= *pbVal;
252     if (pnVal)
253         rVal <<= *pnVal;
254 }
255 
256 
257 struct WID_Name
258 {
259     sal_Int32        nWID;
260     const char  *pPropertyName;
261 };
262 
263 //! order of entries is import (see LinguOptions::GetName)
264 //! since the WID is used as index in this table!
265 WID_Name aWID_Name[] =
266 {
267     { 0,                                  0 },
268     { WID_IS_USE_DICTIONARY_LIST,         UPN_IS_USE_DICTIONARY_LIST },
269     { WID_IS_IGNORE_CONTROL_CHARACTERS,   UPN_IS_IGNORE_CONTROL_CHARACTERS },
270     { WID_IS_SPELL_UPPER_CASE,            UPN_IS_SPELL_UPPER_CASE },
271     { WID_IS_SPELL_WITH_DIGITS,           UPN_IS_SPELL_WITH_DIGITS },
272     { WID_IS_SPELL_CAPITALIZATION,        UPN_IS_SPELL_CAPITALIZATION },
273     { WID_HYPH_MIN_LEADING,               UPN_HYPH_MIN_LEADING },
274     { WID_HYPH_MIN_TRAILING,              UPN_HYPH_MIN_TRAILING },
275     { WID_HYPH_MIN_WORD_LENGTH,           UPN_HYPH_MIN_WORD_LENGTH },
276     { WID_DEFAULT_LOCALE,                 UPN_DEFAULT_LOCALE },
277     { WID_IS_SPELL_AUTO,                  UPN_IS_SPELL_AUTO },
278     { 0,                                  0 },
279     { 0,                                  0 },
280     { WID_IS_SPELL_SPECIAL,               UPN_IS_SPELL_SPECIAL },
281     { WID_IS_HYPH_AUTO,                   UPN_IS_HYPH_AUTO },
282     { WID_IS_HYPH_SPECIAL,                UPN_IS_HYPH_SPECIAL },
283     { WID_IS_WRAP_REVERSE,                UPN_IS_WRAP_REVERSE },
284     { 0,                                  0 },
285     { 0,                                  0 },
286     { 0,                                  0 },
287     { 0,                                  0 },
288     { WID_DEFAULT_LANGUAGE,               UPN_DEFAULT_LANGUAGE },
289     { WID_DEFAULT_LOCALE_CJK,             UPN_DEFAULT_LOCALE_CJK },
290     { WID_DEFAULT_LOCALE_CTL,             UPN_DEFAULT_LOCALE_CTL }
291 };
292 
293 
294 OUString LinguOptions::GetName( sal_Int32 nWID )
295 {
296     MutexGuard  aGuard( GetLinguMutex() );
297 
298     OUString aRes;
299 
300     sal_Int32 nLen = sizeof( aWID_Name ) / sizeof( aWID_Name[0] );
301     if (0 <= nWID  &&  nWID < nLen
302         && aWID_Name[ nWID ].nWID == nWID)
303     {
304         aRes = OUString( RTL_CONSTASCII_USTRINGPARAM(
305                 aWID_Name[ nWID ].pPropertyName ) );
306     }
307     else
308     {
309         DBG_ASSERT( 0,"lng : unknown WID");
310     }
311 
312     return aRes;
313 }
314 
315 
316 ///////////////////////////////////////////////////////////////////////////
317 
318 //! map must be sorted by first entry in alphabetical increasing order.
319 const SfxItemPropertyMapEntry* lcl_GetLinguProps()
320 {
321     static const SfxItemPropertyMapEntry aLinguProps[] =
322     {
323         { MAP_CHAR_LEN(UPN_DEFAULT_LANGUAGE),           WID_DEFAULT_LANGUAGE,
324                 &::getCppuType( (sal_Int16*)0 ),    0, 0 },
325         { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE),             WID_DEFAULT_LOCALE,
326                 &::getCppuType( (Locale* )0),       0, 0 },
327         { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE_CJK),         WID_DEFAULT_LOCALE_CJK,
328                 &::getCppuType( (Locale* )0),       0, 0 },
329         { MAP_CHAR_LEN(UPN_DEFAULT_LOCALE_CTL),         WID_DEFAULT_LOCALE_CTL,
330                 &::getCppuType( (Locale* )0),       0, 0 },
331         { MAP_CHAR_LEN(UPN_HYPH_MIN_LEADING),           WID_HYPH_MIN_LEADING,
332                 &::getCppuType( (sal_Int16*)0 ),    0, 0 },
333         { MAP_CHAR_LEN(UPN_HYPH_MIN_TRAILING),          WID_HYPH_MIN_TRAILING,
334                 &::getCppuType( (sal_Int16*)0 ),    0, 0 },
335         { MAP_CHAR_LEN(UPN_HYPH_MIN_WORD_LENGTH),       WID_HYPH_MIN_WORD_LENGTH,
336                 &::getCppuType( (sal_Int16*)0 ),    0, 0 },
337         { MAP_CHAR_LEN(UPN_IS_GERMAN_PRE_REFORM),       WID_IS_GERMAN_PRE_REFORM,       /*! deprecated !*/
338                 &::getBooleanCppuType(),            0, 0 },
339         { MAP_CHAR_LEN(UPN_IS_HYPH_AUTO),               WID_IS_HYPH_AUTO,
340                 &::getBooleanCppuType(),            0, 0 },
341         { MAP_CHAR_LEN(UPN_IS_HYPH_SPECIAL),            WID_IS_HYPH_SPECIAL,
342                 &::getBooleanCppuType(),            0, 0 },
343         { MAP_CHAR_LEN(UPN_IS_IGNORE_CONTROL_CHARACTERS),   WID_IS_IGNORE_CONTROL_CHARACTERS,
344                 &::getBooleanCppuType(),            0, 0 },
345         { MAP_CHAR_LEN(UPN_IS_SPELL_AUTO),              WID_IS_SPELL_AUTO,
346                 &::getBooleanCppuType(),            0, 0 },
347         { MAP_CHAR_LEN(UPN_IS_SPELL_CAPITALIZATION),    WID_IS_SPELL_CAPITALIZATION,
348                 &::getBooleanCppuType(),            0, 0 },
349         { MAP_CHAR_LEN(UPN_IS_SPELL_HIDE),              WID_IS_SPELL_HIDE,              /*! deprecated !*/
350                 &::getBooleanCppuType(),            0, 0 },
351         { MAP_CHAR_LEN(UPN_IS_SPELL_IN_ALL_LANGUAGES),  WID_IS_SPELL_IN_ALL_LANGUAGES,  /*! deprecated !*/
352                 &::getBooleanCppuType(),            0, 0 },
353         { MAP_CHAR_LEN(UPN_IS_SPELL_SPECIAL),           WID_IS_SPELL_SPECIAL,
354                 &::getBooleanCppuType(),            0, 0 },
355         { MAP_CHAR_LEN(UPN_IS_SPELL_UPPER_CASE),        WID_IS_SPELL_UPPER_CASE,
356                 &::getBooleanCppuType(),            0, 0 },
357         { MAP_CHAR_LEN(UPN_IS_SPELL_WITH_DIGITS),       WID_IS_SPELL_WITH_DIGITS,
358                 &::getBooleanCppuType(),            0, 0 },
359         { MAP_CHAR_LEN(UPN_IS_USE_DICTIONARY_LIST),     WID_IS_USE_DICTIONARY_LIST,
360                 &::getBooleanCppuType(),            0, 0 },
361         { MAP_CHAR_LEN(UPN_IS_WRAP_REVERSE),            WID_IS_WRAP_REVERSE,
362                 &::getBooleanCppuType(),            0, 0 },
363         { 0,0,0,0,0,0 }
364     };
365     return aLinguProps;
366 }
367 LinguProps::LinguProps() :
368     aEvtListeners   (GetLinguMutex()),
369     aPropListeners  (GetLinguMutex()),
370     aPropertyMap(lcl_GetLinguProps())
371 {
372     bDisposing = sal_False;
373 }
374 
375 void LinguProps::launchEvent( const PropertyChangeEvent &rEvt ) const
376 {
377     cppu::OInterfaceContainerHelper *pContainer =
378             aPropListeners.getContainer( rEvt.PropertyHandle );
379     if (pContainer)
380     {
381         cppu::OInterfaceIteratorHelper aIt( *pContainer );
382         while (aIt.hasMoreElements())
383         {
384             Reference< XPropertyChangeListener > xRef( aIt.next(), UNO_QUERY );
385             if (xRef.is())
386                 xRef->propertyChange( rEvt );
387         }
388     }
389 }
390 
391 Reference< XInterface > SAL_CALL LinguProps_CreateInstance(
392             const Reference< XMultiServiceFactory > & /*rSMgr*/ )
393         throw(Exception)
394 {
395     Reference< XInterface > xService = (cppu::OWeakObject*)new LinguProps;
396     return xService;
397 }
398 
399 Reference< XPropertySetInfo > SAL_CALL LinguProps::getPropertySetInfo()
400         throw(RuntimeException)
401 {
402     MutexGuard  aGuard( GetLinguMutex() );
403 
404     static Reference< XPropertySetInfo > aRef =
405             new SfxItemPropertySetInfo( &aPropertyMap );
406     return aRef;
407 }
408 
409 void SAL_CALL LinguProps::setPropertyValue(
410             const OUString& rPropertyName, const Any& rValue )
411         throw(UnknownPropertyException, PropertyVetoException,
412               IllegalArgumentException, WrappedTargetException, RuntimeException)
413 {
414     MutexGuard  aGuard( GetLinguMutex() );
415 
416     const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
417     if (pCur)
418     {
419         Any aOld( aConfig.GetProperty( pCur->nWID ) );
420         if (aOld != rValue && aConfig.SetProperty( pCur->nWID, rValue ))
421         {
422             PropertyChangeEvent aChgEvt( (XPropertySet *) this, rPropertyName,
423                     sal_False, pCur->nWID, aOld, rValue );
424             launchEvent( aChgEvt );
425         }
426     }
427 #ifdef LINGU_EXCEPTIONS
428     else
429     {
430         throw UnknownPropertyException();
431     }
432 #endif
433 }
434 
435 Any SAL_CALL LinguProps::getPropertyValue( const OUString& rPropertyName )
436         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
437 {
438     MutexGuard  aGuard( GetLinguMutex() );
439 
440     Any aRet;
441 
442     const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
443     if(pCur)
444     {
445         aRet = aConfig.GetProperty( pCur->nWID );
446     }
447 #ifdef LINGU_EXCEPTIONS
448     else
449     {
450         throw UnknownPropertyException();
451     }
452 #endif
453 
454     return aRet;
455 }
456 
457 void SAL_CALL LinguProps::addPropertyChangeListener(
458             const OUString& rPropertyName,
459             const Reference< XPropertyChangeListener >& rxListener )
460         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
461 {
462     MutexGuard  aGuard( GetLinguMutex() );
463 
464     if (!bDisposing && rxListener.is())
465     {
466         const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
467         if(pCur)
468             aPropListeners.addInterface( pCur->nWID, rxListener );
469 #ifdef LINGU_EXCEPTIONS
470         else
471         {
472             throw UnknownPropertyException();
473         }
474 #endif
475     }
476 }
477 
478 void SAL_CALL LinguProps::removePropertyChangeListener(
479             const OUString& rPropertyName,
480             const Reference< XPropertyChangeListener >& rxListener )
481         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
482 {
483     MutexGuard  aGuard( GetLinguMutex() );
484 
485     if (!bDisposing && rxListener.is())
486     {
487         const SfxItemPropertySimpleEntry* pCur = aPropertyMap.getByName( rPropertyName );
488         if(pCur)
489             aPropListeners.removeInterface( pCur->nWID, rxListener );
490 #ifdef LINGU_EXCEPTIONS
491         else
492         {
493             throw UnknownPropertyException();
494         }
495 #endif
496     }
497 }
498 
499 void SAL_CALL LinguProps::addVetoableChangeListener(
500             const OUString& /*rPropertyName*/,
501             const Reference< XVetoableChangeListener >& /*xListener*/ )
502         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
503 {
504 //  MutexGuard  aGuard( GetLinguMutex() );
505 }
506 
507 void SAL_CALL LinguProps::removeVetoableChangeListener(
508             const OUString& /*rPropertyName*/,
509             const Reference< XVetoableChangeListener >& /*xListener*/ )
510         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
511 {
512 //  MutexGuard  aGuard( GetLinguMutex() );
513 }
514 
515 
516 void SAL_CALL LinguProps::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
517         throw(UnknownPropertyException, PropertyVetoException,
518               IllegalArgumentException, WrappedTargetException, RuntimeException)
519 {
520     MutexGuard  aGuard( GetLinguMutex() );
521 
522     Any aOld( aConfig.GetProperty( nHandle ) );
523     if (aOld != rValue && aConfig.SetProperty( nHandle, rValue ))
524     {
525         PropertyChangeEvent aChgEvt( (XPropertySet *) this,
526                 LinguOptions::GetName( nHandle ), sal_False, nHandle, aOld, rValue );
527         launchEvent( aChgEvt );
528     }
529 }
530 
531 
532 Any SAL_CALL LinguProps::getFastPropertyValue( sal_Int32 nHandle )
533         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
534 {
535     MutexGuard  aGuard( GetLinguMutex() );
536 
537     Any aRes( aConfig.GetProperty( nHandle ) );
538     return aRes;
539 }
540 
541 
542 Sequence< PropertyValue > SAL_CALL
543     LinguProps::getPropertyValues()
544         throw(RuntimeException)
545 {
546     MutexGuard  aGuard( GetLinguMutex() );
547 
548     sal_Int32 nLen = aPropertyMap.getSize();
549     Sequence< PropertyValue > aProps( nLen );
550     PropertyValue *pProp = aProps.getArray();
551     PropertyEntryVector_t aPropEntries = aPropertyMap.getPropertyEntries();
552     PropertyEntryVector_t::const_iterator aIt = aPropEntries.begin();
553     for (sal_Int32 i = 0;  i < nLen;  ++i, ++aIt)
554     {
555         PropertyValue &rVal = pProp[i];
556         Any aAny( aConfig.GetProperty( aIt->nWID ) );
557 
558         rVal.Name   = aIt->sName;
559         rVal.Handle = aIt->nWID;
560         rVal.Value  = aAny;
561         rVal.State  = PropertyState_DIRECT_VALUE ;
562     }
563     return aProps;
564 }
565 
566 void SAL_CALL
567     LinguProps::setPropertyValues( const Sequence< PropertyValue >& rProps )
568         throw(UnknownPropertyException, PropertyVetoException,
569               IllegalArgumentException, WrappedTargetException, RuntimeException)
570 {
571     MutexGuard  aGuard( GetLinguMutex() );
572 
573     sal_Int32 nLen = rProps.getLength();
574     const PropertyValue *pVal = rProps.getConstArray();
575     for (sal_Int32 i = 0;  i < nLen;  ++i)
576     {
577         const PropertyValue &rVal = pVal[i];
578         setPropertyValue( rVal.Name, rVal.Value );
579     }
580 }
581 
582 void SAL_CALL
583     LinguProps::dispose()
584         throw(RuntimeException)
585 {
586     MutexGuard  aGuard( GetLinguMutex() );
587 
588     if (!bDisposing)
589     {
590         bDisposing = sal_True;
591 
592         //! its too late to save the options here!
593         // (see AppExitListener for saving)
594         //aOpt.Save();  // save (possible) changes before exiting
595 
596         EventObject aEvtObj( (XPropertySet *) this );
597         aEvtListeners.disposeAndClear( aEvtObj );
598         aPropListeners.disposeAndClear( aEvtObj );
599     }
600 }
601 
602 void SAL_CALL
603     LinguProps::addEventListener( const Reference< XEventListener >& rxListener )
604         throw(RuntimeException)
605 {
606     MutexGuard  aGuard( GetLinguMutex() );
607 
608     if (!bDisposing && rxListener.is())
609         aEvtListeners.addInterface( rxListener );
610 }
611 
612 void SAL_CALL
613     LinguProps::removeEventListener( const Reference< XEventListener >& rxListener )
614         throw(RuntimeException)
615 {
616     MutexGuard  aGuard( GetLinguMutex() );
617 
618     if (!bDisposing && rxListener.is())
619         aEvtListeners.removeInterface( rxListener );
620 }
621 
622 
623 ///////////////////////////////////////////////////////////////////////////
624 // Service specific part
625 //
626 
627 // XServiceInfo
628 OUString SAL_CALL LinguProps::getImplementationName()
629         throw(RuntimeException)
630 {
631     MutexGuard  aGuard( GetLinguMutex() );
632     return getImplementationName_Static();
633 }
634 
635 // XServiceInfo
636 sal_Bool SAL_CALL LinguProps::supportsService( const OUString& ServiceName )
637         throw(RuntimeException)
638 {
639     MutexGuard  aGuard( GetLinguMutex() );
640 
641     uno::Sequence< OUString > aSNL = getSupportedServiceNames();
642     const OUString * pArray = aSNL.getConstArray();
643     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
644         if( pArray[i] == ServiceName )
645             return sal_True;
646     return sal_False;
647 }
648 
649 // XServiceInfo
650 uno::Sequence< OUString > SAL_CALL LinguProps::getSupportedServiceNames()
651         throw(RuntimeException)
652 {
653     MutexGuard  aGuard( GetLinguMutex() );
654     return getSupportedServiceNames_Static();
655 }
656 
657 // ORegistryServiceManager_Static
658 uno::Sequence< OUString > LinguProps::getSupportedServiceNames_Static()
659         throw()
660 {
661     MutexGuard  aGuard( GetLinguMutex() );
662 
663     uno::Sequence< OUString > aSNS( 1 );    // auch mehr als 1 Service moeglich
664     aSNS.getArray()[0] = A2OU( SN_LINGU_PROPERTIES );
665     return aSNS;
666 }
667 
668 void * SAL_CALL LinguProps_getFactory( const sal_Char * pImplName,
669             XMultiServiceFactory *pServiceManager, void * )
670 {
671     void * pRet = 0;
672     if ( !LinguProps::getImplementationName_Static().compareToAscii( pImplName ) )
673     {
674         Reference< XSingleServiceFactory > xFactory =
675             cppu::createOneInstanceFactory(
676                 pServiceManager,
677                 LinguProps::getImplementationName_Static(),
678                 LinguProps_CreateInstance,
679                 LinguProps::getSupportedServiceNames_Static());
680         // acquire, because we return an interface pointer instead of a reference
681         xFactory->acquire();
682         pRet = xFactory.get();
683     }
684     return pRet;
685 }
686 
687 ///////////////////////////////////////////////////////////////////////////
688 
689