diff options
Diffstat (limited to 'unotools/source/config/lingucfg.cxx')
-rw-r--r-- | unotools/source/config/lingucfg.cxx | 1180 |
1 files changed, 1180 insertions, 0 deletions
diff --git a/unotools/source/config/lingucfg.cxx b/unotools/source/config/lingucfg.cxx new file mode 100644 index 000000000..a38fb51b6 --- /dev/null +++ b/unotools/source/config/lingucfg.cxx @@ -0,0 +1,1180 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/configuration/theDefaultProvider.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> +#include <i18nlangtag/mslangid.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <tools/debug.hxx> +#include <unotools/configitem.hxx> +#include <unotools/lingucfg.hxx> +#include <unotools/linguprops.hxx> +#include <sal/macros.h> +#include <comphelper/getexpandeduri.hxx> +#include <comphelper/processfactory.hxx> +#include <o3tl/string_view.hxx> +#include <mutex> + +#include "itemholder1.hxx" + +using namespace com::sun::star; + +constexpr OUStringLiteral FILE_PROTOCOL = u"file:///"; + +namespace +{ + std::mutex& theSvtLinguConfigItemMutex() + { + static std::mutex SINGLETON; + return SINGLETON; + } +} + +static bool lcl_SetLocale( LanguageType &rLanguage, const uno::Any &rVal ) +{ + bool bSucc = false; + + lang::Locale aNew; + if (rVal >>= aNew) // conversion successful? + { + LanguageType nNew = LanguageTag::convertToLanguageType( aNew, false); + if (nNew != rLanguage) + { + rLanguage = nNew; + bSucc = true; + } + } + return bSucc; +} + +static OUString lcl_LanguageToCfgLocaleStr( LanguageType nLanguage ) +{ + OUString aRes; + if (LANGUAGE_SYSTEM != nLanguage) + aRes = LanguageTag::convertToBcp47( nLanguage ); + return aRes; +} + +static LanguageType lcl_CfgAnyToLanguage( const uno::Any &rVal ) +{ + OUString aTmp; + rVal >>= aTmp; + return (aTmp.isEmpty()) ? LANGUAGE_SYSTEM : LanguageTag::convertToLanguageTypeWithFallback( aTmp ); +} + +SvtLinguOptions::SvtLinguOptions() + : bROActiveDics(false) + , bROActiveConvDics(false) + , nHyphMinLeading(2) + , nHyphMinTrailing(2) + , nHyphMinWordLength(0) + , bROHyphMinLeading(false) + , bROHyphMinTrailing(false) + , bROHyphMinWordLength(false) + , nDefaultLanguage(LANGUAGE_NONE) + , nDefaultLanguage_CJK(LANGUAGE_NONE) + , nDefaultLanguage_CTL(LANGUAGE_NONE) + , bRODefaultLanguage(false) + , bRODefaultLanguage_CJK(false) + , bRODefaultLanguage_CTL(false) + , bIsSpellSpecial(true) + , bIsSpellAuto(false) + , bIsSpellReverse(false) + , bROIsSpellSpecial(false) + , bROIsSpellAuto(false) + , bROIsSpellReverse(false) + , bIsHyphSpecial(true) + , bIsHyphAuto(false) + , bROIsHyphSpecial(false) + , bROIsHyphAuto(false) + , bIsUseDictionaryList(true) + , bIsIgnoreControlCharacters(true) + , bROIsUseDictionaryList(false) + , bROIsIgnoreControlCharacters(false) + , bIsSpellWithDigits(false) + , bIsSpellUpperCase(false) + , bIsSpellCapitalization(true) + , bROIsSpellWithDigits(false) + , bROIsSpellUpperCase(false) + , bROIsSpellCapitalization(false) + , bIsIgnorePostPositionalWord(true) + , bIsAutoCloseDialog(false) + , bIsShowEntriesRecentlyUsedFirst(false) + , bIsAutoReplaceUniqueEntries(false) + , bIsDirectionToSimplified(true) + , bIsUseCharacterVariants(false) + , bIsTranslateCommonTerms(false) + , bIsReverseMapping(false) + , bROIsIgnorePostPositionalWord(false) + , bROIsAutoCloseDialog(false) + , bROIsShowEntriesRecentlyUsedFirst(false) + , bROIsAutoReplaceUniqueEntries(false) + , bROIsDirectionToSimplified(false) + , bROIsUseCharacterVariants(false) + , bROIsTranslateCommonTerms(false) + , bROIsReverseMapping(false) + , nDataFilesChangedCheckValue(0) + , bRODataFilesChangedCheckValue(false) + , bIsGrammarAuto(false) + , bIsGrammarInteractive(false) + , bROIsGrammarAuto(false) + , bROIsGrammarInteractive(false) +{ +} + +class SvtLinguConfigItem : public utl::ConfigItem +{ + SvtLinguOptions aOpt; + + static bool GetHdlByName( sal_Int32 &rnHdl, std::u16string_view rPropertyName, bool bFullPropName = false ); + static uno::Sequence< OUString > GetPropertyNames(); + void LoadOptions( const uno::Sequence< OUString > &rProperyNames ); + bool SaveOptions( const uno::Sequence< OUString > &rProperyNames ); + + SvtLinguConfigItem(const SvtLinguConfigItem&) = delete; + SvtLinguConfigItem& operator=(const SvtLinguConfigItem&) = delete; + virtual void ImplCommit() override; + +public: + SvtLinguConfigItem(); + + // utl::ConfigItem + virtual void Notify( const css::uno::Sequence< OUString > &rPropertyNames ) override; + + // make some protected functions of utl::ConfigItem public + using utl::ConfigItem::GetNodeNames; + using utl::ConfigItem::GetProperties; + //using utl::ConfigItem::PutProperties; + //using utl::ConfigItem::SetSetProperties; + using utl::ConfigItem::ReplaceSetProperties; + //using utl::ConfigItem::GetReadOnlyStates; + + css::uno::Any + GetProperty( std::u16string_view rPropertyName ) const; + css::uno::Any + GetProperty( sal_Int32 nPropertyHandle ) const; + + bool SetProperty( std::u16string_view rPropertyName, + const css::uno::Any &rValue ); + bool SetProperty( sal_Int32 nPropertyHandle, + const css::uno::Any &rValue ); + + void GetOptions( SvtLinguOptions& ) const; + + bool IsReadOnly( std::u16string_view rPropertyName ) const; + bool IsReadOnly( sal_Int32 nPropertyHandle ) const; +}; + +SvtLinguConfigItem::SvtLinguConfigItem() : + utl::ConfigItem( "Office.Linguistic" ) +{ + const uno::Sequence< OUString > &rPropertyNames = GetPropertyNames(); + LoadOptions( rPropertyNames ); + ClearModified(); + + // request notify events when properties change + EnableNotification( rPropertyNames ); +} + +void SvtLinguConfigItem::Notify( const uno::Sequence< OUString > &rPropertyNames ) +{ + { + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + LoadOptions( rPropertyNames ); + } + NotifyListeners(ConfigurationHints::NONE); +} + +void SvtLinguConfigItem::ImplCommit() +{ + SaveOptions( GetPropertyNames() ); +} + +namespace { + +struct NamesToHdl +{ + const char *pFullPropName; // full qualified name as used in configuration + OUString aPropName; // property name only (atom) of above + sal_Int32 nHdl; // numeric handle representing the property +}; + +} + +NamesToHdl const aNamesToHdl[] = +{ +{/* 0 */ "General/DefaultLocale", UPN_DEFAULT_LOCALE, UPH_DEFAULT_LOCALE}, +{/* 1 */ "General/DictionaryList/ActiveDictionaries", UPN_ACTIVE_DICTIONARIES, UPH_ACTIVE_DICTIONARIES}, +{/* 2 */ "General/DictionaryList/IsUseDictionaryList", UPN_IS_USE_DICTIONARY_LIST, UPH_IS_USE_DICTIONARY_LIST}, +{/* 3 */ "General/IsIgnoreControlCharacters", UPN_IS_IGNORE_CONTROL_CHARACTERS, UPH_IS_IGNORE_CONTROL_CHARACTERS}, +{/* 5 */ "General/DefaultLocale_CJK", UPN_DEFAULT_LOCALE_CJK, UPH_DEFAULT_LOCALE_CJK}, +{/* 6 */ "General/DefaultLocale_CTL", UPN_DEFAULT_LOCALE_CTL, UPH_DEFAULT_LOCALE_CTL}, + +{/* 7 */ "SpellChecking/IsSpellUpperCase", UPN_IS_SPELL_UPPER_CASE, UPH_IS_SPELL_UPPER_CASE}, +{/* 8 */ "SpellChecking/IsSpellWithDigits", UPN_IS_SPELL_WITH_DIGITS, UPH_IS_SPELL_WITH_DIGITS}, +{/* 9 */ "SpellChecking/IsSpellCapitalization", UPN_IS_SPELL_CAPITALIZATION, UPH_IS_SPELL_CAPITALIZATION}, +{/* 10 */ "SpellChecking/IsSpellAuto", UPN_IS_SPELL_AUTO, UPH_IS_SPELL_AUTO}, +{/* 11 */ "SpellChecking/IsSpellSpecial", UPN_IS_SPELL_SPECIAL, UPH_IS_SPELL_SPECIAL}, +{/* 14 */ "SpellChecking/IsReverseDirection", UPN_IS_WRAP_REVERSE, UPH_IS_WRAP_REVERSE}, + +{/* 15 */ "Hyphenation/MinLeading", UPN_HYPH_MIN_LEADING, UPH_HYPH_MIN_LEADING}, +{/* 16 */ "Hyphenation/MinTrailing", UPN_HYPH_MIN_TRAILING, UPH_HYPH_MIN_TRAILING}, +{/* 17 */ "Hyphenation/MinWordLength", UPN_HYPH_MIN_WORD_LENGTH, UPH_HYPH_MIN_WORD_LENGTH}, +{/* 18 */ "Hyphenation/IsHyphSpecial", UPN_IS_HYPH_SPECIAL, UPH_IS_HYPH_SPECIAL}, +{/* 19 */ "Hyphenation/IsHyphAuto", UPN_IS_HYPH_AUTO, UPH_IS_HYPH_AUTO}, + +{/* 20 */ "TextConversion/ActiveConversionDictionaries", UPN_ACTIVE_CONVERSION_DICTIONARIES, UPH_ACTIVE_CONVERSION_DICTIONARIES}, +{/* 21 */ "TextConversion/IsIgnorePostPositionalWord", UPN_IS_IGNORE_POST_POSITIONAL_WORD, UPH_IS_IGNORE_POST_POSITIONAL_WORD}, +{/* 22 */ "TextConversion/IsAutoCloseDialog", UPN_IS_AUTO_CLOSE_DIALOG, UPH_IS_AUTO_CLOSE_DIALOG}, +{/* 23 */ "TextConversion/IsShowEntriesRecentlyUsedFirst", UPN_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST}, +{/* 24 */ "TextConversion/IsAutoReplaceUniqueEntries", UPN_IS_AUTO_REPLACE_UNIQUE_ENTRIES, UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES}, +{/* 25 */ "TextConversion/IsDirectionToSimplified", UPN_IS_DIRECTION_TO_SIMPLIFIED, UPH_IS_DIRECTION_TO_SIMPLIFIED}, +{/* 26 */ "TextConversion/IsUseCharacterVariants", UPN_IS_USE_CHARACTER_VARIANTS, UPH_IS_USE_CHARACTER_VARIANTS}, +{/* 27 */ "TextConversion/IsTranslateCommonTerms", UPN_IS_TRANSLATE_COMMON_TERMS, UPH_IS_TRANSLATE_COMMON_TERMS}, +{/* 28 */ "TextConversion/IsReverseMapping", UPN_IS_REVERSE_MAPPING, UPH_IS_REVERSE_MAPPING}, + +{/* 29 */ "ServiceManager/DataFilesChangedCheckValue", UPN_DATA_FILES_CHANGED_CHECK_VALUE, UPH_DATA_FILES_CHANGED_CHECK_VALUE}, + +{/* 30 */ "GrammarChecking/IsAutoCheck", UPN_IS_GRAMMAR_AUTO, UPH_IS_GRAMMAR_AUTO}, +{/* 31 */ "GrammarChecking/IsInteractiveCheck", UPN_IS_GRAMMAR_INTERACTIVE, UPH_IS_GRAMMAR_INTERACTIVE}, + + /* similar to entry 0 (thus no own configuration entry) but with different property name and type */ +{ nullptr, UPN_DEFAULT_LANGUAGE, UPH_DEFAULT_LANGUAGE}, + +{ nullptr, "", -1} +}; + +uno::Sequence< OUString > SvtLinguConfigItem::GetPropertyNames() +{ + uno::Sequence< OUString > aNames; + + sal_Int32 nMax = SAL_N_ELEMENTS(aNamesToHdl); + + aNames.realloc( nMax ); + OUString *pNames = aNames.getArray(); + sal_Int32 nIdx = 0; + for (sal_Int32 i = 0; i < nMax; ++i) + { + const char *pFullPropName = aNamesToHdl[i].pFullPropName; + if (pFullPropName) + pNames[ nIdx++ ] = OUString::createFromAscii( pFullPropName ); + } + aNames.realloc( nIdx ); + + return aNames; +} + +bool SvtLinguConfigItem::GetHdlByName( + sal_Int32 &rnHdl, + std::u16string_view rPropertyName, + bool bFullPropName ) +{ + NamesToHdl const *pEntry = &aNamesToHdl[0]; + + if (bFullPropName) + { + while (pEntry && pEntry->pFullPropName != nullptr) + { + if (o3tl::equalsAscii(rPropertyName, pEntry->pFullPropName )) + { + rnHdl = pEntry->nHdl; + break; + } + ++pEntry; + } + return pEntry && pEntry->pFullPropName != nullptr; + } + else + { + while (pEntry && pEntry->pFullPropName != nullptr) + { + if (rPropertyName == pEntry->aPropName ) + { + rnHdl = pEntry->nHdl; + break; + } + ++pEntry; + } + return pEntry && pEntry->pFullPropName != nullptr; + } +} + +uno::Any SvtLinguConfigItem::GetProperty( std::u16string_view rPropertyName ) const +{ + sal_Int32 nHdl; + return GetHdlByName( nHdl, rPropertyName ) ? GetProperty( nHdl ) : uno::Any(); +} + +uno::Any SvtLinguConfigItem::GetProperty( sal_Int32 nPropertyHandle ) const +{ + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + + uno::Any aRes; + + const sal_Int16 *pnVal = nullptr; + const LanguageType *plVal = nullptr; + const bool *pbVal = nullptr; + const sal_Int32 *pnInt32Val = nullptr; + + const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt; + switch (nPropertyHandle) + { + case UPH_IS_USE_DICTIONARY_LIST : pbVal = &rOpt.bIsUseDictionaryList; break; + case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters; break; + case UPH_IS_HYPH_AUTO : pbVal = &rOpt.bIsHyphAuto; break; + case UPH_IS_HYPH_SPECIAL : pbVal = &rOpt.bIsHyphSpecial; break; + case UPH_IS_SPELL_AUTO : pbVal = &rOpt.bIsSpellAuto; break; + case UPH_IS_SPELL_SPECIAL : pbVal = &rOpt.bIsSpellSpecial; break; + case UPH_IS_WRAP_REVERSE : pbVal = &rOpt.bIsSpellReverse; break; + case UPH_DEFAULT_LANGUAGE : plVal = &rOpt.nDefaultLanguage; break; + case UPH_IS_SPELL_CAPITALIZATION : pbVal = &rOpt.bIsSpellCapitalization; break; + case UPH_IS_SPELL_WITH_DIGITS : pbVal = &rOpt.bIsSpellWithDigits; break; + case UPH_IS_SPELL_UPPER_CASE : pbVal = &rOpt.bIsSpellUpperCase; break; + case UPH_HYPH_MIN_LEADING : pnVal = &rOpt.nHyphMinLeading; break; + case UPH_HYPH_MIN_TRAILING : pnVal = &rOpt.nHyphMinTrailing; break; + case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &rOpt.nHyphMinWordLength; break; + case UPH_ACTIVE_DICTIONARIES : + { + aRes <<= rOpt.aActiveDics; + break; + } + case UPH_ACTIVE_CONVERSION_DICTIONARIES : + { + aRes <<= rOpt.aActiveConvDics; + break; + } + case UPH_DEFAULT_LOCALE : + { + aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage, false); + break; + } + case UPH_DEFAULT_LOCALE_CJK : + { + aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CJK, false); + break; + } + case UPH_DEFAULT_LOCALE_CTL : + { + aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CTL, false); + break; + } + case UPH_IS_IGNORE_POST_POSITIONAL_WORD : pbVal = &rOpt.bIsIgnorePostPositionalWord; break; + case UPH_IS_AUTO_CLOSE_DIALOG : pbVal = &rOpt.bIsAutoCloseDialog; break; + case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break; + case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break; + + case UPH_IS_DIRECTION_TO_SIMPLIFIED: pbVal = &rOpt.bIsDirectionToSimplified; break; + case UPH_IS_USE_CHARACTER_VARIANTS : pbVal = &rOpt.bIsUseCharacterVariants; break; + case UPH_IS_TRANSLATE_COMMON_TERMS : pbVal = &rOpt.bIsTranslateCommonTerms; break; + case UPH_IS_REVERSE_MAPPING : pbVal = &rOpt.bIsReverseMapping; break; + + case UPH_DATA_FILES_CHANGED_CHECK_VALUE : pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break; + case UPH_IS_GRAMMAR_AUTO: pbVal = &rOpt.bIsGrammarAuto; break; + case UPH_IS_GRAMMAR_INTERACTIVE: pbVal = &rOpt.bIsGrammarInteractive; break; + default : + SAL_WARN( "unotools.config", "unexpected property handle" ); + } + + if (pbVal) + aRes <<= *pbVal; + else if (pnVal) + aRes <<= *pnVal; + else if (plVal) + aRes <<= static_cast<sal_Int16>(static_cast<sal_uInt16>(*plVal)); + else if (pnInt32Val) + aRes <<= *pnInt32Val; + + return aRes; +} + +bool SvtLinguConfigItem::SetProperty( std::u16string_view rPropertyName, const uno::Any &rValue ) +{ + bool bSucc = false; + sal_Int32 nHdl; + if (GetHdlByName( nHdl, rPropertyName )) + bSucc = SetProperty( nHdl, rValue ); + return bSucc; +} + +bool SvtLinguConfigItem::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue ) +{ + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + + bool bSucc = false; + if (!rValue.hasValue()) + return bSucc; + + bool bMod = false; + + sal_Int16 *pnVal = nullptr; + LanguageType *plVal = nullptr; + bool *pbVal = nullptr; + sal_Int32 *pnInt32Val = nullptr; + + SvtLinguOptions &rOpt = aOpt; + switch (nPropertyHandle) + { + case UPH_IS_USE_DICTIONARY_LIST : pbVal = &rOpt.bIsUseDictionaryList; break; + case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters; break; + case UPH_IS_HYPH_AUTO : pbVal = &rOpt.bIsHyphAuto; break; + case UPH_IS_HYPH_SPECIAL : pbVal = &rOpt.bIsHyphSpecial; break; + case UPH_IS_SPELL_AUTO : pbVal = &rOpt.bIsSpellAuto; break; + case UPH_IS_SPELL_SPECIAL : pbVal = &rOpt.bIsSpellSpecial; break; + case UPH_IS_WRAP_REVERSE : pbVal = &rOpt.bIsSpellReverse; break; + case UPH_DEFAULT_LANGUAGE : plVal = &rOpt.nDefaultLanguage; break; + case UPH_IS_SPELL_CAPITALIZATION : pbVal = &rOpt.bIsSpellCapitalization; break; + case UPH_IS_SPELL_WITH_DIGITS : pbVal = &rOpt.bIsSpellWithDigits; break; + case UPH_IS_SPELL_UPPER_CASE : pbVal = &rOpt.bIsSpellUpperCase; break; + case UPH_HYPH_MIN_LEADING : pnVal = &rOpt.nHyphMinLeading; break; + case UPH_HYPH_MIN_TRAILING : pnVal = &rOpt.nHyphMinTrailing; break; + case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &rOpt.nHyphMinWordLength; break; + case UPH_ACTIVE_DICTIONARIES : + { + rValue >>= rOpt.aActiveDics; + bMod = true; + break; + } + case UPH_ACTIVE_CONVERSION_DICTIONARIES : + { + rValue >>= rOpt.aActiveConvDics; + bMod = true; + break; + } + case UPH_DEFAULT_LOCALE : + { + bSucc = lcl_SetLocale( rOpt.nDefaultLanguage, rValue ); + bMod = bSucc; + break; + } + case UPH_DEFAULT_LOCALE_CJK : + { + bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CJK, rValue ); + bMod = bSucc; + break; + } + case UPH_DEFAULT_LOCALE_CTL : + { + bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CTL, rValue ); + bMod = bSucc; + break; + } + case UPH_IS_IGNORE_POST_POSITIONAL_WORD : pbVal = &rOpt.bIsIgnorePostPositionalWord; break; + case UPH_IS_AUTO_CLOSE_DIALOG : pbVal = &rOpt.bIsAutoCloseDialog; break; + case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break; + case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break; + + case UPH_IS_DIRECTION_TO_SIMPLIFIED : pbVal = &rOpt.bIsDirectionToSimplified; break; + case UPH_IS_USE_CHARACTER_VARIANTS : pbVal = &rOpt.bIsUseCharacterVariants; break; + case UPH_IS_TRANSLATE_COMMON_TERMS : pbVal = &rOpt.bIsTranslateCommonTerms; break; + case UPH_IS_REVERSE_MAPPING : pbVal = &rOpt.bIsReverseMapping; break; + + case UPH_DATA_FILES_CHANGED_CHECK_VALUE : pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break; + case UPH_IS_GRAMMAR_AUTO: pbVal = &rOpt.bIsGrammarAuto; break; + case UPH_IS_GRAMMAR_INTERACTIVE: pbVal = &rOpt.bIsGrammarInteractive; break; + default : + SAL_WARN( "unotools.config", "unexpected property handle" ); + } + + if (pbVal) + { + bool bNew = bool(); + if (rValue >>= bNew) + { + if (bNew != *pbVal) + { + *pbVal = bNew; + bMod = true; + } + bSucc = true; + } + } + else if (pnVal) + { + sal_Int16 nNew = sal_Int16(); + if (rValue >>= nNew) + { + if (nNew != *pnVal) + { + *pnVal = nNew; + bMod = true; + } + bSucc = true; + } + } + else if (plVal) + { + sal_Int16 nNew = sal_Int16(); + if (rValue >>= nNew) + { + if (nNew != static_cast<sal_uInt16>(*plVal)) + { + *plVal = LanguageType(static_cast<sal_uInt16>(nNew)); + bMod = true; + } + bSucc = true; + } + } + else if (pnInt32Val) + { + sal_Int32 nNew = sal_Int32(); + if (rValue >>= nNew) + { + if (nNew != *pnInt32Val) + { + *pnInt32Val = nNew; + bMod = true; + } + bSucc = true; + } + } + + if (bMod) + SetModified(); + + NotifyListeners(ConfigurationHints::NONE); + return bSucc; +} + +void SvtLinguConfigItem::GetOptions(SvtLinguOptions &rOptions) const +{ + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + rOptions = aOpt; +} + +void SvtLinguConfigItem::LoadOptions( const uno::Sequence< OUString > &rProperyNames ) +{ + bool bRes = false; + + const OUString *pProperyNames = rProperyNames.getConstArray(); + sal_Int32 nProps = rProperyNames.getLength(); + + const uno::Sequence< uno::Any > aValues = GetProperties( rProperyNames ); + const uno::Sequence< sal_Bool > aROStates = GetReadOnlyStates( rProperyNames ); + + if (nProps && aValues.getLength() == nProps && aROStates.getLength() == nProps) + { + SvtLinguOptions &rOpt = aOpt; + + const uno::Any *pValue = aValues.getConstArray(); + const sal_Bool *pROStates = aROStates.getConstArray(); + for (sal_Int32 i = 0; i < nProps; ++i) + { + const uno::Any &rVal = pValue[i]; + sal_Int32 nPropertyHandle(0); + GetHdlByName( nPropertyHandle, pProperyNames[i], true ); + switch ( nPropertyHandle ) + { + case UPH_DEFAULT_LOCALE : + { rOpt.bRODefaultLanguage = pROStates[i]; rOpt.nDefaultLanguage = lcl_CfgAnyToLanguage( rVal ); } break; + case UPH_ACTIVE_DICTIONARIES : + { rOpt.bROActiveDics = pROStates[i]; rVal >>= rOpt.aActiveDics; } break; + case UPH_IS_USE_DICTIONARY_LIST : + { rOpt.bROIsUseDictionaryList = pROStates[i]; rVal >>= rOpt.bIsUseDictionaryList; } break; + case UPH_IS_IGNORE_CONTROL_CHARACTERS : + { rOpt.bROIsIgnoreControlCharacters = pROStates[i]; rVal >>= rOpt.bIsIgnoreControlCharacters; } break; + case UPH_DEFAULT_LOCALE_CJK : + { rOpt.bRODefaultLanguage_CJK = pROStates[i]; rOpt.nDefaultLanguage_CJK = lcl_CfgAnyToLanguage( rVal ); } break; + case UPH_DEFAULT_LOCALE_CTL : + { rOpt.bRODefaultLanguage_CTL = pROStates[i]; rOpt.nDefaultLanguage_CTL = lcl_CfgAnyToLanguage( rVal ); } break; + + case UPH_IS_SPELL_UPPER_CASE : + { rOpt.bROIsSpellUpperCase = pROStates[i]; rVal >>= rOpt.bIsSpellUpperCase; } break; + case UPH_IS_SPELL_WITH_DIGITS : + { rOpt.bROIsSpellWithDigits = pROStates[i]; rVal >>= rOpt.bIsSpellWithDigits; } break; + case UPH_IS_SPELL_CAPITALIZATION : + { rOpt.bROIsSpellCapitalization = pROStates[i]; rVal >>= rOpt.bIsSpellCapitalization; } break; + case UPH_IS_SPELL_AUTO : + { rOpt.bROIsSpellAuto = pROStates[i]; rVal >>= rOpt.bIsSpellAuto; } break; + case UPH_IS_SPELL_SPECIAL : + { rOpt.bROIsSpellSpecial = pROStates[i]; rVal >>= rOpt.bIsSpellSpecial; } break; + case UPH_IS_WRAP_REVERSE : + { rOpt.bROIsSpellReverse = pROStates[i]; rVal >>= rOpt.bIsSpellReverse; } break; + + case UPH_HYPH_MIN_LEADING : + { rOpt.bROHyphMinLeading = pROStates[i]; rVal >>= rOpt.nHyphMinLeading; } break; + case UPH_HYPH_MIN_TRAILING : + { rOpt.bROHyphMinTrailing = pROStates[i]; rVal >>= rOpt.nHyphMinTrailing; } break; + case UPH_HYPH_MIN_WORD_LENGTH : + { rOpt.bROHyphMinWordLength = pROStates[i]; rVal >>= rOpt.nHyphMinWordLength; } break; + case UPH_IS_HYPH_SPECIAL : + { rOpt.bROIsHyphSpecial = pROStates[i]; rVal >>= rOpt.bIsHyphSpecial; } break; + case UPH_IS_HYPH_AUTO : + { rOpt.bROIsHyphAuto = pROStates[i]; rVal >>= rOpt.bIsHyphAuto; } break; + + case UPH_ACTIVE_CONVERSION_DICTIONARIES : { rOpt.bROActiveConvDics = pROStates[i]; rVal >>= rOpt.aActiveConvDics; } break; + + case UPH_IS_IGNORE_POST_POSITIONAL_WORD : + { rOpt.bROIsIgnorePostPositionalWord = pROStates[i]; rVal >>= rOpt.bIsIgnorePostPositionalWord; } break; + case UPH_IS_AUTO_CLOSE_DIALOG : + { rOpt.bROIsAutoCloseDialog = pROStates[i]; rVal >>= rOpt.bIsAutoCloseDialog; } break; + case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : + { rOpt.bROIsShowEntriesRecentlyUsedFirst = pROStates[i]; rVal >>= rOpt.bIsShowEntriesRecentlyUsedFirst; } break; + case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : + { rOpt.bROIsAutoReplaceUniqueEntries = pROStates[i]; rVal >>= rOpt.bIsAutoReplaceUniqueEntries; } break; + + case UPH_IS_DIRECTION_TO_SIMPLIFIED : + { + rOpt.bROIsDirectionToSimplified = pROStates[i]; + if( ! (rVal >>= rOpt.bIsDirectionToSimplified) ) + { + //default is locale dependent: + if (MsLangId::isTraditionalChinese(rOpt.nDefaultLanguage_CJK)) + { + rOpt.bIsDirectionToSimplified = false; + } + else + { + rOpt.bIsDirectionToSimplified = true; + } + } + } break; + case UPH_IS_USE_CHARACTER_VARIANTS : + { rOpt.bROIsUseCharacterVariants = pROStates[i]; rVal >>= rOpt.bIsUseCharacterVariants; } break; + case UPH_IS_TRANSLATE_COMMON_TERMS : + { rOpt.bROIsTranslateCommonTerms = pROStates[i]; rVal >>= rOpt.bIsTranslateCommonTerms; } break; + case UPH_IS_REVERSE_MAPPING : + { rOpt.bROIsReverseMapping = pROStates[i]; rVal >>= rOpt.bIsReverseMapping; } break; + + case UPH_DATA_FILES_CHANGED_CHECK_VALUE : + { rOpt.bRODataFilesChangedCheckValue = pROStates[i]; rVal >>= rOpt.nDataFilesChangedCheckValue; } break; + + case UPH_IS_GRAMMAR_AUTO: + { rOpt.bROIsGrammarAuto = pROStates[i]; rVal >>= rOpt.bIsGrammarAuto; } + break; + case UPH_IS_GRAMMAR_INTERACTIVE: + { rOpt.bROIsGrammarInteractive = pROStates[i]; rVal >>= rOpt.bIsGrammarInteractive; } + break; + + default: + SAL_WARN( "unotools.config", "unexpected case" ); + } + } + + bRes = true; + } + DBG_ASSERT( bRes, "LoadOptions failed" ); +} + +bool SvtLinguConfigItem::SaveOptions( const uno::Sequence< OUString > &rProperyNames ) +{ + if (!IsModified()) + return true; + + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + + bool bRet = false; + + sal_Int32 nProps = rProperyNames.getLength(); + uno::Sequence< uno::Any > aValues( nProps ); + uno::Any *pValue = aValues.getArray(); + + if (nProps && aValues.getLength() == nProps) + { + const SvtLinguOptions &rOpt = aOpt; + + OUString aTmp( lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage ) ); + *pValue++ <<= aTmp; // 0 + *pValue++ <<= rOpt.aActiveDics; // 1 + *pValue++ <<= rOpt.bIsUseDictionaryList; // 2 + *pValue++ <<= rOpt.bIsIgnoreControlCharacters; // 3 + aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CJK ); + *pValue++ <<= aTmp; // 5 + aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CTL ); + *pValue++ <<= aTmp; // 6 + + *pValue++ <<= rOpt.bIsSpellUpperCase; // 7 + *pValue++ <<= rOpt.bIsSpellWithDigits; // 8 + *pValue++ <<= rOpt.bIsSpellCapitalization; // 9 + *pValue++ <<= rOpt.bIsSpellAuto; // 10 + *pValue++ <<= rOpt.bIsSpellSpecial; // 11 + *pValue++ <<= rOpt.bIsSpellReverse; // 14 + + *pValue++ <<= rOpt.nHyphMinLeading; // 15 + *pValue++ <<= rOpt.nHyphMinTrailing; // 16 + *pValue++ <<= rOpt.nHyphMinWordLength; // 17 + *pValue++ <<= rOpt.bIsHyphSpecial; // 18 + *pValue++ <<= rOpt.bIsHyphAuto; // 19 + + *pValue++ <<= rOpt.aActiveConvDics; // 20 + + *pValue++ <<= rOpt.bIsIgnorePostPositionalWord; // 21 + *pValue++ <<= rOpt.bIsAutoCloseDialog; // 22 + *pValue++ <<= rOpt.bIsShowEntriesRecentlyUsedFirst; // 23 + *pValue++ <<= rOpt.bIsAutoReplaceUniqueEntries; // 24 + + *pValue++ <<= rOpt.bIsDirectionToSimplified; // 25 + *pValue++ <<= rOpt.bIsUseCharacterVariants; // 26 + *pValue++ <<= rOpt.bIsTranslateCommonTerms; // 27 + *pValue++ <<= rOpt.bIsReverseMapping; // 28 + + *pValue++ <<= rOpt.nDataFilesChangedCheckValue; // 29 + *pValue++ <<= rOpt.bIsGrammarAuto; // 30 + *pValue++ <<= rOpt.bIsGrammarInteractive; // 31 + + bRet |= PutProperties( rProperyNames, aValues ); + } + + if (bRet) + ClearModified(); + + return bRet; +} + +bool SvtLinguConfigItem::IsReadOnly( std::u16string_view rPropertyName ) const +{ + bool bReadOnly = false; + sal_Int32 nHdl; + if (GetHdlByName( nHdl, rPropertyName )) + bReadOnly = IsReadOnly( nHdl ); + return bReadOnly; +} + +bool SvtLinguConfigItem::IsReadOnly( sal_Int32 nPropertyHandle ) const +{ + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + + bool bReadOnly = false; + + const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt; + switch(nPropertyHandle) + { + case UPH_IS_USE_DICTIONARY_LIST : bReadOnly = rOpt.bROIsUseDictionaryList; break; + case UPH_IS_IGNORE_CONTROL_CHARACTERS : bReadOnly = rOpt.bROIsIgnoreControlCharacters; break; + case UPH_IS_HYPH_AUTO : bReadOnly = rOpt.bROIsHyphAuto; break; + case UPH_IS_HYPH_SPECIAL : bReadOnly = rOpt.bROIsHyphSpecial; break; + case UPH_IS_SPELL_AUTO : bReadOnly = rOpt.bROIsSpellAuto; break; + case UPH_IS_SPELL_SPECIAL : bReadOnly = rOpt.bROIsSpellSpecial; break; + case UPH_IS_WRAP_REVERSE : bReadOnly = rOpt.bROIsSpellReverse; break; + case UPH_DEFAULT_LANGUAGE : bReadOnly = rOpt.bRODefaultLanguage; break; + case UPH_IS_SPELL_CAPITALIZATION : bReadOnly = rOpt.bROIsSpellCapitalization; break; + case UPH_IS_SPELL_WITH_DIGITS : bReadOnly = rOpt.bROIsSpellWithDigits; break; + case UPH_IS_SPELL_UPPER_CASE : bReadOnly = rOpt.bROIsSpellUpperCase; break; + case UPH_HYPH_MIN_LEADING : bReadOnly = rOpt.bROHyphMinLeading; break; + case UPH_HYPH_MIN_TRAILING : bReadOnly = rOpt.bROHyphMinTrailing; break; + case UPH_HYPH_MIN_WORD_LENGTH : bReadOnly = rOpt.bROHyphMinWordLength; break; + case UPH_ACTIVE_DICTIONARIES : bReadOnly = rOpt.bROActiveDics; break; + case UPH_ACTIVE_CONVERSION_DICTIONARIES : bReadOnly = rOpt.bROActiveConvDics; break; + case UPH_DEFAULT_LOCALE : bReadOnly = rOpt.bRODefaultLanguage; break; + case UPH_DEFAULT_LOCALE_CJK : bReadOnly = rOpt.bRODefaultLanguage_CJK; break; + case UPH_DEFAULT_LOCALE_CTL : bReadOnly = rOpt.bRODefaultLanguage_CTL; break; + case UPH_IS_IGNORE_POST_POSITIONAL_WORD : bReadOnly = rOpt.bROIsIgnorePostPositionalWord; break; + case UPH_IS_AUTO_CLOSE_DIALOG : bReadOnly = rOpt.bROIsAutoCloseDialog; break; + case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : bReadOnly = rOpt.bROIsShowEntriesRecentlyUsedFirst; break; + case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : bReadOnly = rOpt.bROIsAutoReplaceUniqueEntries; break; + case UPH_IS_DIRECTION_TO_SIMPLIFIED : bReadOnly = rOpt.bROIsDirectionToSimplified; break; + case UPH_IS_USE_CHARACTER_VARIANTS : bReadOnly = rOpt.bROIsUseCharacterVariants; break; + case UPH_IS_TRANSLATE_COMMON_TERMS : bReadOnly = rOpt.bROIsTranslateCommonTerms; break; + case UPH_IS_REVERSE_MAPPING : bReadOnly = rOpt.bROIsReverseMapping; break; + case UPH_DATA_FILES_CHANGED_CHECK_VALUE : bReadOnly = rOpt.bRODataFilesChangedCheckValue; break; + case UPH_IS_GRAMMAR_AUTO: bReadOnly = rOpt.bROIsGrammarAuto; break; + case UPH_IS_GRAMMAR_INTERACTIVE: bReadOnly = rOpt.bROIsGrammarInteractive; break; + default : + SAL_WARN( "unotools.config", "unexpected property handle" ); + } + return bReadOnly; +} + +static SvtLinguConfigItem *pCfgItem = nullptr; +static sal_Int32 nCfgItemRefCount = 0; + +constexpr OUStringLiteral aG_Dictionaries = u"Dictionaries"; + +SvtLinguConfig::SvtLinguConfig() +{ + // Global access, must be guarded (multithreading) + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + ++nCfgItemRefCount; +} + +SvtLinguConfig::~SvtLinguConfig() +{ + if (pCfgItem && pCfgItem->IsModified()) + pCfgItem->Commit(); + + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + + if (--nCfgItemRefCount <= 0) + { + delete pCfgItem; + pCfgItem = nullptr; + } +} + +SvtLinguConfigItem & SvtLinguConfig::GetConfigItem() +{ + // Global access, must be guarded (multithreading) + std::unique_lock aGuard(theSvtLinguConfigItemMutex()); + if (!pCfgItem) + { + pCfgItem = new SvtLinguConfigItem; + aGuard.unlock(); + ItemHolder1::holdConfigItem(EItem::LinguConfig); + } + return *pCfgItem; +} + +uno::Sequence< OUString > SvtLinguConfig::GetNodeNames( const OUString &rNode ) const +{ + return GetConfigItem().GetNodeNames( rNode ); +} + +uno::Sequence< uno::Any > SvtLinguConfig::GetProperties( const uno::Sequence< OUString > &rNames ) const +{ + return GetConfigItem().GetProperties(rNames); +} + +bool SvtLinguConfig::ReplaceSetProperties( + const OUString &rNode, const uno::Sequence< beans::PropertyValue >& rValues ) +{ + return GetConfigItem().ReplaceSetProperties( rNode, rValues ); +} + +uno::Any SvtLinguConfig::GetProperty( std::u16string_view rPropertyName ) const +{ + return GetConfigItem().GetProperty( rPropertyName ); +} + +uno::Any SvtLinguConfig::GetProperty( sal_Int32 nPropertyHandle ) const +{ + return GetConfigItem().GetProperty( nPropertyHandle ); +} + +bool SvtLinguConfig::SetProperty( std::u16string_view rPropertyName, const uno::Any &rValue ) +{ + return GetConfigItem().SetProperty( rPropertyName, rValue ); +} + +bool SvtLinguConfig::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue ) +{ + return GetConfigItem().SetProperty( nPropertyHandle, rValue ); +} + +void SvtLinguConfig::GetOptions( SvtLinguOptions &rOptions ) const +{ + GetConfigItem().GetOptions(rOptions); +} + +bool SvtLinguConfig::IsReadOnly( std::u16string_view rPropertyName ) const +{ + return GetConfigItem().IsReadOnly( rPropertyName ); +} + +bool SvtLinguConfig::GetElementNamesFor( + const OUString &rNodeName, + uno::Sequence< OUString > &rElementNames ) const +{ + bool bSuccess = false; + try + { + uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW ); + rElementNames = xNA->getElementNames(); + bSuccess = true; + } + catch (uno::Exception &) + { + } + return bSuccess; +} + +bool SvtLinguConfig::GetSupportedDictionaryFormatsFor( + const OUString &rSetName, + const OUString &rSetEntry, + uno::Sequence< OUString > &rFormatList ) const +{ + if (rSetName.isEmpty() || rSetEntry.isEmpty()) + return false; + bool bSuccess = false; + try + { + uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName( rSetName ), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName( rSetEntry ), uno::UNO_QUERY_THROW ); + if (xNA->getByName( "SupportedDictionaryFormats" ) >>= rFormatList) + bSuccess = true; + DBG_ASSERT( rFormatList.hasElements(), "supported dictionary format list is empty" ); + } + catch (uno::Exception &) + { + } + return bSuccess; +} + +static bool lcl_GetFileUrlFromOrigin( + OUString /*out*/ &rFileUrl, + const OUString &rOrigin ) +{ + OUString aURL( + comphelper::getExpandedUri( + comphelper::getProcessComponentContext(), rOrigin)); + if (aURL.startsWith( FILE_PROTOCOL )) + { + rFileUrl = aURL; + return true; + } + else + { + SAL_WARN( + "unotools.config", "not a file URL, <" << aURL << ">" ); + return false; + } +} + +bool SvtLinguConfig::GetDictionaryEntry( + const OUString &rNodeName, + SvtLinguConfigDictionaryEntry &rDicEntry ) const +{ + if (rNodeName.isEmpty()) + return false; + bool bSuccess = false; + try + { + uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName( aG_Dictionaries ), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW ); + + // read group data... + uno::Sequence< OUString > aLocations; + OUString aFormatName; + uno::Sequence< OUString > aLocaleNames; + bSuccess = (xNA->getByName( "Locations" ) >>= aLocations) && + (xNA->getByName( "Format" ) >>= aFormatName) && + (xNA->getByName( "Locales" ) >>= aLocaleNames); + DBG_ASSERT( aLocations.hasElements(), "Dictionary locations not set" ); + DBG_ASSERT( !aFormatName.isEmpty(), "Dictionary format name not set" ); + DBG_ASSERT( aLocaleNames.hasElements(), "No locales set for the dictionary" ); + + // if successful continue + if (bSuccess) + { + // get file URL's for the locations + for (OUString& rLocation : asNonConstRange(aLocations)) + { + if (!lcl_GetFileUrlFromOrigin( rLocation, rLocation )) + bSuccess = false; + } + + // if everything was fine return the result + if (bSuccess) + { + rDicEntry.aLocations = aLocations; + rDicEntry.aFormatName = aFormatName; + rDicEntry.aLocaleNames = aLocaleNames; + } + } + } + catch (uno::Exception &) + { + } + return bSuccess; +} + +uno::Sequence< OUString > SvtLinguConfig::GetDisabledDictionaries() const +{ + uno::Sequence< OUString > aResult; + try + { + uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW ); + xNA->getByName( "DisabledDictionaries" ) >>= aResult; + } + catch (uno::Exception &) + { + } + return aResult; +} + +std::vector< SvtLinguConfigDictionaryEntry > SvtLinguConfig::GetActiveDictionariesByFormat( + std::u16string_view rFormatName ) const +{ + std::vector< SvtLinguConfigDictionaryEntry > aRes; + if (rFormatName.empty()) + return aRes; + + try + { + uno::Sequence< OUString > aElementNames; + GetElementNamesFor( aG_Dictionaries, aElementNames ); + + const uno::Sequence< OUString > aDisabledDics( GetDisabledDictionaries() ); + + SvtLinguConfigDictionaryEntry aDicEntry; + for (const OUString& rElementName : std::as_const(aElementNames)) + { + // does dictionary match the format we are looking for? + if (GetDictionaryEntry( rElementName, aDicEntry ) && + aDicEntry.aFormatName == rFormatName) + { + // check if it is active or not + bool bDicIsActive = std::none_of(aDisabledDics.begin(), aDisabledDics.end(), + [&rElementName](const OUString& rDic) { return rDic == rElementName; }); + + if (bDicIsActive) + { + DBG_ASSERT( !aDicEntry.aFormatName.isEmpty(), + "FormatName not set" ); + DBG_ASSERT( aDicEntry.aLocations.hasElements(), + "Locations not set" ); + DBG_ASSERT( aDicEntry.aLocaleNames.hasElements(), + "Locales not set" ); + aRes.push_back( aDicEntry ); + } + } + } + } + catch (uno::Exception &) + { + } + + return aRes; +} + +uno::Reference< util::XChangesBatch > const & SvtLinguConfig::GetMainUpdateAccess() const +{ + if (!m_xMainUpdateAccess.is()) + { + try + { + // get configuration provider + uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext(); + uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider = + configuration::theDefaultProvider::get( xContext ); + + // get configuration update access + beans::PropertyValue aValue; + aValue.Name = "nodepath"; + aValue.Value <<= OUString("org.openoffice.Office.Linguistic"); + uno::Sequence< uno::Any > aProps{ uno::Any(aValue) }; + m_xMainUpdateAccess.set( + xConfigurationProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", aProps), + uno::UNO_QUERY_THROW ); + } + catch (uno::Exception &) + { + } + } + + return m_xMainUpdateAccess; +} + +OUString SvtLinguConfig::GetVendorImageUrl_Impl( + const OUString &rServiceImplName, + const OUString &rImageName ) const +{ + OUString aRes; + try + { + uno::Reference< container::XNameAccess > xImagesNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW ); + xImagesNA.set( xImagesNA->getByName("Images"), uno::UNO_QUERY_THROW ); + + uno::Reference< container::XNameAccess > xNA( xImagesNA->getByName("ServiceNameEntries"), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName( rServiceImplName ), uno::UNO_QUERY_THROW ); + uno::Any aAny(xNA->getByName("VendorImagesNode")); + OUString aVendorImagesNode; + if (aAny >>= aVendorImagesNode) + { + xNA = xImagesNA; + xNA.set( xNA->getByName("VendorImages"), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName( aVendorImagesNode ), uno::UNO_QUERY_THROW ); + aAny = xNA->getByName( rImageName ); + OUString aTmp; + if (aAny >>= aTmp) + { + if (lcl_GetFileUrlFromOrigin( aTmp, aTmp )) + aRes = aTmp; + } + } + } + catch (uno::Exception &) + { + DBG_UNHANDLED_EXCEPTION("unotools"); + } + return aRes; +} + +OUString SvtLinguConfig::GetSpellAndGrammarContextSuggestionImage( + const OUString &rServiceImplName +) const +{ + OUString aRes; + if (!rServiceImplName.isEmpty()) + { + aRes = GetVendorImageUrl_Impl( rServiceImplName, "SpellAndGrammarContextMenuSuggestionImage" ); + } + return aRes; +} + +OUString SvtLinguConfig::GetSpellAndGrammarContextDictionaryImage( + const OUString &rServiceImplName +) const +{ + OUString aRes; + if (!rServiceImplName.isEmpty()) + { + aRes = GetVendorImageUrl_Impl( rServiceImplName, "SpellAndGrammarContextMenuDictionaryImage" ); + } + return aRes; +} + +OUString SvtLinguConfig::GetSynonymsContextImage( + const OUString &rServiceImplName +) const +{ + OUString aRes; + if (!rServiceImplName.isEmpty()) + { + OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, "SynonymsContextMenuImage" ) ); + aRes = aPath; + } + return aRes; +} + +bool SvtLinguConfig::HasGrammarChecker() const +{ + bool bRes = false; + + try + { + uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW ); + xNA.set( xNA->getByName("GrammarCheckerList"), uno::UNO_QUERY_THROW ); + + uno::Sequence< OUString > aElementNames( xNA->getElementNames() ); + bRes = aElementNames.hasElements(); + } + catch (const uno::Exception&) + { + } + + return bRes; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |