Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name optlingu.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D CUI_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/qrcodegen/cpp/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/curl/include -I /home/maarten/src/libreoffice/core/external/clew/source/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/cui/inc -I /home/maarten/src/libreoffice/core/cui/source/inc -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx

/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx

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 <vcl/settings.hxx>
21#include <vcl/weld.hxx>
22#include <i18nlangtag/languagetag.hxx>
23#include <i18nlangtag/mslangid.hxx>
24#include <officecfg/Office/Security.hxx>
25#include <unotools/lingucfg.hxx>
26#include <unotools/linguprops.hxx>
27#include <editeng/unolingu.hxx>
28#include <linguistic/misc.hxx>
29#include <sfx2/sfxsids.hrc>
30#include <tools/debug.hxx>
31#include <tools/urlobj.hxx>
32#include <tools/diagnose_ex.h>
33#include <comphelper/processfactory.hxx>
34#include <com/sun/star/linguistic2/LinguServiceManager.hpp>
35#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
36#include <com/sun/star/linguistic2/XSpellChecker.hpp>
37#include <com/sun/star/linguistic2/XProofreader.hpp>
38#include <com/sun/star/linguistic2/XHyphenator.hpp>
39#include <com/sun/star/linguistic2/XThesaurus.hpp>
40#include <com/sun/star/linguistic2/XDictionary.hpp>
41#include <com/sun/star/linguistic2/XDictionaryList.hpp>
42#include <com/sun/star/linguistic2/XLinguProperties.hpp>
43#include <com/sun/star/lang/XServiceDisplayName.hpp>
44#include <com/sun/star/frame/XStorable.hpp>
45#include <unotools/extendedsecurityoptions.hxx>
46#include <svl/eitem.hxx>
47#include <vcl/svapp.hxx>
48#include <sal/log.hxx>
49#include <osl/diagnose.h>
50
51#include <svx/svxdlg.hxx>
52#include <editeng/optitems.hxx>
53#include <optlingu.hxx>
54#include <dialmgr.hxx>
55#include <strings.hrc>
56
57#include <ucbhelper/content.hxx>
58
59#include <vector>
60#include <map>
61
62using namespace ::ucbhelper;
63using namespace ::com::sun::star;
64using namespace css::lang;
65using namespace css::uno;
66using namespace css::linguistic2;
67using namespace css::beans;
68
69const char cSpell[] = SN_SPELLCHECKER"com.sun.star.linguistic2.SpellChecker";
70const char cGrammar[] = SN_GRAMMARCHECKER"com.sun.star.linguistic2.Proofreader";
71const char cHyph[] = SN_HYPHENATOR"com.sun.star.linguistic2.Hyphenator";
72const char cThes[] = SN_THESAURUS"com.sun.star.linguistic2.Thesaurus";
73
74// static ----------------------------------------------------------------
75
76static sal_Int32 lcl_SeqGetEntryPos(
77 const Sequence< OUString > &rSeq, const OUString &rEntry )
78{
79 sal_Int32 i;
80 sal_Int32 nLen = rSeq.getLength();
81 const OUString *pItem = rSeq.getConstArray();
82 for (i = 0; i < nLen; ++i)
83 {
84 if (rEntry == pItem[i])
85 break;
86 }
87 return i < nLen ? i : -1;
88}
89
90static bool KillFile_Impl( const OUString& rURL )
91{
92 bool bRet = true;
93 try
94 {
95 Content aCnt( rURL, uno::Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
96 aCnt.executeCommand( "delete", Any( true ) );
97 }
98 catch( ... )
99 {
100 TOOLS_WARN_EXCEPTION( "cui.options", "KillFile" )do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "cui.options")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "KillFile" << " "
<< exceptionToString(tools_warn_exception)) == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cui.options"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "100" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "KillFile" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "KillFile" << " " <<
exceptionToString(tools_warn_exception); ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "100" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "KillFile" << " " << exceptionToString
(tools_warn_exception)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "100" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "KillFile" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "KillFile" << " " <<
exceptionToString(tools_warn_exception); ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "100" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
101 bRet = false;
102 }
103
104 return bRet;
105}
106
107// 0x 0p 0t 0c nn
108// p: 1 -> parent
109// t: 1 -> spell, 2 -> hyph, 3 -> thes, 4 -> grammar
110// c: 1 -> checked 0 -> unchecked
111// n: index
112
113#define TYPE_SPELLsal_uInt8(1) sal_uInt8(1)
114#define TYPE_GRAMMARsal_uInt8(2) sal_uInt8(2)
115#define TYPE_HYPHsal_uInt8(3) sal_uInt8(3)
116#define TYPE_THESsal_uInt8(4) sal_uInt8(4)
117
118namespace {
119
120class ModuleUserData_Impl
121{
122 bool bParent;
123 bool bIsChecked;
124 sal_uInt8 nType;
125 sal_uInt8 nIndex;
126 OUString sImplName;
127
128public:
129 ModuleUserData_Impl( const OUString& sImpName, bool bIsParent, bool bChecked, sal_uInt8 nSetType, sal_uInt8 nSetIndex ) :
130 bParent(bIsParent),
131 bIsChecked(bChecked),
132 nType(nSetType),
133 nIndex(nSetIndex),
134 sImplName(sImpName)
135 {
136 }
137 bool IsParent() const {return bParent;}
138 sal_uInt8 GetType() const {return nType;}
139 bool IsChecked() const {return bIsChecked;}
140 sal_uInt8 GetIndex() const {return nIndex;}
141 const OUString& GetImplName() const {return sImplName;}
142
143};
144
145
146// User for user-dictionaries (XDictionary interface)
147
148class DicUserData
149{
150 sal_uInt32 nVal;
151
152public:
153 explicit DicUserData(sal_uInt32 nUserData) : nVal( nUserData ) {}
154 DicUserData( sal_uInt16 nEID,
155 bool bChecked, bool bEditable, bool bDeletable );
156
157 sal_uInt32 GetUserData() const { return nVal; }
158 sal_uInt16 GetEntryId() const { return static_cast<sal_uInt16>(nVal >> 16); }
159 bool IsChecked() const { return static_cast<bool>((nVal >> 8) & 0x01); }
160 bool IsDeletable() const { return static_cast<bool>((nVal >> 10) & 0x01); }
161};
162
163}
164
165DicUserData::DicUserData(
166 sal_uInt16 nEID,
167 bool bChecked, bool bEditable, bool bDeletable )
168{
169 DBG_ASSERT( nEID < 65000, "Entry Id out of range" )do { if (true && (!(nEID < 65000))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "169" ": "), "%s", "Entry Id out of range"); } } while (
false)
;
170 nVal = (static_cast<sal_uInt32>(0xFFFF & nEID) << 16) |
171 (static_cast<sal_uInt32>(bChecked ? 1 : 0) << 8) |
172 (static_cast<sal_uInt32>(bEditable ? 1 : 0) << 9) |
173 (static_cast<sal_uInt32>(bDeletable ? 1 : 0) << 10);
174}
175
176/*--------------------------------------------------
177 Entry IDs for options listbox of dialog
178--------------------------------------------------*/
179
180namespace {
181
182enum EID_OPTIONS
183{
184 EID_SPELL_AUTO,
185 EID_GRAMMAR_AUTO,
186 EID_CAPITAL_WORDS,
187 EID_WORDS_WITH_DIGITS,
188 EID_SPELL_SPECIAL,
189 EID_NUM_MIN_WORDLEN,
190 EID_NUM_PRE_BREAK,
191 EID_NUM_POST_BREAK,
192 EID_HYPH_AUTO,
193 EID_HYPH_SPECIAL
194};
195
196}
197
198//! this array must have an entry for every value of EID_OPTIONS.
199// It is used to get the respective property name.
200static const char * aEidToPropName[] =
201{
202 UPN_IS_SPELL_AUTO"IsSpellAuto", // EID_SPELL_AUTO
203 UPN_IS_GRAMMAR_AUTO"IsAutoGrammarCheck", // EID_GRAMMAR_AUTO
204 UPN_IS_SPELL_UPPER_CASE"IsSpellUpperCase", // EID_CAPITAL_WORDS
205 UPN_IS_SPELL_WITH_DIGITS"IsSpellWithDigits", // EID_WORDS_WITH_DIGITS
206 UPN_IS_SPELL_SPECIAL"IsSpellSpecial", // EID_SPELL_SPECIAL
207 UPN_HYPH_MIN_WORD_LENGTH"HyphMinWordLength", // EID_NUM_MIN_WORDLEN,
208 UPN_HYPH_MIN_LEADING"HyphMinLeading", // EID_NUM_PRE_BREAK
209 UPN_HYPH_MIN_TRAILING"HyphMinTrailing", // EID_NUM_POST_BREAK
210 UPN_IS_HYPH_AUTO"IsHyphAuto", // EID_HYPH_AUTO
211 UPN_IS_HYPH_SPECIAL"IsHyphSpecial" // EID_HYPH_SPECIAL
212};
213
214static OUString lcl_GetPropertyName( EID_OPTIONS eEntryId )
215{
216 DBG_ASSERT( static_cast<unsigned int>(eEntryId) < SAL_N_ELEMENTS(aEidToPropName), "index out of range" )do { if (true && (!(static_cast<unsigned int>(eEntryId
) < (sizeof(sal_n_array_size(aEidToPropName)))))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "216" ": "), "%s", "index out of range"); } } while (false
)
;
217 return OUString::createFromAscii( aEidToPropName[ static_cast<int>(eEntryId) ] );
218}
219
220namespace {
221
222class OptionsBreakSet : public weld::GenericDialogController
223{
224 std::unique_ptr<weld::Widget> m_xBeforeFrame;
225 std::unique_ptr<weld::Widget> m_xAfterFrame;
226 std::unique_ptr<weld::Widget> m_xMinimalFrame;
227 std::unique_ptr<weld::SpinButton> m_xBreakNF;
228
229public:
230 OptionsBreakSet(weld::Window* pParent, sal_uInt16 nRID)
231 : GenericDialogController(pParent, "cui/ui/breaknumberoption.ui", "BreakNumberOption")
232 , m_xBeforeFrame(m_xBuilder->weld_widget("beforeframe"))
233 , m_xAfterFrame(m_xBuilder->weld_widget("afterframe"))
234 , m_xMinimalFrame(m_xBuilder->weld_widget("miniframe"))
235 {
236 assert(EID_NUM_PRE_BREAK == nRID || EID_NUM_POST_BREAK == nRID || EID_NUM_MIN_WORDLEN == nRID)(static_cast <bool> (EID_NUM_PRE_BREAK == nRID || EID_NUM_POST_BREAK
== nRID || EID_NUM_MIN_WORDLEN == nRID) ? void (0) : __assert_fail
("EID_NUM_PRE_BREAK == nRID || EID_NUM_POST_BREAK == nRID || EID_NUM_MIN_WORDLEN == nRID"
, "/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
, 236, __extension__ __PRETTY_FUNCTION__))
; //unexpected ID
237
238 if (nRID == EID_NUM_PRE_BREAK)
239 {
240 m_xBeforeFrame->show();
241 m_xBreakNF = m_xBuilder->weld_spin_button("beforebreak");
242 }
243 else if(nRID == EID_NUM_POST_BREAK)
244 {
245 m_xAfterFrame->show();
246 m_xBreakNF = m_xBuilder->weld_spin_button("afterbreak");
247 }
248 else if(nRID == EID_NUM_MIN_WORDLEN)
249 {
250 m_xMinimalFrame->show();
251 m_xBreakNF = m_xBuilder->weld_spin_button("wordlength");
252 }
253 }
254
255 weld::SpinButton& GetNumericFld()
256 {
257 return *m_xBreakNF;
258 }
259};
260
261// class OptionsUserData -------------------------------------------------
262
263class OptionsUserData
264{
265 sal_uInt32 nVal;
266
267public:
268 explicit OptionsUserData( sal_uInt32 nUserData ) : nVal( nUserData ) {}
269 OptionsUserData( sal_uInt16 nEID,
270 bool bHasNV, sal_uInt16 nNumVal,
271 bool bCheckable, bool bChecked );
272
273 sal_uInt32 GetUserData() const { return nVal; }
274 sal_uInt16 GetEntryId() const { return static_cast<sal_uInt16>(nVal >> 16); }
275 bool HasNumericValue() const { return static_cast<bool>((nVal >> 10) & 0x01); }
276 sal_uInt16 GetNumericValue() const { return static_cast<sal_uInt16>(nVal & 0xFF); }
277 bool IsCheckable() const { return static_cast<bool>((nVal >> 9) & 0x01); }
278 bool IsModified() const { return static_cast<bool>((nVal >> 11) & 0x01); }
279
280 void SetNumericValue( sal_uInt8 nNumVal );
281};
282
283}
284
285OptionsUserData::OptionsUserData( sal_uInt16 nEID,
286 bool bHasNV, sal_uInt16 nNumVal,
287 bool bCheckable, bool bChecked )
288{
289 DBG_ASSERT( nEID < 65000, "Entry Id out of range" )do { if (true && (!(nEID < 65000))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "289" ": "), "%s", "Entry Id out of range"); } } while (
false)
;
290 DBG_ASSERT( nNumVal < 256, "value out of range" )do { if (true && (!(nNumVal < 256))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "290" ": "), "%s", "value out of range"); } } while (false
)
;
291 nVal = (static_cast<sal_uInt32>(0xFFFF & nEID) << 16) |
292 (static_cast<sal_uInt32>(bHasNV ? 1 : 0) << 10) |
293 (static_cast<sal_uInt32>(bCheckable ? 1 : 0) << 9) |
294 (static_cast<sal_uInt32>(bChecked ? 1 : 0) << 8) |
295 static_cast<sal_uInt32>(0xFF & nNumVal);
296}
297
298void OptionsUserData::SetNumericValue( sal_uInt8 nNumVal )
299{
300 if (HasNumericValue() && (GetNumericValue() != nNumVal))
301 {
302 nVal &= 0xffffff00;
303 nVal |= nNumVal;
304 nVal |= sal_uInt32(1) << 11; // mark as modified
305 }
306}
307
308// ServiceInfo_Impl ----------------------------------------------------
309
310namespace {
311
312struct ServiceInfo_Impl
313{
314 OUString sDisplayName;
315 OUString sSpellImplName;
316 OUString sHyphImplName;
317 OUString sThesImplName;
318 OUString sGrammarImplName;
319 uno::Reference< XSpellChecker > xSpell;
320 uno::Reference< XHyphenator > xHyph;
321 uno::Reference< XThesaurus > xThes;
322 uno::Reference< XProofreader > xGrammar;
323 bool bConfigured;
324
325 ServiceInfo_Impl() : bConfigured(false) {}
326};
327
328}
329
330typedef std::vector< ServiceInfo_Impl > ServiceInfoArr;
331typedef std::map< LanguageType, Sequence< OUString > > LangImplNameTable;
332
333
334// SvxLinguData_Impl ----------------------------------------------------
335
336class SvxLinguData_Impl
337{
338 //contains services and implementation names sorted by implementation names
339 ServiceInfoArr aDisplayServiceArr;
340 sal_uInt32 nDisplayServices;
341
342 Sequence< Locale > aAllServiceLocales;
343 LangImplNameTable aCfgSpellTable;
344 LangImplNameTable aCfgHyphTable;
345 LangImplNameTable aCfgThesTable;
346 LangImplNameTable aCfgGrammarTable;
347 uno::Reference< XLinguServiceManager2 > xLinguSrvcMgr;
348
349
350 static bool AddRemove( Sequence< OUString > &rConfigured,
351 const OUString &rImplName, bool bAdd );
352
353public:
354 SvxLinguData_Impl();
355
356 uno::Reference<XLinguServiceManager2> & GetManager() { return xLinguSrvcMgr; }
357
358 void SetChecked( const Sequence< OUString > &rConfiguredServices );
359 void Reconfigure( const OUString &rDisplayName, bool bEnable );
360
361 const Sequence<Locale> & GetAllSupportedLocales() const { return aAllServiceLocales; }
362
363 LangImplNameTable & GetSpellTable() { return aCfgSpellTable; }
364 LangImplNameTable & GetHyphTable() { return aCfgHyphTable; }
365 LangImplNameTable & GetThesTable() { return aCfgThesTable; }
366 LangImplNameTable & GetGrammarTable() { return aCfgGrammarTable; }
367
368 ServiceInfoArr & GetDisplayServiceArray() { return aDisplayServiceArr; }
369
370 const sal_uInt32 & GetDisplayServiceCount() const { return nDisplayServices; }
371 void SetDisplayServiceCount( sal_uInt32 nVal ) { nDisplayServices = nVal; }
372
373 // returns the list of service implementation names for the specified
374 // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in
375 // the proper order for the SvxEditModulesDlg (the ones from the
376 // configuration (keeping that order!) first and then the other ones.
377 // I.e. the ones available but not configured in arbitrary order).
378 // They available ones may contain names that do not(!) support that
379 // language.
380 Sequence< OUString > GetSortedImplNames( LanguageType nLang, sal_uInt8 nType );
381
382 ServiceInfo_Impl * GetInfoByImplName( const OUString &rSvcImplName );
383};
384
385
386static sal_Int32 lcl_SeqGetIndex( const Sequence< OUString > &rSeq, const OUString &rTxt )
387{
388 sal_Int32 nRes = -1;
389 sal_Int32 nLen = rSeq.getLength();
390 const OUString *pString = rSeq.getConstArray();
391 for (sal_Int32 i = 0; i < nLen && nRes == -1; ++i)
392 {
393 if (pString[i] == rTxt)
394 nRes = i;
395 }
396 return nRes;
397}
398
399
400Sequence< OUString > SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang, sal_uInt8 nType )
401{
402 LangImplNameTable *pTable = nullptr;
403 switch (nType)
404 {
405 case TYPE_SPELLsal_uInt8(1) : pTable = &aCfgSpellTable; break;
406 case TYPE_HYPHsal_uInt8(3) : pTable = &aCfgHyphTable; break;
407 case TYPE_THESsal_uInt8(4) : pTable = &aCfgThesTable; break;
408 case TYPE_GRAMMARsal_uInt8(2) : pTable = &aCfgGrammarTable; break;
409 }
410 Sequence< OUString > aRes;
411 if (!pTable)
412 {
413 SAL_WARN( "cui.options", "unknown linguistic type" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "cui.options")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "unknown linguistic type"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cui.options"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "413" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "unknown linguistic type"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"unknown linguistic type"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "413" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "unknown linguistic type") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "413" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "unknown linguistic type"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"unknown linguistic type"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "413" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
414 return aRes;
415 }
416 if (pTable->count( nLang ))
417 aRes = (*pTable)[ nLang ]; // add configured services
418 sal_Int32 nIdx = aRes.getLength();
419 DBG_ASSERT( static_cast<sal_Int32>(nDisplayServices) >= nIdx, "size mismatch" )do { if (true && (!(static_cast<sal_Int32>(nDisplayServices
) >= nIdx))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "419" ": "), "%s", "size mismatch"); } } while (false)
;
420 aRes.realloc( nDisplayServices );
421 OUString *pRes = aRes.getArray();
422
423 // add not configured services
424 for (sal_Int32 i = 0; i < static_cast<sal_Int32>(nDisplayServices); ++i)
425 {
426 const ServiceInfo_Impl &rInfo = aDisplayServiceArr[ i ];
427 OUString aImplName;
428 switch (nType)
429 {
430 case TYPE_SPELLsal_uInt8(1) : aImplName = rInfo.sSpellImplName; break;
431 case TYPE_HYPHsal_uInt8(3) : aImplName = rInfo.sHyphImplName; break;
432 case TYPE_THESsal_uInt8(4) : aImplName = rInfo.sThesImplName; break;
433 case TYPE_GRAMMARsal_uInt8(2) : aImplName = rInfo.sGrammarImplName; break;
434 }
435
436 if (!aImplName.isEmpty() && (lcl_SeqGetIndex( aRes, aImplName) == -1)) // name not yet added
437 {
438 DBG_ASSERT( nIdx < aRes.getLength(), "index out of range" )do { if (true && (!(nIdx < aRes.getLength()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "438" ": "), "%s", "index out of range"); } } while (false
)
;
439 if (nIdx < aRes.getLength())
440 pRes[ nIdx++ ] = aImplName;
441 }
442 }
443 // don't forget to put aRes back to its actual size just in case you allocated too much
444 // since all of the names may have already been added
445 // otherwise you get duplicate entries in the edit dialog
446 aRes.realloc( nIdx );
447 return aRes;
448}
449
450
451ServiceInfo_Impl * SvxLinguData_Impl::GetInfoByImplName( const OUString &rSvcImplName )
452{
453 for (sal_uInt32 i = 0; i < nDisplayServices; ++i)
454 {
455 ServiceInfo_Impl &rTmp = aDisplayServiceArr[ i ];
456 if (rTmp.sSpellImplName == rSvcImplName ||
457 rTmp.sHyphImplName == rSvcImplName ||
458 rTmp.sThesImplName == rSvcImplName ||
459 rTmp.sGrammarImplName == rSvcImplName)
460 {
461 return &rTmp;
462 }
463 }
464 return nullptr;
465}
466
467
468static void lcl_MergeLocales(Sequence< Locale >& aAllLocales, const Sequence< Locale >& rAdd)
469{
470 Sequence<Locale> aLocToAdd(rAdd.getLength());
471 Locale* pLocToAdd = aLocToAdd.getArray();
472 sal_Int32 nFound = 0;
473 for(const Locale& i : rAdd)
474 {
475 bool bFound = false;
476 for(const Locale& j : std::as_const(aAllLocales))
477 {
478 if (i.Language == j.Language &&
479 i.Country == j.Country &&
480 i.Variant == j.Variant)
481 {
482 bFound = true;
483 break;
484 }
485 }
486 if(!bFound)
487 {
488 pLocToAdd[nFound++] = i;
489 }
490 }
491 sal_Int32 nLength = aAllLocales.getLength();
492 aAllLocales.realloc( nLength + nFound);
493 Locale* pAllLocales2 = aAllLocales.getArray();
494 for(sal_Int32 i = 0; i < nFound; i++)
495 pAllLocales2[nLength++] = pLocToAdd[i];
496}
497
498static void lcl_MergeDisplayArray(
499 SvxLinguData_Impl &rData,
500 const ServiceInfo_Impl &rToAdd )
501{
502 sal_uInt32 nCnt = 0;
503
504 ServiceInfoArr &rSvcInfoArr = rData.GetDisplayServiceArray();
505 sal_uInt32 nEntries = rData.GetDisplayServiceCount();
506
507 for (sal_uInt32 i = 0; i < nEntries; ++i)
508 {
509 ServiceInfo_Impl& rEntry = rSvcInfoArr[i];
510 if (rEntry.sDisplayName == rToAdd.sDisplayName)
511 {
512 if(rToAdd.xSpell.is())
513 {
514 DBG_ASSERT( !rEntry.xSpell.is() &&do { if (true && (!(!rEntry.xSpell.is() && rEntry
.sSpellImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "516" ": "), "%s", "merge conflict"); } } while (false)
515 rEntry.sSpellImplName.isEmpty(),do { if (true && (!(!rEntry.xSpell.is() && rEntry
.sSpellImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "516" ": "), "%s", "merge conflict"); } } while (false)
516 "merge conflict" )do { if (true && (!(!rEntry.xSpell.is() && rEntry
.sSpellImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "516" ": "), "%s", "merge conflict"); } } while (false)
;
517 rEntry.sSpellImplName = rToAdd.sSpellImplName;
518 rEntry.xSpell = rToAdd.xSpell;
519 }
520 if(rToAdd.xGrammar.is())
521 {
522 DBG_ASSERT( !rEntry.xGrammar.is() &&do { if (true && (!(!rEntry.xGrammar.is() && rEntry
.sGrammarImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "524" ": "), "%s", "merge conflict"); } } while (false)
523 rEntry.sGrammarImplName.isEmpty(),do { if (true && (!(!rEntry.xGrammar.is() && rEntry
.sGrammarImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "524" ": "), "%s", "merge conflict"); } } while (false)
524 "merge conflict" )do { if (true && (!(!rEntry.xGrammar.is() && rEntry
.sGrammarImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "524" ": "), "%s", "merge conflict"); } } while (false)
;
525 rEntry.sGrammarImplName = rToAdd.sGrammarImplName;
526 rEntry.xGrammar = rToAdd.xGrammar;
527 }
528 if(rToAdd.xHyph.is())
529 {
530 DBG_ASSERT( !rEntry.xHyph.is() &&do { if (true && (!(!rEntry.xHyph.is() && rEntry
.sHyphImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "532" ": "), "%s", "merge conflict"); } } while (false)
531 rEntry.sHyphImplName.isEmpty(),do { if (true && (!(!rEntry.xHyph.is() && rEntry
.sHyphImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "532" ": "), "%s", "merge conflict"); } } while (false)
532 "merge conflict" )do { if (true && (!(!rEntry.xHyph.is() && rEntry
.sHyphImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "532" ": "), "%s", "merge conflict"); } } while (false)
;
533 rEntry.sHyphImplName = rToAdd.sHyphImplName;
534 rEntry.xHyph = rToAdd.xHyph;
535 }
536 if(rToAdd.xThes.is())
537 {
538 DBG_ASSERT( !rEntry.xThes.is() &&do { if (true && (!(!rEntry.xThes.is() && rEntry
.sThesImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "540" ": "), "%s", "merge conflict"); } } while (false)
539 rEntry.sThesImplName.isEmpty(),do { if (true && (!(!rEntry.xThes.is() && rEntry
.sThesImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "540" ": "), "%s", "merge conflict"); } } while (false)
540 "merge conflict" )do { if (true && (!(!rEntry.xThes.is() && rEntry
.sThesImplName.isEmpty()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "540" ": "), "%s", "merge conflict"); } } while (false)
;
541 rEntry.sThesImplName = rToAdd.sThesImplName;
542 rEntry.xThes = rToAdd.xThes;
543 }
544 return ;
545 }
546 ++nCnt;
547 }
548 rData.GetDisplayServiceArray().push_back( rToAdd );
549 rData.SetDisplayServiceCount( nCnt + 1 );
550}
551
552SvxLinguData_Impl::SvxLinguData_Impl() :
553 nDisplayServices (0)
554{
555 uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
556 xLinguSrvcMgr = LinguServiceManager::create(xContext);
557
558 const Locale& rCurrentLocale = Application::GetSettings().GetLanguageTag().getLocale();
559 Sequence<Any> aArgs(2);//second arguments has to be empty!
560 aArgs.getArray()[0] <<= LinguMgr::GetLinguPropertySet();
561
562 //read spell checker
563 const Sequence< OUString > aSpellNames = xLinguSrvcMgr->getAvailableServices(
564 cSpell, Locale() );
565
566 for(const OUString& spellName : aSpellNames)
567 {
568 ServiceInfo_Impl aInfo;
569 aInfo.sSpellImplName = spellName;
570 aInfo.xSpell.set(
571 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sSpellImplName, aArgs, xContext), UNO_QUERY);
572
573 uno::Reference<XServiceDisplayName> xDispName(aInfo.xSpell, UNO_QUERY);
574 if(xDispName.is())
575 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
576
577 const Sequence< Locale > aLocales( aInfo.xSpell->getLocales() );
578 //! suppress display of entries with no supported languages (see feature 110994)
579 if (aLocales.hasElements())
580 {
581 lcl_MergeLocales( aAllServiceLocales, aLocales );
582 lcl_MergeDisplayArray( *this, aInfo );
583 }
584 }
585
586 //read grammar checker
587 const Sequence< OUString > aGrammarNames = xLinguSrvcMgr->getAvailableServices(
588 cGrammar, Locale() );
589 for(const OUString& grammarName : aGrammarNames)
590 {
591 ServiceInfo_Impl aInfo;
592 aInfo.sGrammarImplName = grammarName;
593 aInfo.xGrammar.set(
594 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sGrammarImplName, aArgs, xContext), UNO_QUERY);
595
596 uno::Reference<XServiceDisplayName> xDispName(aInfo.xGrammar, UNO_QUERY);
597 if(xDispName.is())
598 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
599
600 const Sequence< Locale > aLocales( aInfo.xGrammar->getLocales() );
601 //! suppress display of entries with no supported languages (see feature 110994)
602 if (aLocales.hasElements())
603 {
604 lcl_MergeLocales( aAllServiceLocales, aLocales );
605 lcl_MergeDisplayArray( *this, aInfo );
606 }
607 }
608
609 //read hyphenator
610 const Sequence< OUString > aHyphNames = xLinguSrvcMgr->getAvailableServices(
611 cHyph, Locale() );
612 for(const OUString& hyphName : aHyphNames)
613 {
614 ServiceInfo_Impl aInfo;
615 aInfo.sHyphImplName = hyphName;
616 aInfo.xHyph.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sHyphImplName, aArgs, xContext), UNO_QUERY);
617
618 uno::Reference<XServiceDisplayName> xDispName(aInfo.xHyph, UNO_QUERY);
619 if(xDispName.is())
620 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
621
622 const Sequence< Locale > aLocales( aInfo.xHyph->getLocales() );
623 //! suppress display of entries with no supported languages (see feature 110994)
624 if (aLocales.hasElements())
625 {
626 lcl_MergeLocales( aAllServiceLocales, aLocales );
627 lcl_MergeDisplayArray( *this, aInfo );
628 }
629 }
630
631 //read thesauri
632 const Sequence< OUString > aThesNames = xLinguSrvcMgr->getAvailableServices(
633 cThes, Locale() );
634 for(const OUString& thesName : aThesNames)
635 {
636 ServiceInfo_Impl aInfo;
637 aInfo.sThesImplName = thesName;
638 aInfo.xThes.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sThesImplName, aArgs, xContext), UNO_QUERY);
639
640 uno::Reference<XServiceDisplayName> xDispName(aInfo.xThes, UNO_QUERY);
641 if(xDispName.is())
642 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
643
644 const Sequence< Locale > aLocales( aInfo.xThes->getLocales() );
645 //! suppress display of entries with no supported languages (see feature 110994)
646 if (aLocales.hasElements())
647 {
648 lcl_MergeLocales( aAllServiceLocales, aLocales );
649 lcl_MergeDisplayArray( *this, aInfo );
650 }
651 }
652
653 Sequence< OUString > aCfgSvcs;
654 for(auto const & locale : std::as_const(aAllServiceLocales))
655 {
656 LanguageType nLang = LanguageTag::convertToLanguageType( locale );
657
658 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cSpell, locale);
659 SetChecked( aCfgSvcs );
660 if (aCfgSvcs.hasElements())
661 aCfgSpellTable[ nLang ] = aCfgSvcs;
662
663 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cGrammar, locale);
664 SetChecked( aCfgSvcs );
665 if (aCfgSvcs.hasElements())
666 aCfgGrammarTable[ nLang ] = aCfgSvcs;
667
668 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cHyph, locale);
669 SetChecked( aCfgSvcs );
670 if (aCfgSvcs.hasElements())
671 aCfgHyphTable[ nLang ] = aCfgSvcs;
672
673 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cThes, locale);
674 SetChecked( aCfgSvcs );
675 if (aCfgSvcs.hasElements())
676 aCfgThesTable[ nLang ] = aCfgSvcs;
677 }
678}
679
680void SvxLinguData_Impl::SetChecked(const Sequence<OUString>& rConfiguredServices)
681{
682 for(OUString const & configService : rConfiguredServices)
683 {
684 for (sal_uInt32 i = 0; i < nDisplayServices; ++i)
685 {
686 ServiceInfo_Impl& rEntry = aDisplayServiceArr[i];
687 if (!rEntry.bConfigured)
688 {
689 const OUString &rSrvcImplName = configService;
690 if (!rSrvcImplName.isEmpty() &&
691 (rEntry.sSpellImplName == rSrvcImplName ||
692 rEntry.sGrammarImplName == rSrvcImplName ||
693 rEntry.sHyphImplName == rSrvcImplName ||
694 rEntry.sThesImplName == rSrvcImplName))
695 {
696 rEntry.bConfigured = true;
697 break;
698 }
699 }
700 }
701 }
702}
703
704bool SvxLinguData_Impl::AddRemove(
705 Sequence< OUString > &rConfigured,
706 const OUString &rImplName, bool bAdd )
707{
708 bool bRet = false; // modified?
709
710 sal_Int32 nEntries = rConfigured.getLength();
711 sal_Int32 nPos = lcl_SeqGetEntryPos(rConfigured, rImplName);
712 if (bAdd && nPos < 0) // add new entry
713 {
714 rConfigured.realloc( ++nEntries );
715 OUString *pConfigured = rConfigured.getArray();
716 pConfigured[nEntries - 1] = rImplName;
717 bRet = true;
718 }
719 else if (!bAdd && nPos >= 0) // remove existing entry
720 {
721 OUString *pConfigured = rConfigured.getArray();
722 for (sal_Int32 i = nPos; i < nEntries - 1; ++i)
723 pConfigured[i] = pConfigured[i + 1];
724 rConfigured.realloc(--nEntries);
725 bRet = true;
726 }
727
728 return bRet;
729}
730
731
732void SvxLinguData_Impl::Reconfigure( const OUString &rDisplayName, bool bEnable )
733{
734 DBG_ASSERT( !rDisplayName.isEmpty(), "empty DisplayName" )do { if (true && (!(!rDisplayName.isEmpty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "734" ": "), "%s", "empty DisplayName"); } } while (false
)
;
735
736 ServiceInfo_Impl *pInfo = nullptr;
737 for (sal_uInt32 i = 0; i < nDisplayServices; ++i)
738 {
739 ServiceInfo_Impl& rTmp = aDisplayServiceArr[i];
740 if (rTmp.sDisplayName == rDisplayName)
741 {
742 pInfo = &rTmp;
743 break;
744 }
745 }
746 DBG_ASSERT( pInfo, "DisplayName entry not found" )do { if (true && (!(pInfo))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "746" ": "), "%s", "DisplayName entry not found"); } } while
(false)
;
747 if (!pInfo)
748 return;
749
750 pInfo->bConfigured = bEnable;
751
752 Sequence< Locale > aLocales;
753 const Locale *pLocale = nullptr;
754 sal_Int32 nLocales = 0;
755 sal_Int32 i;
756
757 // update configured spellchecker entries
758 if (pInfo->xSpell.is())
759 {
760 aLocales = pInfo->xSpell->getLocales();
761 pLocale = aLocales.getConstArray();
762 nLocales = aLocales.getLength();
763 for (i = 0; i < nLocales; ++i)
764 {
765 LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] );
766 if (!aCfgSpellTable.count( nLang ) && bEnable)
767 aCfgSpellTable[ nLang ] = Sequence< OUString >();
768 if (aCfgSpellTable.count( nLang ))
769 AddRemove( aCfgSpellTable[ nLang ], pInfo->sSpellImplName, bEnable );
770 }
771 }
772
773 // update configured grammar checker entries
774 if (pInfo->xGrammar.is())
775 {
776 aLocales = pInfo->xGrammar->getLocales();
777 pLocale = aLocales.getConstArray();
778 nLocales = aLocales.getLength();
779 for (i = 0; i < nLocales; ++i)
780 {
781 LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] );
782 if (!aCfgGrammarTable.count( nLang ) && bEnable)
783 aCfgGrammarTable[ nLang ] = Sequence< OUString >();
784 if (aCfgGrammarTable.count( nLang ))
785 AddRemove( aCfgGrammarTable[ nLang ], pInfo->sGrammarImplName, bEnable );
786 }
787 }
788
789 // update configured hyphenator entries
790 if (pInfo->xHyph.is())
791 {
792 aLocales = pInfo->xHyph->getLocales();
793 pLocale = aLocales.getConstArray();
794 nLocales = aLocales.getLength();
795 for (i = 0; i < nLocales; ++i)
796 {
797 LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] );
798 if (!aCfgHyphTable.count( nLang ) && bEnable)
799 aCfgHyphTable[ nLang ] = Sequence< OUString >();
800 if (aCfgHyphTable.count( nLang ))
801 AddRemove( aCfgHyphTable[ nLang ], pInfo->sHyphImplName, bEnable );
802 }
803 }
804
805 // update configured spellchecker entries
806 if (!pInfo->xThes.is())
807 return;
808
809 aLocales = pInfo->xThes->getLocales();
810 pLocale = aLocales.getConstArray();
811 nLocales = aLocales.getLength();
812 for (i = 0; i < nLocales; ++i)
813 {
814 LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] );
815 if (!aCfgThesTable.count( nLang ) && bEnable)
816 aCfgThesTable[ nLang ] = Sequence< OUString >();
817 if (aCfgThesTable.count( nLang ))
818 AddRemove( aCfgThesTable[ nLang ], pInfo->sThesImplName, bEnable );
819 }
820}
821
822
823// class SvxLinguTabPage -------------------------------------------------
824
825SvxLinguTabPage::SvxLinguTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
826 : SfxTabPage(pPage, pController, "cui/ui/optlingupage.ui", "OptLinguPage", &rSet)
827 , sCapitalWords (CuiResId(RID_SVXSTR_CAPITAL_WORDSreinterpret_cast<char const *>("RID_SVXSTR_CAPITAL_WORDS"
"\004" u8"Check uppercase words")
))
828 , sWordsWithDigits(CuiResId(RID_SVXSTR_WORDS_WITH_DIGITSreinterpret_cast<char const *>("RID_SVXSTR_WORDS_WITH_DIGITS"
"\004" u8"Check words with numbers ")
))
829 , sSpellSpecial (CuiResId(RID_SVXSTR_SPELL_SPECIALreinterpret_cast<char const *>("RID_SVXSTR_SPELL_SPECIAL"
"\004" u8"Check special regions")
))
830 , sSpellAuto (CuiResId(RID_SVXSTR_SPELL_AUTOreinterpret_cast<char const *>("RID_SVXSTR_SPELL_AUTO" "\004"
u8"Check spelling as you type")
))
831 , sGrammarAuto (CuiResId(RID_SVXSTR_GRAMMAR_AUTOreinterpret_cast<char const *>("RID_SVXSTR_GRAMMAR_AUTO"
"\004" u8"Check grammar as you type")
))
832 , sNumMinWordlen (CuiResId(RID_SVXSTR_NUM_MIN_WORDLENreinterpret_cast<char const *>("RID_SVXSTR_NUM_MIN_WORDLEN"
"\004" u8"Minimal number of characters for hyphenation: ")
))
833 , sNumPreBreak (CuiResId(RID_SVXSTR_NUM_PRE_BREAKreinterpret_cast<char const *>("RID_SVXSTR_NUM_PRE_BREAK"
"\004" u8"Characters before line break: ")
))
834 , sNumPostBreak (CuiResId(RID_SVXSTR_NUM_POST_BREAKreinterpret_cast<char const *>("RID_SVXSTR_NUM_POST_BREAK"
"\004" u8"Characters after line break: ")
))
835 , sHyphAuto (CuiResId(RID_SVXSTR_HYPH_AUTOreinterpret_cast<char const *>("RID_SVXSTR_HYPH_AUTO" "\004"
u8"Hyphenate without inquiry")
))
836 , sHyphSpecial (CuiResId(RID_SVXSTR_HYPH_SPECIALreinterpret_cast<char const *>("RID_SVXSTR_HYPH_SPECIAL"
"\004" u8"Hyphenate special regions")
))
837 , nUPN_HYPH_MIN_WORD_LENGTH(-1)
838 , nUPN_HYPH_MIN_LEADING(-1)
839 , nUPN_HYPH_MIN_TRAILING(-1)
840 , m_nDlbClickEventId(nullptr)
841 , m_xLinguModulesFT(m_xBuilder->weld_label("lingumodulesft"))
842 , m_xLinguModulesCLB(m_xBuilder->weld_tree_view("lingumodules"))
843 , m_xLinguModulesEditPB(m_xBuilder->weld_button("lingumodulesedit"))
844 , m_xLinguDicsFT(m_xBuilder->weld_label("lingudictsft"))
845 , m_xLinguDicsCLB(m_xBuilder->weld_tree_view("lingudicts"))
846 , m_xLinguDicsNewPB(m_xBuilder->weld_button("lingudictsnew"))
847 , m_xLinguDicsEditPB(m_xBuilder->weld_button("lingudictsedit"))
848 , m_xLinguDicsDelPB(m_xBuilder->weld_button("lingudictsdelete"))
849 , m_xLinguOptionsCLB(m_xBuilder->weld_tree_view("linguoptions"))
850 , m_xLinguOptionsEditPB(m_xBuilder->weld_button("linguoptionsedit"))
851 , m_xMoreDictsLink(m_xBuilder->weld_link_button("moredictslink"))
852{
853 m_xLinguModulesCLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
854 m_xLinguDicsCLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
855 m_xLinguOptionsCLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
856
857 m_xLinguModulesCLB->connect_changed( LINK( this, SvxLinguTabPage, SelectHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubSelectHdl_Impl)
);
858 m_xLinguModulesCLB->connect_row_activated(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl)::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubBoxDoubleClickHdl_Impl
)
);
859 m_xLinguModulesCLB->connect_toggled(LINK(this, SvxLinguTabPage, ModulesBoxCheckButtonHdl_Impl)::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubModulesBoxCheckButtonHdl_Impl
)
);
860
861 m_xLinguModulesEditPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubClickHdl_Impl)
);
862 m_xLinguOptionsEditPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubClickHdl_Impl)
);
863
864 m_xLinguDicsCLB->connect_changed( LINK( this, SvxLinguTabPage, SelectHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubSelectHdl_Impl)
);
865 m_xLinguDicsCLB->connect_toggled(LINK(this, SvxLinguTabPage, DicsBoxCheckButtonHdl_Impl)::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubDicsBoxCheckButtonHdl_Impl
)
);
866
867 m_xLinguDicsNewPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubClickHdl_Impl)
);
868 m_xLinguDicsEditPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubClickHdl_Impl)
);
869 m_xLinguDicsDelPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubClickHdl_Impl)
);
870
871 m_xLinguOptionsCLB->connect_changed( LINK( this, SvxLinguTabPage, SelectHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubSelectHdl_Impl)
);
872 m_xLinguOptionsCLB->connect_row_activated(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl)::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubBoxDoubleClickHdl_Impl
)
);
873
874 if (officecfg::Office::Security::Hyperlinks::Open::get() == SvtExtendedSecurityOptions::OPEN_NEVER)
875 m_xMoreDictsLink->hide();
876
877 xProp = LinguMgr::GetLinguPropertySet();
878 xDicList.set( LinguMgr::GetDictionaryList() );
879 if (xDicList.is())
880 {
881 // keep references to all **currently** available dictionaries,
882 // since the diclist may get changed meanwhile (e.g. through the API).
883 // We want the dialog to operate on the same set of dictionaries it
884 // was started with.
885 // Also we have to take care to not lose the last reference when
886 // someone else removes a dictionary from the list.
887 // removed dics will be replaced by NULL new entries be added to the end
888 // Thus we may use indices as consistent references.
889 aDics = xDicList->getDictionaries();
890
891 UpdateDicBox_Impl();
892 }
893 else
894 {
895 m_xLinguDicsFT->set_sensitive(false);
896 m_xLinguDicsCLB->set_sensitive(false);
897 m_xLinguDicsNewPB->set_sensitive(false);
898 m_xLinguDicsEditPB->set_sensitive(false);
899 m_xLinguDicsDelPB->set_sensitive(false);
900 }
901}
902
903SvxLinguTabPage::~SvxLinguTabPage()
904{
905 if (m_nDlbClickEventId)
906 {
907 Application::RemoveUserEvent(m_nDlbClickEventId);
908 m_nDlbClickEventId = nullptr;
909 }
910 pLinguData.reset();
911}
912
913std::unique_ptr<SfxTabPage> SvxLinguTabPage::Create( weld::Container* pPage, weld::DialogController* pController,
914 const SfxItemSet* rAttrSet )
915{
916 return std::make_unique<SvxLinguTabPage>( pPage, pController, *rAttrSet );
917}
918
919bool SvxLinguTabPage::FillItemSet( SfxItemSet* rCoreSet )
920{
921 bool bModified = true; // !!!!
922
923 // if not HideGroups was called with GROUP_MODULES...
924 if (m_xLinguModulesCLB->get_visible())
925 {
926 DBG_ASSERT( pLinguData, "pLinguData not yet initialized" )do { if (true && (!(pLinguData))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "926" ": "), "%s", "pLinguData not yet initialized"); } }
while (false)
;
927 if (!pLinguData)
928 pLinguData.reset( new SvxLinguData_Impl );
929
930 // update spellchecker configuration entries
931 const LangImplNameTable *pTable = &pLinguData->GetSpellTable();
932 for (auto const& elem : *pTable)
933 {
934 LanguageType nLang = elem.first;
935 const Sequence< OUString > aImplNames(elem.second);
936 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
937 Locale aLocale( LanguageTag::convertToLocale(nLang) );
938 if (xMgr.is())
939 xMgr->setConfiguredServices( cSpell, aLocale, aImplNames );
940 }
941
942 // update grammar checker configuration entries
943 pTable = &pLinguData->GetGrammarTable();
944 for (auto const& elem : *pTable)
945 {
946 LanguageType nLang = elem.first;
947 const Sequence< OUString > aImplNames(elem.second);
948 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
949 Locale aLocale( LanguageTag::convertToLocale(nLang) );
950 if (xMgr.is())
951 xMgr->setConfiguredServices( cGrammar, aLocale, aImplNames );
952 }
953
954 // update hyphenator configuration entries
955 pTable = &pLinguData->GetHyphTable();
956 for (auto const& elem : *pTable)
957 {
958 LanguageType nLang = elem.first;
959 const Sequence< OUString > aImplNames(elem.second);
960 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
961 Locale aLocale( LanguageTag::convertToLocale(nLang) );
962 if (xMgr.is())
963 xMgr->setConfiguredServices( cHyph, aLocale, aImplNames );
964 }
965
966 // update thesaurus configuration entries
967 pTable = &pLinguData->GetThesTable();
968 for (auto const& elem : *pTable)
969 {
970 LanguageType nLang = elem.first;
971 const Sequence< OUString > aImplNames(elem.second);
972 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
973 Locale aLocale( LanguageTag::convertToLocale(nLang) );
974 if (xMgr.is())
975 xMgr->setConfiguredServices( cThes, aLocale, aImplNames );
976 }
977 }
978
979
980 // activate dictionaries according to checkbox state
981
982 Sequence< OUString > aActiveDics;
983 sal_Int32 nActiveDics = 0;
984 int nEntries = m_xLinguDicsCLB->n_children();
985 for (int i = 0; i < nEntries; ++i)
986 {
987 sal_Int32 nDics = aDics.getLength();
988
989 aActiveDics.realloc( nDics );
990 OUString *pActiveDic = aActiveDics.getArray();
991
992 DicUserData aData(m_xLinguDicsCLB->get_id(i).toUInt32());
993 if (aData.GetEntryId() < nDics)
994 {
995 bool bChecked = m_xLinguDicsCLB->get_toggle(i) == TRISTATE_TRUE;
996 uno::Reference< XDictionary > xDic( aDics.getConstArray()[ i ] );
997 if (xDic.is())
998 {
999 if (LinguMgr::GetIgnoreAllList() == xDic)
1000 bChecked = true;
1001 xDic->setActive( bChecked );
1002
1003 if (bChecked)
1004 {
1005 OUString aDicName( xDic->getName() );
1006 pActiveDic[ nActiveDics++ ] = aDicName;
1007 }
1008 }
1009 }
1010 }
1011
1012 aActiveDics.realloc( nActiveDics );
1013 Any aTmp;
1014 aTmp <<= aActiveDics;
1015 SvtLinguConfig aLngCfg;
1016 aLngCfg.SetProperty( UPH_ACTIVE_DICTIONARIES24, aTmp );
1017
1018
1019 nEntries = m_xLinguOptionsCLB->n_children();
1020 for (int j = 0; j < nEntries; ++j)
1021 {
1022 OptionsUserData aData(m_xLinguOptionsCLB->get_id(j).toUInt32());
1023 OUString aPropName( lcl_GetPropertyName( static_cast<EID_OPTIONS>(aData.GetEntryId()) ) );
1024
1025 Any aAny;
1026 if (aData.IsCheckable())
1027 {
1028 bool bChecked = m_xLinguOptionsCLB->get_toggle(j) == TRISTATE_TRUE;
1029 aAny <<= bChecked;
1030 }
1031 else if (aData.HasNumericValue())
1032 {
1033 sal_Int16 nVal = aData.GetNumericValue();
1034 aAny <<= nVal;
1035 }
1036
1037 if (xProp.is())
1038 xProp->setPropertyValue( aPropName, aAny );
1039 aLngCfg.SetProperty( aPropName, aAny );
1040 }
1041
1042 OptionsUserData aPreBreakData(m_xLinguOptionsCLB->get_id(EID_NUM_PRE_BREAK).toUInt32());
1043 OptionsUserData aPostBreakData(m_xLinguOptionsCLB->get_id(EID_NUM_POST_BREAK).toUInt32());
1044 if ( aPreBreakData.IsModified() || aPostBreakData.IsModified() )
1045 {
1046 SfxHyphenRegionItem aHyp( GetWhich( SID_ATTR_HYPHENREGION(((((10000 + 1499) + 1) + 499) + 1) + 12) ) );
1047 aHyp.GetMinLead() = static_cast<sal_uInt8>(aPreBreakData.GetNumericValue());
1048 aHyp.GetMinTrail() = static_cast<sal_uInt8>(aPostBreakData.GetNumericValue());
1049 rCoreSet->Put( aHyp );
1050 }
1051
1052 // automatic spell checking
1053 bool bNewAutoCheck = m_xLinguOptionsCLB->get_toggle(EID_SPELL_AUTO) == TRISTATE_TRUE;
1054 const SfxPoolItem* pOld = GetOldItem( *rCoreSet, SID_AUTOSPELL_CHECK(((((10000 + 1499) + 1) + 499) + 1) + 21) );
1055 if ( !pOld || static_cast<const SfxBoolItem*>(pOld)->GetValue() != bNewAutoCheck )
1056 {
1057 rCoreSet->Put( SfxBoolItem( GetWhich( SID_AUTOSPELL_CHECK(((((10000 + 1499) + 1) + 499) + 1) + 21) ),
1058 bNewAutoCheck ) );
1059 bModified = true;
1060 }
1061
1062 return bModified;
1063}
1064
1065sal_uInt32 SvxLinguTabPage::GetDicUserData( const uno::Reference< XDictionary > &rxDic, sal_uInt16 nIdx )
1066{
1067 sal_uInt32 nRes = 0;
1068 DBG_ASSERT( rxDic.is(), "dictionary not supplied" )do { if (true && (!(rxDic.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1068" ": "), "%s", "dictionary not supplied"); } } while
(false)
;
1069 if (rxDic.is())
1070 {
1071 uno::Reference< frame::XStorable > xStor( rxDic, UNO_QUERY );
1072
1073 bool bChecked = rxDic->isActive();
1074 bool bEditable = !xStor.is() || !xStor->isReadonly();
1075 bool bDeletable = bEditable;
1076
1077 nRes = DicUserData( nIdx,
1078 bChecked, bEditable, bDeletable ).GetUserData();
1079 }
1080 return nRes;
1081}
1082
1083
1084void SvxLinguTabPage::AddDicBoxEntry(
1085 const uno::Reference< XDictionary > &rxDic,
1086 sal_uInt16 nIdx )
1087{
1088 m_xLinguDicsCLB->freeze();
1089
1090 OUString aTxt( ::GetDicInfoStr( rxDic->getName(),
1091 LanguageTag( rxDic->getLocale() ).getLanguageType(),
1092 DictionaryType_NEGATIVE == rxDic->getDictionaryType() ) );
1093 m_xLinguDicsCLB->append(); // append at end
1094 int nEntry = m_xLinguDicsCLB->n_children() - 1;
1095 DicUserData aData( GetDicUserData( rxDic, nIdx ) );
1096 m_xLinguDicsCLB->set_id(nEntry, OUString::number(aData.GetUserData()));
1097 m_xLinguDicsCLB->set_toggle(nEntry, aData.IsChecked() ? TRISTATE_TRUE : TRISTATE_FALSE);
1098 m_xLinguDicsCLB->set_text(nEntry, aTxt, 0); // append at end
1099
1100 m_xLinguDicsCLB->thaw();
1101}
1102
1103void SvxLinguTabPage::UpdateDicBox_Impl()
1104{
1105 m_xLinguDicsCLB->freeze();
1106 m_xLinguDicsCLB->clear();
1107
1108 sal_Int32 nDics = aDics.getLength();
1109 const uno::Reference< XDictionary > *pDic = aDics.getConstArray();
1110 for (sal_Int32 i = 0; i < nDics; ++i)
1111 {
1112 const uno::Reference< XDictionary > &rDic = pDic[i];
1113 if (rDic.is())
1114 AddDicBoxEntry( rDic, static_cast<sal_uInt16>(i) );
1115 }
1116
1117 m_xLinguDicsCLB->thaw();
1118 if (m_xLinguDicsCLB->n_children())
1119 {
1120 m_xLinguDicsCLB->select(0);
1121 SelectHdl_Impl(*m_xLinguDicsCLB);
1122 }
1123}
1124
1125void SvxLinguTabPage::UpdateModulesBox_Impl()
1126{
1127 if (!pLinguData)
1128 return;
1129
1130 const ServiceInfoArr &rAllDispSrvcArr = pLinguData->GetDisplayServiceArray();
1131 const sal_uInt32 nDispSrvcCount = pLinguData->GetDisplayServiceCount();
1132
1133 m_xLinguModulesCLB->clear();
1134
1135 for (sal_uInt32 i = 0; i < nDispSrvcCount; ++i)
1136 {
1137 const ServiceInfo_Impl &rInfo = rAllDispSrvcArr[i];
1138 m_xLinguModulesCLB->append();
1139 m_xLinguModulesCLB->set_id(i, OUString::number(reinterpret_cast<sal_Int64>(&rInfo)));
1140 m_xLinguModulesCLB->set_toggle(i, rInfo.bConfigured ? TRISTATE_TRUE : TRISTATE_FALSE);
1141 m_xLinguModulesCLB->set_text(i, rInfo.sDisplayName, 0);
1142 }
1143 if (nDispSrvcCount)
1144 {
1145 m_xLinguModulesCLB->select(0);
1146 SelectHdl_Impl(*m_xLinguModulesCLB);
1147 }
1148 m_xLinguModulesEditPB->set_sensitive( nDispSrvcCount > 0 );
1149}
1150
1151void SvxLinguTabPage::Reset( const SfxItemSet* rSet )
1152{
1153 // if not HideGroups was called with GROUP_MODULES...
1154 if (m_xLinguModulesCLB->get_visible())
1155 {
1156 if (!pLinguData)
1157 pLinguData.reset( new SvxLinguData_Impl );
1158 UpdateModulesBox_Impl();
1159 }
1160
1161
1162 // get data from configuration
1163 SvtLinguConfig aLngCfg;
1164
1165 m_xLinguOptionsCLB->freeze();
1166 m_xLinguOptionsCLB->clear();
1167
1168 sal_Int16 nVal = 0;
1169 bool bVal = false;
1170 sal_uInt32 nUserData = 0;
1171
1172 m_xLinguOptionsCLB->append();
1173 int nEntry = 0;
1174
1175 aLngCfg.GetProperty( UPN_IS_SPELL_AUTO"IsSpellAuto" ) >>= bVal;
1176 const SfxPoolItem* pItem = GetItem( *rSet, SID_AUTOSPELL_CHECK(((((10000 + 1499) + 1) + 499) + 1) + 21) );
1177 if (pItem)
1178 bVal = static_cast<const SfxBoolItem *>(pItem)->GetValue();
1179 nUserData = OptionsUserData( EID_SPELL_AUTO, false, 0, true, bVal).GetUserData();
1180 m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE);
1181 m_xLinguOptionsCLB->set_text(nEntry, sSpellAuto, 0);
1182 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1183
1184 m_xLinguOptionsCLB->append();
1185 ++nEntry;
1186
1187 aLngCfg.GetProperty( UPN_IS_GRAMMAR_AUTO"IsAutoGrammarCheck" ) >>= bVal;
1188 nUserData = OptionsUserData( EID_GRAMMAR_AUTO, false, 0, true, bVal).GetUserData();
1189 m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE);
1190 m_xLinguOptionsCLB->set_text(nEntry, sGrammarAuto, 0);
1191 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1192
1193 m_xLinguOptionsCLB->append();
1194 ++nEntry;
1195
1196 aLngCfg.GetProperty( UPN_IS_SPELL_UPPER_CASE"IsSpellUpperCase" ) >>= bVal;
1197 nUserData = OptionsUserData( EID_CAPITAL_WORDS, false, 0, true, bVal).GetUserData();
1198 m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE);
1199 m_xLinguOptionsCLB->set_text(nEntry, sCapitalWords, 0);
1200 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1201
1202 m_xLinguOptionsCLB->append();
1203 ++nEntry;
1204
1205 aLngCfg.GetProperty( UPN_IS_SPELL_WITH_DIGITS"IsSpellWithDigits" ) >>= bVal;
1206 nUserData = OptionsUserData( EID_WORDS_WITH_DIGITS, false, 0, true, bVal).GetUserData();
1207 m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE);
1208 m_xLinguOptionsCLB->set_text(nEntry, sWordsWithDigits, 0);
1209 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1210
1211 m_xLinguOptionsCLB->append();
1212 ++nEntry;
1213
1214 aLngCfg.GetProperty( UPN_IS_SPELL_SPECIAL"IsSpellSpecial" ) >>= bVal;
1215 nUserData = OptionsUserData( EID_SPELL_SPECIAL, false, 0, true, bVal).GetUserData();
1216 m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE);
1217 m_xLinguOptionsCLB->set_text(nEntry, sSpellSpecial, 0);
1218 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1219
1220 m_xLinguOptionsCLB->append();
1221 ++nEntry;
1222
1223 aLngCfg.GetProperty( UPN_HYPH_MIN_WORD_LENGTH"HyphMinWordLength" ) >>= nVal;
1224 nUserData = OptionsUserData( EID_NUM_MIN_WORDLEN, true, static_cast<sal_uInt16>(nVal), false, false).GetUserData();
1225 m_xLinguOptionsCLB->set_text(nEntry, sNumMinWordlen + " " + OUString::number(nVal), 0);
1226 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1227 nUPN_HYPH_MIN_WORD_LENGTH = nEntry;
1228
1229 const SfxHyphenRegionItem *pHyp = nullptr;
1230 sal_uInt16 nWhich = GetWhich( SID_ATTR_HYPHENREGION(((((10000 + 1499) + 1) + 499) + 1) + 12) );
1231 if ( rSet->GetItemState( nWhich, false ) == SfxItemState::SET )
1232 pHyp = &static_cast<const SfxHyphenRegionItem &>( rSet->Get( nWhich ) );
1233
1234 m_xLinguOptionsCLB->append();
1235 ++nEntry;
1236
1237 aLngCfg.GetProperty( UPN_HYPH_MIN_LEADING"HyphMinLeading" ) >>= nVal;
1238 if (pHyp)
1239 nVal = static_cast<sal_Int16>(pHyp->GetMinLead());
1240 nUserData = OptionsUserData( EID_NUM_PRE_BREAK, true, static_cast<sal_uInt16>(nVal), false, false).GetUserData();
1241 m_xLinguOptionsCLB->set_text(nEntry, sNumPreBreak + " " + OUString::number(nVal), 0);
1242 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1243 nUPN_HYPH_MIN_LEADING = nEntry;
1244
1245 m_xLinguOptionsCLB->append();
1246 ++nEntry;
1247
1248 aLngCfg.GetProperty( UPN_HYPH_MIN_TRAILING"HyphMinTrailing" ) >>= nVal;
1249 if (pHyp)
1250 nVal = static_cast<sal_Int16>(pHyp->GetMinTrail());
1251 nUserData = OptionsUserData( EID_NUM_POST_BREAK, true, static_cast<sal_uInt16>(nVal), false, false).GetUserData();
1252 m_xLinguOptionsCLB->set_text(nEntry, sNumPostBreak + " " + OUString::number(nVal), 0);
1253 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1254 nUPN_HYPH_MIN_TRAILING = nEntry;
1255
1256 m_xLinguOptionsCLB->append();
1257 ++nEntry;
1258
1259 aLngCfg.GetProperty( UPN_IS_HYPH_AUTO"IsHyphAuto" ) >>= bVal;
1260 nUserData = OptionsUserData( EID_HYPH_AUTO, false, 0, true, bVal).GetUserData();
1261 m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE);
1262 m_xLinguOptionsCLB->set_text(nEntry, sHyphAuto, 0);
1263 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1264
1265 m_xLinguOptionsCLB->append();
1266 ++nEntry;
1267
1268 aLngCfg.GetProperty( UPN_IS_HYPH_SPECIAL"IsHyphSpecial" ) >>= bVal;
1269 nUserData = OptionsUserData( EID_HYPH_SPECIAL, false, 0, true, bVal).GetUserData();
1270 m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE);
1271 m_xLinguOptionsCLB->set_text(nEntry, sHyphSpecial, 0);
1272 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData));
1273
1274 m_xLinguOptionsCLB->thaw();
1275
1276 m_xLinguOptionsCLB->select(0);
1277 SelectHdl_Impl(*m_xLinguOptionsCLB);
1278
1279 m_xLinguModulesCLB->set_size_request(m_xLinguModulesCLB->get_preferred_size().Width(),
1280 m_xLinguModulesCLB->get_height_rows(3));
1281 m_xLinguDicsCLB->set_size_request(m_xLinguDicsCLB->get_preferred_size().Width(),
1282 m_xLinguDicsCLB->get_height_rows(5));
1283 m_xLinguOptionsCLB->set_size_request(m_xLinguOptionsCLB->get_preferred_size().Width(),
1284 m_xLinguOptionsCLB->get_height_rows(5));
1285}
1286
1287IMPL_LINK(SvxLinguTabPage, BoxDoubleClickHdl_Impl, weld::TreeView&, rBox, bool)bool SvxLinguTabPage::LinkStubBoxDoubleClickHdl_Impl(void * instance
, weld::TreeView& data) { return static_cast<SvxLinguTabPage
*>(instance)->BoxDoubleClickHdl_Impl(data); } bool SvxLinguTabPage
::BoxDoubleClickHdl_Impl(weld::TreeView& rBox)
1288{
1289 if (&rBox == m_xLinguModulesCLB.get() && !m_nDlbClickEventId)
1290 {
1291 //! in order to avoid a bug causing a GPF when double clicking
1292 //! on a module entry and exiting the "Edit Modules" dialog
1293 //! after that.
1294 m_nDlbClickEventId = Application::PostUserEvent(LINK(this, SvxLinguTabPage, PostDblClickHdl_Impl)::tools::detail::makeLink( ::tools::detail::castTo<SvxLinguTabPage
*>(this), &SvxLinguTabPage::LinkStubPostDblClickHdl_Impl
)
);
1295 }
1296 else if (&rBox == m_xLinguOptionsCLB.get())
1297 {
1298 ClickHdl_Impl(*m_xLinguOptionsEditPB);
1299 }
1300 return true;
1301}
1302
1303IMPL_LINK_NOARG(SvxLinguTabPage, PostDblClickHdl_Impl, void*, void)void SvxLinguTabPage::LinkStubPostDblClickHdl_Impl(void * instance
, void* data) { return static_cast<SvxLinguTabPage *>(instance
)->PostDblClickHdl_Impl(data); } void SvxLinguTabPage::PostDblClickHdl_Impl
(__attribute__ ((unused)) void*)
1304{
1305 m_nDlbClickEventId = nullptr;
1306 ClickHdl_Impl(*m_xLinguModulesEditPB);
1307}
1308
1309IMPL_LINK(SvxLinguTabPage, ModulesBoxCheckButtonHdl_Impl, const weld::TreeView::iter_col&, rRowCol, void)void SvxLinguTabPage::LinkStubModulesBoxCheckButtonHdl_Impl(void
* instance, const weld::TreeView::iter_col& data) { return
static_cast<SvxLinguTabPage *>(instance)->ModulesBoxCheckButtonHdl_Impl
(data); } void SvxLinguTabPage::ModulesBoxCheckButtonHdl_Impl
(const weld::TreeView::iter_col& rRowCol)
1310{
1311 if (!pLinguData)
1312 return;
1313 pLinguData->Reconfigure(m_xLinguModulesCLB->get_text(rRowCol.first),
1314 m_xLinguModulesCLB->get_toggle(rRowCol.first) == TRISTATE_TRUE);
1315}
1316
1317IMPL_LINK(SvxLinguTabPage, DicsBoxCheckButtonHdl_Impl, const weld::TreeView::iter_col&, rRowCol, void)void SvxLinguTabPage::LinkStubDicsBoxCheckButtonHdl_Impl(void
* instance, const weld::TreeView::iter_col& data) { return
static_cast<SvxLinguTabPage *>(instance)->DicsBoxCheckButtonHdl_Impl
(data); } void SvxLinguTabPage::DicsBoxCheckButtonHdl_Impl(const
weld::TreeView::iter_col& rRowCol)
1318{
1319 const uno::Reference<XDictionary> &rDic = aDics.getConstArray()[m_xLinguDicsCLB->get_iter_index_in_parent(rRowCol.first)];
1320 if (LinguMgr::GetIgnoreAllList() == rDic)
1321 m_xLinguDicsCLB->set_toggle(rRowCol.first, TRISTATE_TRUE);
1322}
1323
1324IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void)void SvxLinguTabPage::LinkStubClickHdl_Impl(void * instance, weld
::Button& data) { return static_cast<SvxLinguTabPage *
>(instance)->ClickHdl_Impl(data); } void SvxLinguTabPage
::ClickHdl_Impl(weld::Button& rBtn)
1
Calling 'SvxLinguTabPage::ClickHdl_Impl'
1325{
1326 if (m_xLinguModulesEditPB.get() == &rBtn)
2
Assuming the condition is false
3
Taking false branch
1327 {
1328 if (!pLinguData)
1329 pLinguData.reset( new SvxLinguData_Impl );
1330
1331 SvxLinguData_Impl aOldLinguData( *pLinguData );
1332 SvxEditModulesDlg aDlg(GetFrameWeld(), *pLinguData);
1333 if (aDlg.run() != RET_OK)
1334 *pLinguData = aOldLinguData;
1335
1336 // evaluate new status of 'bConfigured' flag
1337 sal_uInt32 nLen = pLinguData->GetDisplayServiceCount();
1338 for (sal_uInt32 i = 0; i < nLen; ++i)
1339 pLinguData->GetDisplayServiceArray()[i].bConfigured = false;
1340 const Locale* pAllLocales = pLinguData->GetAllSupportedLocales().getConstArray();
1341 sal_Int32 nLocales = pLinguData->GetAllSupportedLocales().getLength();
1342 for (sal_Int32 k = 0; k < nLocales; ++k)
1343 {
1344 LanguageType nLang = LanguageTag::convertToLanguageType( pAllLocales[k] );
1345 if (pLinguData->GetSpellTable().count( nLang ))
1346 pLinguData->SetChecked( pLinguData->GetSpellTable()[ nLang ] );
1347 if (pLinguData->GetGrammarTable().count( nLang ))
1348 pLinguData->SetChecked( pLinguData->GetGrammarTable()[ nLang ] );
1349 if (pLinguData->GetHyphTable().count( nLang ))
1350 pLinguData->SetChecked( pLinguData->GetHyphTable()[ nLang ] );
1351 if (pLinguData->GetThesTable().count( nLang ))
1352 pLinguData->SetChecked( pLinguData->GetThesTable()[ nLang ] );
1353 }
1354
1355 // show new status of modules
1356 UpdateModulesBox_Impl();
1357 }
1358 else if (m_xLinguDicsNewPB.get() == &rBtn)
4
Assuming the condition is true
5
Taking true branch
1359 {
1360 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1361 ScopedVclPtr<AbstractSvxNewDictionaryDialog> aDlg(pFact->CreateSvxNewDictionaryDialog(GetFrameWeld()));
6
Calling constructor for 'ScopedVclPtr<AbstractSvxNewDictionaryDialog>'
13
Returning from constructor for 'ScopedVclPtr<AbstractSvxNewDictionaryDialog>'
14
Calling implicit destructor for 'VclPtr<AbstractSvxNewDictionaryDialog>'
15
Calling '~Reference'
22
Returning from '~Reference'
23
Returning from destructor for 'VclPtr<AbstractSvxNewDictionaryDialog>'
1362 uno::Reference< XDictionary > xNewDic;
1363 if ( aDlg->Execute() == RET_OK )
24
Calling 'VclPtr::operator->'
1364 xNewDic = aDlg->GetNewDictionary();
1365 if ( xNewDic.is() )
1366 {
1367 // add new dics to the end
1368 sal_Int32 nLen = aDics.getLength();
1369 aDics.realloc( nLen + 1 );
1370
1371 aDics.getArray()[ nLen ] = xNewDic;
1372
1373 AddDicBoxEntry( xNewDic, static_cast<sal_uInt16>(nLen) );
1374 }
1375 }
1376 else if (m_xLinguDicsEditPB.get() == &rBtn)
1377 {
1378 int nEntry = m_xLinguDicsCLB->get_selected_index();
1379 if (nEntry != -1)
1380 {
1381 DicUserData aData(m_xLinguDicsCLB->get_id(nEntry).toUInt32());
1382 sal_uInt16 nDicPos = aData.GetEntryId();
1383 sal_Int32 nDics = aDics.getLength();
1384 if (nDicPos < nDics)
1385 {
1386 uno::Reference< XDictionary > xDic = aDics.getConstArray()[ nDicPos ];
1387 if (xDic.is())
1388 {
1389 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1390 ScopedVclPtr<VclAbstractDialog> aDlg(pFact->CreateSvxEditDictionaryDialog(GetFrameWeld(), xDic->getName()));
1391 aDlg->Execute();
1392 }
1393 }
1394 }
1395 }
1396 else if (m_xLinguDicsDelPB.get() == &rBtn)
1397 {
1398 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletedictionarydialog.ui"));
1399 std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("QueryDeleteDictionaryDialog"));
1400 if (RET_NO == xQuery->run())
1401 return;
1402
1403 int nEntry = m_xLinguDicsCLB->get_selected_index();
1404 if (nEntry != -1)
1405 {
1406 DicUserData aData(m_xLinguDicsCLB->get_id(nEntry).toUInt32());
1407 sal_uInt16 nDicPos = aData.GetEntryId();
1408 sal_Int32 nDics = aDics.getLength();
1409 if (nDicPos < nDics)
1410 {
1411 uno::Reference< XDictionary > xDic = aDics.getConstArray()[ nDicPos ];
1412 if (xDic.is())
1413 {
1414 if (LinguMgr::GetIgnoreAllList() == xDic)
1415 xDic->clear();
1416 else
1417 {
1418 if (xDicList.is())
1419 xDicList->removeDictionary( xDic );
1420
1421 uno::Reference< frame::XStorable > xStor( xDic, UNO_QUERY );
1422 if ( xStor->hasLocation() && !xStor->isReadonly() )
1423 {
1424 OUString sURL = xStor->getLocation();
1425 INetURLObject aObj(sURL);
1426 DBG_ASSERT( aObj.GetProtocol() == INetProtocol::File,do { if (true && (!(aObj.GetProtocol() == INetProtocol
::File))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN),
("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1427" ": "), "%s", "non-file URLs cannot be deleted"); }
} while (false)
1427 "non-file URLs cannot be deleted" )do { if (true && (!(aObj.GetProtocol() == INetProtocol
::File))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN),
("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1427" ": "), "%s", "non-file URLs cannot be deleted"); }
} while (false)
;
1428 if ( aObj.GetProtocol() == INetProtocol::File )
1429 {
1430 KillFile_Impl( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1431 }
1432 }
1433
1434 aDics.getArray()[ nDicPos ] = nullptr;
1435
1436 // remove entry from checklistbox
1437 int nCnt = m_xLinguDicsCLB->n_children();
1438 for (int i = 0; i < nCnt; ++i)
1439 {
1440 DicUserData aDicData(m_xLinguDicsCLB->get_id(i).toUInt32());
1441 if (aDicData.GetEntryId() == nDicPos )
1442 {
1443 m_xLinguDicsCLB->remove(i);
1444 break;
1445 }
1446 }
1447 DBG_ASSERT( nCnt > m_xLinguDicsCLB->n_children(),do { if (true && (!(nCnt > m_xLinguDicsCLB->n_children
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1448" ": "), "%s", "remove failed ?"); } } while (false
)
1448 "remove failed ?")do { if (true && (!(nCnt > m_xLinguDicsCLB->n_children
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1448" ": "), "%s", "remove failed ?"); } } while (false
)
;
1449 }
1450 }
1451 }
1452 }
1453 }
1454 else if (m_xLinguOptionsEditPB.get() == &rBtn)
1455 {
1456 int nEntry = m_xLinguOptionsCLB->get_selected_index();
1457 DBG_ASSERT(nEntry != -1, "no entry selected")do { if (true && (!(nEntry != -1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1457" ": "), "%s", "no entry selected"); } } while (false
)
;
1458 if (nEntry != -1)
1459 {
1460 OptionsUserData aData(m_xLinguOptionsCLB->get_id(nEntry).toUInt32());
1461 if (aData.HasNumericValue())
1462 {
1463 sal_uInt16 nRID = aData.GetEntryId();
1464 OptionsBreakSet aDlg(GetFrameWeld(), nRID);
1465 aDlg.GetNumericFld().set_value(aData.GetNumericValue());
1466 if (RET_OK == aDlg.run())
1467 {
1468 int nVal = aDlg.GetNumericFld().get_value();
1469 if (-1 != nVal && aData.GetNumericValue() != nVal)
1470 {
1471 aData.SetNumericValue( static_cast<sal_uInt8>(nVal) ); //! sets IsModified !
1472 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(aData.GetUserData()));
1473 if (nEntry == nUPN_HYPH_MIN_WORD_LENGTH)
1474 m_xLinguOptionsCLB->set_text(nEntry, sNumMinWordlen + " " + OUString::number(nVal), 0);
1475 else if (nEntry == nUPN_HYPH_MIN_LEADING)
1476 m_xLinguOptionsCLB->set_text(nEntry, sNumPreBreak + " " + OUString::number(nVal), 0);
1477 else if (nEntry == nUPN_HYPH_MIN_TRAILING)
1478 m_xLinguOptionsCLB->set_text(nEntry, sNumPostBreak + " " + OUString::number(nVal), 0);
1479 m_xLinguOptionsCLB->set_id(nEntry, OUString::number(aData.GetUserData()));
1480 }
1481 }
1482 }
1483 }
1484 }
1485 else
1486 {
1487 OSL_FAIL( "rBtn unexpected value" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1487" ": "), "%s", "rBtn unexpected value"); } } while (
false)
;
1488 }
1489}
1490
1491IMPL_LINK(SvxLinguTabPage, SelectHdl_Impl, weld::TreeView&, rBox, void)void SvxLinguTabPage::LinkStubSelectHdl_Impl(void * instance,
weld::TreeView& data) { return static_cast<SvxLinguTabPage
*>(instance)->SelectHdl_Impl(data); } void SvxLinguTabPage
::SelectHdl_Impl(weld::TreeView& rBox)
1492{
1493 if (m_xLinguModulesCLB.get() == &rBox)
1494 {
1495 }
1496 else if (m_xLinguDicsCLB.get() == &rBox)
1497 {
1498 int nEntry = rBox.get_selected_index();
1499 if (nEntry != -1)
1500 {
1501 DicUserData aData(rBox.get_id(nEntry).toUInt32());
1502
1503 // always allow to edit (i.e. at least view the content of the dictionary)
1504 m_xLinguDicsEditPB->set_sensitive( true );
1505 m_xLinguDicsDelPB->set_sensitive( aData.IsDeletable() );
1506 }
1507 }
1508 else if (m_xLinguOptionsCLB.get() == &rBox)
1509 {
1510 int nEntry = rBox.get_selected_index();
1511 if (nEntry != -1)
1512 {
1513 OptionsUserData aData(rBox.get_id(nEntry).toUInt32());
1514 m_xLinguOptionsEditPB->set_sensitive( aData.HasNumericValue() );
1515 }
1516 }
1517 else
1518 {
1519 OSL_FAIL( "rBox unexpected value" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1519" ": "), "%s", "rBox unexpected value"); } } while (
false)
;
1520 }
1521}
1522
1523void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp )
1524{
1525 if ( 0 != ( GROUP_MODULES(sal_uInt16(0x0008)) & nGrp ) )
1526 {
1527 m_xLinguModulesFT->hide();
1528 m_xLinguModulesCLB->hide();
1529 m_xLinguModulesEditPB->hide();
1530
1531 if (officecfg::Office::Security::Hyperlinks::Open::get() != SvtExtendedSecurityOptions::OPEN_NEVER)
1532 {
1533 m_xMoreDictsLink->show();
1534 }
1535 }
1536}
1537
1538SvxEditModulesDlg::SvxEditModulesDlg(weld::Window* pParent, SvxLinguData_Impl& rData)
1539 : GenericDialogController(pParent, "cui/ui/editmodulesdialog.ui", "EditModulesDialog")
1540 , sSpell(CuiResId(RID_SVXSTR_SPELLreinterpret_cast<char const *>("RID_SVXSTR_SPELL" "\004"
u8"Spelling")
))
1541 , sHyph(CuiResId(RID_SVXSTR_HYPHreinterpret_cast<char const *>("RID_SVXSTR_HYPH" "\004"
u8"Hyphenation")
))
1542 , sThes(CuiResId(RID_SVXSTR_THESreinterpret_cast<char const *>("RID_SVXSTR_THES" "\004"
u8"Thesaurus")
))
1543 , sGrammar(CuiResId(RID_SVXSTR_GRAMMARreinterpret_cast<char const *>("RID_SVXSTR_GRAMMAR" "\004"
u8"Grammar")
))
1544 , rLinguData(rData)
1545 , m_xModulesCLB(m_xBuilder->weld_tree_view("lingudicts"))
1546 , m_xPrioUpPB(m_xBuilder->weld_button("up"))
1547 , m_xPrioDownPB(m_xBuilder->weld_button("down"))
1548 , m_xBackPB(m_xBuilder->weld_button("back"))
1549 , m_xMoreDictsLink(m_xBuilder->weld_link_button("moredictslink"))
1550 , m_xClosePB(m_xBuilder->weld_button("close"))
1551 , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("language")))
1552{
1553 m_xModulesCLB->set_size_request(m_xModulesCLB->get_approximate_digit_width() * 40,
1554 m_xModulesCLB->get_height_rows(12));
1555
1556 m_xModulesCLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
1557
1558 pDefaultLinguData.reset( new SvxLinguData_Impl( rLinguData ) );
1559
1560 m_xModulesCLB->connect_changed( LINK( this, SvxEditModulesDlg, SelectHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxEditModulesDlg
*>(this), &SvxEditModulesDlg::LinkStubSelectHdl_Impl)
);
1561 m_xModulesCLB->connect_toggled(LINK(this, SvxEditModulesDlg, BoxCheckButtonHdl_Impl)::tools::detail::makeLink( ::tools::detail::castTo<SvxEditModulesDlg
*>(this), &SvxEditModulesDlg::LinkStubBoxCheckButtonHdl_Impl
)
);
1562
1563 m_xClosePB->connect_clicked( LINK( this, SvxEditModulesDlg, ClickHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxEditModulesDlg
*>(this), &SvxEditModulesDlg::LinkStubClickHdl_Impl)
);
1564 m_xPrioUpPB->connect_clicked( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxEditModulesDlg
*>(this), &SvxEditModulesDlg::LinkStubUpDownHdl_Impl)
);
1565 m_xPrioDownPB->connect_clicked( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxEditModulesDlg
*>(this), &SvxEditModulesDlg::LinkStubUpDownHdl_Impl)
);
1566 m_xBackPB->connect_clicked( LINK( this, SvxEditModulesDlg, BackHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxEditModulesDlg
*>(this), &SvxEditModulesDlg::LinkStubBackHdl_Impl)
);
1567 // in case of not installed language modules
1568 m_xPrioUpPB->set_sensitive( false );
1569 m_xPrioDownPB->set_sensitive( false );
1570
1571 if (officecfg::Office::Security::Hyperlinks::Open::get() == SvtExtendedSecurityOptions::OPEN_NEVER)
1572 m_xMoreDictsLink->hide();
1573
1574 // set that we want the checkbox shown if spellchecking is available
1575 m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::EMPTY, false, false, true);
1576
1577 //fill language box
1578 const Sequence< Locale >& rLoc = rLinguData.GetAllSupportedLocales();
1579 for (Locale const & locale : rLoc)
1580 {
1581 LanguageType nLang = LanguageTag::convertToLanguageType( locale );
1582 m_xLanguageLB->InsertLanguage(nLang);
1583 }
1584 LanguageType eSysLang = MsLangId::getSystemLanguage();
1585 m_xLanguageLB->set_active_id( eSysLang );
1586 if (m_xLanguageLB->get_active_id() != eSysLang)
1587 m_xLanguageLB->set_active(0);
1588
1589 m_xLanguageLB->connect_changed( LINK( this, SvxEditModulesDlg, LangSelectListBoxHdl_Impl )::tools::detail::makeLink( ::tools::detail::castTo<SvxEditModulesDlg
*>(this), &SvxEditModulesDlg::LinkStubLangSelectListBoxHdl_Impl
)
);
1590 LangSelectHdl_Impl(m_xLanguageLB.get());
1591}
1592
1593SvxEditModulesDlg::~SvxEditModulesDlg()
1594{
1595 for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
1596 delete reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
1597}
1598
1599IMPL_LINK( SvxEditModulesDlg, SelectHdl_Impl, weld::TreeView&, rBox, void )void SvxEditModulesDlg::LinkStubSelectHdl_Impl(void * instance
, weld::TreeView& data) { return static_cast<SvxEditModulesDlg
*>(instance)->SelectHdl_Impl(data); } void SvxEditModulesDlg
::SelectHdl_Impl(weld::TreeView& rBox)
1600{
1601 int nCurPos = rBox.get_selected_index();
1602 if (nCurPos == -1)
1603 return;
1604
1605 bool bDisableUp = true;
1606 bool bDisableDown = true;
1607 ModuleUserData_Impl* pData = reinterpret_cast<ModuleUserData_Impl*>(rBox.get_id(nCurPos).toInt64());
1608 if (!pData->IsParent() && pData->GetType() != TYPE_HYPHsal_uInt8(3))
1609 {
1610 if (nCurPos < rBox.n_children() - 1)
1611 {
1612 bDisableDown = reinterpret_cast<ModuleUserData_Impl*>(rBox.get_id(nCurPos + 1).toInt64())->IsParent();
1613 }
1614 if (nCurPos > 1)
1615 {
1616 bDisableUp = reinterpret_cast<ModuleUserData_Impl*>(rBox.get_id(nCurPos - 1).toInt64())->IsParent();
1617 }
1618 }
1619 m_xPrioUpPB->set_sensitive(!bDisableUp);
1620 m_xPrioDownPB->set_sensitive(!bDisableDown);
1621}
1622
1623IMPL_LINK( SvxEditModulesDlg, BoxCheckButtonHdl_Impl, const weld::TreeView::iter_col&, rRowCol, void )void SvxEditModulesDlg::LinkStubBoxCheckButtonHdl_Impl(void *
instance, const weld::TreeView::iter_col& data) { return
static_cast<SvxEditModulesDlg *>(instance)->BoxCheckButtonHdl_Impl
(data); } void SvxEditModulesDlg::BoxCheckButtonHdl_Impl(const
weld::TreeView::iter_col& rRowCol)
1624{
1625 ModuleUserData_Impl* pData = reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(rRowCol.first).toInt64());
1626 if (pData->IsParent() || pData->GetType() != TYPE_HYPHsal_uInt8(3))
1627 return;
1628
1629 // make hyphenator checkboxes function as radio-buttons
1630 // (at most one box may be checked)
1631 auto nPos = m_xModulesCLB->get_iter_index_in_parent(rRowCol.first);
1632 for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
1633 {
1634 pData = reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
1635 if (!pData->IsParent() && pData->GetType() == TYPE_HYPHsal_uInt8(3) && i != nPos)
1636 {
1637 m_xModulesCLB->set_toggle(i, TRISTATE_FALSE);
1638 }
1639 }
1640}
1641
1642IMPL_LINK_NOARG(SvxEditModulesDlg, LangSelectListBoxHdl_Impl, weld::ComboBox&, void)void SvxEditModulesDlg::LinkStubLangSelectListBoxHdl_Impl(void
* instance, weld::ComboBox& data) { return static_cast<
SvxEditModulesDlg *>(instance)->LangSelectListBoxHdl_Impl
(data); } void SvxEditModulesDlg::LangSelectListBoxHdl_Impl(__attribute__
((unused)) weld::ComboBox&)
1643{
1644 LangSelectHdl_Impl(m_xLanguageLB.get());
1645}
1646
1647void SvxEditModulesDlg::LangSelectHdl_Impl(const SvxLanguageBox* pBox)
1648{
1649 LanguageType eCurLanguage = m_xLanguageLB->get_active_id();
1650 static Locale aLastLocale;
1651 Locale aCurLocale( LanguageTag::convertToLocale( eCurLanguage));
1652
1653 if (pBox)
1654 {
1655 // save old probably changed settings
1656 // before switching to new language entries
1657
1658 LanguageType nLang = LanguageTag::convertToLanguageType( aLastLocale );
1659
1660 sal_Int32 nStart = 0, nLocalIndex = 0;
1661 Sequence< OUString > aChange;
1662 bool bChanged = false;
1663 for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
1664 {
1665 ModuleUserData_Impl* pData = reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
1666 if (pData->IsParent())
1667 {
1668 if (bChanged)
1669 {
1670 LangImplNameTable *pTable = nullptr;
1671 sal_uInt8 nType = pData->GetType();
1672 switch (nType - 1)
1673 {
1674 case TYPE_SPELLsal_uInt8(1) : pTable = &rLinguData.GetSpellTable(); break;
1675 case TYPE_GRAMMARsal_uInt8(2) : pTable = &rLinguData.GetGrammarTable(); break;
1676 case TYPE_HYPHsal_uInt8(3) : pTable = &rLinguData.GetHyphTable(); break;
1677 case TYPE_THESsal_uInt8(4) : pTable = &rLinguData.GetThesTable(); break;
1678 }
1679 if (pTable)
1680 {
1681 aChange.realloc(nStart);
1682 (*pTable)[ nLang ] = aChange;
1683 }
1684 }
1685 nLocalIndex = nStart = 0;
1686 aChange.realloc(nEntryCount);
1687 bChanged = false;
1688 }
1689 else
1690 {
1691 OUString* pChange = aChange.getArray();
1692 pChange[nStart] = pData->GetImplName();
1693 bChanged |= pData->GetIndex() != nLocalIndex ||
1694 static_cast<TriState>(pData->IsChecked()) != m_xModulesCLB->get_toggle(i);
1695 if (m_xModulesCLB->get_toggle(i))
1696 nStart++;
1697 ++nLocalIndex;
1698 }
1699 }
1700 if(bChanged)
1701 {
1702 aChange.realloc(nStart);
1703 rLinguData.GetThesTable()[ nLang ] = aChange;
1704 }
1705 }
1706
1707 for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i)
1708 delete reinterpret_cast<ModuleUserData_Impl*>(m_xModulesCLB->get_id(i).toInt64());
1709 m_xModulesCLB->clear();
1710
1711 // display entries for new selected language
1712
1713 if (LANGUAGE_DONTKNOWLanguageType(0x03FF) != eCurLanguage)
1714 {
1715 sal_Int32 n;
1716 ServiceInfo_Impl* pInfo;
1717
1718 int nRow = 0;
1719 // spellchecker entries
1720
1721 ModuleUserData_Impl* pUserData = new ModuleUserData_Impl(
1722 OUString(), true, false, TYPE_SPELLsal_uInt8(1), 0 );
1723 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pUserData)));
1724 m_xModulesCLB->append(nullptr);
1725 m_xModulesCLB->set_id(nRow, sId);
1726 m_xModulesCLB->set_text(nRow, sSpell, 0);
1727 m_xModulesCLB->set_text_emphasis(nRow, true, 0);
1728 ++nRow;
1729
1730 Sequence< OUString > aNames( rLinguData.GetSortedImplNames( eCurLanguage, TYPE_SPELLsal_uInt8(1) ) );
1731 const OUString *pName = aNames.getConstArray();
1732 sal_Int32 nNames = aNames.getLength();
1733 sal_Int32 nLocalIndex = 0; // index relative to parent
1734 for (n = 0; n < nNames; ++n)
1735 {
1736 OUString aImplName;
1737 bool bIsSuppLang = false;
1738
1739 pInfo = rLinguData.GetInfoByImplName( pName[n] );
1740 if (pInfo)
1741 {
1742 bIsSuppLang = pInfo->xSpell.is() &&
1743 pInfo->xSpell->hasLocale( aCurLocale );
1744 aImplName = pInfo->sSpellImplName;
1745 }
1746 if (!aImplName.isEmpty() && bIsSuppLang)
1747 {
1748 OUString aTxt( pInfo->sDisplayName );
1749
1750 LangImplNameTable &rTable = rLinguData.GetSpellTable();
1751 const bool bHasLang = rTable.count( eCurLanguage );
1752 if (!bHasLang)
1753 {
1754 SAL_INFO( "cui.options", "language entry missing" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "cui.options")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "language entry missing"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1754" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1754" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "language entry missing") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1754" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1754" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
; // only relevant if all languages found should be supported
1755 }
1756 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
1757 pUserData = new ModuleUserData_Impl( aImplName, false,
1758 bCheck, TYPE_SPELLsal_uInt8(1), static_cast<sal_uInt8>(nLocalIndex++) );
1759 sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
1760
1761 m_xModulesCLB->append(nullptr);
1762 m_xModulesCLB->set_id(nRow, sId);
1763 m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE);
1764 m_xModulesCLB->set_text(nRow, aTxt, 0);
1765 m_xModulesCLB->set_text_emphasis(nRow, false, 0);
1766 ++nRow;
1767 }
1768 }
1769
1770 // grammar checker entries
1771
1772 pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_GRAMMARsal_uInt8(2), 0 );
1773 sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
1774 m_xModulesCLB->append(nullptr);
1775 m_xModulesCLB->set_id(nRow, sId);
1776 m_xModulesCLB->set_text(nRow, sGrammar, 0);
1777 m_xModulesCLB->set_text_emphasis(nRow, true, 0);
1778 ++nRow;
1779
1780 aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_GRAMMARsal_uInt8(2) );
1781 pName = aNames.getConstArray();
1782 nNames = aNames.getLength();
1783 nLocalIndex = 0;
1784 for (n = 0; n < nNames; ++n)
1785 {
1786 OUString aImplName;
1787 bool bIsSuppLang = false;
1788
1789 pInfo = rLinguData.GetInfoByImplName( pName[n] );
1790 if (pInfo)
1791 {
1792 bIsSuppLang = pInfo->xGrammar.is() &&
1793 pInfo->xGrammar->hasLocale( aCurLocale );
1794 aImplName = pInfo->sGrammarImplName;
1795 }
1796 if (!aImplName.isEmpty() && bIsSuppLang)
1797 {
1798 OUString aTxt( pInfo->sDisplayName );
1799
1800 LangImplNameTable &rTable = rLinguData.GetGrammarTable();
1801 const bool bHasLang = rTable.count( eCurLanguage );
1802 if (!bHasLang)
1803 {
1804 SAL_INFO( "cui.options", "language entry missing" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "cui.options")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "language entry missing"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1804" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1804" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "language entry missing") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1804" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1804" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
; // only relevant if all languages found should be supported
1805 }
1806 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
1807 pUserData = new ModuleUserData_Impl( aImplName, false,
1808 bCheck, TYPE_GRAMMARsal_uInt8(2), static_cast<sal_uInt8>(nLocalIndex++) );
1809
1810 sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
1811
1812 m_xModulesCLB->append(nullptr);
1813 m_xModulesCLB->set_id(nRow, sId);
1814 m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE);
1815 m_xModulesCLB->set_text(nRow, aTxt, 0);
1816 m_xModulesCLB->set_text_emphasis(nRow, false, 0);
1817 ++nRow;
1818 }
1819 }
1820
1821 // hyphenator entries
1822
1823 pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_HYPHsal_uInt8(3), 0 );
1824 sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
1825 m_xModulesCLB->append(nullptr);
1826 m_xModulesCLB->set_id(nRow, sId);
1827 m_xModulesCLB->set_text(nRow, sHyph, 0);
1828 m_xModulesCLB->set_text_emphasis(nRow, true, 0);
1829 ++nRow;
1830
1831 aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_HYPHsal_uInt8(3) );
1832 pName = aNames.getConstArray();
1833 nNames = aNames.getLength();
1834 nLocalIndex = 0;
1835 for (n = 0; n < nNames; ++n)
1836 {
1837 OUString aImplName;
1838 bool bIsSuppLang = false;
1839
1840 pInfo = rLinguData.GetInfoByImplName( pName[n] );
1841 if (pInfo)
1842 {
1843 bIsSuppLang = pInfo->xHyph.is() &&
1844 pInfo->xHyph->hasLocale( aCurLocale );
1845 aImplName = pInfo->sHyphImplName;
1846 }
1847 if (!aImplName.isEmpty() && bIsSuppLang)
1848 {
1849 OUString aTxt( pInfo->sDisplayName );
1850
1851 LangImplNameTable &rTable = rLinguData.GetHyphTable();
1852 const bool bHasLang = rTable.count( eCurLanguage );
1853 if (!bHasLang)
1854 {
1855 SAL_INFO( "cui.options", "language entry missing" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "cui.options")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "language entry missing"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1855" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1855" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "language entry missing") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1855" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1855" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
; // only relevant if all languages found should be supported
1856 }
1857 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
1858 pUserData = new ModuleUserData_Impl( aImplName, false,
1859 bCheck, TYPE_HYPHsal_uInt8(3), static_cast<sal_uInt8>(nLocalIndex++) );
1860 sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
1861
1862 m_xModulesCLB->append(nullptr);
1863 m_xModulesCLB->set_id(nRow, sId);
1864 m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE);
1865 m_xModulesCLB->set_text(nRow, aTxt, 0);
1866 m_xModulesCLB->set_text_emphasis(nRow, false, 0);
1867 ++nRow;
1868 }
1869 }
1870
1871 // thesaurus entries
1872
1873 pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_THESsal_uInt8(4), 0 );
1874 sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
1875 m_xModulesCLB->append(nullptr);
1876 m_xModulesCLB->set_id(nRow, sId);
1877 m_xModulesCLB->set_text(nRow, sThes, 0);
1878 m_xModulesCLB->set_text_emphasis(nRow, true, 0);
1879 ++nRow;
1880
1881 aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_THESsal_uInt8(4) );
1882 pName = aNames.getConstArray();
1883 nNames = aNames.getLength();
1884 nLocalIndex = 0;
1885 for (n = 0; n < nNames; ++n)
1886 {
1887 OUString aImplName;
1888 bool bIsSuppLang = false;
1889
1890 pInfo = rLinguData.GetInfoByImplName( pName[n] );
1891 if (pInfo)
1892 {
1893 bIsSuppLang = pInfo->xThes.is() &&
1894 pInfo->xThes->hasLocale( aCurLocale );
1895 aImplName = pInfo->sThesImplName;
1896 }
1897 if (!aImplName.isEmpty() && bIsSuppLang)
1898 {
1899 OUString aTxt( pInfo->sDisplayName );
1900
1901 LangImplNameTable &rTable = rLinguData.GetThesTable();
1902 const bool bHasLang = rTable.count( eCurLanguage );
1903 if (!bHasLang)
1904 {
1905 SAL_INFO( "cui.options", "language entry missing" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "cui.options")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "language entry missing"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"
), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1905" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1905" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "language entry missing") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1905" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "language entry missing"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"language entry missing"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("cui.options"), ("/home/maarten/src/libreoffice/core/cui/source/options/optlingu.cxx"
":" "1905" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
; // only relevant if all languages found should be supported
1906 }
1907 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
1908 pUserData = new ModuleUserData_Impl( aImplName, false,
1909 bCheck, TYPE_THESsal_uInt8(4), static_cast<sal_uInt8>(nLocalIndex++) );
1910 sId = OUString::number(reinterpret_cast<sal_Int64>(pUserData));
1911
1912 m_xModulesCLB->append(nullptr);
1913 m_xModulesCLB->set_id(nRow, sId);
1914 m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE);
1915 m_xModulesCLB->set_text(nRow, aTxt, 0);
1916 m_xModulesCLB->set_text_emphasis(nRow, false, 0);
1917 ++nRow;
1918 }
1919 }
1920 }
1921 aLastLocale = aCurLocale;
1922}
1923
1924IMPL_LINK( SvxEditModulesDlg, UpDownHdl_Impl, weld::Button&, rBtn, void )void SvxEditModulesDlg::LinkStubUpDownHdl_Impl(void * instance
, weld::Button& data) { return static_cast<SvxEditModulesDlg
*>(instance)->UpDownHdl_Impl(data); } void SvxEditModulesDlg
::UpDownHdl_Impl(weld::Button& rBtn)
1925{
1926 bool bUp = m_xPrioUpPB.get() == &rBtn;
1927 int nCurPos = m_xModulesCLB->get_selected_index();
1928 if (nCurPos == -1)
1929 return;
1930
1931 m_xModulesCLB->freeze();
1932
1933 OUString sId(m_xModulesCLB->get_id(nCurPos));
1934 OUString sStr(m_xModulesCLB->get_text(nCurPos));
1935 bool bIsChecked = m_xModulesCLB->get_toggle(nCurPos);
1936
1937 m_xModulesCLB->remove(nCurPos);
1938
1939 int nDestPos = bUp ? nCurPos - 1 : nCurPos + 1;
1940
1941 m_xModulesCLB->insert_text(nDestPos, sStr);
1942 m_xModulesCLB->set_id(nDestPos, sId);
1943 m_xModulesCLB->set_toggle(nDestPos, bIsChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
1944
1945 m_xModulesCLB->thaw();
1946
1947 m_xModulesCLB->select(nDestPos);
1948 SelectHdl_Impl(*m_xModulesCLB);
1949}
1950
1951IMPL_LINK_NOARG(SvxEditModulesDlg, ClickHdl_Impl, weld::Button&, void)void SvxEditModulesDlg::LinkStubClickHdl_Impl(void * instance
, weld::Button& data) { return static_cast<SvxEditModulesDlg
*>(instance)->ClickHdl_Impl(data); } void SvxEditModulesDlg
::ClickHdl_Impl(__attribute__ ((unused)) weld::Button&)
1952{
1953 // store language config
1954 LangSelectHdl_Impl(m_xLanguageLB.get());
1955 m_xDialog->response(RET_OK);
1956}
1957
1958IMPL_LINK_NOARG(SvxEditModulesDlg, BackHdl_Impl, weld::Button&, void)void SvxEditModulesDlg::LinkStubBackHdl_Impl(void * instance,
weld::Button& data) { return static_cast<SvxEditModulesDlg
*>(instance)->BackHdl_Impl(data); } void SvxEditModulesDlg
::BackHdl_Impl(__attribute__ ((unused)) weld::Button&)
1959{
1960 rLinguData = *pDefaultLinguData;
1961 LangSelectHdl_Impl(nullptr);
1962}
1963
1964/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
25
Calling 'Reference::get'
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
7
Calling implicit copy constructor for 'VclPtr<AbstractSvxNewDictionaryDialog>'
8
Calling copy constructor for 'Reference<AbstractSvxNewDictionaryDialog>'
11
Returning from copy constructor for 'Reference<AbstractSvxNewDictionaryDialog>'
12
Returning from copy constructor for 'VclPtr<AbstractSvxNewDictionaryDialog>'
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
9
Assuming field 'm_pBody' is non-null
10
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody
15.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
)
16
Taking true branch
113 m_pBody->release();
17
Calling 'VclReferenceBase::release'
21
Returning; memory was released
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
26
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
18
Assuming the condition is true
19
Taking true branch
40 delete this;
20
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif