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_unotools.hxx"
30 
31 
32 #include <com/sun/star/lang/Locale.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/container/XNameContainer.hpp>
37 #include <com/sun/star/container/XNameReplace.hpp>
38 #include "com/sun/star/util/XMacroExpander.hpp"
39 #include "com/sun/star/beans/XPropertySet.hpp"
40 #include <rtl/uri.hxx>
41 #include <vos/mutex.hxx>
42 #include <i18npool/mslangid.hxx>
43 #include <tools/debug.hxx>
44 #include <tools/string.hxx>
45 #include <unotools/lingucfg.hxx>
46 #include <unotools/linguprops.hxx>
47 
48 #include <comphelper/processfactory.hxx>
49 
50 #include <itemholder1.hxx>
51 
52 using namespace rtl;
53 using namespace com::sun::star;
54 
55 #define A2OU(x)        ::rtl::OUString::createFromAscii( x )
56 #define EXPAND_PROTOCOL     "vnd.sun.star.expand:"
57 #define FILE_PROTOCOL       "file:///"
58 
59 ///////////////////////////////////////////////////////////////////////////
60 
61 
62 static osl::Mutex &  GetOwnMutex()
63 {
64     static osl::Mutex aMutex;
65     return aMutex;
66 }
67 
68 
69 ///////////////////////////////////////////////////////////////////////////
70 
71 
72 static sal_Bool lcl_SetLocale( sal_Int16 &rLanguage, const uno::Any &rVal )
73 {
74     sal_Bool bSucc = sal_False;
75 
76     lang::Locale aNew;
77     if (rVal >>= aNew)	// conversion successful?
78     {
79         sal_Int16 nNew = MsLangId::convertLocaleToLanguage( aNew );
80         if (nNew != rLanguage)
81         {
82             rLanguage = nNew;
83             bSucc = sal_True;
84         }
85     }
86     return bSucc;
87 }
88 
89 
90 static inline const OUString lcl_LanguageToCfgLocaleStr( sal_Int16 nLanguage )
91 {
92     OUString aRes;
93     if (LANGUAGE_SYSTEM != nLanguage)
94         aRes = MsLangId::convertLanguageToIsoString( nLanguage );
95     return aRes;
96 }
97 
98 
99 static sal_Int16 lcl_CfgAnyToLanguage( const uno::Any &rVal )
100 {
101     OUString aTmp;
102     rVal >>= aTmp;
103     return (aTmp.getLength() == 0) ? LANGUAGE_SYSTEM : MsLangId::convertIsoStringToLanguage( aTmp );
104 }
105 
106 
107 //////////////////////////////////////////////////////////////////////
108 
109 SvtLinguOptions::SvtLinguOptions()
110 {
111     nDefaultLanguage = LANGUAGE_NONE;
112 	nDefaultLanguage_CJK = LANGUAGE_NONE;
113 	nDefaultLanguage_CTL = LANGUAGE_NONE;
114 
115 	// general options
116 	bIsUseDictionaryList	=
117 	bIsIgnoreControlCharacters	= sal_True;
118 
119 	// spelling options
120 	bIsSpellCapitalization	=
121 	bIsSpellSpecial			= sal_True;
122 	bIsSpellAuto			=
123 	bIsSpellReverse			=
124 	bIsSpellWithDigits		=
125 	bIsSpellUpperCase		= sal_False;
126 
127     // text conversion options
128     bIsIgnorePostPositionalWord     = sal_True;
129     bIsAutoCloseDialog              =
130     bIsShowEntriesRecentlyUsedFirst =
131     bIsAutoReplaceUniqueEntries     = sal_False;
132     bIsDirectionToSimplified        = sal_True;
133     bIsUseCharacterVariants         =
134     bIsTranslateCommonTerms         =
135     bIsReverseMapping               = sal_False;
136 
137     bROIsDirectionToSimplified      =
138     bROIsUseCharacterVariants       =
139     bROIsTranslateCommonTerms       =
140     bROIsReverseMapping             = sal_False;
141 
142 	// hyphenation options
143 	bIsHyphSpecial			= sal_True;
144 	bIsHyphAuto				= sal_False;
145 	nHyphMinLeading			=
146 	nHyphMinTrailing		= 2;
147 	nHyphMinWordLength		= 0;
148 
149     nDataFilesChangedCheckValue = 0;
150 
151     //grammar options
152     bIsGrammarAuto = sal_False,
153     bIsGrammarInteractive = sal_False;
154 
155 }
156 
157 
158 //////////////////////////////////////////////////////////////////////
159 
160 
161 class SvtLinguConfigItem : public utl::ConfigItem
162 {
163     SvtLinguOptions     aOpt;
164 
165     // disallow copy-constructor and assignment-operator for now
166     SvtLinguConfigItem( const SvtLinguConfigItem & );
167     SvtLinguConfigItem & operator = ( const SvtLinguConfigItem & );
168 
169     static sal_Bool GetHdlByName( sal_Int32 &rnHdl, const OUString &rPropertyName, sal_Bool bFullPropName = sal_False );
170     static const uno::Sequence< OUString > & GetPropertyNames();
171     sal_Bool                LoadOptions( const uno::Sequence< OUString > &rProperyNames );
172     sal_Bool                SaveOptions( const uno::Sequence< OUString > &rProperyNames );
173 
174 public:
175     SvtLinguConfigItem();
176     virtual ~SvtLinguConfigItem();
177 
178     // utl::ConfigItem
179     virtual void    Notify( const com::sun::star::uno::Sequence< rtl::OUString > &rPropertyNames );
180     virtual void    Commit();
181 
182     // make some protected functions of utl::ConfigItem public
183     using utl::ConfigItem::GetNodeNames;
184     using utl::ConfigItem::GetProperties;
185     //using utl::ConfigItem::PutProperties;
186     //using utl::ConfigItem::SetSetProperties;
187     using utl::ConfigItem::ReplaceSetProperties;
188     //using utl::ConfigItem::GetReadOnlyStates;
189 
190 
191     com::sun::star::uno::Any
192             GetProperty( const rtl::OUString &rPropertyName ) const;
193     com::sun::star::uno::Any
194             GetProperty( sal_Int32 nPropertyHandle ) const;
195 
196     sal_Bool    SetProperty( const rtl::OUString &rPropertyName,
197                          const com::sun::star::uno::Any &rValue );
198     sal_Bool    SetProperty( sal_Int32 nPropertyHandle,
199                          const com::sun::star::uno::Any &rValue );
200 
201     sal_Bool    GetOptions( SvtLinguOptions &rOptions ) const;
202     sal_Bool    SetOptions( const SvtLinguOptions &rOptions );
203 
204     sal_Bool    IsReadOnly( const rtl::OUString &rPropertyName ) const;
205     sal_Bool    IsReadOnly( sal_Int32 nPropertyHandle ) const;
206 };
207 
208 
209 SvtLinguConfigItem::SvtLinguConfigItem() :
210     utl::ConfigItem( String::CreateFromAscii( "Office.Linguistic" ) )
211 {
212     LoadOptions( GetPropertyNames() );
213     ClearModified();
214 
215     // request notify events when properties change
216     EnableNotification( GetPropertyNames() );
217 }
218 
219 
220 SvtLinguConfigItem::~SvtLinguConfigItem()
221 {
222     //! Commit (SaveOptions) will be called by the d-tor of the base called !
223 }
224 
225 
226 void SvtLinguConfigItem::Notify( const uno::Sequence< OUString > &rPropertyNames )
227 {
228     LoadOptions( rPropertyNames );
229 	NotifyListeners(0);
230 }
231 
232 
233 void SvtLinguConfigItem::Commit()
234 {
235     SaveOptions( GetPropertyNames() );
236 }
237 
238 
239 static struct NamesToHdl
240 {
241     const char   *pFullPropName;      // full qualified name as used in configuration
242     const char   *pPropName;          // property name only (atom) of above
243     sal_Int32   nHdl;               // numeric handle representing the property
244 }aNamesToHdl[] =
245 {
246 {/*  0 */    "General/DefaultLocale",                         UPN_DEFAULT_LOCALE,                    UPH_DEFAULT_LOCALE},
247 {/*  1 */    "General/DictionaryList/ActiveDictionaries",     UPN_ACTIVE_DICTIONARIES,               UPH_ACTIVE_DICTIONARIES},
248 {/*  2 */    "General/DictionaryList/IsUseDictionaryList",    UPN_IS_USE_DICTIONARY_LIST,            UPH_IS_USE_DICTIONARY_LIST},
249 {/*  3 */    "General/IsIgnoreControlCharacters",             UPN_IS_IGNORE_CONTROL_CHARACTERS,      UPH_IS_IGNORE_CONTROL_CHARACTERS},
250 {/*  5 */    "General/DefaultLocale_CJK",                     UPN_DEFAULT_LOCALE_CJK,                UPH_DEFAULT_LOCALE_CJK},
251 {/*  6 */    "General/DefaultLocale_CTL",                     UPN_DEFAULT_LOCALE_CTL,                UPH_DEFAULT_LOCALE_CTL},
252 
253 {/*  7 */    "SpellChecking/IsSpellUpperCase",                UPN_IS_SPELL_UPPER_CASE,               UPH_IS_SPELL_UPPER_CASE},
254 {/*  8 */    "SpellChecking/IsSpellWithDigits",               UPN_IS_SPELL_WITH_DIGITS,              UPH_IS_SPELL_WITH_DIGITS},
255 {/*  9 */    "SpellChecking/IsSpellCapitalization",           UPN_IS_SPELL_CAPITALIZATION,           UPH_IS_SPELL_CAPITALIZATION},
256 {/* 10 */    "SpellChecking/IsSpellAuto",                     UPN_IS_SPELL_AUTO,                     UPH_IS_SPELL_AUTO},
257 {/* 11 */    "SpellChecking/IsSpellSpecial",                  UPN_IS_SPELL_SPECIAL,                  UPH_IS_SPELL_SPECIAL},
258 {/* 14 */    "SpellChecking/IsReverseDirection",              UPN_IS_WRAP_REVERSE,                   UPH_IS_WRAP_REVERSE},
259 
260 {/* 15 */    "Hyphenation/MinLeading",                        UPN_HYPH_MIN_LEADING,                  UPH_HYPH_MIN_LEADING},
261 {/* 16 */    "Hyphenation/MinTrailing",                       UPN_HYPH_MIN_TRAILING,                 UPH_HYPH_MIN_TRAILING},
262 {/* 17 */    "Hyphenation/MinWordLength",                     UPN_HYPH_MIN_WORD_LENGTH,              UPH_HYPH_MIN_WORD_LENGTH},
263 {/* 18 */    "Hyphenation/IsHyphSpecial",                     UPN_IS_HYPH_SPECIAL,                   UPH_IS_HYPH_SPECIAL},
264 {/* 19 */    "Hyphenation/IsHyphAuto",                        UPN_IS_HYPH_AUTO,                      UPH_IS_HYPH_AUTO},
265 
266 {/* 20 */    "TextConversion/ActiveConversionDictionaries",   UPN_ACTIVE_CONVERSION_DICTIONARIES,        UPH_ACTIVE_CONVERSION_DICTIONARIES},
267 {/* 21 */    "TextConversion/IsIgnorePostPositionalWord",     UPN_IS_IGNORE_POST_POSITIONAL_WORD,        UPH_IS_IGNORE_POST_POSITIONAL_WORD},
268 {/* 22 */    "TextConversion/IsAutoCloseDialog",              UPN_IS_AUTO_CLOSE_DIALOG,                  UPH_IS_AUTO_CLOSE_DIALOG},
269 {/* 23 */    "TextConversion/IsShowEntriesRecentlyUsedFirst", UPN_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST,   UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST},
270 {/* 24 */    "TextConversion/IsAutoReplaceUniqueEntries",     UPN_IS_AUTO_REPLACE_UNIQUE_ENTRIES,        UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES},
271 {/* 25 */    "TextConversion/IsDirectionToSimplified",        UPN_IS_DIRECTION_TO_SIMPLIFIED,            UPH_IS_DIRECTION_TO_SIMPLIFIED},
272 {/* 26 */    "TextConversion/IsUseCharacterVariants",         UPN_IS_USE_CHARACTER_VARIANTS,             UPH_IS_USE_CHARACTER_VARIANTS},
273 {/* 27 */    "TextConversion/IsTranslateCommonTerms",         UPN_IS_TRANSLATE_COMMON_TERMS,             UPH_IS_TRANSLATE_COMMON_TERMS},
274 {/* 28 */    "TextConversion/IsReverseMapping",               UPN_IS_REVERSE_MAPPING,                    UPH_IS_REVERSE_MAPPING},
275 
276 {/* 29 */    "ServiceManager/DataFilesChangedCheckValue",     UPN_DATA_FILES_CHANGED_CHECK_VALUE,        UPH_DATA_FILES_CHANGED_CHECK_VALUE},
277 
278 {/* 30 */    "GrammarChecking/IsAutoCheck",                   UPN_IS_GRAMMAR_AUTO,                      UPH_IS_GRAMMAR_AUTO},
279 {/* 31 */    "GrammarChecking/IsInteractiveCheck",            UPN_IS_GRAMMAR_INTERACTIVE,               UPH_IS_GRAMMAR_INTERACTIVE},
280 
281             /* similar to entry 0 (thus no own configuration entry) but with different property name and type */
282 {            NULL,											 UPN_DEFAULT_LANGUAGE,                      UPH_DEFAULT_LANGUAGE},
283 
284 {            NULL,                                            NULL,                                      -1}
285 };
286 
287 
288 const uno::Sequence< OUString > & SvtLinguConfigItem::GetPropertyNames()
289 {
290     static uno::Sequence< OUString > aNames;
291 	static sal_Bool bInitialized = sal_False;
292 
293 	if (!bInitialized)
294 	{
295 		sal_Int32 nMax = sizeof(aNamesToHdl) / sizeof(aNamesToHdl[0]);
296 
297 		aNames.realloc( nMax );
298 		OUString *pNames = aNames.getArray();
299 		sal_Int32 nIdx = 0;
300 		for (sal_Int32 i = 0; i < nMax;  ++i)
301 		{
302 			const sal_Char *pFullPropName = aNamesToHdl[i].pFullPropName;
303 			if (pFullPropName)
304 				pNames[ nIdx++ ] = A2OU( pFullPropName );
305 		}
306 		aNames.realloc( nIdx );
307 		bInitialized = sal_True;
308 	}
309 	return aNames;
310 }
311 
312 
313 sal_Bool SvtLinguConfigItem::GetHdlByName(
314 	sal_Int32 &rnHdl,
315 	const OUString &rPropertyName,
316 	sal_Bool bFullPropName )
317 {
318     NamesToHdl *pEntry = &aNamesToHdl[0];
319 
320 	if (bFullPropName)
321 	{
322 		while (pEntry && pEntry->pFullPropName != NULL)
323 		{
324 			if (0 == rPropertyName.compareToAscii( pEntry->pFullPropName ))
325 			{
326 				rnHdl = pEntry->nHdl;
327 				break;
328 			}
329 			++pEntry;
330 		}
331 		return pEntry && pEntry->pFullPropName != NULL;
332 	}
333 	else
334 	{
335 		while (pEntry && pEntry->pPropName != NULL)
336 		{
337 			if (0 == rPropertyName.compareToAscii( pEntry->pPropName ))
338 			{
339 				rnHdl = pEntry->nHdl;
340 				break;
341 			}
342 			++pEntry;
343 		}
344 		return pEntry && pEntry->pPropName != NULL;
345 	}
346 }
347 
348 
349 uno::Any SvtLinguConfigItem::GetProperty( const OUString &rPropertyName ) const
350 {
351     osl::MutexGuard aGuard( GetOwnMutex() );
352 
353     sal_Int32 nHdl;
354     return GetHdlByName( nHdl, rPropertyName ) ? GetProperty( nHdl ) : uno::Any();
355 }
356 
357 
358 uno::Any SvtLinguConfigItem::GetProperty( sal_Int32 nPropertyHandle ) const
359 {
360     osl::MutexGuard aGuard( GetOwnMutex() );
361 
362     uno::Any aRes;
363 
364     const sal_Int16 *pnVal = 0;
365     const sal_Bool  *pbVal = 0;
366     const sal_Int32 *pnInt32Val = 0;
367 
368     const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
369     switch (nPropertyHandle)
370     {
371         case UPH_IS_USE_DICTIONARY_LIST :   pbVal = &rOpt.bIsUseDictionaryList; break;
372         case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters;   break;
373         case UPH_IS_HYPH_AUTO :             pbVal = &rOpt.bIsHyphAuto;  break;
374         case UPH_IS_HYPH_SPECIAL :          pbVal = &rOpt.bIsHyphSpecial;   break;
375         case UPH_IS_SPELL_AUTO :            pbVal = &rOpt.bIsSpellAuto; break;
376         case UPH_IS_SPELL_SPECIAL :         pbVal = &rOpt.bIsSpellSpecial;  break;
377         case UPH_IS_WRAP_REVERSE :          pbVal = &rOpt.bIsSpellReverse;  break;
378         case UPH_DEFAULT_LANGUAGE :         pnVal = &rOpt.nDefaultLanguage; break;
379         case UPH_IS_SPELL_CAPITALIZATION :  pbVal = &rOpt.bIsSpellCapitalization;       break;
380         case UPH_IS_SPELL_WITH_DIGITS :     pbVal = &rOpt.bIsSpellWithDigits;   break;
381         case UPH_IS_SPELL_UPPER_CASE :      pbVal = &rOpt.bIsSpellUpperCase;        break;
382         case UPH_HYPH_MIN_LEADING :         pnVal = &rOpt.nHyphMinLeading;      break;
383         case UPH_HYPH_MIN_TRAILING :        pnVal = &rOpt.nHyphMinTrailing; break;
384         case UPH_HYPH_MIN_WORD_LENGTH :     pnVal = &rOpt.nHyphMinWordLength;   break;
385         case UPH_ACTIVE_DICTIONARIES :
386         {
387             aRes <<= rOpt.aActiveDics;
388             break;
389         }
390         case UPH_ACTIVE_CONVERSION_DICTIONARIES :
391         {
392             aRes <<= rOpt.aActiveConvDics;
393             break;
394         }
395         case UPH_DEFAULT_LOCALE :
396         {
397             lang::Locale aLocale( MsLangId::convertLanguageToLocale( rOpt.nDefaultLanguage, false ) );
398             aRes.setValue( &aLocale, ::getCppuType((lang::Locale*)0 ));
399             break;
400         }
401         case UPH_DEFAULT_LOCALE_CJK :
402         {
403             lang::Locale aLocale( MsLangId::convertLanguageToLocale( rOpt.nDefaultLanguage_CJK, false ) );
404             aRes.setValue( &aLocale, ::getCppuType((lang::Locale*)0 ));
405             break;
406         }
407         case UPH_DEFAULT_LOCALE_CTL :
408         {
409             lang::Locale aLocale( MsLangId::convertLanguageToLocale( rOpt.nDefaultLanguage_CTL, false ) );
410             aRes.setValue( &aLocale, ::getCppuType((lang::Locale*)0 ));
411             break;
412         }
413         case UPH_IS_IGNORE_POST_POSITIONAL_WORD :       pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
414         case UPH_IS_AUTO_CLOSE_DIALOG :                 pbVal = &rOpt.bIsAutoCloseDialog; break;
415         case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :  pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
416         case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :       pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
417 
418         case UPH_IS_DIRECTION_TO_SIMPLIFIED:            pbVal = &rOpt.bIsDirectionToSimplified; break;
419         case UPH_IS_USE_CHARACTER_VARIANTS :            pbVal = &rOpt.bIsUseCharacterVariants; break;
420         case UPH_IS_TRANSLATE_COMMON_TERMS :            pbVal = &rOpt.bIsTranslateCommonTerms; break;
421         case UPH_IS_REVERSE_MAPPING :                   pbVal = &rOpt.bIsReverseMapping; break;
422 
423         case UPH_DATA_FILES_CHANGED_CHECK_VALUE :       pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
424         case UPH_IS_GRAMMAR_AUTO:                       pbVal = &rOpt.bIsGrammarAuto; break;
425         case UPH_IS_GRAMMAR_INTERACTIVE:                pbVal = &rOpt.bIsGrammarInteractive; break;
426         default :
427             DBG_ASSERT( 0, "unexpected property handle" );
428     }
429 
430     if (pbVal)
431         aRes <<= *pbVal;
432     else if (pnVal)
433         aRes <<= *pnVal;
434     else if (pnInt32Val)
435         aRes <<= *pnInt32Val;
436 
437     return aRes;
438 }
439 
440 
441 sal_Bool SvtLinguConfigItem::SetProperty( const OUString &rPropertyName, const uno::Any &rValue )
442 {
443     osl::MutexGuard aGuard( GetOwnMutex() );
444 
445     sal_Bool bSucc = sal_False;
446     sal_Int32 nHdl;
447     if (GetHdlByName( nHdl, rPropertyName ))
448         bSucc = SetProperty( nHdl, rValue );
449     return bSucc;
450 }
451 
452 
453 sal_Bool SvtLinguConfigItem::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
454 {
455     osl::MutexGuard aGuard( GetOwnMutex() );
456 
457     sal_Bool bSucc = sal_False;
458     if (!rValue.hasValue())
459         return bSucc;
460 
461     sal_Bool bMod = sal_False;
462 
463     sal_Int16 *pnVal = 0;
464     sal_Bool  *pbVal = 0;
465     sal_Int32 *pnInt32Val = 0;
466 
467     SvtLinguOptions &rOpt = aOpt;
468     switch (nPropertyHandle)
469     {
470         case UPH_IS_USE_DICTIONARY_LIST :   pbVal = &rOpt.bIsUseDictionaryList;    break;
471         case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters;  break;
472         case UPH_IS_HYPH_AUTO :             pbVal = &rOpt.bIsHyphAuto; break;
473         case UPH_IS_HYPH_SPECIAL :          pbVal = &rOpt.bIsHyphSpecial;  break;
474         case UPH_IS_SPELL_AUTO :            pbVal = &rOpt.bIsSpellAuto;    break;
475         case UPH_IS_SPELL_SPECIAL :         pbVal = &rOpt.bIsSpellSpecial; break;
476         case UPH_IS_WRAP_REVERSE :          pbVal = &rOpt.bIsSpellReverse; break;
477         case UPH_DEFAULT_LANGUAGE :         pnVal = &rOpt.nDefaultLanguage;    break;
478         case UPH_IS_SPELL_CAPITALIZATION :  pbVal = &rOpt.bIsSpellCapitalization;      break;
479         case UPH_IS_SPELL_WITH_DIGITS :     pbVal = &rOpt.bIsSpellWithDigits;  break;
480         case UPH_IS_SPELL_UPPER_CASE :      pbVal = &rOpt.bIsSpellUpperCase;       break;
481         case UPH_HYPH_MIN_LEADING :         pnVal = &rOpt.nHyphMinLeading;     break;
482         case UPH_HYPH_MIN_TRAILING :        pnVal = &rOpt.nHyphMinTrailing;    break;
483         case UPH_HYPH_MIN_WORD_LENGTH :     pnVal = &rOpt.nHyphMinWordLength;  break;
484         case UPH_ACTIVE_DICTIONARIES :
485         {
486             rValue >>= rOpt.aActiveDics;
487             bMod = sal_True;
488             break;
489         }
490         case UPH_ACTIVE_CONVERSION_DICTIONARIES :
491         {
492             rValue >>= rOpt.aActiveConvDics;
493             bMod = sal_True;
494             break;
495         }
496         case UPH_DEFAULT_LOCALE :
497         {
498             bSucc = lcl_SetLocale( rOpt.nDefaultLanguage, rValue );
499             bMod = bSucc;
500             break;
501         }
502         case UPH_DEFAULT_LOCALE_CJK :
503         {
504             bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CJK, rValue );
505             bMod = bSucc;
506             break;
507         }
508         case UPH_DEFAULT_LOCALE_CTL :
509         {
510             bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CTL, rValue );
511             bMod = bSucc;
512             break;
513         }
514         case UPH_IS_IGNORE_POST_POSITIONAL_WORD :       pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
515         case UPH_IS_AUTO_CLOSE_DIALOG :                 pbVal = &rOpt.bIsAutoCloseDialog; break;
516         case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :  pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
517         case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :       pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
518 
519         case UPH_IS_DIRECTION_TO_SIMPLIFIED :           pbVal = &rOpt.bIsDirectionToSimplified; break;
520         case UPH_IS_USE_CHARACTER_VARIANTS :            pbVal = &rOpt.bIsUseCharacterVariants; break;
521         case UPH_IS_TRANSLATE_COMMON_TERMS :            pbVal = &rOpt.bIsTranslateCommonTerms; break;
522         case UPH_IS_REVERSE_MAPPING :                   pbVal = &rOpt.bIsReverseMapping; break;
523 
524         case UPH_DATA_FILES_CHANGED_CHECK_VALUE :       pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
525         case UPH_IS_GRAMMAR_AUTO:                       pbVal = &rOpt.bIsGrammarAuto; break;
526         case UPH_IS_GRAMMAR_INTERACTIVE:                pbVal = &rOpt.bIsGrammarInteractive; break;
527         default :
528             DBG_ASSERT( 0, "unexpected property handle" );
529     }
530 
531     if (pbVal)
532     {
533         sal_Bool bNew = sal_Bool();
534         if (rValue >>= bNew)
535         {
536             if (bNew != *pbVal)
537             {
538                 *pbVal = bNew;
539                 bMod = sal_True;
540             }
541             bSucc = sal_True;
542         }
543     }
544     else if (pnVal)
545     {
546         sal_Int16 nNew = sal_Int16();
547         if (rValue >>= nNew)
548         {
549             if (nNew != *pnVal)
550             {
551                 *pnVal = nNew;
552                 bMod = sal_True;
553             }
554             bSucc = sal_True;
555         }
556     }
557     else if (pnInt32Val)
558     {
559         sal_Int32 nNew = sal_Int32();
560         if (rValue >>= nNew)
561         {
562             if (nNew != *pnInt32Val)
563             {
564                 *pnInt32Val = nNew;
565                 bMod = sal_True;
566             }
567             bSucc = sal_True;
568         }
569     }
570 
571     if (bMod)
572         SetModified();
573 
574 	NotifyListeners(0);
575     return bSucc;
576 }
577 
578 
579 sal_Bool SvtLinguConfigItem::GetOptions( SvtLinguOptions &rOptions ) const
580 {
581     osl::MutexGuard aGuard( GetOwnMutex() );
582 
583     rOptions = aOpt;
584     return sal_True;
585 }
586 
587 
588 sal_Bool SvtLinguConfigItem::SetOptions( const SvtLinguOptions &rOptions )
589 {
590     osl::MutexGuard aGuard( GetOwnMutex() );
591 
592     aOpt = rOptions;
593     SetModified();
594 	NotifyListeners(0);
595     return sal_True;
596 }
597 
598 
599 sal_Bool SvtLinguConfigItem::LoadOptions( const uno::Sequence< OUString > &rProperyNames )
600 {
601     osl::MutexGuard aGuard( GetOwnMutex() );
602 
603     sal_Bool bRes = sal_False;
604 
605     const OUString *pProperyNames = rProperyNames.getConstArray();
606     sal_Int32 nProps = rProperyNames.getLength();
607 
608     const uno::Sequence< uno::Any > aValues = GetProperties( rProperyNames );
609     const uno::Sequence< sal_Bool > aROStates = GetReadOnlyStates( rProperyNames );
610 
611     if (nProps  &&  aValues.getLength() == nProps &&  aROStates.getLength() == nProps)
612     {
613         SvtLinguOptions &rOpt = aOpt;
614 
615         const uno::Any *pValue = aValues.getConstArray();
616         const sal_Bool *pROStates = aROStates.getConstArray();
617         for (sal_Int32 i = 0;  i < nProps;  ++i)
618         {
619             const uno::Any &rVal = pValue[i];
620             sal_Int32 nPropertyHandle;
621             GetHdlByName( nPropertyHandle, pProperyNames[i], sal_True );
622             switch ( nPropertyHandle )
623             {
624                 case UPH_DEFAULT_LOCALE :
625                     { rOpt.bRODefaultLanguage = pROStates[i]; rOpt.nDefaultLanguage = lcl_CfgAnyToLanguage( rVal ); } break;
626                 case UPH_ACTIVE_DICTIONARIES :
627                     { rOpt.bROActiveDics = pROStates[i]; rVal >>= rOpt.aActiveDics;   } break;
628                 case UPH_IS_USE_DICTIONARY_LIST :
629                     { rOpt.bROIsUseDictionaryList = pROStates[i]; rVal >>= rOpt.bIsUseDictionaryList;  } break;
630                 case UPH_IS_IGNORE_CONTROL_CHARACTERS :
631                     { rOpt.bROIsIgnoreControlCharacters = pROStates[i]; rVal >>= rOpt.bIsIgnoreControlCharacters;    } break;
632                 case UPH_DEFAULT_LOCALE_CJK :
633                     { rOpt.bRODefaultLanguage_CJK = pROStates[i]; rOpt.nDefaultLanguage_CJK = lcl_CfgAnyToLanguage( rVal );    } break;
634                 case UPH_DEFAULT_LOCALE_CTL :
635                     { rOpt.bRODefaultLanguage_CTL = pROStates[i]; rOpt.nDefaultLanguage_CTL = lcl_CfgAnyToLanguage( rVal );    } break;
636 
637                 case UPH_IS_SPELL_UPPER_CASE :
638                     { rOpt.bROIsSpellUpperCase = pROStates[i]; rVal >>= rOpt.bIsSpellUpperCase; } break;
639                 case UPH_IS_SPELL_WITH_DIGITS :
640                     { rOpt.bROIsSpellWithDigits = pROStates[i]; rVal >>= rOpt.bIsSpellWithDigits;    } break;
641                 case UPH_IS_SPELL_CAPITALIZATION :
642                     { rOpt.bROIsSpellCapitalization = pROStates[i]; rVal >>= rOpt.bIsSpellCapitalization;    } break;
643                 case UPH_IS_SPELL_AUTO :
644                     { rOpt.bROIsSpellAuto = pROStates[i]; rVal >>= rOpt.bIsSpellAuto;  } break;
645                 case UPH_IS_SPELL_SPECIAL :
646                     { rOpt.bROIsSpellSpecial = pROStates[i]; rVal >>= rOpt.bIsSpellSpecial;   } break;
647                 case UPH_IS_WRAP_REVERSE :
648                     { rOpt.bROIsSpellReverse = pROStates[i]; rVal >>= rOpt.bIsSpellReverse;   } break;
649 
650                 case UPH_HYPH_MIN_LEADING :
651                     { rOpt.bROHyphMinLeading = pROStates[i]; rVal >>= rOpt.nHyphMinLeading;   } break;
652                 case UPH_HYPH_MIN_TRAILING :
653                     { rOpt.bROHyphMinTrailing = pROStates[i]; rVal >>= rOpt.nHyphMinTrailing;  } break;
654                 case UPH_HYPH_MIN_WORD_LENGTH :
655                     { rOpt.bROHyphMinWordLength = pROStates[i]; rVal >>= rOpt.nHyphMinWordLength;    } break;
656                 case UPH_IS_HYPH_SPECIAL :
657                     { rOpt.bROIsHyphSpecial = pROStates[i]; rVal >>= rOpt.bIsHyphSpecial;    } break;
658                 case UPH_IS_HYPH_AUTO :
659                     { rOpt.bROIsHyphAuto = pROStates[i]; rVal >>= rOpt.bIsHyphAuto;   } break;
660 
661                 case UPH_ACTIVE_CONVERSION_DICTIONARIES : { rOpt.bROActiveConvDics = pROStates[i]; rVal >>= rOpt.aActiveConvDics;   } break;
662 
663                 case UPH_IS_IGNORE_POST_POSITIONAL_WORD :
664                     { rOpt.bROIsIgnorePostPositionalWord = pROStates[i]; rVal >>= rOpt.bIsIgnorePostPositionalWord;  } break;
665                 case UPH_IS_AUTO_CLOSE_DIALOG :
666                     { rOpt.bROIsAutoCloseDialog = pROStates[i]; rVal >>= rOpt.bIsAutoCloseDialog;  } break;
667                 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :
668                     { rOpt.bROIsShowEntriesRecentlyUsedFirst = pROStates[i]; rVal >>= rOpt.bIsShowEntriesRecentlyUsedFirst;  } break;
669                 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :
670                     { rOpt.bROIsAutoReplaceUniqueEntries = pROStates[i]; rVal >>= rOpt.bIsAutoReplaceUniqueEntries;  } break;
671 
672                 case UPH_IS_DIRECTION_TO_SIMPLIFIED :
673                     { rOpt.bROIsDirectionToSimplified = pROStates[i];
674                             if( ! (rVal >>= rOpt.bIsDirectionToSimplified) )
675                             {
676                                 //default is locale dependent:
677                                 if(  rOpt.nDefaultLanguage_CJK == LANGUAGE_CHINESE_HONGKONG
678                                   || rOpt.nDefaultLanguage_CJK == LANGUAGE_CHINESE_MACAU
679                                   || rOpt.nDefaultLanguage_CJK == LANGUAGE_CHINESE_TRADITIONAL )
680                                 {
681                                     rOpt.bIsDirectionToSimplified = sal_False;
682                                 }
683                                 else
684                                 {
685                                     rOpt.bIsDirectionToSimplified = sal_True;
686                                 }
687                             }
688                     } break;
689                 case UPH_IS_USE_CHARACTER_VARIANTS :
690                     { rOpt.bROIsUseCharacterVariants = pROStates[i]; rVal >>= rOpt.bIsUseCharacterVariants;  } break;
691                 case UPH_IS_TRANSLATE_COMMON_TERMS :
692                     { rOpt.bROIsTranslateCommonTerms = pROStates[i]; rVal >>= rOpt.bIsTranslateCommonTerms;  } break;
693                 case UPH_IS_REVERSE_MAPPING :
694                     { rOpt.bROIsReverseMapping = pROStates[i]; rVal >>= rOpt.bIsReverseMapping;  } break;
695 
696                 case UPH_DATA_FILES_CHANGED_CHECK_VALUE :
697                     { rOpt.bRODataFilesChangedCheckValue = pROStates[i]; rVal >>= rOpt.nDataFilesChangedCheckValue;  } break;
698 
699                 case UPH_IS_GRAMMAR_AUTO:
700                     { rOpt.bROIsGrammarAuto = pROStates[i]; rVal >>= rOpt.bIsGrammarAuto; }
701                 break;
702                 case UPH_IS_GRAMMAR_INTERACTIVE:
703                     { rOpt.bROIsGrammarInteractive = pROStates[i]; rVal >>= rOpt.bIsGrammarInteractive; }
704                 break;
705 
706                 default:
707                     DBG_ASSERT( 0, "unexpected case" );
708             }
709         }
710 
711         bRes = sal_True;
712     }
713     DBG_ASSERT( bRes, "LoadOptions failed" );
714 
715     return bRes;
716 }
717 
718 
719 sal_Bool SvtLinguConfigItem::SaveOptions( const uno::Sequence< OUString > &rProperyNames )
720 {
721     if (!IsModified())
722         return sal_True;
723 
724     osl::MutexGuard aGuard( GetOwnMutex() );
725 
726     sal_Bool bRet = sal_False;
727     const uno::Type &rBOOL     = ::getBooleanCppuType();
728     const uno::Type &rINT16    = ::getCppuType( (sal_Int16 *) NULL );
729     const uno::Type &rINT32    = ::getCppuType( (sal_Int32 *) NULL );
730 
731     sal_Int32 nProps = rProperyNames.getLength();
732     uno::Sequence< uno::Any > aValues( nProps );
733     uno::Any *pValue = aValues.getArray();
734 
735     if (nProps  &&  aValues.getLength() == nProps)
736     {
737         const SvtLinguOptions &rOpt = aOpt;
738 
739         OUString aTmp( lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage ) );
740         *pValue++ = uno::makeAny( aTmp );                               //   0
741         *pValue++ = uno::makeAny( rOpt.aActiveDics );                   //   1
742         pValue++->setValue( &rOpt.bIsUseDictionaryList, rBOOL );        //   2
743         pValue++->setValue( &rOpt.bIsIgnoreControlCharacters, rBOOL );  //   3
744         aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CJK );
745         *pValue++ = uno::makeAny( aTmp );                               //   5
746         aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CTL );
747         *pValue++ = uno::makeAny( aTmp );                               //   6
748 
749         pValue++->setValue( &rOpt.bIsSpellUpperCase, rBOOL );          //   7
750         pValue++->setValue( &rOpt.bIsSpellWithDigits, rBOOL );         //   8
751         pValue++->setValue( &rOpt.bIsSpellCapitalization, rBOOL );     //   9
752         pValue++->setValue( &rOpt.bIsSpellAuto, rBOOL );               //  10
753         pValue++->setValue( &rOpt.bIsSpellSpecial, rBOOL );            //  11
754         pValue++->setValue( &rOpt.bIsSpellReverse, rBOOL );            //  14
755 
756         pValue++->setValue( &rOpt.nHyphMinLeading, rINT16 );           //  15
757         pValue++->setValue( &rOpt.nHyphMinTrailing, rINT16 );          //  16
758         pValue++->setValue( &rOpt.nHyphMinWordLength, rINT16 );        //  17
759         pValue++->setValue( &rOpt.bIsHyphSpecial, rBOOL );             //  18
760         pValue++->setValue( &rOpt.bIsHyphAuto, rBOOL );                //  19
761 
762         *pValue++ = uno::makeAny( rOpt.aActiveConvDics );               //   20
763 
764         pValue++->setValue( &rOpt.bIsIgnorePostPositionalWord, rBOOL ); //  21
765         pValue++->setValue( &rOpt.bIsAutoCloseDialog, rBOOL );          //  22
766         pValue++->setValue( &rOpt.bIsShowEntriesRecentlyUsedFirst, rBOOL ); //  23
767         pValue++->setValue( &rOpt.bIsAutoReplaceUniqueEntries, rBOOL ); //  24
768 
769         pValue++->setValue( &rOpt.bIsDirectionToSimplified, rBOOL ); //  25
770         pValue++->setValue( &rOpt.bIsUseCharacterVariants, rBOOL ); //  26
771         pValue++->setValue( &rOpt.bIsTranslateCommonTerms, rBOOL ); //  27
772         pValue++->setValue( &rOpt.bIsReverseMapping, rBOOL ); //  28
773 
774         pValue++->setValue( &rOpt.nDataFilesChangedCheckValue, rINT32 ); //  29
775         pValue++->setValue( &rOpt.bIsGrammarAuto, rBOOL ); //  30
776         pValue++->setValue( &rOpt.bIsGrammarInteractive, rBOOL ); // 31
777 
778         bRet |= PutProperties( rProperyNames, aValues );
779     }
780 
781     if (bRet)
782         ClearModified();
783 
784     return bRet;
785 }
786 
787 sal_Bool SvtLinguConfigItem::IsReadOnly( const rtl::OUString &rPropertyName ) const
788 {
789     osl::MutexGuard aGuard( GetOwnMutex() );
790 
791     sal_Bool bReadOnly = sal_False;
792     sal_Int32 nHdl;
793     if (GetHdlByName( nHdl, rPropertyName ))
794         bReadOnly = IsReadOnly( nHdl );
795     return bReadOnly;
796 }
797 
798 sal_Bool SvtLinguConfigItem::IsReadOnly( sal_Int32 nPropertyHandle ) const
799 {
800     osl::MutexGuard aGuard( GetOwnMutex() );
801 
802     sal_Bool bReadOnly = sal_False;
803 
804     const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
805     switch(nPropertyHandle)
806     {
807         case UPH_IS_USE_DICTIONARY_LIST         : bReadOnly = rOpt.bROIsUseDictionaryList      ; break;
808         case UPH_IS_IGNORE_CONTROL_CHARACTERS   : bReadOnly = rOpt.bROIsIgnoreControlCharacters; break;
809         case UPH_IS_HYPH_AUTO                   : bReadOnly = rOpt.bROIsHyphAuto               ; break;
810         case UPH_IS_HYPH_SPECIAL                : bReadOnly = rOpt.bROIsHyphSpecial            ; break;
811         case UPH_IS_SPELL_AUTO                  : bReadOnly = rOpt.bROIsSpellAuto              ; break;
812         case UPH_IS_SPELL_SPECIAL               : bReadOnly = rOpt.bROIsSpellSpecial           ; break;
813         case UPH_IS_WRAP_REVERSE                : bReadOnly = rOpt.bROIsSpellReverse           ; break;
814         case UPH_DEFAULT_LANGUAGE               : bReadOnly = rOpt.bRODefaultLanguage          ; break;
815         case UPH_IS_SPELL_CAPITALIZATION        : bReadOnly = rOpt.bROIsSpellCapitalization    ; break;
816         case UPH_IS_SPELL_WITH_DIGITS           : bReadOnly = rOpt.bROIsSpellWithDigits        ; break;
817         case UPH_IS_SPELL_UPPER_CASE            : bReadOnly = rOpt.bROIsSpellUpperCase         ; break;
818         case UPH_HYPH_MIN_LEADING               : bReadOnly = rOpt.bROHyphMinLeading           ; break;
819         case UPH_HYPH_MIN_TRAILING              : bReadOnly = rOpt.bROHyphMinTrailing          ; break;
820         case UPH_HYPH_MIN_WORD_LENGTH           : bReadOnly = rOpt.bROHyphMinWordLength        ; break;
821         case UPH_ACTIVE_DICTIONARIES            : bReadOnly = rOpt.bROActiveDics               ; break;
822         case UPH_ACTIVE_CONVERSION_DICTIONARIES : bReadOnly = rOpt.bROActiveConvDics           ; break;
823         case UPH_DEFAULT_LOCALE                 : bReadOnly = rOpt.bRODefaultLanguage          ; break;
824         case UPH_DEFAULT_LOCALE_CJK             : bReadOnly = rOpt.bRODefaultLanguage_CJK      ; break;
825         case UPH_DEFAULT_LOCALE_CTL             : bReadOnly = rOpt.bRODefaultLanguage_CTL      ; break;
826         case UPH_IS_IGNORE_POST_POSITIONAL_WORD :       bReadOnly = rOpt.bROIsIgnorePostPositionalWord; break;
827         case UPH_IS_AUTO_CLOSE_DIALOG :                 bReadOnly = rOpt.bROIsAutoCloseDialog; break;
828         case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :  bReadOnly = rOpt.bROIsShowEntriesRecentlyUsedFirst; break;
829         case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :       bReadOnly = rOpt.bROIsAutoReplaceUniqueEntries; break;
830         case UPH_IS_DIRECTION_TO_SIMPLIFIED : bReadOnly = rOpt.bROIsDirectionToSimplified; break;
831         case UPH_IS_USE_CHARACTER_VARIANTS : bReadOnly = rOpt.bROIsUseCharacterVariants; break;
832         case UPH_IS_TRANSLATE_COMMON_TERMS : bReadOnly = rOpt.bROIsTranslateCommonTerms; break;
833         case UPH_IS_REVERSE_MAPPING :        bReadOnly = rOpt.bROIsReverseMapping; break;
834         case UPH_DATA_FILES_CHANGED_CHECK_VALUE :       bReadOnly = rOpt.bRODataFilesChangedCheckValue; break;
835         case UPH_IS_GRAMMAR_AUTO:                       bReadOnly = rOpt.bROIsGrammarAuto; break;
836         case UPH_IS_GRAMMAR_INTERACTIVE:                bReadOnly = rOpt.bROIsGrammarInteractive; break;
837         default :
838             DBG_ASSERT( 0, "unexpected property handle" );
839     }
840     return bReadOnly;
841 }
842 
843 //////////////////////////////////////////////////////////////////////
844 
845 static SvtLinguConfigItem *pCfgItem = 0;
846 static sal_Int32           nCfgItemRefCount = 0;
847 
848 static const rtl::OUString aG_SupportedDictionaryFormats( A2OU("SupportedDictionaryFormats") );
849 static const rtl::OUString aG_Dictionaries( A2OU("Dictionaries") );
850 static const rtl::OUString aG_Locations( A2OU("Locations") );
851 static const rtl::OUString aG_Format( A2OU("Format") );
852 static const rtl::OUString aG_Locales( A2OU("Locales") );
853 static const rtl::OUString aG_DisabledDictionaries( A2OU("DisabledDictionaries") );
854 static const rtl::OUString aG_LastActiveDictionaries( A2OU("LastActiveDictionaries") );
855 
856 SvtLinguConfig::SvtLinguConfig()
857 {
858     // Global access, must be guarded (multithreading)
859     osl::MutexGuard aGuard( GetOwnMutex() );
860     ++nCfgItemRefCount;
861 }
862 
863 
864 SvtLinguConfig::~SvtLinguConfig()
865 {
866     osl::MutexGuard aGuard( GetOwnMutex() );
867 
868     if (pCfgItem && pCfgItem->IsModified())
869         pCfgItem->Commit();
870 
871     if (--nCfgItemRefCount <= 0)
872     {
873         if (pCfgItem)
874             delete pCfgItem;
875         pCfgItem = 0;
876     }
877 }
878 
879 
880 SvtLinguConfigItem & SvtLinguConfig::GetConfigItem()
881 {
882     // Global access, must be guarded (multithreading)
883     osl::MutexGuard aGuard( GetOwnMutex() );
884     if (!pCfgItem)
885     {
886         pCfgItem = new SvtLinguConfigItem;
887         ItemHolder1::holdConfigItem(E_LINGUCFG);
888     }
889     return *pCfgItem;
890 }
891 
892 
893 uno::Sequence< OUString > SvtLinguConfig::GetNodeNames( const OUString &rNode )
894 {
895     return GetConfigItem().GetNodeNames( rNode );
896 }
897 
898 
899 uno::Sequence< uno::Any > SvtLinguConfig::GetProperties( const uno::Sequence< OUString > &rNames )
900 {
901     return GetConfigItem().GetProperties(rNames);
902 }
903 
904 
905 sal_Bool SvtLinguConfig::ReplaceSetProperties(
906         const OUString &rNode, uno::Sequence< beans::PropertyValue > rValues )
907 {
908     return GetConfigItem().ReplaceSetProperties( rNode, rValues );
909 }
910 
911 
912 uno::Any SvtLinguConfig::GetProperty( const OUString &rPropertyName ) const
913 {
914     return GetConfigItem().GetProperty( rPropertyName );
915 }
916 
917 
918 uno::Any SvtLinguConfig::GetProperty( sal_Int32 nPropertyHandle ) const
919 {
920     return GetConfigItem().GetProperty( nPropertyHandle );
921 }
922 
923 
924 sal_Bool SvtLinguConfig::SetProperty( const OUString &rPropertyName, const uno::Any &rValue )
925 {
926     return GetConfigItem().SetProperty( rPropertyName, rValue );
927 }
928 
929 
930 sal_Bool SvtLinguConfig::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
931 {
932     return GetConfigItem().SetProperty( nPropertyHandle, rValue );
933 }
934 
935 
936 sal_Bool SvtLinguConfig::GetOptions( SvtLinguOptions &rOptions ) const
937 {
938     return GetConfigItem().GetOptions( rOptions );
939 }
940 
941 
942 sal_Bool SvtLinguConfig::SetOptions( const SvtLinguOptions &rOptions )
943 {
944     return GetConfigItem().SetOptions( rOptions );
945 }
946 
947 
948 sal_Bool SvtLinguConfig::IsReadOnly( const rtl::OUString &rPropertyName ) const
949 {
950     return GetConfigItem().IsReadOnly( rPropertyName );
951 }
952 
953 sal_Bool SvtLinguConfig::IsReadOnly( sal_Int32 nPropertyHandle ) const
954 {
955     return GetConfigItem().IsReadOnly( nPropertyHandle );
956 }
957 
958 sal_Bool SvtLinguConfig::GetElementNamesFor(
959      const rtl::OUString &rNodeName,
960      uno::Sequence< rtl::OUString > &rElementNames ) const
961 {
962     bool bSuccess = false;
963     try
964     {
965         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
966         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
967         xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW );
968         rElementNames = xNA->getElementNames();
969         bSuccess = true;
970     }
971     catch (uno::Exception &)
972     {
973     }
974     return bSuccess;
975 }
976 
977 static uno::Reference< container::XNameAccess > GetOrCreateSetEntry_Impl(
978     const uno::Reference< container::XNameAccess > &rxSetNameAccess,
979     const rtl::OUString &rEntryName )
980 {
981     uno::Reference< container::XNameAccess > xResult;
982     try
983     {
984         if (!rxSetNameAccess->hasByName( rEntryName ))
985         {
986             uno::Reference< lang::XSingleServiceFactory > xFactory( rxSetNameAccess, uno::UNO_QUERY_THROW);
987             uno::Reference< uno::XInterface > xNewEntry( xFactory->createInstance() );
988             uno::Reference< container::XNameContainer > xNC( rxSetNameAccess, uno::UNO_QUERY_THROW );
989             xNC->insertByName( rEntryName, makeAny( xNewEntry ) );
990         }
991         xResult.set( rxSetNameAccess->getByName( rEntryName ), uno::UNO_QUERY_THROW );
992     }
993     catch (uno::Exception &)
994     {
995     }
996     return xResult;
997 }
998 
999 sal_Bool SvtLinguConfig::GetSupportedDictionaryFormatsFor(
1000     const rtl::OUString &rSetName,
1001     const rtl::OUString &rSetEntry,
1002     uno::Sequence< rtl::OUString > &rFormatList ) const
1003 {
1004     if (rSetName.getLength() == 0 || rSetEntry.getLength() == 0)
1005         return sal_False;
1006     bool bSuccess = false;
1007     try
1008     {
1009         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1010         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
1011         xNA.set( xNA->getByName( rSetName ), uno::UNO_QUERY_THROW );
1012         xNA.set( xNA->getByName( rSetEntry ), uno::UNO_QUERY_THROW );
1013         if (xNA->getByName( aG_SupportedDictionaryFormats ) >>= rFormatList)
1014             bSuccess = true;
1015         DBG_ASSERT( rFormatList.getLength(), "supported dictionary format list is empty" );
1016     }
1017     catch (uno::Exception &)
1018     {
1019     }
1020     return bSuccess;
1021 }
1022 
1023 void SvtLinguConfig::SetOrCreateSupportedDictionaryFormatsFor(
1024     const rtl::OUString &rSetName,
1025     const rtl::OUString &rSetEntry,
1026     const uno::Sequence< rtl::OUString > &rFormatList  ) const
1027 {
1028     if (rSetName.getLength() == 0 || rSetEntry.getLength() == 0)
1029         return;
1030     try
1031     {
1032         DBG_ASSERT( rFormatList.getLength(), "applying empty format list. Really??" );
1033 
1034         uno::Reference< util::XChangesBatch > xUpdateAccess( GetMainUpdateAccess() );
1035         uno::Reference< container::XNameAccess > xNA( xUpdateAccess, uno::UNO_QUERY_THROW );
1036         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
1037         xNA.set( xNA->getByName( rSetName ), uno::UNO_QUERY_THROW );
1038         xNA = GetOrCreateSetEntry_Impl( xNA, rSetEntry );
1039 
1040         uno::Reference< container::XNameReplace > xNR( xNA, uno::UNO_QUERY_THROW );
1041         xNR->replaceByName( aG_SupportedDictionaryFormats, uno::makeAny( rFormatList ) );
1042 
1043         xUpdateAccess->commitChanges();
1044     }
1045     catch (uno::Exception &)
1046     {
1047     }
1048 }
1049 
1050 
1051 static uno::WeakReference< util::XMacroExpander > aG_xMacroExpander;
1052 
1053 static uno::Reference< util::XMacroExpander > lcl_GetMacroExpander()
1054 {
1055     uno::Reference< util::XMacroExpander > xMacroExpander( aG_xMacroExpander );
1056     if ( !xMacroExpander.is() )
1057     {
1058         if ( !xMacroExpander.is() )
1059         {
1060             uno::Reference< uno::XComponentContext > xContext;
1061             uno::Reference< beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
1062             xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
1063             if ( xContext.is() )
1064             {
1065                 aG_xMacroExpander =  uno::Reference< com::sun::star::util::XMacroExpander >( xContext->getValueByName(
1066                                         OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))),
1067                                         uno::UNO_QUERY );
1068                 xMacroExpander = aG_xMacroExpander;
1069             }
1070         }
1071     }
1072 
1073     return xMacroExpander;
1074 }
1075 
1076 
1077 static bool lcl_GetFileUrlFromOrigin(
1078     OUString /*out*/ &rFileUrl,
1079     const OUString &rOrigin,
1080     uno::Reference< util::XMacroExpander > &rxMacroExpander )
1081 {
1082     bool bSuccess = false;
1083     if (rOrigin.getLength() > 0 && rxMacroExpander.is())
1084     {
1085         rtl::OUString aURL( rOrigin );
1086         if (( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 ) &&
1087             rxMacroExpander.is() )
1088         {
1089             // cut protocol
1090             OUString aMacro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) );
1091             // decode uric class chars
1092             aMacro = Uri::decode( aMacro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
1093             // expand macro string
1094             aURL = rxMacroExpander->expandMacros( aMacro );
1095 
1096             bool bIsFileUrl = aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( FILE_PROTOCOL )) == 0;
1097             if (bIsFileUrl)
1098             {
1099                 rFileUrl = aURL;
1100                 bSuccess = true;
1101             }
1102             else
1103             {
1104                 DBG_ASSERT( bIsFileUrl, "not a file URL");
1105             }
1106         }
1107         else
1108         {
1109             DBG_ASSERT( 0, "failed to get file URL" );
1110         }
1111     }
1112     return bSuccess;
1113 }
1114 
1115 
1116 sal_Bool SvtLinguConfig::GetDictionaryEntry(
1117     const rtl::OUString &rNodeName,
1118     SvtLinguConfigDictionaryEntry &rDicEntry ) const
1119 {
1120     if (rNodeName.getLength() == 0)
1121         return sal_False;
1122     bool bSuccess = false;
1123     try
1124     {
1125         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1126         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
1127         xNA.set( xNA->getByName( aG_Dictionaries ), uno::UNO_QUERY_THROW );
1128         xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW );
1129 
1130         // read group data...
1131         uno::Sequence< rtl::OUString >	aLocations;
1132         rtl::OUString					aFormatName;
1133 		uno::Sequence< rtl::OUString >  aLocaleNames;
1134         bSuccess =  (xNA->getByName( aG_Locations ) >>= aLocations)  &&
1135                     (xNA->getByName( aG_Format )    >>= aFormatName) &&
1136                     (xNA->getByName( aG_Locales )   >>= aLocaleNames);
1137         DBG_ASSERT( aLocations.getLength(), "Dictionary locations not set" );
1138         DBG_ASSERT( aFormatName.getLength(), "Dictionary format name not set" );
1139         DBG_ASSERT( aLocaleNames.getLength(), "No locales set for the dictionary" );
1140 
1141         // if sucessful continue
1142         if (bSuccess)
1143         {
1144             // get file URL's for the locations
1145             uno::Reference< util::XMacroExpander > xMacroExpander( lcl_GetMacroExpander() );
1146             for (sal_Int32 i = 0;  i < aLocations.getLength();  ++i)
1147             {
1148                 rtl::OUString &rLocation = aLocations[i];
1149                 if (!lcl_GetFileUrlFromOrigin( rLocation, rLocation, xMacroExpander ))
1150                     bSuccess = false;
1151             }
1152 
1153             // if everything was fine return the result
1154             if (bSuccess)
1155             {
1156                 rDicEntry.aLocations    = aLocations;
1157                 rDicEntry.aFormatName   = aFormatName;
1158                 rDicEntry.aLocaleNames  = aLocaleNames;
1159             }
1160         }
1161     }
1162     catch (uno::Exception &)
1163     {
1164     }
1165     return bSuccess;
1166 }
1167 
1168 void SvtLinguConfig::SetOrCreateDictionaryEntry(
1169     const rtl::OUString &rNodeName,
1170     const SvtLinguConfigDictionaryEntry &rDicEntry ) const
1171 {
1172     if (rNodeName.getLength() == 0)
1173         return;
1174     try
1175     {
1176         uno::Reference< util::XChangesBatch > xUpdateAccess( GetMainUpdateAccess() );
1177         uno::Reference< container::XNameAccess > xNA( xUpdateAccess, uno::UNO_QUERY_THROW );
1178         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
1179         xNA.set( xNA->getByName( aG_Dictionaries ), uno::UNO_QUERY_THROW );
1180         xNA = GetOrCreateSetEntry_Impl( xNA, rNodeName );
1181 
1182         DBG_ASSERT( rDicEntry.aLocations.getLength(), "Applying empty dictionary locations. Really correct??" );
1183         DBG_ASSERT( rDicEntry.aFormatName.getLength(), "Applying empty dictionary format name. Really correct??" );
1184         DBG_ASSERT( rDicEntry.aLocaleNames.getLength(), "Applying empty list of locales for the dictionary. Really correct??" );
1185 
1186         uno::Reference< container::XNameReplace > xNR( xNA, uno::UNO_QUERY_THROW );
1187         xNR->replaceByName( aG_Locations, uno::makeAny( rDicEntry.aLocations ) );
1188         xNR->replaceByName( aG_Format,    uno::makeAny( rDicEntry.aFormatName ) );
1189         xNR->replaceByName( aG_Locales,   uno::makeAny( rDicEntry.aLocaleNames ) );
1190 
1191         xUpdateAccess->commitChanges();
1192     }
1193     catch (uno::Exception &)
1194     {
1195     }
1196 }
1197 
1198 uno::Sequence< rtl::OUString > SvtLinguConfig::GetDisabledDictionaries() const
1199 {
1200     uno::Sequence< rtl::OUString > aResult;
1201     try
1202     {
1203         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1204         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
1205         xNA->getByName( aG_DisabledDictionaries ) >>= aResult;
1206     }
1207     catch (uno::Exception &)
1208     {
1209     }
1210     return aResult;
1211 }
1212 
1213 void SvtLinguConfig::SetDisabledDictionaries(
1214     const uno::Sequence< rtl::OUString > &rDictionaries ) const
1215 {
1216     try
1217     {
1218         uno::Reference< util::XChangesBatch > xUpdateAccess( GetMainUpdateAccess() );
1219         uno::Reference< container::XNameAccess > xNA( xUpdateAccess, uno::UNO_QUERY_THROW );
1220         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
1221         if (xNA->hasByName( aG_DisabledDictionaries ))
1222         {
1223             uno::Reference< container::XNameReplace > xNR( xNA, uno::UNO_QUERY_THROW );
1224             xNR->replaceByName( aG_DisabledDictionaries, makeAny( rDictionaries ) );
1225         }
1226         else
1227         {
1228             uno::Reference< container::XNameContainer > xNC( xNA, uno::UNO_QUERY_THROW );
1229             xNC->insertByName( aG_DisabledDictionaries, makeAny( rDictionaries ) );
1230         }
1231 
1232         xUpdateAccess->commitChanges();
1233     }
1234     catch (uno::Exception &)
1235     {
1236     }
1237 }
1238 
1239 std::vector< SvtLinguConfigDictionaryEntry > SvtLinguConfig::GetActiveDictionariesByFormat(
1240     const rtl::OUString &rFormatName )
1241 {
1242     std::vector< SvtLinguConfigDictionaryEntry > aRes;
1243     if (rFormatName.getLength() == 0)
1244         return aRes;
1245 
1246     try
1247     {
1248         uno::Sequence< rtl::OUString > aElementNames;
1249         GetElementNamesFor( aG_Dictionaries, aElementNames );
1250         sal_Int32 nLen = aElementNames.getLength();
1251         const rtl::OUString *pElementNames = aElementNames.getConstArray();
1252 
1253         SvtLinguConfigDictionaryEntry aDicEntry;
1254         for (sal_Int32 i = 0;  i < nLen;  ++i)
1255         {
1256             // does dictionary match the format we are looking for?
1257             if (GetDictionaryEntry( pElementNames[i], aDicEntry ) &&
1258                 aDicEntry.aFormatName == rFormatName)
1259             {
1260                 // check if it is active or not
1261                 bool bDicIsActive = true;
1262                 const uno::Sequence< rtl::OUString > aDisabledDics( GetDisabledDictionaries() );
1263                 for (sal_Int32 k = 0;  bDicIsActive && k < aDisabledDics.getLength();  ++k)
1264                 {
1265                     if (aDisabledDics[k] == pElementNames[i])
1266                         bDicIsActive = false;
1267                 }
1268 
1269                 if (bDicIsActive)
1270                 {
1271                     DBG_ASSERT( aDicEntry.aFormatName.getLength(),
1272                             "FormatName not set" );
1273                     DBG_ASSERT( aDicEntry.aLocations.getLength(),
1274                             "Locations not set" );
1275                     DBG_ASSERT( aDicEntry.aLocaleNames.getLength(),
1276                             "Locales not set" );
1277                     aRes.push_back( aDicEntry );
1278                 }
1279             }
1280         }
1281     }
1282     catch (uno::Exception &)
1283     {
1284     }
1285 
1286     return aRes;
1287 }
1288 
1289 
1290 uno::Reference< util::XChangesBatch > SvtLinguConfig::GetMainUpdateAccess() const
1291 {
1292     if (!m_xMainUpdateAccess.is())
1293     {
1294         try
1295         {
1296             // get configuration provider
1297             uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider;
1298             uno::Reference< lang::XMultiServiceFactory > xMgr = comphelper::getProcessServiceFactory();
1299             if (xMgr.is())
1300             {
1301                 xConfigurationProvider = uno::Reference< lang::XMultiServiceFactory > (
1302                         xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM(
1303                             "com.sun.star.configuration.ConfigurationProvider" ) ) ),
1304                         uno::UNO_QUERY_THROW ) ;
1305             }
1306 
1307             // get configuration update access
1308             beans::PropertyValue aValue;
1309             aValue.Name  = A2OU( "nodepath" );
1310             aValue.Value = uno::makeAny( A2OU("org.openoffice.Office.Linguistic") );
1311             uno::Sequence< uno::Any > aProps(1);
1312             aProps[0] <<= aValue;
1313             m_xMainUpdateAccess = uno::Reference< util::XChangesBatch >(
1314                     xConfigurationProvider->createInstanceWithArguments(
1315                         A2OU( "com.sun.star.configuration.ConfigurationUpdateAccess" ), aProps ),
1316                         uno::UNO_QUERY_THROW );
1317         }
1318         catch (uno::Exception &)
1319         {
1320         }
1321     }
1322 
1323     return m_xMainUpdateAccess;
1324 }
1325 
1326 
1327 rtl::OUString SvtLinguConfig::GetVendorImageUrl_Impl(
1328     const rtl::OUString &rServiceImplName,
1329     const rtl::OUString &rImageName ) const
1330 {
1331     rtl::OUString aRes;
1332     try
1333     {
1334         uno::Reference< container::XNameAccess > xImagesNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1335         xImagesNA.set( xImagesNA->getByName( A2OU("Images") ), uno::UNO_QUERY_THROW );
1336 
1337         uno::Reference< container::XNameAccess > xNA( xImagesNA->getByName( A2OU("ServiceNameEntries") ), uno::UNO_QUERY_THROW );
1338         xNA.set( xNA->getByName( rServiceImplName ), uno::UNO_QUERY_THROW );
1339         uno::Any aAny( xNA->getByName( A2OU("VendorImagesNode") ) );
1340         rtl::OUString aVendorImagesNode;
1341         if (aAny >>= aVendorImagesNode)
1342         {
1343             xNA = xImagesNA;
1344             xNA.set( xNA->getByName( A2OU("VendorImages") ), uno::UNO_QUERY_THROW );
1345             xNA.set( xNA->getByName( aVendorImagesNode ), uno::UNO_QUERY_THROW );
1346             aAny = xNA->getByName( rImageName );
1347             rtl::OUString aTmp;
1348             if (aAny >>= aTmp)
1349             {
1350                 uno::Reference< util::XMacroExpander > xMacroExpander( lcl_GetMacroExpander() );
1351                 if (lcl_GetFileUrlFromOrigin( aTmp, aTmp, xMacroExpander ))
1352                     aRes = aTmp;
1353             }
1354         }
1355     }
1356     catch (uno::Exception &)
1357     {
1358         DBG_ASSERT( 0, "exception caught. GetVendorImageUrl_Impl failed" );
1359     }
1360     return aRes;
1361 }
1362 
1363 
1364 rtl::OUString SvtLinguConfig::GetSpellAndGrammarDialogImage(
1365     const rtl::OUString &rServiceImplName,
1366     bool bHighContrast ) const
1367 {
1368     rtl::OUString   aRes;
1369     if (rServiceImplName.getLength() > 0)
1370     {
1371         rtl::OUString aImageName( A2OU( bHighContrast ? "SpellAndGrammarDialogImage_HC" : "SpellAndGrammarDialogImage" ));
1372         rtl::OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
1373         aRes = aPath;
1374     }
1375     return aRes;
1376 }
1377 
1378 
1379 rtl::OUString SvtLinguConfig::GetSpellAndGrammarContextSuggestionImage(
1380     const rtl::OUString &rServiceImplName,
1381     bool bHighContrast ) const
1382 {
1383     rtl::OUString   aRes;
1384     if (rServiceImplName.getLength() > 0)
1385     {
1386         rtl::OUString aImageName( A2OU( bHighContrast ? "SpellAndGrammarContextMenuSuggestionImage_HC" : "SpellAndGrammarContextMenuSuggestionImage" ));
1387         rtl::OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
1388         aRes = aPath;
1389     }
1390     return aRes;
1391 }
1392 
1393 
1394 rtl::OUString SvtLinguConfig::GetSpellAndGrammarContextDictionaryImage(
1395     const rtl::OUString &rServiceImplName,
1396     bool bHighContrast ) const
1397 {
1398     rtl::OUString   aRes;
1399     if (rServiceImplName.getLength() > 0)
1400     {
1401         rtl::OUString aImageName( A2OU( bHighContrast ? "SpellAndGrammarContextMenuDictionaryImage_HC" : "SpellAndGrammarContextMenuDictionaryImage" ));
1402         rtl::OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
1403         aRes = aPath;
1404     }
1405     return aRes;
1406 }
1407 
1408 
1409 ::rtl::OUString SvtLinguConfig::GetThesaurusDialogImage(
1410     const ::rtl::OUString &rServiceImplName,
1411     bool bHighContrast ) const
1412 {
1413     rtl::OUString   aRes;
1414     if (rServiceImplName.getLength() > 0)
1415     {
1416         rtl::OUString aImageName( A2OU( bHighContrast ? "ThesaurusDialogImage_HC" : "ThesaurusDialogImage" ));
1417         rtl::OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
1418         aRes = aPath;
1419     }
1420     return aRes;
1421 }
1422 
1423 
1424 ::rtl::OUString SvtLinguConfig::GetSynonymsContextImage(
1425     const ::rtl::OUString &rServiceImplName,
1426     bool bHighContrast ) const
1427 {
1428     rtl::OUString   aRes;
1429     if (rServiceImplName.getLength() > 0)
1430     {
1431         rtl::OUString aImageName( A2OU( bHighContrast ? "SynonymsContextMenuImage_HC" : "SynonymsContextMenuImage" ));
1432         rtl::OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
1433         aRes = aPath;
1434     }
1435     return aRes;
1436 }
1437 
1438 
1439 bool SvtLinguConfig::HasVendorImages( const char *pImageName ) const
1440 {
1441     bool bRes = false;
1442     if (pImageName)
1443     {
1444         try
1445         {
1446             uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1447             xNA.set( xNA->getByName( A2OU("Images") ), uno::UNO_QUERY_THROW );
1448             xNA.set( xNA->getByName( A2OU("VendorImages") ), uno::UNO_QUERY_THROW );
1449 
1450             uno::Sequence< rtl::OUString > aElementNames( xNA->getElementNames() );
1451             sal_Int32 nVendors = aElementNames.getLength();
1452             const rtl::OUString *pVendor = aElementNames.getConstArray();
1453             for (sal_Int32 i = 0;  i < nVendors;  ++i)
1454             {
1455                 uno::Reference< container::XNameAccess > xNA2( xNA->getByName( pVendor[i] ), uno::UNO_QUERY_THROW  );
1456                 uno::Sequence< rtl::OUString > aPropNames( xNA2->getElementNames() );
1457                 sal_Int32 nProps = aPropNames.getLength();
1458                 const rtl::OUString *pPropNames = aPropNames.getConstArray();
1459                 for (sal_Int32 k = 0;  k < nProps;  ++k)
1460                 {
1461                     // for a quicker check we ignore the HC image names here
1462                     const OUString &rName = pPropNames[k];
1463                     if (rName.equalsAscii( pImageName ))
1464                     {
1465                         bRes = true;
1466                         break;
1467                     }
1468                 }
1469             }
1470         }
1471         catch (uno::Exception &)
1472         {
1473             DBG_ASSERT( 0, "exception caught. HasVendorImages failed" );
1474         }
1475     }
1476     return bRes;
1477 }
1478 
1479 
1480 bool SvtLinguConfig::HasGrammarChecker() const
1481 {
1482 	bool bRes = false;
1483 
1484 	try
1485 	{
1486         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1487         xNA.set( xNA->getByName( A2OU("ServiceManager") ), uno::UNO_QUERY_THROW );
1488 		xNA.set( xNA->getByName( A2OU("GrammarCheckerList") ), uno::UNO_QUERY_THROW );
1489 
1490 		uno::Sequence< rtl::OUString > aElementNames( xNA->getElementNames() );
1491 		bRes = aElementNames.getLength() > 0;
1492 	}
1493 	catch (uno::Exception &)
1494 	{
1495 	}
1496 
1497     return bRes;
1498 }
1499 
1500 //////////////////////////////////////////////////////////////////////
1501 
1502