Coverage Report

Created: 2025-11-16 09:57

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