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