LCOV - code coverage report
Current view: top level - unotools/source/config - lingucfg.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 352 548 64.2 %
Date: 2014-11-03 Functions: 33 45 73.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sal/config.h>
      21             : 
      22             : #include <boost/noncopyable.hpp>
      23             : #include <com/sun/star/lang/Locale.hpp>
      24             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      25             : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
      26             : #include <com/sun/star/configuration/theDefaultProvider.hpp>
      27             : #include <com/sun/star/container/XNameAccess.hpp>
      28             : #include <com/sun/star/container/XNameContainer.hpp>
      29             : #include <com/sun/star/container/XNameReplace.hpp>
      30             : #include <com/sun/star/util/theMacroExpander.hpp>
      31             : #include <rtl/uri.hxx>
      32             : #include <rtl/instance.hxx>
      33             : #include <osl/mutex.hxx>
      34             : #include <i18nlangtag/mslangid.hxx>
      35             : #include <i18nlangtag/languagetag.hxx>
      36             : #include <tools/debug.hxx>
      37             : #include <unotools/lingucfg.hxx>
      38             : #include <unotools/linguprops.hxx>
      39             : #include <sal/macros.h>
      40             : 
      41             : #include <comphelper/processfactory.hxx>
      42             : 
      43             : #include "itemholder1.hxx"
      44             : 
      45             : using namespace com::sun::star;
      46             : 
      47             : using ::rtl::Uri;
      48             : 
      49             : #define EXPAND_PROTOCOL     "vnd.sun.star.expand:"
      50             : #define FILE_PROTOCOL       "file:///"
      51             : 
      52             : namespace
      53             : {
      54             :     class theSvtLinguConfigItemMutex :
      55             :         public rtl::Static< osl::Mutex, theSvtLinguConfigItemMutex > {};
      56             : }
      57             : 
      58          12 : static bool lcl_SetLocale( sal_Int16 &rLanguage, const uno::Any &rVal )
      59             : {
      60          12 :     bool bSucc = false;
      61             : 
      62          12 :     lang::Locale aNew;
      63          12 :     if (rVal >>= aNew)  // conversion successful?
      64             :     {
      65          12 :         sal_Int16 nNew = LanguageTag::convertToLanguageType( aNew, false);
      66          12 :         if (nNew != rLanguage)
      67             :         {
      68          12 :             rLanguage = nNew;
      69          12 :             bSucc = true;
      70             :         }
      71             :     }
      72          12 :     return bSucc;
      73             : }
      74             : 
      75           6 : static inline const OUString lcl_LanguageToCfgLocaleStr( sal_Int16 nLanguage )
      76             : {
      77           6 :     OUString aRes;
      78           6 :     if (LANGUAGE_SYSTEM != nLanguage)
      79           6 :         aRes = LanguageTag::convertToBcp47( nLanguage );
      80           6 :     return aRes;
      81             : }
      82             : 
      83         522 : static sal_Int16 lcl_CfgAnyToLanguage( const uno::Any &rVal )
      84             : {
      85         522 :     OUString aTmp;
      86         522 :     rVal >>= aTmp;
      87         522 :     return (aTmp.isEmpty()) ? LANGUAGE_SYSTEM : LanguageTag::convertToLanguageTypeWithFallback( aTmp );
      88             : }
      89             : 
      90       82490 : SvtLinguOptions::SvtLinguOptions()
      91             :     : bROActiveDics(false)
      92             :     , bROActiveConvDics(false)
      93             :     , nHyphMinLeading(2)
      94             :     , nHyphMinTrailing(2)
      95             :     , nHyphMinWordLength(0)
      96             :     , bROHyphMinLeading(false)
      97             :     , bROHyphMinTrailing(false)
      98             :     , bROHyphMinWordLength(false)
      99             :     , nDefaultLanguage(LANGUAGE_NONE)
     100             :     , nDefaultLanguage_CJK(LANGUAGE_NONE)
     101             :     , nDefaultLanguage_CTL(LANGUAGE_NONE)
     102             :     , bRODefaultLanguage(false)
     103             :     , bRODefaultLanguage_CJK(false)
     104             :     , bRODefaultLanguage_CTL(false)
     105             :     , bIsSpellSpecial(true)
     106             :     , bIsSpellAuto(false)
     107             :     , bIsSpellReverse(false)
     108             :     , bROIsSpellSpecial(false)
     109             :     , bROIsSpellAuto(false)
     110             :     , bROIsSpellReverse(false)
     111             :     , bIsHyphSpecial(true)
     112             :     , bIsHyphAuto(false)
     113             :     , bROIsHyphSpecial(false)
     114             :     , bROIsHyphAuto(false)
     115             :     , bIsUseDictionaryList(true)
     116             :     , bIsIgnoreControlCharacters(true)
     117             :     , bROIsUseDictionaryList(false)
     118             :     , bROIsIgnoreControlCharacters(false)
     119             :     , bIsSpellWithDigits(false)
     120             :     , bIsSpellUpperCase(false)
     121             :     , bIsSpellCapitalization(true)
     122             :     , bROIsSpellWithDigits(false)
     123             :     , bROIsSpellUpperCase(false)
     124             :     , bROIsSpellCapitalization(false)
     125             :     , bIsIgnorePostPositionalWord(true)
     126             :     , bIsAutoCloseDialog(false)
     127             :     , bIsShowEntriesRecentlyUsedFirst(false)
     128             :     , bIsAutoReplaceUniqueEntries(false)
     129             :     , bIsDirectionToSimplified(true)
     130             :     , bIsUseCharacterVariants(false)
     131             :     , bIsTranslateCommonTerms(false)
     132             :     , bIsReverseMapping(false)
     133             :     , bROIsIgnorePostPositionalWord(false)
     134             :     , bROIsAutoCloseDialog(false)
     135             :     , bROIsShowEntriesRecentlyUsedFirst(false)
     136             :     , bROIsAutoReplaceUniqueEntries(false)
     137             :     , bROIsDirectionToSimplified(false)
     138             :     , bROIsUseCharacterVariants(false)
     139             :     , bROIsTranslateCommonTerms(false)
     140             :     , bROIsReverseMapping(false)
     141             :     , nDataFilesChangedCheckValue(0)
     142             :     , bRODataFilesChangedCheckValue(false)
     143             :     , bIsGrammarAuto(false)
     144             :     , bIsGrammarInteractive(false)
     145             :     , bROIsGrammarAuto(false)
     146       82490 :     , bROIsGrammarInteractive(false)
     147             : {
     148       82490 : }
     149             : 
     150             : class SvtLinguConfigItem: public utl::ConfigItem, private boost::noncopyable
     151             : {
     152             :     SvtLinguOptions     aOpt;
     153             : 
     154             :     static bool GetHdlByName( sal_Int32 &rnHdl, const OUString &rPropertyName, bool bFullPropName = false );
     155             :     static const uno::Sequence< OUString > GetPropertyNames();
     156             :     bool                LoadOptions( const uno::Sequence< OUString > &rProperyNames );
     157             :     bool                SaveOptions( const uno::Sequence< OUString > &rProperyNames );
     158             : 
     159             : public:
     160             :     SvtLinguConfigItem();
     161             :     virtual ~SvtLinguConfigItem();
     162             : 
     163             :     // utl::ConfigItem
     164             :     virtual void    Notify( const com::sun::star::uno::Sequence< OUString > &rPropertyNames ) SAL_OVERRIDE;
     165             :     virtual void    Commit() SAL_OVERRIDE;
     166             : 
     167             :     // make some protected functions of utl::ConfigItem public
     168             :     using utl::ConfigItem::GetNodeNames;
     169             :     using utl::ConfigItem::GetProperties;
     170             :     //using utl::ConfigItem::PutProperties;
     171             :     //using utl::ConfigItem::SetSetProperties;
     172             :     using utl::ConfigItem::ReplaceSetProperties;
     173             :     //using utl::ConfigItem::GetReadOnlyStates;
     174             : 
     175             :     com::sun::star::uno::Any
     176             :             GetProperty( const OUString &rPropertyName ) const;
     177             :     com::sun::star::uno::Any
     178             :             GetProperty( sal_Int32 nPropertyHandle ) const;
     179             : 
     180             :     bool    SetProperty( const OUString &rPropertyName,
     181             :                          const com::sun::star::uno::Any &rValue );
     182             :     bool    SetProperty( sal_Int32 nPropertyHandle,
     183             :                          const com::sun::star::uno::Any &rValue );
     184             : 
     185             :     const SvtLinguOptions& GetOptions() const;
     186             : 
     187             :     bool    IsReadOnly( const OUString &rPropertyName ) const;
     188             :     bool    IsReadOnly( sal_Int32 nPropertyHandle ) const;
     189             : };
     190             : 
     191         174 : SvtLinguConfigItem::SvtLinguConfigItem() :
     192         174 :     utl::ConfigItem( OUString("Office.Linguistic") )
     193             : {
     194         174 :     const uno::Sequence< OUString > &rPropertyNames = GetPropertyNames();
     195         174 :     LoadOptions( rPropertyNames );
     196         174 :     ClearModified();
     197             : 
     198             :     // request notify events when properties change
     199         174 :     EnableNotification( rPropertyNames );
     200         174 : }
     201             : 
     202         338 : SvtLinguConfigItem::~SvtLinguConfigItem()
     203             : {
     204             :     //! Commit (SaveOptions) will be called by the d-tor of the base called !
     205         338 : }
     206             : 
     207           0 : void SvtLinguConfigItem::Notify( const uno::Sequence< OUString > &rPropertyNames )
     208             : {
     209           0 :     LoadOptions( rPropertyNames );
     210           0 :     NotifyListeners(0);
     211           0 : }
     212             : 
     213           2 : void SvtLinguConfigItem::Commit()
     214             : {
     215           2 :     SaveOptions( GetPropertyNames() );
     216           2 : }
     217             : 
     218             : static struct NamesToHdl
     219             : {
     220             :     const char   *pFullPropName;      // full qualified name as used in configuration
     221             :     const char   *pPropName;          // property name only (atom) of above
     222             :     sal_Int32   nHdl;               // numeric handle representing the property
     223             : }aNamesToHdl[] =
     224             : {
     225             : {/*  0 */    "General/DefaultLocale",                         UPN_DEFAULT_LOCALE,                    UPH_DEFAULT_LOCALE},
     226             : {/*  1 */    "General/DictionaryList/ActiveDictionaries",     UPN_ACTIVE_DICTIONARIES,               UPH_ACTIVE_DICTIONARIES},
     227             : {/*  2 */    "General/DictionaryList/IsUseDictionaryList",    UPN_IS_USE_DICTIONARY_LIST,            UPH_IS_USE_DICTIONARY_LIST},
     228             : {/*  3 */    "General/IsIgnoreControlCharacters",             UPN_IS_IGNORE_CONTROL_CHARACTERS,      UPH_IS_IGNORE_CONTROL_CHARACTERS},
     229             : {/*  5 */    "General/DefaultLocale_CJK",                     UPN_DEFAULT_LOCALE_CJK,                UPH_DEFAULT_LOCALE_CJK},
     230             : {/*  6 */    "General/DefaultLocale_CTL",                     UPN_DEFAULT_LOCALE_CTL,                UPH_DEFAULT_LOCALE_CTL},
     231             : 
     232             : {/*  7 */    "SpellChecking/IsSpellUpperCase",                UPN_IS_SPELL_UPPER_CASE,               UPH_IS_SPELL_UPPER_CASE},
     233             : {/*  8 */    "SpellChecking/IsSpellWithDigits",               UPN_IS_SPELL_WITH_DIGITS,              UPH_IS_SPELL_WITH_DIGITS},
     234             : {/*  9 */    "SpellChecking/IsSpellCapitalization",           UPN_IS_SPELL_CAPITALIZATION,           UPH_IS_SPELL_CAPITALIZATION},
     235             : {/* 10 */    "SpellChecking/IsSpellAuto",                     UPN_IS_SPELL_AUTO,                     UPH_IS_SPELL_AUTO},
     236             : {/* 11 */    "SpellChecking/IsSpellSpecial",                  UPN_IS_SPELL_SPECIAL,                  UPH_IS_SPELL_SPECIAL},
     237             : {/* 14 */    "SpellChecking/IsReverseDirection",              UPN_IS_WRAP_REVERSE,                   UPH_IS_WRAP_REVERSE},
     238             : 
     239             : {/* 15 */    "Hyphenation/MinLeading",                        UPN_HYPH_MIN_LEADING,                  UPH_HYPH_MIN_LEADING},
     240             : {/* 16 */    "Hyphenation/MinTrailing",                       UPN_HYPH_MIN_TRAILING,                 UPH_HYPH_MIN_TRAILING},
     241             : {/* 17 */    "Hyphenation/MinWordLength",                     UPN_HYPH_MIN_WORD_LENGTH,              UPH_HYPH_MIN_WORD_LENGTH},
     242             : {/* 18 */    "Hyphenation/IsHyphSpecial",                     UPN_IS_HYPH_SPECIAL,                   UPH_IS_HYPH_SPECIAL},
     243             : {/* 19 */    "Hyphenation/IsHyphAuto",                        UPN_IS_HYPH_AUTO,                      UPH_IS_HYPH_AUTO},
     244             : 
     245             : {/* 20 */    "TextConversion/ActiveConversionDictionaries",   UPN_ACTIVE_CONVERSION_DICTIONARIES,        UPH_ACTIVE_CONVERSION_DICTIONARIES},
     246             : {/* 21 */    "TextConversion/IsIgnorePostPositionalWord",     UPN_IS_IGNORE_POST_POSITIONAL_WORD,        UPH_IS_IGNORE_POST_POSITIONAL_WORD},
     247             : {/* 22 */    "TextConversion/IsAutoCloseDialog",              UPN_IS_AUTO_CLOSE_DIALOG,                  UPH_IS_AUTO_CLOSE_DIALOG},
     248             : {/* 23 */    "TextConversion/IsShowEntriesRecentlyUsedFirst", UPN_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST,   UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST},
     249             : {/* 24 */    "TextConversion/IsAutoReplaceUniqueEntries",     UPN_IS_AUTO_REPLACE_UNIQUE_ENTRIES,        UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES},
     250             : {/* 25 */    "TextConversion/IsDirectionToSimplified",        UPN_IS_DIRECTION_TO_SIMPLIFIED,            UPH_IS_DIRECTION_TO_SIMPLIFIED},
     251             : {/* 26 */    "TextConversion/IsUseCharacterVariants",         UPN_IS_USE_CHARACTER_VARIANTS,             UPH_IS_USE_CHARACTER_VARIANTS},
     252             : {/* 27 */    "TextConversion/IsTranslateCommonTerms",         UPN_IS_TRANSLATE_COMMON_TERMS,             UPH_IS_TRANSLATE_COMMON_TERMS},
     253             : {/* 28 */    "TextConversion/IsReverseMapping",               UPN_IS_REVERSE_MAPPING,                    UPH_IS_REVERSE_MAPPING},
     254             : 
     255             : {/* 29 */    "ServiceManager/DataFilesChangedCheckValue",     UPN_DATA_FILES_CHANGED_CHECK_VALUE,        UPH_DATA_FILES_CHANGED_CHECK_VALUE},
     256             : 
     257             : {/* 30 */    "GrammarChecking/IsAutoCheck",                   UPN_IS_GRAMMAR_AUTO,                      UPH_IS_GRAMMAR_AUTO},
     258             : {/* 31 */    "GrammarChecking/IsInteractiveCheck",            UPN_IS_GRAMMAR_INTERACTIVE,               UPH_IS_GRAMMAR_INTERACTIVE},
     259             : 
     260             :             /* similar to entry 0 (thus no own configuration entry) but with different property name and type */
     261             : {            NULL,                                           UPN_DEFAULT_LANGUAGE,                      UPH_DEFAULT_LANGUAGE},
     262             : 
     263             : {            NULL,                                            NULL,                                      -1}
     264             : };
     265             : 
     266         176 : const uno::Sequence< OUString > SvtLinguConfigItem::GetPropertyNames()
     267             : {
     268         176 :     uno::Sequence< OUString > aNames;
     269             : 
     270         176 :     sal_Int32 nMax = SAL_N_ELEMENTS(aNamesToHdl);
     271             : 
     272         176 :     aNames.realloc( nMax );
     273         176 :     OUString *pNames = aNames.getArray();
     274         176 :     sal_Int32 nIdx = 0;
     275        5632 :     for (sal_Int32 i = 0; i < nMax;  ++i)
     276             :     {
     277        5456 :         const sal_Char *pFullPropName = aNamesToHdl[i].pFullPropName;
     278        5456 :         if (pFullPropName)
     279        5104 :             pNames[ nIdx++ ] = OUString::createFromAscii( pFullPropName );
     280             :     }
     281         176 :     aNames.realloc( nIdx );
     282             : 
     283         176 :     return aNames;
     284             : }
     285             : 
     286       49986 : bool SvtLinguConfigItem::GetHdlByName(
     287             :     sal_Int32 &rnHdl,
     288             :     const OUString &rPropertyName,
     289             :     bool bFullPropName )
     290             : {
     291       49986 :     NamesToHdl *pEntry = &aNamesToHdl[0];
     292             : 
     293       49986 :     if (bFullPropName)
     294             :     {
     295       80736 :         while (pEntry && pEntry->pFullPropName != NULL)
     296             :         {
     297       75690 :             if (rPropertyName.equalsAscii( pEntry->pFullPropName ))
     298             :             {
     299        5046 :                 rnHdl = pEntry->nHdl;
     300        5046 :                 break;
     301             :             }
     302       70644 :             ++pEntry;
     303             :         }
     304        5046 :         return pEntry && pEntry->pFullPropName != NULL;
     305             :     }
     306             :     else
     307             :     {
     308     1295340 :         while (pEntry && pEntry->pPropName != NULL)
     309             :         {
     310     1250400 :             if (rPropertyName.equalsAscii( pEntry->pPropName ))
     311             :             {
     312       44940 :                 rnHdl = pEntry->nHdl;
     313       44940 :                 break;
     314             :             }
     315     1205460 :             ++pEntry;
     316             :         }
     317       44940 :         return pEntry && pEntry->pPropName != NULL;
     318             :     }
     319             : }
     320             : 
     321       44940 : uno::Any SvtLinguConfigItem::GetProperty( const OUString &rPropertyName ) const
     322             : {
     323       44940 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     324             : 
     325             :     sal_Int32 nHdl;
     326       44940 :     return GetHdlByName( nHdl, rPropertyName ) ? GetProperty( nHdl ) : uno::Any();
     327             : }
     328             : 
     329      109966 : uno::Any SvtLinguConfigItem::GetProperty( sal_Int32 nPropertyHandle ) const
     330             : {
     331      109966 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     332             : 
     333      109966 :     uno::Any aRes;
     334             : 
     335      109966 :     const sal_Int16 *pnVal = 0;
     336      109966 :     const bool  *pbVal = 0;
     337      109966 :     const sal_Int32 *pnInt32Val = 0;
     338             : 
     339      109966 :     const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
     340      109966 :     switch (nPropertyHandle)
     341             :     {
     342       32035 :         case UPH_IS_USE_DICTIONARY_LIST :   pbVal = &rOpt.bIsUseDictionaryList; break;
     343       32036 :         case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters;   break;
     344          26 :         case UPH_IS_HYPH_AUTO :             pbVal = &rOpt.bIsHyphAuto;  break;
     345          26 :         case UPH_IS_HYPH_SPECIAL :          pbVal = &rOpt.bIsHyphSpecial;   break;
     346          27 :         case UPH_IS_SPELL_AUTO :            pbVal = &rOpt.bIsSpellAuto; break;
     347         156 :         case UPH_IS_SPELL_SPECIAL :         pbVal = &rOpt.bIsSpellSpecial;  break;
     348         286 :         case UPH_IS_WRAP_REVERSE :          pbVal = &rOpt.bIsSpellReverse;  break;
     349          29 :         case UPH_DEFAULT_LANGUAGE :         pnVal = &rOpt.nDefaultLanguage; break;
     350          58 :         case UPH_IS_SPELL_CAPITALIZATION :  pbVal = &rOpt.bIsSpellCapitalization;       break;
     351          58 :         case UPH_IS_SPELL_WITH_DIGITS :     pbVal = &rOpt.bIsSpellWithDigits;   break;
     352          58 :         case UPH_IS_SPELL_UPPER_CASE :      pbVal = &rOpt.bIsSpellUpperCase;        break;
     353          39 :         case UPH_HYPH_MIN_LEADING :         pnVal = &rOpt.nHyphMinLeading;      break;
     354          36 :         case UPH_HYPH_MIN_TRAILING :        pnVal = &rOpt.nHyphMinTrailing; break;
     355          36 :         case UPH_HYPH_MIN_WORD_LENGTH :     pnVal = &rOpt.nHyphMinWordLength;   break;
     356             :         case UPH_ACTIVE_DICTIONARIES :
     357             :         {
     358           0 :             aRes <<= rOpt.aActiveDics;
     359           0 :             break;
     360             :         }
     361             :         case UPH_ACTIVE_CONVERSION_DICTIONARIES :
     362             :         {
     363           0 :             aRes <<= rOpt.aActiveConvDics;
     364           0 :             break;
     365             :         }
     366             :         case UPH_DEFAULT_LOCALE :
     367             :         {
     368         136 :             lang::Locale aLocale( LanguageTag::convertToLocale( rOpt.nDefaultLanguage, false) );
     369         136 :             aRes.setValue( &aLocale, cppu::UnoType<lang::Locale>::get());
     370         136 :             break;
     371             :         }
     372             :         case UPH_DEFAULT_LOCALE_CJK :
     373             :         {
     374         136 :             lang::Locale aLocale( LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CJK, false) );
     375         136 :             aRes.setValue( &aLocale, cppu::UnoType<lang::Locale>::get());
     376         136 :             break;
     377             :         }
     378             :         case UPH_DEFAULT_LOCALE_CTL :
     379             :         {
     380         136 :             lang::Locale aLocale( LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CTL, false) );
     381         136 :             aRes.setValue( &aLocale, cppu::UnoType<lang::Locale>::get());
     382         136 :             break;
     383             :         }
     384           8 :         case UPH_IS_IGNORE_POST_POSITIONAL_WORD :       pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
     385           0 :         case UPH_IS_AUTO_CLOSE_DIALOG :                 pbVal = &rOpt.bIsAutoCloseDialog; break;
     386           8 :         case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :  pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
     387           8 :         case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :       pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
     388             : 
     389           0 :         case UPH_IS_DIRECTION_TO_SIMPLIFIED:            pbVal = &rOpt.bIsDirectionToSimplified; break;
     390           0 :         case UPH_IS_USE_CHARACTER_VARIANTS :            pbVal = &rOpt.bIsUseCharacterVariants; break;
     391           0 :         case UPH_IS_TRANSLATE_COMMON_TERMS :            pbVal = &rOpt.bIsTranslateCommonTerms; break;
     392           0 :         case UPH_IS_REVERSE_MAPPING :                   pbVal = &rOpt.bIsReverseMapping; break;
     393             : 
     394           0 :         case UPH_DATA_FILES_CHANGED_CHECK_VALUE :       pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
     395       44610 :         case UPH_IS_GRAMMAR_AUTO:                       pbVal = &rOpt.bIsGrammarAuto; break;
     396           0 :         case UPH_IS_GRAMMAR_INTERACTIVE:                pbVal = &rOpt.bIsGrammarInteractive; break;
     397             :         default :
     398             :             DBG_ASSERT( false, "unexpected property handle" );
     399             :     }
     400             : 
     401      109966 :     if (pbVal)
     402      109400 :         aRes <<= *pbVal;
     403         566 :     else if (pnVal)
     404         140 :         aRes <<= *pnVal;
     405         426 :     else if (pnInt32Val)
     406           0 :         aRes <<= *pnInt32Val;
     407             : 
     408      109966 :     return aRes;
     409             : }
     410             : 
     411           0 : bool SvtLinguConfigItem::SetProperty( const OUString &rPropertyName, const uno::Any &rValue )
     412             : {
     413           0 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     414             : 
     415           0 :     bool bSucc = false;
     416             :     sal_Int32 nHdl;
     417           0 :     if (GetHdlByName( nHdl, rPropertyName ))
     418           0 :         bSucc = SetProperty( nHdl, rValue );
     419           0 :     return bSucc;
     420             : }
     421             : 
     422         126 : bool SvtLinguConfigItem::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
     423             : {
     424         126 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     425             : 
     426         126 :     bool bSucc = false;
     427         126 :     if (!rValue.hasValue())
     428           0 :         return bSucc;
     429             : 
     430         126 :     bool bMod = false;
     431             : 
     432         126 :     sal_Int16 *pnVal = 0;
     433         126 :     bool  *pbVal = 0;
     434         126 :     sal_Int32 *pnInt32Val = 0;
     435             : 
     436         126 :     SvtLinguOptions &rOpt = aOpt;
     437         126 :     switch (nPropertyHandle)
     438             :     {
     439           8 :         case UPH_IS_USE_DICTIONARY_LIST :   pbVal = &rOpt.bIsUseDictionaryList;    break;
     440           8 :         case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters;  break;
     441           8 :         case UPH_IS_HYPH_AUTO :             pbVal = &rOpt.bIsHyphAuto; break;
     442           8 :         case UPH_IS_HYPH_SPECIAL :          pbVal = &rOpt.bIsHyphSpecial;  break;
     443           8 :         case UPH_IS_SPELL_AUTO :            pbVal = &rOpt.bIsSpellAuto;    break;
     444           8 :         case UPH_IS_SPELL_SPECIAL :         pbVal = &rOpt.bIsSpellSpecial; break;
     445           8 :         case UPH_IS_WRAP_REVERSE :          pbVal = &rOpt.bIsSpellReverse; break;
     446           9 :         case UPH_DEFAULT_LANGUAGE :         pnVal = &rOpt.nDefaultLanguage;    break;
     447           8 :         case UPH_IS_SPELL_CAPITALIZATION :  pbVal = &rOpt.bIsSpellCapitalization;      break;
     448           8 :         case UPH_IS_SPELL_WITH_DIGITS :     pbVal = &rOpt.bIsSpellWithDigits;  break;
     449           8 :         case UPH_IS_SPELL_UPPER_CASE :      pbVal = &rOpt.bIsSpellUpperCase;       break;
     450           9 :         case UPH_HYPH_MIN_LEADING :         pnVal = &rOpt.nHyphMinLeading;     break;
     451           8 :         case UPH_HYPH_MIN_TRAILING :        pnVal = &rOpt.nHyphMinTrailing;    break;
     452           8 :         case UPH_HYPH_MIN_WORD_LENGTH :     pnVal = &rOpt.nHyphMinWordLength;  break;
     453             :         case UPH_ACTIVE_DICTIONARIES :
     454             :         {
     455           0 :             rValue >>= rOpt.aActiveDics;
     456           0 :             bMod = true;
     457           0 :             break;
     458             :         }
     459             :         case UPH_ACTIVE_CONVERSION_DICTIONARIES :
     460             :         {
     461           0 :             rValue >>= rOpt.aActiveConvDics;
     462           0 :             bMod = true;
     463           0 :             break;
     464             :         }
     465             :         case UPH_DEFAULT_LOCALE :
     466             :         {
     467           8 :             bSucc = lcl_SetLocale( rOpt.nDefaultLanguage, rValue );
     468           8 :             bMod = bSucc;
     469           8 :             break;
     470             :         }
     471             :         case UPH_DEFAULT_LOCALE_CJK :
     472             :         {
     473           2 :             bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CJK, rValue );
     474           2 :             bMod = bSucc;
     475           2 :             break;
     476             :         }
     477             :         case UPH_DEFAULT_LOCALE_CTL :
     478             :         {
     479           2 :             bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CTL, rValue );
     480           2 :             bMod = bSucc;
     481           2 :             break;
     482             :         }
     483           0 :         case UPH_IS_IGNORE_POST_POSITIONAL_WORD :       pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
     484           0 :         case UPH_IS_AUTO_CLOSE_DIALOG :                 pbVal = &rOpt.bIsAutoCloseDialog; break;
     485           0 :         case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :  pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
     486           0 :         case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :       pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
     487             : 
     488           0 :         case UPH_IS_DIRECTION_TO_SIMPLIFIED :           pbVal = &rOpt.bIsDirectionToSimplified; break;
     489           0 :         case UPH_IS_USE_CHARACTER_VARIANTS :            pbVal = &rOpt.bIsUseCharacterVariants; break;
     490           0 :         case UPH_IS_TRANSLATE_COMMON_TERMS :            pbVal = &rOpt.bIsTranslateCommonTerms; break;
     491           0 :         case UPH_IS_REVERSE_MAPPING :                   pbVal = &rOpt.bIsReverseMapping; break;
     492             : 
     493           0 :         case UPH_DATA_FILES_CHANGED_CHECK_VALUE :       pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
     494           0 :         case UPH_IS_GRAMMAR_AUTO:                       pbVal = &rOpt.bIsGrammarAuto; break;
     495           0 :         case UPH_IS_GRAMMAR_INTERACTIVE:                pbVal = &rOpt.bIsGrammarInteractive; break;
     496             :         default :
     497             :             DBG_ASSERT( false, "unexpected property handle" );
     498             :     }
     499             : 
     500         126 :     if (pbVal)
     501             :     {
     502          80 :         bool bNew = bool();
     503          80 :         if (rValue >>= bNew)
     504             :         {
     505          80 :             if (bNew != *pbVal)
     506             :             {
     507          80 :                 *pbVal = bNew;
     508          80 :                 bMod = true;
     509             :             }
     510          80 :             bSucc = true;
     511             :         }
     512             :     }
     513          46 :     else if (pnVal)
     514             :     {
     515          34 :         sal_Int16 nNew = sal_Int16();
     516          34 :         if (rValue >>= nNew)
     517             :         {
     518          34 :             if (nNew != *pnVal)
     519             :             {
     520          34 :                 *pnVal = nNew;
     521          34 :                 bMod = true;
     522             :             }
     523          34 :             bSucc = true;
     524             :         }
     525             :     }
     526          12 :     else if (pnInt32Val)
     527             :     {
     528           0 :         sal_Int32 nNew = sal_Int32();
     529           0 :         if (rValue >>= nNew)
     530             :         {
     531           0 :             if (nNew != *pnInt32Val)
     532             :             {
     533           0 :                 *pnInt32Val = nNew;
     534           0 :                 bMod = true;
     535             :             }
     536           0 :             bSucc = true;
     537             :         }
     538             :     }
     539             : 
     540         126 :     if (bMod)
     541         126 :         SetModified();
     542             : 
     543         126 :     NotifyListeners(0);
     544         126 :     return bSucc;
     545             : }
     546             : 
     547       82104 : const SvtLinguOptions& SvtLinguConfigItem::GetOptions() const
     548             : {
     549       82104 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     550       82104 :     return aOpt;
     551             : }
     552             : 
     553         174 : bool SvtLinguConfigItem::LoadOptions( const uno::Sequence< OUString > &rProperyNames )
     554             : {
     555         174 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     556             : 
     557         174 :     bool bRes = false;
     558             : 
     559         174 :     const OUString *pProperyNames = rProperyNames.getConstArray();
     560         174 :     sal_Int32 nProps = rProperyNames.getLength();
     561             : 
     562         348 :     const uno::Sequence< uno::Any > aValues = GetProperties( rProperyNames );
     563         348 :     const uno::Sequence< sal_Bool > aROStates = GetReadOnlyStates( rProperyNames );
     564             : 
     565         174 :     if (nProps  &&  aValues.getLength() == nProps &&  aROStates.getLength() == nProps)
     566             :     {
     567         174 :         SvtLinguOptions &rOpt = aOpt;
     568             : 
     569         174 :         const uno::Any *pValue = aValues.getConstArray();
     570         174 :         const sal_Bool *pROStates = aROStates.getConstArray();
     571        5220 :         for (sal_Int32 i = 0;  i < nProps;  ++i)
     572             :         {
     573        5046 :             const uno::Any &rVal = pValue[i];
     574             :             sal_Int32 nPropertyHandle;
     575        5046 :             GetHdlByName( nPropertyHandle, pProperyNames[i], true );
     576        5046 :             switch ( nPropertyHandle )
     577             :             {
     578             :                 case UPH_DEFAULT_LOCALE :
     579         174 :                     { rOpt.bRODefaultLanguage = pROStates[i]; rOpt.nDefaultLanguage = lcl_CfgAnyToLanguage( rVal ); } break;
     580             :                 case UPH_ACTIVE_DICTIONARIES :
     581         174 :                     { rOpt.bROActiveDics = pROStates[i]; rVal >>= rOpt.aActiveDics;   } break;
     582             :                 case UPH_IS_USE_DICTIONARY_LIST :
     583         174 :                     { rOpt.bROIsUseDictionaryList = pROStates[i]; rVal >>= rOpt.bIsUseDictionaryList;  } break;
     584             :                 case UPH_IS_IGNORE_CONTROL_CHARACTERS :
     585         174 :                     { rOpt.bROIsIgnoreControlCharacters = pROStates[i]; rVal >>= rOpt.bIsIgnoreControlCharacters;    } break;
     586             :                 case UPH_DEFAULT_LOCALE_CJK :
     587         174 :                     { rOpt.bRODefaultLanguage_CJK = pROStates[i]; rOpt.nDefaultLanguage_CJK = lcl_CfgAnyToLanguage( rVal );    } break;
     588             :                 case UPH_DEFAULT_LOCALE_CTL :
     589         174 :                     { rOpt.bRODefaultLanguage_CTL = pROStates[i]; rOpt.nDefaultLanguage_CTL = lcl_CfgAnyToLanguage( rVal );    } break;
     590             : 
     591             :                 case UPH_IS_SPELL_UPPER_CASE :
     592         174 :                     { rOpt.bROIsSpellUpperCase = pROStates[i]; rVal >>= rOpt.bIsSpellUpperCase; } break;
     593             :                 case UPH_IS_SPELL_WITH_DIGITS :
     594         174 :                     { rOpt.bROIsSpellWithDigits = pROStates[i]; rVal >>= rOpt.bIsSpellWithDigits;    } break;
     595             :                 case UPH_IS_SPELL_CAPITALIZATION :
     596         174 :                     { rOpt.bROIsSpellCapitalization = pROStates[i]; rVal >>= rOpt.bIsSpellCapitalization;    } break;
     597             :                 case UPH_IS_SPELL_AUTO :
     598         174 :                     { rOpt.bROIsSpellAuto = pROStates[i]; rVal >>= rOpt.bIsSpellAuto;  } break;
     599             :                 case UPH_IS_SPELL_SPECIAL :
     600         174 :                     { rOpt.bROIsSpellSpecial = pROStates[i]; rVal >>= rOpt.bIsSpellSpecial;   } break;
     601             :                 case UPH_IS_WRAP_REVERSE :
     602         174 :                     { rOpt.bROIsSpellReverse = pROStates[i]; rVal >>= rOpt.bIsSpellReverse;   } break;
     603             : 
     604             :                 case UPH_HYPH_MIN_LEADING :
     605         174 :                     { rOpt.bROHyphMinLeading = pROStates[i]; rVal >>= rOpt.nHyphMinLeading;   } break;
     606             :                 case UPH_HYPH_MIN_TRAILING :
     607         174 :                     { rOpt.bROHyphMinTrailing = pROStates[i]; rVal >>= rOpt.nHyphMinTrailing;  } break;
     608             :                 case UPH_HYPH_MIN_WORD_LENGTH :
     609         174 :                     { rOpt.bROHyphMinWordLength = pROStates[i]; rVal >>= rOpt.nHyphMinWordLength;    } break;
     610             :                 case UPH_IS_HYPH_SPECIAL :
     611         174 :                     { rOpt.bROIsHyphSpecial = pROStates[i]; rVal >>= rOpt.bIsHyphSpecial;    } break;
     612             :                 case UPH_IS_HYPH_AUTO :
     613         174 :                     { rOpt.bROIsHyphAuto = pROStates[i]; rVal >>= rOpt.bIsHyphAuto;   } break;
     614             : 
     615         174 :                 case UPH_ACTIVE_CONVERSION_DICTIONARIES : { rOpt.bROActiveConvDics = pROStates[i]; rVal >>= rOpt.aActiveConvDics;   } break;
     616             : 
     617             :                 case UPH_IS_IGNORE_POST_POSITIONAL_WORD :
     618         174 :                     { rOpt.bROIsIgnorePostPositionalWord = pROStates[i]; rVal >>= rOpt.bIsIgnorePostPositionalWord;  } break;
     619             :                 case UPH_IS_AUTO_CLOSE_DIALOG :
     620         174 :                     { rOpt.bROIsAutoCloseDialog = pROStates[i]; rVal >>= rOpt.bIsAutoCloseDialog;  } break;
     621             :                 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :
     622         174 :                     { rOpt.bROIsShowEntriesRecentlyUsedFirst = pROStates[i]; rVal >>= rOpt.bIsShowEntriesRecentlyUsedFirst;  } break;
     623             :                 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :
     624         174 :                     { rOpt.bROIsAutoReplaceUniqueEntries = pROStates[i]; rVal >>= rOpt.bIsAutoReplaceUniqueEntries;  } break;
     625             : 
     626             :                 case UPH_IS_DIRECTION_TO_SIMPLIFIED :
     627         174 :                     { rOpt.bROIsDirectionToSimplified = pROStates[i];
     628         174 :                             if( ! (rVal >>= rOpt.bIsDirectionToSimplified) )
     629             :                             {
     630             :                                 //default is locale dependent:
     631         174 :                                 if (MsLangId::isTraditionalChinese(rOpt.nDefaultLanguage_CJK))
     632             :                                 {
     633           0 :                                     rOpt.bIsDirectionToSimplified = false;
     634             :                                 }
     635             :                                 else
     636             :                                 {
     637         174 :                                     rOpt.bIsDirectionToSimplified = true;
     638             :                                 }
     639             :                             }
     640         174 :                     } break;
     641             :                 case UPH_IS_USE_CHARACTER_VARIANTS :
     642         174 :                     { rOpt.bROIsUseCharacterVariants = pROStates[i]; rVal >>= rOpt.bIsUseCharacterVariants;  } break;
     643             :                 case UPH_IS_TRANSLATE_COMMON_TERMS :
     644         174 :                     { rOpt.bROIsTranslateCommonTerms = pROStates[i]; rVal >>= rOpt.bIsTranslateCommonTerms;  } break;
     645             :                 case UPH_IS_REVERSE_MAPPING :
     646         174 :                     { rOpt.bROIsReverseMapping = pROStates[i]; rVal >>= rOpt.bIsReverseMapping;  } break;
     647             : 
     648             :                 case UPH_DATA_FILES_CHANGED_CHECK_VALUE :
     649         174 :                     { rOpt.bRODataFilesChangedCheckValue = pROStates[i]; rVal >>= rOpt.nDataFilesChangedCheckValue;  } break;
     650             : 
     651             :                 case UPH_IS_GRAMMAR_AUTO:
     652         174 :                     { rOpt.bROIsGrammarAuto = pROStates[i]; rVal >>= rOpt.bIsGrammarAuto; }
     653         174 :                 break;
     654             :                 case UPH_IS_GRAMMAR_INTERACTIVE:
     655         174 :                     { rOpt.bROIsGrammarInteractive = pROStates[i]; rVal >>= rOpt.bIsGrammarInteractive; }
     656         174 :                 break;
     657             : 
     658             :                 default:
     659             :                     DBG_ASSERT( false, "unexpected case" );
     660             :             }
     661             :         }
     662             : 
     663         174 :         bRes = true;
     664             :     }
     665             :     DBG_ASSERT( bRes, "LoadOptions failed" );
     666             : 
     667         348 :     return bRes;
     668             : }
     669             : 
     670           2 : bool SvtLinguConfigItem::SaveOptions( const uno::Sequence< OUString > &rProperyNames )
     671             : {
     672           2 :     if (!IsModified())
     673           0 :         return true;
     674             : 
     675           2 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     676             : 
     677           2 :     bool bRet = false;
     678           2 :     const uno::Type &rBOOL     = ::getBooleanCppuType();
     679           2 :     const uno::Type &rINT16    = cppu::UnoType<sal_Int16>::get();
     680           2 :     const uno::Type &rINT32    = cppu::UnoType<sal_Int32>::get();
     681             : 
     682           2 :     sal_Int32 nProps = rProperyNames.getLength();
     683           4 :     uno::Sequence< uno::Any > aValues( nProps );
     684           2 :     uno::Any *pValue = aValues.getArray();
     685             : 
     686           2 :     if (nProps  &&  aValues.getLength() == nProps)
     687             :     {
     688           2 :         const SvtLinguOptions &rOpt = aOpt;
     689             : 
     690           2 :         OUString aTmp( lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage ) );
     691           2 :         *pValue++ = uno::makeAny( aTmp );                               //   0
     692           2 :         *pValue++ = uno::makeAny( rOpt.aActiveDics );                   //   1
     693           2 :         pValue++->setValue( &rOpt.bIsUseDictionaryList, rBOOL );        //   2
     694           2 :         pValue++->setValue( &rOpt.bIsIgnoreControlCharacters, rBOOL );  //   3
     695           2 :         aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CJK );
     696           2 :         *pValue++ = uno::makeAny( aTmp );                               //   5
     697           2 :         aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CTL );
     698           2 :         *pValue++ = uno::makeAny( aTmp );                               //   6
     699             : 
     700           2 :         pValue++->setValue( &rOpt.bIsSpellUpperCase, rBOOL );          //   7
     701           2 :         pValue++->setValue( &rOpt.bIsSpellWithDigits, rBOOL );         //   8
     702           2 :         pValue++->setValue( &rOpt.bIsSpellCapitalization, rBOOL );     //   9
     703           2 :         pValue++->setValue( &rOpt.bIsSpellAuto, rBOOL );               //  10
     704           2 :         pValue++->setValue( &rOpt.bIsSpellSpecial, rBOOL );            //  11
     705           2 :         pValue++->setValue( &rOpt.bIsSpellReverse, rBOOL );            //  14
     706             : 
     707           2 :         pValue++->setValue( &rOpt.nHyphMinLeading, rINT16 );           //  15
     708           2 :         pValue++->setValue( &rOpt.nHyphMinTrailing, rINT16 );          //  16
     709           2 :         pValue++->setValue( &rOpt.nHyphMinWordLength, rINT16 );        //  17
     710           2 :         pValue++->setValue( &rOpt.bIsHyphSpecial, rBOOL );             //  18
     711           2 :         pValue++->setValue( &rOpt.bIsHyphAuto, rBOOL );                //  19
     712             : 
     713           2 :         *pValue++ = uno::makeAny( rOpt.aActiveConvDics );               //   20
     714             : 
     715           2 :         pValue++->setValue( &rOpt.bIsIgnorePostPositionalWord, rBOOL ); //  21
     716           2 :         pValue++->setValue( &rOpt.bIsAutoCloseDialog, rBOOL );          //  22
     717           2 :         pValue++->setValue( &rOpt.bIsShowEntriesRecentlyUsedFirst, rBOOL ); //  23
     718           2 :         pValue++->setValue( &rOpt.bIsAutoReplaceUniqueEntries, rBOOL ); //  24
     719             : 
     720           2 :         pValue++->setValue( &rOpt.bIsDirectionToSimplified, rBOOL ); //  25
     721           2 :         pValue++->setValue( &rOpt.bIsUseCharacterVariants, rBOOL ); //  26
     722           2 :         pValue++->setValue( &rOpt.bIsTranslateCommonTerms, rBOOL ); //  27
     723           2 :         pValue++->setValue( &rOpt.bIsReverseMapping, rBOOL ); //  28
     724             : 
     725           2 :         pValue++->setValue( &rOpt.nDataFilesChangedCheckValue, rINT32 ); //  29
     726           2 :         pValue++->setValue( &rOpt.bIsGrammarAuto, rBOOL ); //  30
     727           2 :         pValue++->setValue( &rOpt.bIsGrammarInteractive, rBOOL ); // 31
     728             : 
     729           2 :         bRet |= PutProperties( rProperyNames, aValues );
     730             :     }
     731             : 
     732           2 :     if (bRet)
     733           2 :         ClearModified();
     734             : 
     735           4 :     return bRet;
     736             : }
     737             : 
     738           0 : bool SvtLinguConfigItem::IsReadOnly( const OUString &rPropertyName ) const
     739             : {
     740           0 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     741             : 
     742           0 :     bool bReadOnly = false;
     743             :     sal_Int32 nHdl;
     744           0 :     if (GetHdlByName( nHdl, rPropertyName ))
     745           0 :         bReadOnly = IsReadOnly( nHdl );
     746           0 :     return bReadOnly;
     747             : }
     748             : 
     749           0 : bool SvtLinguConfigItem::IsReadOnly( sal_Int32 nPropertyHandle ) const
     750             : {
     751           0 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     752             : 
     753           0 :     bool bReadOnly = false;
     754             : 
     755           0 :     const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
     756           0 :     switch(nPropertyHandle)
     757             :     {
     758           0 :         case UPH_IS_USE_DICTIONARY_LIST         : bReadOnly = rOpt.bROIsUseDictionaryList; break;
     759           0 :         case UPH_IS_IGNORE_CONTROL_CHARACTERS   : bReadOnly = rOpt.bROIsIgnoreControlCharacters; break;
     760           0 :         case UPH_IS_HYPH_AUTO                   : bReadOnly = rOpt.bROIsHyphAuto; break;
     761           0 :         case UPH_IS_HYPH_SPECIAL                : bReadOnly = rOpt.bROIsHyphSpecial; break;
     762           0 :         case UPH_IS_SPELL_AUTO                  : bReadOnly = rOpt.bROIsSpellAuto; break;
     763           0 :         case UPH_IS_SPELL_SPECIAL               : bReadOnly = rOpt.bROIsSpellSpecial; break;
     764           0 :         case UPH_IS_WRAP_REVERSE                : bReadOnly = rOpt.bROIsSpellReverse; break;
     765           0 :         case UPH_DEFAULT_LANGUAGE               : bReadOnly = rOpt.bRODefaultLanguage; break;
     766           0 :         case UPH_IS_SPELL_CAPITALIZATION        : bReadOnly = rOpt.bROIsSpellCapitalization; break;
     767           0 :         case UPH_IS_SPELL_WITH_DIGITS           : bReadOnly = rOpt.bROIsSpellWithDigits; break;
     768           0 :         case UPH_IS_SPELL_UPPER_CASE            : bReadOnly = rOpt.bROIsSpellUpperCase; break;
     769           0 :         case UPH_HYPH_MIN_LEADING               : bReadOnly = rOpt.bROHyphMinLeading; break;
     770           0 :         case UPH_HYPH_MIN_TRAILING              : bReadOnly = rOpt.bROHyphMinTrailing; break;
     771           0 :         case UPH_HYPH_MIN_WORD_LENGTH           : bReadOnly = rOpt.bROHyphMinWordLength; break;
     772           0 :         case UPH_ACTIVE_DICTIONARIES            : bReadOnly = rOpt.bROActiveDics; break;
     773           0 :         case UPH_ACTIVE_CONVERSION_DICTIONARIES : bReadOnly = rOpt.bROActiveConvDics; break;
     774           0 :         case UPH_DEFAULT_LOCALE                 : bReadOnly = rOpt.bRODefaultLanguage; break;
     775           0 :         case UPH_DEFAULT_LOCALE_CJK             : bReadOnly = rOpt.bRODefaultLanguage_CJK; break;
     776           0 :         case UPH_DEFAULT_LOCALE_CTL             : bReadOnly = rOpt.bRODefaultLanguage_CTL; break;
     777           0 :         case UPH_IS_IGNORE_POST_POSITIONAL_WORD :       bReadOnly = rOpt.bROIsIgnorePostPositionalWord; break;
     778           0 :         case UPH_IS_AUTO_CLOSE_DIALOG :                 bReadOnly = rOpt.bROIsAutoCloseDialog; break;
     779           0 :         case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :  bReadOnly = rOpt.bROIsShowEntriesRecentlyUsedFirst; break;
     780           0 :         case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :       bReadOnly = rOpt.bROIsAutoReplaceUniqueEntries; break;
     781           0 :         case UPH_IS_DIRECTION_TO_SIMPLIFIED : bReadOnly = rOpt.bROIsDirectionToSimplified; break;
     782           0 :         case UPH_IS_USE_CHARACTER_VARIANTS : bReadOnly = rOpt.bROIsUseCharacterVariants; break;
     783           0 :         case UPH_IS_TRANSLATE_COMMON_TERMS : bReadOnly = rOpt.bROIsTranslateCommonTerms; break;
     784           0 :         case UPH_IS_REVERSE_MAPPING :        bReadOnly = rOpt.bROIsReverseMapping; break;
     785           0 :         case UPH_DATA_FILES_CHANGED_CHECK_VALUE :       bReadOnly = rOpt.bRODataFilesChangedCheckValue; break;
     786           0 :         case UPH_IS_GRAMMAR_AUTO:                       bReadOnly = rOpt.bROIsGrammarAuto; break;
     787           0 :         case UPH_IS_GRAMMAR_INTERACTIVE:                bReadOnly = rOpt.bROIsGrammarInteractive; break;
     788             :         default :
     789             :             DBG_ASSERT( false, "unexpected property handle" );
     790             :     }
     791           0 :     return bReadOnly;
     792             : }
     793             : 
     794             : static SvtLinguConfigItem *pCfgItem = 0;
     795             : static sal_Int32           nCfgItemRefCount = 0;
     796             : 
     797             : static const char aG_SupportedDictionaryFormats[] = "SupportedDictionaryFormats";
     798             : static const char aG_Dictionaries[] = "Dictionaries";
     799             : static const char aG_Locations[] = "Locations";
     800             : static const char aG_Format[] = "Format";
     801             : static const char aG_Locales[] = "Locales";
     802             : static const char aG_DisabledDictionaries[] = "DisabledDictionaries";
     803             : 
     804      127722 : SvtLinguConfig::SvtLinguConfig()
     805             : {
     806             :     // Global access, must be guarded (multithreading)
     807      127722 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     808      127722 :     ++nCfgItemRefCount;
     809      127722 : }
     810             : 
     811      255606 : SvtLinguConfig::~SvtLinguConfig()
     812             : {
     813      127717 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     814             : 
     815      127717 :     if (pCfgItem && pCfgItem->IsModified())
     816           0 :         pCfgItem->Commit();
     817             : 
     818      127717 :     if (--nCfgItemRefCount <= 0)
     819             :     {
     820         169 :         if (pCfgItem)
     821         169 :             delete pCfgItem;
     822         169 :         pCfgItem = 0;
     823      127717 :     }
     824      127889 : }
     825             : 
     826      196876 : SvtLinguConfigItem & SvtLinguConfig::GetConfigItem()
     827             : {
     828             :     // Global access, must be guarded (multithreading)
     829      196876 :     osl::MutexGuard aGuard(theSvtLinguConfigItemMutex::get());
     830      196876 :     if (!pCfgItem)
     831             :     {
     832         174 :         pCfgItem = new SvtLinguConfigItem;
     833         174 :         ItemHolder1::holdConfigItem(E_LINGUCFG);
     834             :     }
     835      196876 :     return *pCfgItem;
     836             : }
     837             : 
     838        3520 : uno::Sequence< OUString > SvtLinguConfig::GetNodeNames( const OUString &rNode )
     839             : {
     840        3520 :     return GetConfigItem().GetNodeNames( rNode );
     841             : }
     842             : 
     843         280 : uno::Sequence< uno::Any > SvtLinguConfig::GetProperties( const uno::Sequence< OUString > &rNames )
     844             : {
     845         280 :     return GetConfigItem().GetProperties(rNames);
     846             : }
     847             : 
     848         880 : bool SvtLinguConfig::ReplaceSetProperties(
     849             :         const OUString &rNode, const uno::Sequence< beans::PropertyValue >& rValues )
     850             : {
     851         880 :     return GetConfigItem().ReplaceSetProperties( rNode, rValues );
     852             : }
     853             : 
     854       44940 : uno::Any SvtLinguConfig::GetProperty( const OUString &rPropertyName ) const
     855             : {
     856       44940 :     return GetConfigItem().GetProperty( rPropertyName );
     857             : }
     858             : 
     859       65026 : uno::Any SvtLinguConfig::GetProperty( sal_Int32 nPropertyHandle ) const
     860             : {
     861       65026 :     return GetConfigItem().GetProperty( nPropertyHandle );
     862             : }
     863             : 
     864           0 : bool SvtLinguConfig::SetProperty( const OUString &rPropertyName, const uno::Any &rValue )
     865             : {
     866           0 :     return GetConfigItem().SetProperty( rPropertyName, rValue );
     867             : }
     868             : 
     869         126 : bool SvtLinguConfig::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
     870             : {
     871         126 :     return GetConfigItem().SetProperty( nPropertyHandle, rValue );
     872             : }
     873             : 
     874       82104 : bool SvtLinguConfig::GetOptions( SvtLinguOptions &rOptions ) const
     875             : {
     876       82104 :     rOptions = GetConfigItem().GetOptions();
     877       82104 :     return true;
     878             : }
     879             : 
     880           0 : bool SvtLinguConfig::IsReadOnly( const OUString &rPropertyName ) const
     881             : {
     882           0 :     return GetConfigItem().IsReadOnly( rPropertyName );
     883             : }
     884             : 
     885         132 : bool SvtLinguConfig::GetElementNamesFor(
     886             :      const OUString &rNodeName,
     887             :      uno::Sequence< OUString > &rElementNames ) const
     888             : {
     889         132 :     bool bSuccess = false;
     890             :     try
     891             :     {
     892         132 :         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
     893         132 :         xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
     894         132 :         xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW );
     895         132 :         rElementNames = xNA->getElementNames();
     896         132 :         bSuccess = true;
     897             :     }
     898           0 :     catch (uno::Exception &)
     899             :     {
     900             :     }
     901         132 :     return bSuccess;
     902             : }
     903             : 
     904         132 : bool SvtLinguConfig::GetSupportedDictionaryFormatsFor(
     905             :     const OUString &rSetName,
     906             :     const OUString &rSetEntry,
     907             :     uno::Sequence< OUString > &rFormatList ) const
     908             : {
     909         132 :     if (rSetName.isEmpty() || rSetEntry.isEmpty())
     910           0 :         return false;
     911         132 :     bool bSuccess = false;
     912             :     try
     913             :     {
     914         132 :         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
     915         132 :         xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
     916         132 :         xNA.set( xNA->getByName( rSetName ), uno::UNO_QUERY_THROW );
     917         132 :         xNA.set( xNA->getByName( rSetEntry ), uno::UNO_QUERY_THROW );
     918         132 :         if (xNA->getByName( OUString(aG_SupportedDictionaryFormats) ) >>= rFormatList)
     919         132 :             bSuccess = true;
     920         132 :         DBG_ASSERT( rFormatList.getLength(), "supported dictionary format list is empty" );
     921             :     }
     922           0 :     catch (uno::Exception &)
     923             :     {
     924             :     }
     925         132 :     return bSuccess;
     926             : }
     927             : 
     928           0 : static bool lcl_GetFileUrlFromOrigin(
     929             :     OUString /*out*/ &rFileUrl,
     930             :     const OUString &rOrigin )
     931             : {
     932           0 :     bool bSuccess = false;
     933           0 :     if (!rOrigin.isEmpty())
     934             :     {
     935           0 :         OUString aURL( rOrigin );
     936           0 :         if ( aURL.startsWith( EXPAND_PROTOCOL ) )
     937             :         {
     938             :             // cut protocol
     939           0 :             OUString aMacro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) );
     940             :             // decode uric class chars
     941           0 :             aMacro = Uri::decode( aMacro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
     942             :             // expand macro string
     943           0 :             aURL = util::theMacroExpander::get(
     944           0 :                 comphelper::getProcessComponentContext() )->expandMacros(
     945           0 :                     aMacro );
     946             : 
     947           0 :             bool bIsFileUrl = aURL.startsWith( FILE_PROTOCOL );
     948           0 :             if (bIsFileUrl)
     949             :             {
     950           0 :                 rFileUrl = aURL;
     951           0 :                 bSuccess = true;
     952             :             }
     953             :             else
     954             :             {
     955             :                 SAL_WARN(
     956             :                     "unotools.config", "not a file URL, <" << aURL << ">" );
     957           0 :             }
     958             :         }
     959             :         else
     960             :         {
     961             :             SAL_WARN(
     962             :                 "unotools.config", "failed to get file URL, <" << aURL << ">" );
     963           0 :         }
     964             :     }
     965           0 :     return bSuccess;
     966             : }
     967             : 
     968           0 : bool SvtLinguConfig::GetDictionaryEntry(
     969             :     const OUString &rNodeName,
     970             :     SvtLinguConfigDictionaryEntry &rDicEntry ) const
     971             : {
     972           0 :     if (rNodeName.isEmpty())
     973           0 :         return false;
     974           0 :     bool bSuccess = false;
     975             :     try
     976             :     {
     977           0 :         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
     978           0 :         xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
     979           0 :         xNA.set( xNA->getByName(OUString(aG_Dictionaries)), uno::UNO_QUERY_THROW );
     980           0 :         xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW );
     981             : 
     982             :         // read group data...
     983           0 :         uno::Sequence< OUString >  aLocations;
     984           0 :         OUString                   aFormatName;
     985           0 :         uno::Sequence< OUString >  aLocaleNames;
     986           0 :         bSuccess =  (xNA->getByName( OUString(aG_Locations) ) >>= aLocations)  &&
     987           0 :                     (xNA->getByName( OUString(aG_Format) )    >>= aFormatName) &&
     988           0 :                     (xNA->getByName( OUString(aG_Locales) )   >>= aLocaleNames);
     989             :         DBG_ASSERT( aLocations.getLength(), "Dictionary locations not set" );
     990             :         DBG_ASSERT( !aFormatName.isEmpty(), "Dictionary format name not set" );
     991             :         DBG_ASSERT( aLocaleNames.getLength(), "No locales set for the dictionary" );
     992             : 
     993             :         // if successful continue
     994           0 :         if (bSuccess)
     995             :         {
     996             :             // get file URL's for the locations
     997           0 :             for (sal_Int32 i = 0;  i < aLocations.getLength();  ++i)
     998             :             {
     999           0 :                 OUString &rLocation = aLocations[i];
    1000           0 :                 if (!lcl_GetFileUrlFromOrigin( rLocation, rLocation ))
    1001           0 :                     bSuccess = false;
    1002             :             }
    1003             : 
    1004             :             // if everything was fine return the result
    1005           0 :             if (bSuccess)
    1006             :             {
    1007           0 :                 rDicEntry.aLocations    = aLocations;
    1008           0 :                 rDicEntry.aFormatName   = aFormatName;
    1009           0 :                 rDicEntry.aLocaleNames  = aLocaleNames;
    1010             :             }
    1011           0 :         }
    1012             :     }
    1013           0 :     catch (uno::Exception &)
    1014             :     {
    1015             :     }
    1016           0 :     return bSuccess;
    1017             : }
    1018             : 
    1019         132 : uno::Sequence< OUString > SvtLinguConfig::GetDisabledDictionaries() const
    1020             : {
    1021         132 :     uno::Sequence< OUString > aResult;
    1022             :     try
    1023             :     {
    1024         132 :         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
    1025         132 :         xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
    1026         132 :         xNA->getByName( OUString(aG_DisabledDictionaries) ) >>= aResult;
    1027             :     }
    1028           0 :     catch (uno::Exception &)
    1029             :     {
    1030             :     }
    1031         132 :     return aResult;
    1032             : }
    1033             : 
    1034         132 : std::vector< SvtLinguConfigDictionaryEntry > SvtLinguConfig::GetActiveDictionariesByFormat(
    1035             :     const OUString &rFormatName )
    1036             : {
    1037         132 :     std::vector< SvtLinguConfigDictionaryEntry > aRes;
    1038         132 :     if (rFormatName.isEmpty())
    1039           0 :         return aRes;
    1040             : 
    1041             :     try
    1042             :     {
    1043         132 :         uno::Sequence< OUString > aElementNames;
    1044         132 :         GetElementNamesFor( OUString(aG_Dictionaries), aElementNames );
    1045         132 :         sal_Int32 nLen = aElementNames.getLength();
    1046         132 :         const OUString *pElementNames = aElementNames.getConstArray();
    1047             : 
    1048         264 :         const uno::Sequence< OUString > aDisabledDics( GetDisabledDictionaries() );
    1049             : 
    1050         264 :         SvtLinguConfigDictionaryEntry aDicEntry;
    1051         132 :         for (sal_Int32 i = 0;  i < nLen;  ++i)
    1052             :         {
    1053             :             // does dictionary match the format we are looking for?
    1054           0 :             if (GetDictionaryEntry( pElementNames[i], aDicEntry ) &&
    1055           0 :                 aDicEntry.aFormatName == rFormatName)
    1056             :             {
    1057             :                 // check if it is active or not
    1058           0 :                 bool bDicIsActive = true;
    1059           0 :                 for (sal_Int32 k = 0;  bDicIsActive && k < aDisabledDics.getLength();  ++k)
    1060             :                 {
    1061           0 :                     if (aDisabledDics[k] == pElementNames[i])
    1062           0 :                         bDicIsActive = false;
    1063             :                 }
    1064             : 
    1065           0 :                 if (bDicIsActive)
    1066             :                 {
    1067             :                     DBG_ASSERT( !aDicEntry.aFormatName.isEmpty(),
    1068             :                             "FormatName not set" );
    1069             :                     DBG_ASSERT( aDicEntry.aLocations.getLength(),
    1070             :                             "Locations not set" );
    1071             :                     DBG_ASSERT( aDicEntry.aLocaleNames.getLength(),
    1072             :                             "Locales not set" );
    1073           0 :                     aRes.push_back( aDicEntry );
    1074             :                 }
    1075             :             }
    1076         132 :         }
    1077             :     }
    1078           0 :     catch (uno::Exception &)
    1079             :     {
    1080             :     }
    1081             : 
    1082         132 :     return aRes;
    1083             : }
    1084             : 
    1085         800 : uno::Reference< util::XChangesBatch > SvtLinguConfig::GetMainUpdateAccess() const
    1086             : {
    1087         800 :     if (!m_xMainUpdateAccess.is())
    1088             :     {
    1089             :         try
    1090             :         {
    1091             :             // get configuration provider
    1092         536 :             uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
    1093             :             uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider =
    1094        1072 :                     configuration::theDefaultProvider::get( xContext );
    1095             : 
    1096             :             // get configuration update access
    1097        1072 :             beans::PropertyValue aValue;
    1098         536 :             aValue.Name  = "nodepath";
    1099         536 :             aValue.Value = uno::makeAny(OUString("org.openoffice.Office.Linguistic"));
    1100        1072 :             uno::Sequence< uno::Any > aProps(1);
    1101         536 :             aProps[0] <<= aValue;
    1102        1072 :             m_xMainUpdateAccess = uno::Reference< util::XChangesBatch >(
    1103         536 :                     xConfigurationProvider->createInstanceWithArguments(
    1104         536 :                         OUString("com.sun.star.configuration.ConfigurationUpdateAccess"), aProps),
    1105        1072 :                         uno::UNO_QUERY_THROW );
    1106             :         }
    1107           0 :         catch (uno::Exception &)
    1108             :         {
    1109             :         }
    1110             :     }
    1111             : 
    1112         800 :     return m_xMainUpdateAccess;
    1113             : }
    1114             : 
    1115           0 : OUString SvtLinguConfig::GetVendorImageUrl_Impl(
    1116             :     const OUString &rServiceImplName,
    1117             :     const OUString &rImageName ) const
    1118             : {
    1119           0 :     OUString aRes;
    1120             :     try
    1121             :     {
    1122           0 :         uno::Reference< container::XNameAccess > xImagesNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
    1123           0 :         xImagesNA.set( xImagesNA->getByName("Images"), uno::UNO_QUERY_THROW );
    1124             : 
    1125           0 :         uno::Reference< container::XNameAccess > xNA( xImagesNA->getByName("ServiceNameEntries"), uno::UNO_QUERY_THROW );
    1126           0 :         xNA.set( xNA->getByName( rServiceImplName ), uno::UNO_QUERY_THROW );
    1127           0 :         uno::Any aAny(xNA->getByName("VendorImagesNode"));
    1128           0 :         OUString aVendorImagesNode;
    1129           0 :         if (aAny >>= aVendorImagesNode)
    1130             :         {
    1131           0 :             xNA = xImagesNA;
    1132           0 :             xNA.set( xNA->getByName("VendorImages"), uno::UNO_QUERY_THROW );
    1133           0 :             xNA.set( xNA->getByName( aVendorImagesNode ), uno::UNO_QUERY_THROW );
    1134           0 :             aAny = xNA->getByName( rImageName );
    1135           0 :             OUString aTmp;
    1136           0 :             if (aAny >>= aTmp)
    1137             :             {
    1138           0 :                 if (lcl_GetFileUrlFromOrigin( aTmp, aTmp ))
    1139           0 :                     aRes = aTmp;
    1140           0 :             }
    1141           0 :         }
    1142             :     }
    1143           0 :     catch (uno::Exception &)
    1144             :     {
    1145             :         DBG_ASSERT( false, "exception caught. GetVendorImageUrl_Impl failed" );
    1146             :     }
    1147           0 :     return aRes;
    1148             : }
    1149             : 
    1150           0 : OUString SvtLinguConfig::GetSpellAndGrammarContextSuggestionImage(
    1151             :     const OUString &rServiceImplName
    1152             : ) const
    1153             : {
    1154           0 :     OUString   aRes;
    1155           0 :     if (!rServiceImplName.isEmpty())
    1156             :     {
    1157           0 :         OUString aImageName( "SpellAndGrammarContextMenuSuggestionImage" );
    1158           0 :         OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
    1159           0 :         aRes = aPath;
    1160             :     }
    1161           0 :     return aRes;
    1162             : }
    1163             : 
    1164           0 : OUString SvtLinguConfig::GetSpellAndGrammarContextDictionaryImage(
    1165             :     const OUString &rServiceImplName
    1166             : ) const
    1167             : {
    1168           0 :     OUString   aRes;
    1169           0 :     if (!rServiceImplName.isEmpty())
    1170             :     {
    1171           0 :         OUString aImageName( "SpellAndGrammarContextMenuDictionaryImage" );
    1172           0 :         OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
    1173           0 :         aRes = aPath;
    1174             :     }
    1175           0 :     return aRes;
    1176             : }
    1177             : 
    1178           0 : OUString SvtLinguConfig::GetSynonymsContextImage(
    1179             :     const OUString &rServiceImplName
    1180             : ) const
    1181             : {
    1182           0 :     OUString   aRes;
    1183           0 :     if (!rServiceImplName.isEmpty())
    1184             :     {
    1185           0 :         OUString aImageName( "SynonymsContextMenuImage" );
    1186           0 :         OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, aImageName ) );
    1187           0 :         aRes = aPath;
    1188             :     }
    1189           0 :     return aRes;
    1190             : }
    1191             : 
    1192         404 : bool SvtLinguConfig::HasGrammarChecker() const
    1193             : {
    1194         404 :     bool bRes = false;
    1195             : 
    1196             :     try
    1197             :     {
    1198         404 :         uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
    1199         404 :         xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
    1200         404 :         xNA.set( xNA->getByName("GrammarCheckerList"), uno::UNO_QUERY_THROW );
    1201             : 
    1202         808 :         uno::Sequence< OUString > aElementNames( xNA->getElementNames() );
    1203         808 :         bRes = aElementNames.getLength() > 0;
    1204             :     }
    1205           0 :     catch (const uno::Exception&)
    1206             :     {
    1207             :     }
    1208             : 
    1209         404 :     return bRes;
    1210             : }
    1211             : 
    1212             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10