xref: /core/cui/source/tabpages/autocdlg.cxx (revision 39dfb639)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <i18nutil/unicode.hxx>
23 #include <o3tl/safeint.hxx>
24 #include <utility>
25 #include <vcl/event.hxx>
26 #include <vcl/keycodes.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/transfer.hxx>
29 #include <sfx2/app.hxx>
30 #include <sfx2/objsh.hxx>
31 #include <sfx2/viewsh.hxx>
32 #include <unotools/charclass.hxx>
33 #include <unotools/collatorwrapper.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <vcl/svapp.hxx>
36 #include <sfx2/module.hxx>
37 #include <svl/eitem.hxx>
38 #include <svl/cjkoptions.hxx>
39 #include <svl/ctloptions.hxx>
40 #include <svx/SmartTagMgr.hxx>
41 #include <com/sun/star/smarttags/XSmartTagRecognizer.hpp>
42 #include <rtl/strbuf.hxx>
43 #include <o3tl/temporary.hxx>
44 #include <osl/diagnose.h>
45 #include <tools/debug.hxx>
46 
47 #include <autocdlg.hxx>
48 #include <editeng/acorrcfg.hxx>
49 #include <editeng/svxacorr.hxx>
50 #include <svx/cuicharmap.hxx>
51 #include <strings.hrc>
52 #include <dialmgr.hxx>
53 #include <svx/svxids.hrc>
54 
55 static LanguageType eLastDialogLanguage = LANGUAGE_SYSTEM;
56 
57 using namespace ::com::sun::star;
58 
OfaAutoCorrDlg(weld::Window * pParent,const SfxItemSet * _pSet)59 OfaAutoCorrDlg::OfaAutoCorrDlg(weld::Window* pParent, const SfxItemSet* _pSet )
60     : SfxTabDialogController(pParent, u"cui/ui/autocorrectdialog.ui"_ustr, u"AutoCorrectDialog"_ustr, _pSet)
61     , m_xLanguageBox(m_xBuilder->weld_widget(u"langbox"_ustr))
62     , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"lang"_ustr)))
63 {
64     bool bShowSWOptions = false;
65     bool bOpenSmartTagOptions = false;
66 
67     if ( _pSet )
68     {
69         const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(_pSet, SID_AUTO_CORRECT_DLG, false);
70         if ( pItem && pItem->GetValue() )
71             bShowSWOptions = true;
72 
73         const SfxBoolItem* pItem2 = SfxItemSet::GetItem<SfxBoolItem>(_pSet, SID_OPEN_SMARTTAGOPTIONS, false);
74         if ( pItem2 && pItem2->GetValue() )
75             bOpenSmartTagOptions = true;
76     }
77 
78     AddTabPage(u"options"_ustr, OfaAutocorrOptionsPage::Create, nullptr);
79     AddTabPage(u"applypage"_ustr, OfaSwAutoFmtOptionsPage::Create, nullptr);
80     AddTabPage(u"wordcompletion"_ustr, OfaAutoCompleteTabPage::Create, nullptr);
81     AddTabPage(u"smarttags"_ustr, OfaSmartTagOptionsTabPage::Create, nullptr);
82 
83     if (!bShowSWOptions)
84     {
85         RemoveTabPage(u"applypage"_ustr);
86         RemoveTabPage(u"wordcompletion"_ustr);
87         RemoveTabPage(u"smarttags"_ustr);
88     }
89     else
90     {
91         // remove smart tag tab page if no extensions are installed
92         SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
93         SvxSwAutoFormatFlags& rOpt = pAutoCorrect->GetSwFlags();
94         if (!rOpt.pSmartTagMgr || 0 == rOpt.pSmartTagMgr->NumberOfRecognizers())
95             RemoveTabPage(u"smarttags"_ustr);
96 
97         RemoveTabPage(u"options"_ustr);
98     }
99 
100     AddTabPage(u"replace"_ustr, OfaAutocorrReplacePage::Create, nullptr);
101     AddTabPage(u"exceptions"_ustr,  OfaAutocorrExceptPage::Create, nullptr);
102     AddTabPage(u"localized"_ustr, OfaQuoteTabPage::Create, nullptr);
103 
104     // initialize languages
105     //! LANGUAGE_NONE is displayed as '[All]' and the LanguageType
106     //! will be set to LANGUAGE_UNDETERMINED
107     SvxLanguageListFlags nLangList = SvxLanguageListFlags::WESTERN;
108 
109     if( SvtCTLOptions::IsCTLFontEnabled() )
110         nLangList |= SvxLanguageListFlags::CTL;
111     if( SvtCJKOptions::IsCJKFontEnabled() )
112         nLangList |= SvxLanguageListFlags::CJK;
113     m_xLanguageLB->SetLanguageList( nLangList, true, true );
114     m_xLanguageLB->set_active_id( LANGUAGE_NONE );
115     int nPos = m_xLanguageLB->get_active();
116     DBG_ASSERT(nPos != -1, "listbox entry missing" );
117     m_xLanguageLB->set_id(nPos, LANGUAGE_UNDETERMINED);
118 
119     // Initializing doesn't work for static on linux - therefore here
120     if (LANGUAGE_SYSTEM == eLastDialogLanguage)
121         eLastDialogLanguage = Application::GetSettings().GetLanguageTag().getLanguageType();
122 
123     LanguageType nSelectLang = LANGUAGE_UNDETERMINED;
124     nPos = m_xLanguageLB->find_id(eLastDialogLanguage);
125     if (nPos != -1)
126         nSelectLang = eLastDialogLanguage;
127     m_xLanguageLB->set_active_id(nSelectLang);
128 
129     m_xLanguageLB->connect_changed(LINK(this, OfaAutoCorrDlg, SelectLanguageHdl));
130 
131     if ( bOpenSmartTagOptions )
132         SetCurPageId(u"smarttags"_ustr);
133 }
134 
~OfaAutoCorrDlg()135 OfaAutoCorrDlg::~OfaAutoCorrDlg()
136 {
137 }
138 
EnableLanguage(bool bEnable)139 void OfaAutoCorrDlg::EnableLanguage(bool bEnable)
140 {
141     m_xLanguageBox->set_sensitive(bEnable);
142 }
143 
lcl_FindEntry(weld::TreeView & rLB,const OUString & rEntry,CollatorWrapper const & rCmpClass)144 static bool lcl_FindEntry(weld::TreeView& rLB, const OUString& rEntry,
145                           CollatorWrapper const & rCmpClass)
146 {
147     int nCount = rLB.n_children();
148     int nSelPos = rLB.get_selected_index();
149     for (int i = 0; i < nCount; i++)
150     {
151         if (0 == rCmpClass.compareString(rEntry, rLB.get_text(i)))
152         {
153             rLB.select(i);
154             return true;
155         }
156     }
157     if (nSelPos != -1)
158         rLB.unselect(nSelPos);
159     return false;
160 }
161 
IMPL_LINK_NOARG(OfaAutoCorrDlg,SelectLanguageHdl,weld::ComboBox &,void)162 IMPL_LINK_NOARG(OfaAutoCorrDlg, SelectLanguageHdl, weld::ComboBox&, void)
163 {
164     LanguageType eNewLang = m_xLanguageLB->get_active_id();
165     // save old settings and fill anew
166     if(eNewLang == eLastDialogLanguage)
167         return;
168 
169     OUString sPageId = GetCurPageId();
170     if (sPageId == "replace")
171     {
172         OfaAutocorrReplacePage* pPage = static_cast<OfaAutocorrReplacePage*>(GetTabPage(sPageId));
173         assert(pPage);
174         pPage->SetLanguage(eNewLang);
175     }
176     else if (sPageId == "exceptions")
177     {
178         OfaAutocorrExceptPage* pPage = static_cast<OfaAutocorrExceptPage*>(GetTabPage(sPageId));
179         assert(pPage);
180         pPage->SetLanguage(eNewLang);
181     }
182 }
183 
OfaAutocorrOptionsPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)184 OfaAutocorrOptionsPage::OfaAutocorrOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
185     : SfxTabPage(pPage, pController, u"cui/ui/acoroptionspage.ui"_ustr, u"AutocorrectOptionsPage"_ustr, &rSet)
186     , m_sInput(CuiResId(RID_CUISTR_USE_REPLACE))
187     , m_sDoubleCaps(CuiResId(RID_CUISTR_CPTL_STT_WORD))
188     , m_sStartCap(CuiResId(RID_CUISTR_CPTL_STT_SENT))
189     , m_sBoldUnderline(CuiResId(RID_CUISTR_BOLD_UNDER))
190     , m_sURL(CuiResId(RID_CUISTR_DETECT_URL))
191     , m_sDOI(CuiResId(RID_CUISTR_DETECT_DOI))
192     , m_sNoDblSpaces(CuiResId(RID_CUISTR_NO_DBL_SPACES))
193     , m_sDash(CuiResId(RID_CUISTR_DASH))
194     , m_sAccidentalCaps(CuiResId(RID_CUISTR_CORRECT_ACCIDENTAL_CAPS_LOCK))
195     , m_xCheckLB(m_xBuilder->weld_tree_view(u"checklist"_ustr))
196 {
197     m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
198     m_xCheckLB->set_size_request(-1, m_xCheckLB->get_height_rows(10));
199 }
200 
~OfaAutocorrOptionsPage()201 OfaAutocorrOptionsPage::~OfaAutocorrOptionsPage()
202 {
203 }
204 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)205 std::unique_ptr<SfxTabPage> OfaAutocorrOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController,
206                                                            const SfxItemSet* rSet)
207 {
208     return std::make_unique<OfaAutocorrOptionsPage>(pPage, pController, *rSet);
209 }
210 
211 #define CBCOL_FIRST     0
212 #define CBCOL_SECOND    1
213 #define CBCOL_BOTH      2
214 
FillItemSet(SfxItemSet *)215 bool OfaAutocorrOptionsPage::FillItemSet( SfxItemSet* )
216 {
217     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
218     ACFlags nFlags = pAutoCorrect->GetFlags();
219 
220     int nPos = 0;
221     pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect,          m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
222     pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord,     m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
223     pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
224     pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl,      m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
225     pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr,          m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
226     pAutoCorrect->SetAutoCorrFlag(ACFlags::SetDOIAttr,           m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
227     pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash,        m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
228     pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace,    m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
229     pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock,      m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
230 
231     bool bReturn = nFlags != pAutoCorrect->GetFlags();
232     if(bReturn )
233     {
234         SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
235         rCfg.SetModified();
236         rCfg.Commit();
237     }
238     return bReturn;
239 }
240 
ActivatePage(const SfxItemSet &)241 void    OfaAutocorrOptionsPage::ActivatePage( const SfxItemSet& )
242 {
243     static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false);
244 }
245 
InsertEntry(const OUString & rTxt)246 void OfaAutocorrOptionsPage::InsertEntry(const OUString& rTxt)
247 {
248     m_xCheckLB->append();
249     const int nRow = m_xCheckLB->n_children() - 1;
250     m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE);
251     m_xCheckLB->set_text(nRow, rTxt, 0);
252 }
253 
Reset(const SfxItemSet *)254 void OfaAutocorrOptionsPage::Reset( const SfxItemSet* )
255 {
256     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
257     const ACFlags nFlags = pAutoCorrect->GetFlags();
258 
259     m_xCheckLB->freeze();
260     m_xCheckLB->clear();
261 
262     InsertEntry(m_sInput);
263     InsertEntry(m_sDoubleCaps);
264     InsertEntry(m_sStartCap);
265     InsertEntry(m_sBoldUnderline);
266     InsertEntry(m_sURL);
267     InsertEntry(m_sDOI);
268     InsertEntry(m_sDash);
269     InsertEntry(m_sNoDblSpaces);
270     InsertEntry(m_sAccidentalCaps);
271 
272     int nPos = 0;
273     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE );
274     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE );
275     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE );
276     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE );
277     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE );
278     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::SetDOIAttr) ? TRISTATE_TRUE : TRISTATE_FALSE );
279     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE );
280     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE );
281     m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE );
282 
283     m_xCheckLB->thaw();
284 }
285 
286 /*********************************************************************/
287 /*                                                                   */
288 /*  helping struct for dUserData of the Checklistbox                 */
289 /*                                                                   */
290 /*********************************************************************/
291 
292 namespace {
293 
294 struct ImpUserData
295 {
296     OUString  *pString;
297     vcl::Font *pFont;
298 
ImpUserData__anonffeffcef0111::ImpUserData299     ImpUserData(OUString* pText, vcl::Font* pFnt)
300         { pString = pText; pFont = pFnt;}
301 };
302 
303 
304 /*********************************************************************/
305 /*                                                                   */
306 /*  dialog for per cent settings                                     */
307 /*                                                                   */
308 /*********************************************************************/
309 
310 class OfaAutoFmtPrcntSet : public weld::GenericDialogController
311 {
312     std::unique_ptr<weld::MetricSpinButton> m_xPrcntMF;
313 public:
OfaAutoFmtPrcntSet(weld::Window * pParent)314     explicit OfaAutoFmtPrcntSet(weld::Window* pParent)
315         : GenericDialogController(pParent, u"cui/ui/percentdialog.ui"_ustr, u"PercentDialog"_ustr)
316         , m_xPrcntMF(m_xBuilder->weld_metric_spin_button(u"margin"_ustr, FieldUnit::PERCENT))
317     {
318     }
319 
GetPrcntFld()320     weld::MetricSpinButton& GetPrcntFld()
321     {
322         return *m_xPrcntMF;
323     }
324 };
325 
326 /*********************************************************************/
327 /*                                                                   */
328 /*  use TabPage autoformat                                           */
329 /*                                                                   */
330 /*********************************************************************/
331 
332 enum OfaAutoFmtOptions
333 {
334     USE_REPLACE_TABLE,
335     CORR_UPPER,
336     BEGIN_UPPER,
337     BOLD_UNDERLINE,
338     DETECT_URL,
339     DETECT_DOI,
340     REPLACE_DASHES,
341     DEL_SPACES_AT_STT_END,
342     DEL_SPACES_BETWEEN_LINES,
343     IGNORE_DBLSPACE,
344     CORRECT_CAPS_LOCK,
345     APPLY_NUMBERING,
346     APPLY_NUMBERING_AFTER_SPACE,
347     INSERT_BORDER,
348     CREATE_TABLE,
349     REPLACE_STYLES,
350     DEL_EMPTY_NODE,
351     REPLACE_USER_COLL,
352     REPLACE_BULLETS,
353     MERGE_SINGLE_LINE_PARA
354 };
355 
356 }
357 
OfaSwAutoFmtOptionsPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)358 OfaSwAutoFmtOptionsPage::OfaSwAutoFmtOptionsPage(weld::Container* pPage, weld::DialogController* pController,
359                                                  const SfxItemSet& rSet )
360     : SfxTabPage(pPage, pController, u"cui/ui/applyautofmtpage.ui"_ustr, u"ApplyAutoFmtPage"_ustr, &rSet)
361     , sDeleteEmptyPara(CuiResId(RID_CUISTR_DEL_EMPTY_PARA))
362     , sUseReplaceTbl(CuiResId(RID_CUISTR_USE_REPLACE))
363     , sCapitalStartWord(CuiResId(RID_CUISTR_CPTL_STT_WORD))
364     , sCapitalStartSentence(CuiResId(RID_CUISTR_CPTL_STT_SENT))
365     , sUserStyle(CuiResId(RID_CUISTR_USER_STYLE))
366     , sBullet(CuiResId(RID_CUISTR_BULLET))
367     , sBoldUnder(CuiResId(RID_CUISTR_BOLD_UNDER))
368     , sNoDblSpaces(CuiResId(RID_CUISTR_NO_DBL_SPACES))
369     , sCorrectCapsLock(CuiResId(RID_CUISTR_CORRECT_ACCIDENTAL_CAPS_LOCK))
370     , sDetectURL(CuiResId(RID_CUISTR_DETECT_URL))
371     , sDetectDOI(CuiResId(RID_CUISTR_DETECT_DOI))
372     , sDash(CuiResId(RID_CUISTR_DASH))
373     , sRightMargin(CuiResId(RID_CUISTR_RIGHT_MARGIN))
374     , sNum(CuiResId(RID_CUISTR_NUM))
375     , sBulletsAfterSpace(CuiResId(RID_SVXSTR_NUM_FORMAT_AFTER_SPACE))
376     , sBorder(CuiResId(RID_CUISTR_BORDER))
377     , sTable(CuiResId(RID_CUISTR_CREATE_TABLE))
378     , sReplaceTemplates(CuiResId(RID_CUISTR_REPLACE_TEMPLATES))
379     , sDelSpaceAtSttEnd(CuiResId(RID_CUISTR_DEL_SPACES_AT_STT_END))
380     , sDelSpaceBetweenLines(CuiResId(RID_CUISTR_DEL_SPACES_BETWEEN_LINES))
381     , nPercent(50)
382     , m_xCheckLB(m_xBuilder->weld_tree_view(u"list"_ustr))
383     , m_xEditPB(m_xBuilder->weld_button(u"edit"_ustr))
384 {
385     m_xCheckLB->connect_changed(LINK(this, OfaSwAutoFmtOptionsPage, SelectHdl));
386     m_xCheckLB->connect_row_activated(LINK(this, OfaSwAutoFmtOptionsPage, DoubleClickEditHdl));
387 
388     std::vector<int> aWidths
389     {
390         o3tl::narrowing<int>(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(0)).Width() * 2),
391         o3tl::narrowing<int>(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(1)).Width() * 2)
392     };
393     m_xCheckLB->set_column_fixed_widths(aWidths);
394 
395     m_xEditPB->connect_clicked(LINK(this, OfaSwAutoFmtOptionsPage, EditHdl));
396 }
397 
CreateEntry(const OUString & rTxt,sal_uInt16 nCol)398 void OfaSwAutoFmtOptionsPage::CreateEntry(const OUString& rTxt, sal_uInt16 nCol)
399 {
400     m_xCheckLB->append();
401     const int nRow = m_xCheckLB->n_children() - 1;
402     if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH)
403         m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST);
404     if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH)
405         m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND);
406     m_xCheckLB->set_text(nRow, rTxt, 2);
407 }
408 
~OfaSwAutoFmtOptionsPage()409 OfaSwAutoFmtOptionsPage::~OfaSwAutoFmtOptionsPage()
410 {
411     delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(REPLACE_BULLETS));
412     delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(APPLY_NUMBERING));
413     delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(MERGE_SINGLE_LINE_PARA));
414 }
415 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)416 std::unique_ptr<SfxTabPage> OfaSwAutoFmtOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController,
417                                                             const SfxItemSet* rAttrSet)
418 {
419     return std::make_unique<OfaSwAutoFmtOptionsPage>(pPage, pController, *rAttrSet);
420 }
421 
FillItemSet(SfxItemSet *)422 bool OfaSwAutoFmtOptionsPage::FillItemSet( SfxItemSet*  )
423 {
424     bool bModified = false;
425     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
426     SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
427     ACFlags nFlags = pAutoCorrect->GetFlags();
428 
429     bool bCheck = m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_FIRST) == TRISTATE_TRUE;
430     bModified |= pOpt->bAutoCorrect != bCheck;
431     pOpt->bAutoCorrect = bCheck;
432     pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect,
433                         m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE);
434 
435     bCheck = m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_FIRST) == TRISTATE_TRUE;
436     bModified |= pOpt->bCapitalStartWord != bCheck;
437     pOpt->bCapitalStartWord = bCheck;
438     pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord,
439                         m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_SECOND) == TRISTATE_TRUE);
440 
441     bCheck = m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_FIRST) == TRISTATE_TRUE;
442     bModified |= pOpt->bCapitalStartSentence != bCheck;
443     pOpt->bCapitalStartSentence = bCheck;
444     pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence,
445                         m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_SECOND) == TRISTATE_TRUE);
446 
447     bCheck = m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_FIRST) == TRISTATE_TRUE;
448     bModified |= pOpt->bChgWeightUnderl != bCheck;
449     pOpt->bChgWeightUnderl = bCheck;
450     pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl,
451                         m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_SECOND) == TRISTATE_TRUE);
452 
453     pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace,
454                         m_xCheckLB->get_toggle(IGNORE_DBLSPACE, CBCOL_SECOND) == TRISTATE_TRUE);
455 
456     pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock,
457                         m_xCheckLB->get_toggle(CORRECT_CAPS_LOCK, CBCOL_SECOND) == TRISTATE_TRUE);
458 
459     bCheck = m_xCheckLB->get_toggle(DETECT_URL, CBCOL_FIRST) == TRISTATE_TRUE;
460     bModified |= pOpt->bSetINetAttr != bCheck;
461     pOpt->bSetINetAttr = bCheck;
462     pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr,
463                         m_xCheckLB->get_toggle(DETECT_URL, CBCOL_SECOND) == TRISTATE_TRUE);
464 
465     bCheck = m_xCheckLB->get_toggle(DETECT_DOI, CBCOL_FIRST) == TRISTATE_TRUE;
466     bModified |= pOpt->bSetDOIAttr != bCheck;
467     pOpt->bSetDOIAttr = bCheck;
468     pAutoCorrect->SetAutoCorrFlag(ACFlags::SetDOIAttr,
469                         m_xCheckLB->get_toggle(DETECT_DOI, CBCOL_SECOND) == TRISTATE_TRUE);
470 
471     bCheck = m_xCheckLB->get_toggle(DEL_EMPTY_NODE, CBCOL_FIRST) == TRISTATE_TRUE;
472     bModified |= pOpt->bDelEmptyNode != bCheck;
473     pOpt->bDelEmptyNode = bCheck;
474 
475     bCheck = m_xCheckLB->get_toggle(REPLACE_USER_COLL, CBCOL_FIRST) == TRISTATE_TRUE;
476     bModified |= pOpt->bChgUserColl != bCheck;
477     pOpt->bChgUserColl = bCheck;
478 
479     bCheck = m_xCheckLB->get_toggle(REPLACE_BULLETS, CBCOL_FIRST) == TRISTATE_TRUE;
480     bModified |= pOpt->bChgEnumNum != bCheck;
481     pOpt->bChgEnumNum = bCheck;
482     bModified |= aBulletFont != pOpt->aBulletFont;
483     pOpt->aBulletFont = aBulletFont;
484     bModified |= sBulletChar != OUString(&pOpt->cBullet, 1);
485     pOpt->cBullet = sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
486 
487     bModified |= aByInputBulletFont != pOpt->aByInputBulletFont;
488     bModified |= sByInputBulletChar != OUString(&pOpt->cByInputBullet, 1);
489     pOpt->aByInputBulletFont = aByInputBulletFont;
490     pOpt->cByInputBullet = sByInputBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
491 
492     bCheck = m_xCheckLB->get_toggle(MERGE_SINGLE_LINE_PARA, CBCOL_FIRST) == TRISTATE_TRUE;
493     bModified |= pOpt->bRightMargin != bCheck;
494     pOpt->bRightMargin = bCheck;
495     bModified |= nPercent != pOpt->nRightMargin;
496     pOpt->nRightMargin = static_cast<sal_uInt8>(nPercent);
497 
498     bCheck = m_xCheckLB->get_toggle(APPLY_NUMBERING, CBCOL_SECOND) == TRISTATE_TRUE;
499     bModified |= pOpt->bSetNumRule != bCheck;
500     pOpt->bSetNumRule = bCheck;
501 
502     bCheck = m_xCheckLB->get_toggle(APPLY_NUMBERING_AFTER_SPACE, CBCOL_SECOND) == TRISTATE_TRUE;
503     bModified |= pOpt->bSetNumRuleAfterSpace != bCheck;
504     pOpt->bSetNumRuleAfterSpace = bCheck;
505 
506     bCheck = m_xCheckLB->get_toggle(INSERT_BORDER, CBCOL_SECOND) == TRISTATE_TRUE;
507     bModified |= pOpt->bSetBorder != bCheck;
508     pOpt->bSetBorder = bCheck;
509 
510     bCheck = m_xCheckLB->get_toggle(CREATE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE;
511     bModified |= pOpt->bCreateTable != bCheck;
512     pOpt->bCreateTable = bCheck;
513 
514     bCheck = m_xCheckLB->get_toggle(REPLACE_STYLES, CBCOL_SECOND) == TRISTATE_TRUE;
515     bModified |= pOpt->bReplaceStyles != bCheck;
516     pOpt->bReplaceStyles = bCheck;
517 
518     bCheck = m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_FIRST) == TRISTATE_TRUE;
519     bModified |= pOpt->bChgToEnEmDash != bCheck;
520     pOpt->bChgToEnEmDash = bCheck;
521     pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash,
522                         m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_SECOND) == TRISTATE_TRUE);
523 
524     bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_FIRST) == TRISTATE_TRUE;
525     bModified |= pOpt->bAFormatDelSpacesAtSttEnd != bCheck;
526     pOpt->bAFormatDelSpacesAtSttEnd = bCheck;
527     bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_SECOND) == TRISTATE_TRUE;
528     bModified |= pOpt->bAFormatByInpDelSpacesAtSttEnd != bCheck;
529     pOpt->bAFormatByInpDelSpacesAtSttEnd = bCheck;
530 
531     bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_FIRST) == TRISTATE_TRUE;
532     bModified |= pOpt->bAFormatDelSpacesBetweenLines != bCheck;
533     pOpt->bAFormatDelSpacesBetweenLines = bCheck;
534     bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_SECOND) == TRISTATE_TRUE;
535     bModified |= pOpt->bAFormatByInpDelSpacesBetweenLines != bCheck;
536     pOpt->bAFormatByInpDelSpacesBetweenLines = bCheck;
537 
538     if(bModified || nFlags != pAutoCorrect->GetFlags())
539     {
540         SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
541         rCfg.SetModified();
542         rCfg.Commit();
543     }
544 
545     return true;
546 }
547 
ActivatePage(const SfxItemSet &)548 void    OfaSwAutoFmtOptionsPage::ActivatePage( const SfxItemSet& )
549 {
550     static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false);
551 }
552 
Reset(const SfxItemSet *)553 void OfaSwAutoFmtOptionsPage::Reset( const SfxItemSet* )
554 {
555     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
556     SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
557     const ACFlags nFlags = pAutoCorrect->GetFlags();
558 
559     aBulletFont = pOpt->aBulletFont;
560     sBulletChar = OUString(&pOpt->cBullet, 1);
561 
562     aByInputBulletFont = pOpt->aByInputBulletFont;
563     sByInputBulletChar = OUString(&pOpt->cByInputBullet, 1);
564 
565     nPercent = pOpt->nRightMargin;
566     sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag());
567 
568     m_xCheckLB->freeze();
569     m_xCheckLB->clear();
570 
571     // The following entries have to be inserted in the same order
572     // as in the OfaAutoFmtOptions-enum!
573     CreateEntry(sUseReplaceTbl,     CBCOL_BOTH  );
574     CreateEntry(sCapitalStartWord,  CBCOL_BOTH  );
575     CreateEntry(sCapitalStartSentence, CBCOL_BOTH  );
576     CreateEntry(sBoldUnder,         CBCOL_BOTH  );
577     CreateEntry(sDetectURL,         CBCOL_BOTH  );
578     CreateEntry(sDetectDOI,         CBCOL_BOTH  );
579     CreateEntry(sDash,              CBCOL_BOTH  );
580     CreateEntry(sDelSpaceAtSttEnd,  CBCOL_BOTH  );
581     CreateEntry(sDelSpaceBetweenLines, CBCOL_BOTH  );
582 
583     CreateEntry(sNoDblSpaces,       CBCOL_SECOND);
584     CreateEntry(sCorrectCapsLock,   CBCOL_SECOND);
585     CreateEntry(sNum.replaceFirst("%1", sBulletChar), CBCOL_SECOND);
586     CreateEntry(sBulletsAfterSpace,  CBCOL_SECOND);
587     CreateEntry(sBorder,            CBCOL_SECOND);
588     CreateEntry(sTable,             CBCOL_SECOND);
589     CreateEntry(sReplaceTemplates,  CBCOL_SECOND);
590     CreateEntry(sDeleteEmptyPara,   CBCOL_FIRST );
591     CreateEntry(sUserStyle,         CBCOL_FIRST );
592     CreateEntry(sBullet.replaceFirst("%1", sByInputBulletChar), CBCOL_FIRST);
593     CreateEntry(sRightMargin.replaceFirst("%1", sMargin), CBCOL_FIRST);
594 
595     m_xCheckLB->set_toggle(USE_REPLACE_TABLE, pOpt->bAutoCorrect ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
596     m_xCheckLB->set_toggle(USE_REPLACE_TABLE, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
597     m_xCheckLB->set_toggle(CORR_UPPER, pOpt->bCapitalStartWord ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
598     m_xCheckLB->set_toggle(CORR_UPPER, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
599     m_xCheckLB->set_toggle(BEGIN_UPPER, pOpt->bCapitalStartSentence ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
600     m_xCheckLB->set_toggle(BEGIN_UPPER, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
601     m_xCheckLB->set_toggle(BOLD_UNDERLINE, pOpt->bChgWeightUnderl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
602     m_xCheckLB->set_toggle(BOLD_UNDERLINE, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
603     m_xCheckLB->set_toggle(DETECT_URL, pOpt->bSetINetAttr ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
604     m_xCheckLB->set_toggle(DETECT_URL, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
605     m_xCheckLB->set_toggle(DETECT_DOI, pOpt->bSetDOIAttr ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
606     m_xCheckLB->set_toggle(DETECT_DOI, bool(nFlags & ACFlags::SetDOIAttr) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
607     m_xCheckLB->set_toggle(REPLACE_DASHES, pOpt->bChgToEnEmDash ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
608     m_xCheckLB->set_toggle(REPLACE_DASHES, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
609     m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
610     m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatByInpDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
611     m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
612     m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatByInpDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
613     m_xCheckLB->set_toggle(IGNORE_DBLSPACE, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
614     m_xCheckLB->set_toggle(CORRECT_CAPS_LOCK, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
615     m_xCheckLB->set_toggle(APPLY_NUMBERING, pOpt->bSetNumRule ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
616     m_xCheckLB->set_toggle(APPLY_NUMBERING_AFTER_SPACE, pOpt->bSetNumRuleAfterSpace ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
617     m_xCheckLB->set_toggle(INSERT_BORDER, pOpt->bSetBorder ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
618     m_xCheckLB->set_toggle(CREATE_TABLE, pOpt->bCreateTable ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
619     m_xCheckLB->set_toggle(REPLACE_STYLES, pOpt->bReplaceStyles ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
620     m_xCheckLB->set_toggle(DEL_EMPTY_NODE, pOpt->bDelEmptyNode ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
621     m_xCheckLB->set_toggle(REPLACE_USER_COLL, pOpt->bChgUserColl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
622     m_xCheckLB->set_toggle(REPLACE_BULLETS, pOpt->bChgEnumNum ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
623     m_xCheckLB->set_toggle(MERGE_SINGLE_LINE_PARA, pOpt->bRightMargin ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
624 
625     ImpUserData* pUserData = new ImpUserData(&sBulletChar, &aBulletFont);
626     OUString sId(weld::toId(pUserData));
627     m_xCheckLB->set_id(REPLACE_BULLETS, sId);
628 
629     pUserData = new ImpUserData(&sMargin, nullptr);
630     sId = weld::toId(pUserData);
631     m_xCheckLB->set_id(MERGE_SINGLE_LINE_PARA, sId);
632 
633     ImpUserData* pUserData2 = new ImpUserData(&sByInputBulletChar, &aByInputBulletFont);
634     sId = weld::toId(pUserData2);
635     m_xCheckLB->set_id(APPLY_NUMBERING, sId);
636 
637     m_xCheckLB->thaw();
638 }
639 
IMPL_LINK(OfaSwAutoFmtOptionsPage,SelectHdl,weld::TreeView &,rBox,void)640 IMPL_LINK(OfaSwAutoFmtOptionsPage, SelectHdl, weld::TreeView&, rBox, void)
641 {
642     m_xEditPB->set_sensitive(rBox.get_selected_id().toInt64() != 0);
643 }
644 
IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage,DoubleClickEditHdl,weld::TreeView &,bool)645 IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, DoubleClickEditHdl, weld::TreeView&, bool)
646 {
647     EditHdl(*m_xEditPB);
648     return true;
649 }
650 
IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage,EditHdl,weld::Button &,void)651 IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, EditHdl, weld::Button&, void)
652 {
653     int nSelEntryPos = m_xCheckLB->get_selected_index();
654     if (nSelEntryPos == REPLACE_BULLETS || nSelEntryPos == APPLY_NUMBERING)
655     {
656         SvxCharacterMap aMapDlg(GetFrameWeld(), nullptr, nullptr);
657         ImpUserData* pUserData = weld::fromId<ImpUserData*>(m_xCheckLB->get_id(nSelEntryPos));
658         aMapDlg.SetCharFont(*pUserData->pFont);
659         aMapDlg.SetChar( (*pUserData->pString)[0] );
660         if (RET_OK == aMapDlg.run())
661         {
662             const vcl::Font& aFont(aMapDlg.GetCharFont());
663             *pUserData->pFont = aFont;
664             sal_UCS4 aChar = aMapDlg.GetChar();
665             // using the UCS4 constructor
666             OUString aOUStr( &aChar, 1 );
667             *pUserData->pString = aOUStr;
668             if (nSelEntryPos == REPLACE_BULLETS)
669                 m_xCheckLB->set_text(nSelEntryPos, sNum.replaceFirst("%1", aOUStr), 2);
670             else
671                 m_xCheckLB->set_text(nSelEntryPos, sBullet.replaceFirst("%1", aOUStr), 2);
672         }
673     }
674     else if( MERGE_SINGLE_LINE_PARA == nSelEntryPos )
675     {
676         // dialog for per cent settings
677         OfaAutoFmtPrcntSet aDlg(GetFrameWeld());
678         aDlg.GetPrcntFld().set_value(nPercent, FieldUnit::PERCENT);
679         if (aDlg.run() == RET_OK)
680         {
681             nPercent = static_cast<sal_uInt16>(aDlg.GetPrcntFld().get_value(FieldUnit::PERCENT));
682             sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag());
683             m_xCheckLB->set_text(nSelEntryPos, sRightMargin.replaceFirst("%1", sMargin), 2);
684         }
685     }
686 }
687 
688 
OfaAutocorrReplacePage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)689 OfaAutocorrReplacePage::OfaAutocorrReplacePage(weld::Container* pPage, weld::DialogController* pController,
690                                                const SfxItemSet& rSet)
691     : SfxTabPage(pPage, pController, u"cui/ui/acorreplacepage.ui"_ustr, u"AcorReplacePage"_ustr, &rSet)
692     , maCompareClass(comphelper::getProcessComponentContext())
693     , eLang(eLastDialogLanguage)
694     , bHasSelectionText(false)
695     , bFirstSelect(true)
696     , bReplaceEditChanged(false)
697     , bSWriter(true)
698     , m_xTextOnlyCB(m_xBuilder->weld_check_button(u"textonly"_ustr))
699     , m_xShortED(m_xBuilder->weld_entry(u"origtext"_ustr))
700     , m_xReplaceED(m_xBuilder->weld_entry(u"newtext"_ustr))
701     , m_xReplaceTLB(m_xBuilder->weld_tree_view(u"tabview"_ustr))
702     , m_xNewReplacePB(m_xBuilder->weld_button(u"new"_ustr))
703     , m_xReplacePB(m_xBuilder->weld_button(u"replace"_ustr))
704     , m_xDeleteReplacePB(m_xBuilder->weld_button(u"delete"_ustr))
705     , m_xButtonBox(m_xBuilder->weld_container(u"buttonbox"_ustr))
706 {
707     sNew = m_xNewReplacePB->get_label();
708     sModify = m_xReplacePB->get_label();
709 
710     // lock down the width of the button box to its max
711     // desired width
712     auto nMaxWidth = m_xButtonBox->get_preferred_size().Width();
713     m_xButtonBox->set_size_request(nMaxWidth, -1);
714     m_xReplacePB->hide();
715 
716     // tdf#125348 set some small but fixed initial width size, final width will
717     // depend on the size of the entry boxes
718     m_xReplaceTLB->set_size_request(42, m_xReplaceTLB->get_height_rows(10));
719 
720     SfxModule *pMod = SfxApplication::GetModule(SfxToolsModule::Writer);
721     bSWriter = pMod == SfxModule::GetActiveModule();
722 
723     LanguageTag aLanguageTag( eLastDialogLanguage );
724     maCompareClass.loadDefaultCollator( aLanguageTag.getLocale(), 0 );
725     pCharClass.reset( new CharClass( std::move(aLanguageTag) ) );
726 
727     auto nColWidth = m_xReplaceTLB->get_approximate_digit_width() * 32;
728     m_aReplaceFixedWidths.push_back(nColWidth);
729     m_aReplaceFixedWidths.push_back(nColWidth);
730 
731     m_xReplaceTLB->connect_changed( LINK(this, OfaAutocorrReplacePage, SelectHdl) );
732     m_xNewReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) );
733     m_xDeleteReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) );
734     m_xShortED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) );
735     m_xReplaceED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) );
736     m_xShortED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) );
737     m_xReplaceED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) );
738     m_xShortED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl));
739     m_xReplaceED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl));
740 }
741 
~OfaAutocorrReplacePage()742 OfaAutocorrReplacePage::~OfaAutocorrReplacePage()
743 {
744     aDoubleStringTable.clear();
745     aChangesTable.clear();
746 
747     pCharClass.reset();
748 }
749 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)750 std::unique_ptr<SfxTabPage> OfaAutocorrReplacePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
751 {
752     return std::make_unique<OfaAutocorrReplacePage>(pPage, pController, *rSet);
753 }
754 
ActivatePage(const SfxItemSet &)755 void OfaAutocorrReplacePage::ActivatePage( const SfxItemSet& )
756 {
757     if(eLang != eLastDialogLanguage)
758         SetLanguage(eLastDialogLanguage);
759     static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(true);
760 }
761 
DeactivatePage(SfxItemSet *)762 DeactivateRC OfaAutocorrReplacePage::DeactivatePage( SfxItemSet*  )
763 {
764     return DeactivateRC::LeavePage;
765 }
766 
FillItemSet(SfxItemSet *)767 bool OfaAutocorrReplacePage::FillItemSet( SfxItemSet* )
768 {
769     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
770 
771     for (StringChangeTable::reverse_iterator it = aChangesTable.rbegin(); it != aChangesTable.rend(); ++it)
772     {
773         LanguageType eCurrentLang = it->first;
774         StringChangeList& rStringChangeList = it->second;
775         std::vector<SvxAutocorrWord> aDeleteWords;
776         std::vector<SvxAutocorrWord> aNewWords;
777 
778         aDeleteWords.reserve( rStringChangeList.aDeletedEntries.size() );
779         for (const DoubleString & deleteEntry : rStringChangeList.aDeletedEntries)
780         {
781             SvxAutocorrWord aDeleteWord( deleteEntry.sShort, deleteEntry.sLong );
782             aDeleteWords.push_back( aDeleteWord );
783         }
784 
785         aNewWords.reserve( rStringChangeList.aNewEntries.size() );
786         for (const DoubleString & newEntry : rStringChangeList.aNewEntries)
787         {
788             //fdo#67697 if the user data is set then we want to retain the
789             //source formatting of the entry, so don't use the optimized
790             //text-only MakeCombinedChanges for this entry
791             bool bKeepSourceFormatting = newEntry.pUserData == &bHasSelectionText;
792             if (bKeepSourceFormatting)
793             {
794                 if (SfxObjectShell* pSh = SfxObjectShell::Current())
795                     pAutoCorrect->PutText(newEntry.sShort, *pSh, eCurrentLang);
796                 continue;
797             }
798 
799             SvxAutocorrWord aNewWord( newEntry.sShort, newEntry.sLong );
800             aNewWords.push_back( aNewWord );
801         }
802         pAutoCorrect->MakeCombinedChanges( aNewWords, aDeleteWords, eCurrentLang );
803     }
804     aChangesTable.clear();
805     return false;
806 }
807 
RefillReplaceBox(bool bFromReset,LanguageType eOldLanguage,LanguageType eNewLanguage)808 void OfaAutocorrReplacePage::RefillReplaceBox(bool bFromReset,
809                                         LanguageType eOldLanguage,
810                                         LanguageType eNewLanguage)
811 {
812     eLang = eNewLanguage;
813     if(bFromReset)
814     {
815         aDoubleStringTable.clear();
816         aChangesTable.clear();
817     }
818     else
819     {
820         DoubleStringArray* pArray;
821         if(aDoubleStringTable.find(eOldLanguage) != aDoubleStringTable.end())
822         {
823             pArray = &aDoubleStringTable[eOldLanguage];
824             pArray->clear();
825         }
826         else
827         {
828             pArray = &aDoubleStringTable[eOldLanguage]; // create new array
829         }
830 
831         m_xReplaceTLB->all_foreach([this, &pArray](weld::TreeIter& rIter) {
832             pArray->push_back(DoubleString(m_xReplaceTLB->get_text(rIter, 0),
833                                            m_xReplaceTLB->get_text(rIter, 1)));
834             DoubleString& rDouble = pArray->back();
835             rDouble.pUserData = weld::fromId<void*>(m_xReplaceTLB->get_id(rIter));
836             return false;
837         });
838     }
839 
840     if( !bSWriter )
841         aFormatText.clear();
842 
843     if (aDoubleStringTable.find(eLang) != aDoubleStringTable.end())
844     {
845         DoubleStringArray& rArray = aDoubleStringTable[eNewLanguage];
846 
847         m_xReplaceTLB->bulk_insert_for_each(rArray.size(), [this, &rArray](weld::TreeIter& rIter, int nIndex) {
848             DoubleString &rDouble = rArray[nIndex];
849             bool bTextOnly = nullptr == rDouble.pUserData;
850             // formatted text is only in Writer
851             if (bSWriter || bTextOnly)
852             {
853                 if (!bTextOnly)
854                 {
855                     // that means: with format info or even with selection text
856                     OUString sId = weld::toId(rDouble.pUserData);
857                     m_xReplaceTLB->set_id(rIter, sId);
858                 }
859                 m_xReplaceTLB->set_text(rIter, rDouble.sShort, 0);
860                 m_xReplaceTLB->set_text(rIter, rDouble.sLong, 1);
861             }
862             else
863             {
864                 aFormatText.insert(rDouble.sShort);
865             }
866         }, nullptr, &m_aReplaceFixedWidths);
867     }
868     else
869     {
870         SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
871         SvxAutocorrWordList* pWordList = pAutoCorrect->LoadAutocorrWordList(eLang);
872         const SvxAutocorrWordList::AutocorrWordSetType & rContent = pWordList->getSortedContent();
873         m_xReplaceTLB->bulk_insert_for_each(rContent.size(), [this, rContent](weld::TreeIter& rIter, int nIndex) {
874             auto const& elem = rContent[nIndex];
875             bool bTextOnly = elem.IsTextOnly();
876             // formatted text is only in Writer
877             if (bSWriter || bTextOnly)
878             {
879                 if (!bTextOnly)
880                 {
881                     // that means: with format info or even with selection text
882                     OUString sId = weld::toId(m_xTextOnlyCB.get());
883                     m_xReplaceTLB->set_id(rIter, sId);
884                 }
885                 m_xReplaceTLB->set_text(rIter, elem.GetShort(), 0);
886                 m_xReplaceTLB->set_text(rIter, elem.GetLong(), 1);
887             }
888             else
889             {
890                 aFormatText.insert(elem.GetShort());
891             }
892         }, nullptr, &m_aReplaceFixedWidths);
893         m_xNewReplacePB->set_sensitive(false);
894         m_xDeleteReplacePB->set_sensitive(false);
895     }
896 
897     SfxViewShell* pViewShell = SfxViewShell::Current();
898     if (pViewShell && pViewShell->HasSelection())
899     {
900         bHasSelectionText = true;
901         const OUString sSelection( pViewShell->GetSelectionText() );
902         m_xReplaceED->set_text(sSelection);
903         m_xTextOnlyCB->set_active(!bSWriter);
904         m_xTextOnlyCB->set_sensitive(bSWriter && !sSelection.isEmpty());
905     }
906     else
907     {
908         m_xTextOnlyCB->set_active(true);
909         m_xTextOnlyCB->set_sensitive(false);
910     }
911 }
912 
Reset(const SfxItemSet *)913 void OfaAutocorrReplacePage::Reset( const SfxItemSet* )
914 {
915     RefillReplaceBox(true, eLang, eLang);
916     m_xShortED->grab_focus();
917 }
918 
SetLanguage(LanguageType eSet)919 void OfaAutocorrReplacePage::SetLanguage(LanguageType eSet)
920 {
921     //save old settings and refill
922     if(eSet != eLang)
923     {
924         RefillReplaceBox(false, eLang, eSet);
925         eLastDialogLanguage = eSet;
926 
927         LanguageTag aLanguageTag( eLastDialogLanguage );
928         maCompareClass = CollatorWrapper( comphelper::getProcessComponentContext() );
929         maCompareClass.loadDefaultCollator( aLanguageTag.getLocale(), 0 );
930         pCharClass.reset( new CharClass( std::move(aLanguageTag) ) );
931         ModifyHdl(*m_xShortED);
932     }
933 }
934 
IMPL_LINK(OfaAutocorrReplacePage,SelectHdl,weld::TreeView &,rBox,void)935 IMPL_LINK(OfaAutocorrReplacePage, SelectHdl, weld::TreeView&, rBox, void)
936 {
937     if(!bFirstSelect || !bHasSelectionText)
938     {
939         int nEntry = rBox.get_selected_index();
940         OUString sTmpShort(rBox.get_text(nEntry, 0));
941         // if the text is set via ModifyHdl, the cursor is always at the beginning
942         // of a word, although you're editing here
943         bool bSameContent = 0 == maCompareClass.compareString(sTmpShort, m_xShortED->get_text());
944         int nStartPos, nEndPos;
945         m_xShortED->get_selection_bounds(nStartPos, nEndPos);
946         if (m_xShortED->get_text() != sTmpShort)
947         {
948             m_xShortED->set_text(sTmpShort);
949             // if it was only a different notation, the selection has to be set again
950             if (bSameContent)
951             {
952                 m_xShortED->select_region(nStartPos, nEndPos);
953             }
954         }
955         m_xReplaceED->set_text(rBox.get_text(nEntry, 1));
956         // with UserData there is a Formatinfo
957         m_xTextOnlyCB->set_active(rBox.get_id(nEntry).isEmpty());
958     }
959     else
960     {
961         bFirstSelect = false;
962     }
963 
964     m_xNewReplacePB->set_sensitive(false);
965     m_xDeleteReplacePB->set_sensitive(true);
966 };
967 
NewEntry(const OUString & sShort,const OUString & sLong,bool bKeepSourceFormatting)968 void OfaAutocorrReplacePage::NewEntry(const OUString& sShort, const OUString& sLong, bool bKeepSourceFormatting)
969 {
970     DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries;
971     for (size_t i = 0; i < rNewArray.size(); i++)
972     {
973         if (rNewArray[i].sShort == sShort)
974         {
975             rNewArray.erase(rNewArray.begin() + i);
976             break;
977         }
978     }
979 
980     DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries;
981     for (size_t i = 0; i < rDeletedArray.size(); i++)
982     {
983         if (rDeletedArray[i].sShort == sShort)
984         {
985             rDeletedArray.erase(rDeletedArray.begin() + i);
986             break;
987         }
988     }
989 
990     DoubleString aNewString(sShort, sLong);
991     rNewArray.push_back(aNewString);
992     if (bKeepSourceFormatting)
993         rNewArray.back().pUserData = &bHasSelectionText;
994 }
995 
DeleteEntry(const OUString & sShort,const OUString & sLong)996 void OfaAutocorrReplacePage::DeleteEntry(const OUString& sShort, const OUString& sLong)
997 {
998     DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries;
999     for (size_t i = 0; i < rNewArray.size(); i++)
1000     {
1001         if (rNewArray[i].sShort == sShort)
1002         {
1003             rNewArray.erase(rNewArray.begin() + i);
1004             break;
1005         }
1006     }
1007 
1008     DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries;
1009     for (size_t i = 0; i < rDeletedArray.size(); i++)
1010     {
1011         if (rDeletedArray[i].sShort == sShort)
1012         {
1013             rDeletedArray.erase(rDeletedArray.begin() + i);
1014             break;
1015         }
1016     }
1017 
1018     DoubleString aDeletedString(sShort, sLong);
1019     rDeletedArray.push_back(aDeletedString);
1020 }
1021 
IMPL_LINK(OfaAutocorrReplacePage,NewDelButtonHdl,weld::Button &,rBtn,void)1022 IMPL_LINK(OfaAutocorrReplacePage, NewDelButtonHdl, weld::Button&, rBtn, void)
1023 {
1024     NewDelHdl(&rBtn);
1025 }
1026 
IMPL_LINK(OfaAutocorrReplacePage,NewDelActionHdl,weld::Entry &,rEdit,bool)1027 IMPL_LINK(OfaAutocorrReplacePage, NewDelActionHdl, weld::Entry&, rEdit, bool)
1028 {
1029     return NewDelHdl(&rEdit);
1030 }
1031 
IMPL_LINK_NOARG(OfaAutocorrReplacePage,EntrySizeAllocHdl,const Size &,void)1032 IMPL_LINK_NOARG(OfaAutocorrReplacePage, EntrySizeAllocHdl, const Size&, void)
1033 {
1034     m_aReplaceFixedWidths.clear();
1035     int x, y, width, height;
1036     if (m_xReplaceED->get_extents_relative_to(*m_xReplaceTLB, x, y, width, height))
1037     {
1038         m_aReplaceFixedWidths.push_back(x);
1039         m_aReplaceFixedWidths.push_back(width - 1);
1040         m_xReplaceTLB->set_column_fixed_widths(m_aReplaceFixedWidths);
1041     }
1042 }
1043 
NewDelHdl(const weld::Widget * pBtn)1044 bool OfaAutocorrReplacePage::NewDelHdl(const weld::Widget* pBtn)
1045 {
1046     int nEntry = m_xReplaceTLB->get_selected_index();
1047     if (pBtn == m_xDeleteReplacePB.get())
1048     {
1049         DBG_ASSERT( nEntry != -1, "no entry selected" );
1050         if (nEntry != -1)
1051         {
1052             DeleteEntry(m_xReplaceTLB->get_text(nEntry, 0), m_xReplaceTLB->get_text(nEntry, 1));
1053             m_xReplaceTLB->remove(nEntry);
1054             ModifyHdl(*m_xShortED);
1055             return true;
1056         }
1057     }
1058 
1059     if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive())
1060     {
1061         OUString sEntry(m_xShortED->get_text());
1062         if (!sEntry.isEmpty() && (!m_xReplaceED->get_text().isEmpty() ||
1063                 ( bHasSelectionText && bSWriter ) ))
1064         {
1065             bool bKeepSourceFormatting = !bReplaceEditChanged && !m_xTextOnlyCB->get_active();
1066 
1067             NewEntry(m_xShortED->get_text(), m_xReplaceED->get_text(), bKeepSourceFormatting);
1068             m_xReplaceTLB->freeze();
1069             int nPos = -1;
1070             if (nEntry != -1)
1071             {
1072                 nPos = nEntry;
1073                 m_xReplaceTLB->remove(nEntry);
1074             }
1075             else
1076             {
1077                 int j;
1078                 int nCount = m_xReplaceTLB->n_children();
1079                 for (j = 0; j < nCount; ++j)
1080                 {
1081                     if (0 >= maCompareClass.compareString(sEntry, m_xReplaceTLB->get_text(j, 0)))
1082                         break;
1083                 }
1084                 nPos = j;
1085             }
1086 
1087             OUString sId;
1088             if (bKeepSourceFormatting)
1089             {
1090                 sId = weld::toId(&bHasSelectionText); // new formatted text
1091             }
1092 
1093             m_xReplaceTLB->insert(nPos, sEntry, &sId, nullptr, nullptr);
1094             m_xReplaceTLB->set_text(nPos, m_xReplaceED->get_text(), 1);
1095             m_xReplaceTLB->thaw();
1096             m_xReplaceTLB->scroll_to_row(nPos);
1097             // if the request came from the ReplaceEdit, give focus to the ShortEdit
1098             if (m_xReplaceED->has_focus())
1099             {
1100                 m_xShortED->grab_focus();
1101             }
1102         }
1103     }
1104     else
1105     {
1106         // this can only be an enter in one of the two edit fields
1107         // which means EndDialog() - has to be evaluated in KeyInput
1108         return false;
1109     }
1110     ModifyHdl(*m_xShortED);
1111     return true;
1112 }
1113 
IMPL_LINK(OfaAutocorrReplacePage,ModifyHdl,weld::Entry &,rEdt,void)1114 IMPL_LINK(OfaAutocorrReplacePage, ModifyHdl, weld::Entry&, rEdt, void)
1115 {
1116     std::unique_ptr<weld::TreeIter> xFirstSel(m_xReplaceTLB->make_iterator());
1117     bool bFirstSelIterSet = m_xReplaceTLB->get_selected(xFirstSel.get());
1118     bool bShort = &rEdt == m_xShortED.get();
1119     const OUString rEntry = rEdt.get_text();
1120     const OUString rRepString = m_xReplaceED->get_text();
1121     OUString aWordStr(pCharClass->lowercase(rEntry));
1122 
1123     if(bShort)
1124     {
1125         if(!rEntry.isEmpty())
1126         {
1127             bool bFound = false;
1128             bool bTmpSelEntry=false;
1129 
1130             m_xReplaceTLB->all_foreach([this, &rEntry, &rRepString, &bFound,
1131                                         &bTmpSelEntry, &bFirstSelIterSet,
1132                                         &xFirstSel, &aWordStr](weld::TreeIter& rIter){
1133                 OUString aTestStr = m_xReplaceTLB->get_text(rIter, 0);
1134                 if( maCompareClass.compareString(rEntry, aTestStr ) == 0 )
1135                 {
1136                     if (!rRepString.isEmpty())
1137                         bFirstSelect = true;
1138                     m_xReplaceTLB->set_cursor(rIter);
1139                     m_xReplaceTLB->copy_iterator(rIter, *xFirstSel);
1140                     bFirstSelIterSet = true;
1141                     m_xNewReplacePB->set_label(sModify);
1142                     bFound = true;
1143                     return true;
1144                 }
1145                 else
1146                 {
1147                     aTestStr = pCharClass->lowercase( aTestStr );
1148                     if( !bTmpSelEntry && ( aTestStr.startsWith(aWordStr)
1149                         // find also with ".*" and between :colons:
1150                         || aTestStr.replaceAll(".*","").replaceAll(":", "").startsWith(aWordStr) ) )
1151                     {
1152                         m_xReplaceTLB->scroll_to_row(rIter);
1153                         bTmpSelEntry = true;
1154                     }
1155                 }
1156                 return false;
1157             });
1158             if( !bFound )
1159             {
1160                 m_xReplaceTLB->select(-1);
1161                 bFirstSelIterSet = false;
1162                 m_xNewReplacePB->set_label(sNew);
1163                 if( bReplaceEditChanged )
1164                     m_xTextOnlyCB->set_sensitive(false);
1165             }
1166             m_xDeleteReplacePB->set_sensitive(bFound);
1167         }
1168         else if (m_xReplaceTLB->n_children() > 0)
1169         {
1170             m_xReplaceTLB->scroll_to_row(0);
1171         }
1172 
1173     }
1174     else if( !bShort )
1175     {
1176         bReplaceEditChanged = true;
1177         if (bFirstSelIterSet)
1178         {
1179             m_xNewReplacePB->set_label(sModify);
1180         }
1181     }
1182 
1183     const OUString& rShortTxt = m_xShortED->get_text();
1184     bool bEnableNew = !rShortTxt.isEmpty() &&
1185                         ( !rRepString.isEmpty() ||
1186                                 ( bHasSelectionText && bSWriter )) &&
1187                         ( !bFirstSelIterSet || rRepString !=
1188                                 m_xReplaceTLB->get_text(*xFirstSel, 1) );
1189     if( bEnableNew )
1190     {
1191         for (auto const& elem : aFormatText)
1192         {
1193             if(elem == rShortTxt)
1194             {
1195                 bEnableNew = false;
1196                 break;
1197             }
1198         }
1199     }
1200     m_xNewReplacePB->set_sensitive(bEnableNew);
1201 }
1202 
lcl_FindInArray(std::vector<OUString> & rStrings,std::u16string_view rString)1203 static bool lcl_FindInArray(std::vector<OUString>& rStrings, std::u16string_view rString)
1204 {
1205     for (auto const& elem : rStrings)
1206     {
1207         if(elem == rString)
1208         {
1209             return true;
1210         }
1211     }
1212     return false;
1213 }
1214 
OfaAutocorrExceptPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)1215 OfaAutocorrExceptPage::OfaAutocorrExceptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
1216     : SfxTabPage(pPage, pController, u"cui/ui/acorexceptpage.ui"_ustr, u"AcorExceptPage"_ustr, &rSet)
1217     , maCompareClass(comphelper::getProcessComponentContext())
1218     , eLang(eLastDialogLanguage)
1219     , m_xAbbrevED(m_xBuilder->weld_entry(u"abbrev"_ustr))
1220     , m_xAbbrevLB(m_xBuilder->weld_tree_view(u"abbrevlist"_ustr))
1221     , m_xNewAbbrevPB(m_xBuilder->weld_button(u"newabbrev"_ustr))
1222     , m_xDelAbbrevPB(m_xBuilder->weld_button(u"delabbrev"_ustr))
1223     , m_xAutoAbbrevCB(m_xBuilder->weld_check_button(u"autoabbrev"_ustr))
1224     , m_xDoubleCapsED(m_xBuilder->weld_entry(u"double"_ustr))
1225     , m_xDoubleCapsLB(m_xBuilder->weld_tree_view(u"doublelist"_ustr))
1226     , m_xNewDoublePB(m_xBuilder->weld_button(u"newdouble"_ustr))
1227     , m_xDelDoublePB(m_xBuilder->weld_button(u"deldouble"_ustr))
1228     , m_xAutoCapsCB(m_xBuilder->weld_check_button(u"autodouble"_ustr))
1229 {
1230     m_xAbbrevLB->make_sorted();
1231     m_xAbbrevLB->set_size_request(-1, m_xAbbrevLB->get_height_rows(6));
1232 
1233     m_xDoubleCapsLB->make_sorted();
1234     m_xDoubleCapsLB->set_size_request(-1, m_xDoubleCapsLB->get_height_rows(6));
1235 
1236     css::lang::Locale aLcl( LanguageTag::convertToLocale(eLastDialogLanguage ));
1237     maCompareClass.loadDefaultCollator( aLcl, 0 );
1238 
1239     m_xNewAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl));
1240     m_xDelAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl));
1241     m_xNewDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl));
1242     m_xDelDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl));
1243 
1244     m_xAbbrevLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl));
1245     m_xDoubleCapsLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl));
1246     m_xAbbrevED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl));
1247     m_xDoubleCapsED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl));
1248 
1249     m_xAbbrevED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl));
1250     m_xDoubleCapsED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl));
1251 }
1252 
~OfaAutocorrExceptPage()1253 OfaAutocorrExceptPage::~OfaAutocorrExceptPage()
1254 {
1255     aStringsTable.clear();
1256 }
1257 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)1258 std::unique_ptr<SfxTabPage> OfaAutocorrExceptPage::Create(weld::Container* pPage, weld::DialogController* pController,
1259                                                  const SfxItemSet* rSet)
1260 {
1261     return std::make_unique<OfaAutocorrExceptPage>(pPage, pController, *rSet);
1262 }
1263 
ActivatePage(const SfxItemSet &)1264 void    OfaAutocorrExceptPage::ActivatePage( const SfxItemSet& )
1265 {
1266     if(eLang != eLastDialogLanguage)
1267         SetLanguage(eLastDialogLanguage);
1268     static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(true);
1269 }
1270 
DeactivatePage(SfxItemSet *)1271 DeactivateRC OfaAutocorrExceptPage::DeactivatePage( SfxItemSet* )
1272 {
1273     return DeactivateRC::LeavePage;
1274 }
1275 
FillItemSet(SfxItemSet *)1276 bool OfaAutocorrExceptPage::FillItemSet( SfxItemSet*  )
1277 {
1278     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
1279     for(StringsTable::reverse_iterator it1 = aStringsTable.rbegin(); it1 != aStringsTable.rend(); ++it1)
1280     {
1281         LanguageType eCurLang = it1->first;
1282         StringsArrays& rArrays = it1->second;
1283         if(eCurLang != eLang) // current language is treated later
1284         {
1285             SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWordStartExceptList(eCurLang);
1286 
1287             if(pWrdList)
1288             {
1289                 size_t nCount = pWrdList->size();
1290                 size_t i;
1291                 for( i = nCount; i; )
1292                 {
1293                     OUString aString = (*pWrdList)[ --i ];
1294 
1295                     if( !lcl_FindInArray(rArrays.aDoubleCapsStrings, aString))
1296                     {
1297                       pWrdList->erase_at(i);
1298                     }
1299                 }
1300 
1301                 for (auto const& elem : rArrays.aDoubleCapsStrings)
1302                 {
1303                     pWrdList->insert(elem);
1304                 }
1305                 pAutoCorrect->SaveWordStartExceptList(eCurLang);
1306             }
1307 
1308             SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eCurLang);
1309 
1310             if(pCplList)
1311             {
1312                 size_t nCount = pCplList->size();
1313                 size_t i;
1314                 for( i = nCount; i; )
1315                 {
1316                     OUString aString = (*pCplList)[ --i ];
1317                     if( !lcl_FindInArray(rArrays.aAbbrevStrings, aString))
1318                     {
1319                         pCplList->erase_at(i);
1320                     }
1321                 }
1322 
1323                 for (auto const& elem : rArrays.aAbbrevStrings)
1324                 {
1325                     pCplList->insert(elem);
1326                 }
1327 
1328                 pAutoCorrect->SaveCplSttExceptList(eCurLang);
1329             }
1330         }
1331     }
1332     aStringsTable.clear();
1333 
1334     SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWordStartExceptList(eLang);
1335 
1336     if(pWrdList)
1337     {
1338         size_t nCount = pWrdList->size();
1339         size_t i;
1340         for( i = nCount; i; )
1341         {
1342             OUString aString = (*pWrdList)[ --i ];
1343             if (m_xDoubleCapsLB->find_text(aString) == -1)
1344             {
1345                 pWrdList->erase_at(i);
1346             }
1347         }
1348         nCount = m_xDoubleCapsLB->n_children();
1349         for( i = 0; i < nCount; ++i )
1350         {
1351             pWrdList->insert(m_xDoubleCapsLB->get_text(i));
1352         }
1353         pAutoCorrect->SaveWordStartExceptList(eLang);
1354     }
1355 
1356     SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eLang);
1357 
1358     if(pCplList)
1359     {
1360         size_t nCount = pCplList->size();
1361         for( size_t i = nCount; i; )
1362         {
1363             OUString aString = (*pCplList)[ --i ];
1364             if (m_xAbbrevLB->find_text(aString) == -1)
1365             {
1366                 pCplList->erase_at(i);
1367             }
1368         }
1369         sal_Int32 nAbbrevCount = m_xAbbrevLB->n_children();
1370         for( sal_Int32 ia = 0; ia < nAbbrevCount; ++ia )
1371         {
1372             pCplList->insert(m_xAbbrevLB->get_text(ia));
1373         }
1374         pAutoCorrect->SaveCplSttExceptList(eLang);
1375     }
1376     if (m_xAutoAbbrevCB->get_state_changed_from_saved())
1377         pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordCplSttLst, m_xAutoAbbrevCB->get_active());
1378     if (m_xAutoCapsCB->get_state_changed_from_saved())
1379         pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordWordStartLst, m_xAutoCapsCB->get_active());
1380     return false;
1381 }
1382 
SetLanguage(LanguageType eSet)1383 void OfaAutocorrExceptPage::SetLanguage(LanguageType eSet)
1384 {
1385     if(eLang != eSet)
1386     {
1387         // save old settings and fill anew
1388         RefillReplaceBoxes(false, eLang, eSet);
1389         eLastDialogLanguage = eSet;
1390         maCompareClass = CollatorWrapper( comphelper::getProcessComponentContext() );
1391         maCompareClass.loadDefaultCollator( LanguageTag::convertToLocale( eLastDialogLanguage ), 0 );
1392         ModifyHdl(*m_xAbbrevED);
1393         ModifyHdl(*m_xDoubleCapsED);
1394     }
1395 }
1396 
RefillReplaceBoxes(bool bFromReset,LanguageType eOldLanguage,LanguageType eNewLanguage)1397 void OfaAutocorrExceptPage::RefillReplaceBoxes(bool bFromReset,
1398                                         LanguageType eOldLanguage,
1399                                         LanguageType eNewLanguage)
1400 {
1401     eLang = eNewLanguage;
1402     if(bFromReset)
1403     {
1404         aStringsTable.clear();
1405     }
1406     else
1407     {
1408         StringsArrays* pArrays;
1409         if(aStringsTable.find(eOldLanguage) != aStringsTable.end())
1410         {
1411             pArrays = &aStringsTable[eOldLanguage];
1412             pArrays->aAbbrevStrings.clear();
1413             pArrays->aDoubleCapsStrings.clear();
1414         }
1415         else
1416         {
1417             pArrays = &aStringsTable[eOldLanguage]; // create new array
1418         }
1419 
1420         sal_Int32 i, nCount;
1421         nCount = m_xAbbrevLB->n_children();
1422         for(i = 0; i < nCount; i++)
1423             pArrays->aAbbrevStrings.push_back(m_xAbbrevLB->get_text(i));
1424 
1425         nCount = m_xDoubleCapsLB->n_children();
1426         for(i = 0; i < nCount; i++)
1427             pArrays->aDoubleCapsStrings.push_back(m_xDoubleCapsLB->get_text(i));
1428     }
1429     m_xDoubleCapsLB->clear();
1430     m_xAbbrevLB->clear();
1431     m_xAbbrevED->set_text(u""_ustr);
1432     m_xDoubleCapsED->set_text(u""_ustr);
1433 
1434     if(aStringsTable.find(eLang) != aStringsTable.end())
1435     {
1436         StringsArrays& rArrays = aStringsTable[eLang];
1437         for (auto const& elem : rArrays.aAbbrevStrings)
1438             m_xAbbrevLB->append_text(elem);
1439 
1440         for (auto const& elem : rArrays.aDoubleCapsStrings)
1441             m_xDoubleCapsLB->append_text(elem);
1442     }
1443     else
1444     {
1445         SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
1446         const SvStringsISortDtor* pCplList = pAutoCorrect->GetCplSttExceptList(eLang);
1447         const SvStringsISortDtor* pWrdList = pAutoCorrect->GetWordStartExceptList(eLang);
1448         size_t i;
1449         for( i = 0; i < pCplList->size(); i++ )
1450         {
1451             m_xAbbrevLB->append_text((*pCplList)[i]);
1452         }
1453         for( i = 0; i < pWrdList->size(); i++ )
1454         {
1455             m_xDoubleCapsLB->append_text((*pWrdList)[i]);
1456         }
1457     }
1458 }
1459 
Reset(const SfxItemSet *)1460 void OfaAutocorrExceptPage::Reset( const SfxItemSet* )
1461 {
1462     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
1463     RefillReplaceBoxes(true, eLang, eLang);
1464     m_xAutoAbbrevCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordCplSttLst));
1465     m_xAutoCapsCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordWordStartLst));
1466     m_xAutoAbbrevCB->save_state();
1467     m_xAutoCapsCB->save_state();
1468 }
1469 
IMPL_LINK(OfaAutocorrExceptPage,NewDelButtonHdl,weld::Button &,rBtn,void)1470 IMPL_LINK(OfaAutocorrExceptPage, NewDelButtonHdl, weld::Button&, rBtn, void)
1471 {
1472     NewDelHdl(&rBtn);
1473 }
1474 
IMPL_LINK(OfaAutocorrExceptPage,NewDelActionHdl,weld::Entry &,rEdit,bool)1475 IMPL_LINK(OfaAutocorrExceptPage, NewDelActionHdl, weld::Entry&, rEdit, bool)
1476 {
1477     return NewDelHdl(&rEdit);
1478 }
1479 
NewDelHdl(const weld::Widget * pBtn)1480 bool OfaAutocorrExceptPage::NewDelHdl(const weld::Widget* pBtn)
1481 {
1482     if ((pBtn == m_xNewAbbrevPB.get() || pBtn == m_xAbbrevED.get())
1483         && !m_xAbbrevED->get_text().isEmpty() && m_xNewAbbrevPB->get_sensitive())
1484     {
1485         m_xAbbrevLB->append_text(m_xAbbrevED->get_text());
1486         ModifyHdl(*m_xAbbrevED);
1487     }
1488     else if(pBtn == m_xDelAbbrevPB.get())
1489     {
1490         m_xAbbrevLB->remove_text(m_xAbbrevED->get_text());
1491         ModifyHdl(*m_xAbbrevED);
1492     }
1493     else if((pBtn == m_xNewDoublePB.get() || pBtn == m_xDoubleCapsED.get() )
1494             && !m_xDoubleCapsED->get_text().isEmpty() && m_xNewDoublePB->get_sensitive())
1495     {
1496         m_xDoubleCapsLB->append_text(m_xDoubleCapsED->get_text());
1497         ModifyHdl(*m_xDoubleCapsED);
1498     }
1499     else if (pBtn == m_xDelDoublePB.get())
1500     {
1501         m_xDoubleCapsLB->remove_text(m_xDoubleCapsED->get_text());
1502         ModifyHdl(*m_xDoubleCapsED);
1503     }
1504     else
1505     {
1506         // we didn't do anything, if this was because of 'activate' in an
1507         // entry then let it continue to close the dialog like the replace
1508         // page does
1509         return false;
1510     }
1511     return true;
1512 }
1513 
IMPL_LINK(OfaAutocorrExceptPage,SelectHdl,weld::TreeView &,rBox,void)1514 IMPL_LINK(OfaAutocorrExceptPage, SelectHdl, weld::TreeView&, rBox, void)
1515 {
1516     if (&rBox == m_xAbbrevLB.get())
1517     {
1518         m_xAbbrevED->set_text(rBox.get_selected_text());
1519         m_xNewAbbrevPB->set_sensitive(false);
1520         m_xDelAbbrevPB->set_sensitive(true);
1521     }
1522     else
1523     {
1524         m_xDoubleCapsED->set_text(rBox.get_selected_text());
1525         m_xNewDoublePB->set_sensitive(false);
1526         m_xDelDoublePB->set_sensitive(true);
1527     }
1528 }
1529 
IMPL_LINK(OfaAutocorrExceptPage,ModifyHdl,weld::Entry &,rEdt,void)1530 IMPL_LINK(OfaAutocorrExceptPage, ModifyHdl, weld::Entry&, rEdt, void)
1531 {
1532     const OUString& sEntry = rEdt.get_text();
1533     bool bEntryLen = !sEntry.isEmpty();
1534     if (&rEdt == m_xAbbrevED.get())
1535     {
1536         bool bSame = lcl_FindEntry(*m_xAbbrevLB, sEntry, maCompareClass);
1537         if(bSame && sEntry != m_xAbbrevLB->get_selected_text())
1538             rEdt.set_text(m_xAbbrevLB->get_selected_text());
1539         m_xNewAbbrevPB->set_sensitive(!bSame && bEntryLen);
1540         m_xDelAbbrevPB->set_sensitive(bSame && bEntryLen);
1541     }
1542     else
1543     {
1544         bool bSame = lcl_FindEntry(*m_xDoubleCapsLB, sEntry, maCompareClass);
1545         if(bSame && sEntry != m_xDoubleCapsLB->get_selected_text())
1546             rEdt.set_text(m_xDoubleCapsLB->get_selected_text());
1547         m_xNewDoublePB->set_sensitive(!bSame && bEntryLen);
1548         m_xDelDoublePB->set_sensitive(bSame && bEntryLen);
1549     }
1550 }
1551 
1552 namespace {
1553 
1554 enum OfaQuoteOptions
1555 {
1556     ADD_NONBRK_SPACE,
1557     REPLACE_1ST,
1558     TRANSLITERATE_RTL,
1559     REPLACE_ANGLE_QUOTES
1560 };
1561 
1562 }
1563 
CreateEntry(weld::TreeView & rCheckLB,const OUString & rTxt,sal_uInt16 nCol,sal_uInt16 nTextCol)1564 void OfaQuoteTabPage::CreateEntry(weld::TreeView& rCheckLB, const OUString& rTxt, sal_uInt16 nCol, sal_uInt16 nTextCol)
1565 {
1566     rCheckLB.append();
1567     const int nRow = rCheckLB.n_children() - 1;
1568     if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH)
1569         rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST);
1570     if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH)
1571         rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND);
1572     rCheckLB.set_text(nRow, rTxt, nTextCol);
1573 }
1574 
OfaQuoteTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)1575 OfaQuoteTabPage::OfaQuoteTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
1576     : SfxTabPage(pPage, pController, u"cui/ui/applylocalizedpage.ui"_ustr, u"ApplyLocalizedPage"_ustr, &rSet)
1577     , sNonBrkSpace(CuiResId(RID_CUISTR_NON_BREAK_SPACE))
1578     , sOrdinal(CuiResId(RID_CUISTR_ORDINAL))
1579     , sTransliterateRTL(CuiResId(RID_CUISTR_OLD_HUNGARIAN))
1580     , sAngleQuotes(CuiResId(RID_CUISTR_ANGLE_QUOTES))
1581     , cSglStartQuote(0)
1582     , cSglEndQuote(0)
1583     , cStartQuote(0)
1584     , cEndQuote(0)
1585     , m_xSingleTypoCB(m_xBuilder->weld_check_button(u"singlereplace"_ustr))
1586     , m_xSglStartQuotePB(m_xBuilder->weld_button(u"startsingle"_ustr))
1587     , m_xSglStartExFT(m_xBuilder->weld_label(u"singlestartex"_ustr))
1588     , m_xSglEndQuotePB(m_xBuilder->weld_button(u"endsingle"_ustr))
1589     , m_xSglEndExFT(m_xBuilder->weld_label(u"singleendex"_ustr))
1590     , m_xSglStandardPB(m_xBuilder->weld_button(u"defaultsingle"_ustr))
1591     , m_xDoubleTypoCB(m_xBuilder->weld_check_button(u"doublereplace"_ustr))
1592     , m_xDblStartQuotePB(m_xBuilder->weld_button(u"startdouble"_ustr))
1593     , m_xDblStartExFT(m_xBuilder->weld_label(u"doublestartex"_ustr))
1594     , m_xDblEndQuotePB(m_xBuilder->weld_button(u"enddouble"_ustr))
1595     , m_xDblEndExFT(m_xBuilder->weld_label(u"doubleendex"_ustr))
1596     , m_xDblStandardPB(m_xBuilder->weld_button(u"defaultdouble"_ustr))
1597     , m_sStandard(m_xSglStartExFT->get_label())
1598     , m_xCheckLB(m_xBuilder->weld_tree_view(u"checklist"_ustr))
1599     , m_xSwCheckLB(m_xBuilder->weld_tree_view(u"list"_ustr))
1600 {
1601     m_xSwCheckLB->set_size_request(m_xSwCheckLB->get_approximate_digit_width() * 50,
1602                                    m_xSwCheckLB->get_height_rows(6));
1603 
1604     bool bShowSWOptions = false;
1605 
1606     const SfxBoolItem* pItem = rSet.GetItem<SfxBoolItem>(SID_AUTO_CORRECT_DLG, false);
1607     if ( pItem && pItem->GetValue() )
1608         bShowSWOptions = true;
1609 
1610     if ( bShowSWOptions )
1611     {
1612         std::vector<int> aWidths
1613         {
1614             o3tl::narrowing<int>(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(0)).Width() * 2),
1615             o3tl::narrowing<int>(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(1)).Width() * 2)
1616         };
1617         m_xSwCheckLB->set_column_fixed_widths(aWidths);
1618         m_xCheckLB->hide();
1619     }
1620     else
1621     {
1622         m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
1623         m_xSwCheckLB->hide();
1624     }
1625 
1626     m_xDblStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl));
1627     m_xDblEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl));
1628     m_xSglStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl));
1629     m_xSglEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl));
1630     m_xDblStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl));
1631     m_xSglStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl));
1632 }
1633 
~OfaQuoteTabPage()1634 OfaQuoteTabPage::~OfaQuoteTabPage()
1635 {
1636 }
1637 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)1638 std::unique_ptr<SfxTabPage> OfaQuoteTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
1639                                                     const SfxItemSet* rAttrSet)
1640 {
1641     return std::make_unique<OfaQuoteTabPage>(pPage, pController, *rAttrSet);
1642 }
1643 
FillItemSet(SfxItemSet *)1644 bool OfaQuoteTabPage::FillItemSet( SfxItemSet*  )
1645 {
1646     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
1647 
1648     ACFlags nFlags = pAutoCorrect->GetFlags();
1649 
1650     if (m_xCheckLB->get_visible())
1651     {
1652         int nPos = 0;
1653         pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
1654         pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
1655         pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
1656         pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE);
1657     }
1658 
1659     bool bModified = false;
1660     if (m_xSwCheckLB->get_visible())
1661     {
1662         SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
1663 
1664         bool bCheck = m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_FIRST) == TRISTATE_TRUE;
1665         bModified |= pOpt->bAddNonBrkSpace != bCheck;
1666         pOpt->bAddNonBrkSpace = bCheck;
1667         pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace,
1668                             m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_SECOND) == TRISTATE_TRUE);
1669 
1670         bCheck = m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_FIRST) == TRISTATE_TRUE;
1671         bModified |= pOpt->bChgOrdinalNumber != bCheck;
1672         pOpt->bChgOrdinalNumber = bCheck;
1673         pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber,
1674                         m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_SECOND) == TRISTATE_TRUE);
1675 
1676         bCheck = m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_FIRST) == TRISTATE_TRUE;
1677         bModified |= pOpt->bTransliterateRTL != bCheck;
1678         pOpt->bTransliterateRTL = bCheck;
1679         pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL,
1680                         m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_SECOND) == TRISTATE_TRUE);
1681 
1682         bCheck = m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_FIRST) == TRISTATE_TRUE;
1683         bModified |= pOpt->bChgAngleQuotes != bCheck;
1684         pOpt->bChgAngleQuotes = bCheck;
1685         pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes,
1686                         m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_SECOND) == TRISTATE_TRUE);
1687     }
1688 
1689     pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgQuotes, m_xDoubleTypoCB->get_active());
1690     pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgSglQuotes, m_xSingleTypoCB->get_active());
1691     bool bReturn = nFlags != pAutoCorrect->GetFlags();
1692     if(cStartQuote != pAutoCorrect->GetStartDoubleQuote())
1693     {
1694         bReturn = true;
1695         sal_Unicode cUCS2 = static_cast<sal_Unicode>(cStartQuote); //TODO
1696         pAutoCorrect->SetStartDoubleQuote(cUCS2);
1697     }
1698     if(cEndQuote != pAutoCorrect->GetEndDoubleQuote())
1699     {
1700         bReturn = true;
1701         sal_Unicode cUCS2 = static_cast<sal_Unicode>(cEndQuote); //TODO
1702         pAutoCorrect->SetEndDoubleQuote(cUCS2);
1703     }
1704     if(cSglStartQuote != pAutoCorrect->GetStartSingleQuote())
1705     {
1706         bReturn = true;
1707         sal_Unicode cUCS2 = static_cast<sal_Unicode>(cSglStartQuote); //TODO
1708         pAutoCorrect->SetStartSingleQuote(cUCS2);
1709     }
1710     if(cSglEndQuote != pAutoCorrect->GetEndSingleQuote())
1711     {
1712         bReturn = true;
1713         sal_Unicode cUCS2 = static_cast<sal_Unicode>(cSglEndQuote); //TODO
1714         pAutoCorrect->SetEndSingleQuote(cUCS2);
1715     }
1716 
1717     if( bModified || bReturn )
1718     {
1719         SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
1720         rCfg.SetModified();
1721         rCfg.Commit();
1722     }
1723     return bReturn;
1724 }
1725 
ActivatePage(const SfxItemSet &)1726 void OfaQuoteTabPage::ActivatePage( const SfxItemSet& )
1727 {
1728     static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false);
1729 }
1730 
Reset(const SfxItemSet *)1731 void OfaQuoteTabPage::Reset( const SfxItemSet* )
1732 {
1733     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
1734     const ACFlags nFlags = pAutoCorrect->GetFlags();
1735 
1736     // Initialize the Sw options
1737     if (m_xSwCheckLB->get_visible())
1738     {
1739         SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
1740 
1741         m_xSwCheckLB->freeze();
1742         m_xSwCheckLB->clear();
1743 
1744         CreateEntry(*m_xSwCheckLB, sNonBrkSpace, CBCOL_BOTH, 2);
1745         CreateEntry(*m_xSwCheckLB, sOrdinal, CBCOL_BOTH, 2);
1746         CreateEntry(*m_xSwCheckLB, sTransliterateRTL, CBCOL_BOTH, 2);
1747         CreateEntry(*m_xSwCheckLB, sAngleQuotes, CBCOL_BOTH, 2);
1748 
1749         m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, pOpt->bAddNonBrkSpace ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
1750         m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
1751         m_xSwCheckLB->set_toggle(REPLACE_1ST, pOpt->bChgOrdinalNumber ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
1752         m_xSwCheckLB->set_toggle(REPLACE_1ST, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
1753         m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, pOpt->bTransliterateRTL ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
1754         m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
1755         m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, pOpt->bChgAngleQuotes ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST);
1756         m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND);
1757 
1758         m_xSwCheckLB->thaw();
1759     }
1760 
1761     // Initialize the non Sw options
1762     if (m_xCheckLB->get_visible())
1763     {
1764         m_xCheckLB->freeze();
1765         m_xCheckLB->clear();
1766 
1767         int nPos = 0;
1768         m_xCheckLB->append();
1769         m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE);
1770         m_xCheckLB->set_text(nPos++, sNonBrkSpace, 0);
1771         m_xCheckLB->append();
1772         m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE);
1773         m_xCheckLB->set_text(nPos++, sOrdinal, 0);
1774         m_xCheckLB->append();
1775         m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE);
1776         m_xCheckLB->set_text(nPos++, sTransliterateRTL, 0);
1777         m_xCheckLB->append();
1778         m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE);
1779         m_xCheckLB->set_text(nPos++, sAngleQuotes, 0);
1780 
1781         m_xCheckLB->thaw();
1782     }
1783 
1784     // Initialize the quote stuffs
1785     m_xDoubleTypoCB->set_active(bool(nFlags & ACFlags::ChgQuotes));
1786     m_xSingleTypoCB->set_active(bool(nFlags & ACFlags::ChgSglQuotes));
1787     m_xDoubleTypoCB->save_state();
1788     m_xSingleTypoCB->save_state();
1789 
1790     cStartQuote = pAutoCorrect->GetStartDoubleQuote();
1791     cEndQuote = pAutoCorrect->GetEndDoubleQuote();
1792     cSglStartQuote = pAutoCorrect->GetStartSingleQuote();
1793     cSglEndQuote = pAutoCorrect->GetEndSingleQuote();
1794 
1795     m_xSglStartExFT->set_label(ChangeStringExt_Impl(cSglStartQuote));
1796     m_xSglEndExFT->set_label(ChangeStringExt_Impl(cSglEndQuote));
1797     m_xDblStartExFT->set_label(ChangeStringExt_Impl(cStartQuote));
1798     m_xDblEndExFT->set_label(ChangeStringExt_Impl(cEndQuote));
1799 }
1800 
1801 #define SGL_START       0
1802 #define DBL_START       1
1803 #define SGL_END         2
1804 #define DBL_END         3
1805 
1806 
IMPL_LINK(OfaQuoteTabPage,QuoteHdl,weld::Button &,rBtn,void)1807 IMPL_LINK(OfaQuoteTabPage, QuoteHdl, weld::Button&, rBtn, void)
1808 {
1809     sal_uInt16 nMode = SGL_START;
1810     if (&rBtn == m_xSglEndQuotePB.get())
1811         nMode = SGL_END;
1812     else if (&rBtn == m_xDblStartQuotePB.get())
1813         nMode = DBL_START;
1814     else if (&rBtn == m_xDblEndQuotePB.get())
1815         nMode = DBL_END;
1816     // start character selection dialog
1817     SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr);
1818     aMap.SetCharFont( OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT,
1819                         LANGUAGE_ENGLISH_US, GetDefaultFontFlags::OnlyOne ));
1820     aMap.set_title(nMode < SGL_END ? CuiResId(RID_CUISTR_STARTQUOTE)  : CuiResId(RID_CUISTR_ENDQUOTE));
1821     sal_UCS4 cDlg;
1822     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
1823     LanguageType eLang = Application::GetSettings().GetLanguageTag().getLanguageType();
1824     switch( nMode )
1825     {
1826         case SGL_START:
1827             cDlg = cSglStartQuote;
1828             if(cDlg == 0)
1829                 cDlg = pAutoCorrect->GetQuote('\'', true, eLang);
1830         break;
1831         case SGL_END:
1832             cDlg = cSglEndQuote;
1833             if(cDlg == 0)
1834                 cDlg = pAutoCorrect->GetQuote('\'', false, eLang);
1835         break;
1836         case DBL_START:
1837             cDlg = cStartQuote;
1838             if(cDlg == 0)
1839                 cDlg = pAutoCorrect->GetQuote('\"', true, eLang);
1840         break;
1841         case DBL_END:
1842             cDlg = cEndQuote;
1843             if(cDlg == 0)
1844                 cDlg = pAutoCorrect->GetQuote('\"', false, eLang);
1845         break;
1846         default:
1847             OSL_FAIL("svx::OfaQuoteTabPage::QuoteHdl(), how to initialize cDlg?" );
1848             cDlg = 0;
1849             break;
1850 
1851     }
1852     aMap.SetChar(  cDlg );
1853     aMap.DisableFontSelection();
1854     if (aMap.run() != RET_OK)
1855         return;
1856 
1857     sal_UCS4 cNewChar = aMap.GetChar();
1858     switch( nMode )
1859     {
1860         case SGL_START:
1861             cSglStartQuote = cNewChar;
1862             m_xSglStartExFT->set_label(ChangeStringExt_Impl(cNewChar));
1863         break;
1864         case SGL_END:
1865             cSglEndQuote = cNewChar;
1866             m_xSglEndExFT->set_label(ChangeStringExt_Impl(cNewChar));
1867         break;
1868         case DBL_START:
1869             cStartQuote = cNewChar;
1870             m_xDblStartExFT->set_label(ChangeStringExt_Impl(cNewChar));
1871         break;
1872         case DBL_END:
1873             cEndQuote = cNewChar;
1874             m_xDblEndExFT->set_label(ChangeStringExt_Impl(cNewChar));
1875         break;
1876     }
1877 }
1878 
IMPL_LINK(OfaQuoteTabPage,StdQuoteHdl,weld::Button &,rBtn,void)1879 IMPL_LINK(OfaQuoteTabPage, StdQuoteHdl, weld::Button&, rBtn, void)
1880 {
1881     if (&rBtn == m_xDblStandardPB.get())
1882     {
1883         cStartQuote = 0;
1884         m_xDblStartExFT->set_label(ChangeStringExt_Impl(0));
1885         cEndQuote = 0;
1886         m_xDblEndExFT->set_label(ChangeStringExt_Impl(0));
1887 
1888     }
1889     else
1890     {
1891         cSglStartQuote = 0;
1892         m_xSglStartExFT->set_label(ChangeStringExt_Impl(0));
1893         cSglEndQuote = 0;
1894         m_xSglEndExFT->set_label(ChangeStringExt_Impl(0));
1895     }
1896 }
1897 
ChangeStringExt_Impl(sal_UCS4 cChar)1898 OUString OfaQuoteTabPage::ChangeStringExt_Impl( sal_UCS4 cChar )
1899 {
1900     if (!cChar)
1901         return m_sStandard;
1902 
1903     // convert codepoint value to unicode-hex string
1904     sal_UCS4 aStrCodes[32] = { 0, ' ', '(', 'U', '+', '0' };
1905     aStrCodes[0] = cChar;
1906     int nFullLen = 5;
1907     int nHexLen = 4;
1908     while( (cChar >> (4*nHexLen)) != 0 )
1909         ++nHexLen;
1910     for( int i = nHexLen; --i >= 0;)
1911     {
1912         sal_UCS4 cHexDigit = ((cChar >> (4*i)) & 0x0f) + '0';
1913         if( cHexDigit > '9' )
1914             cHexDigit += 'A' - ('9' + 1);
1915         aStrCodes[ nFullLen++ ] = cHexDigit;
1916     }
1917     aStrCodes[ nFullLen++ ] = ')';
1918     // using the new UCS4 constructor
1919     OUString aOUStr( aStrCodes, nFullLen );
1920     return aOUStr;
1921 }
1922 
OfaAutoCompleteTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)1923 OfaAutoCompleteTabPage::OfaAutoCompleteTabPage(weld::Container* pPage, weld::DialogController* pController,
1924     const SfxItemSet& rSet)
1925     : SfxTabPage(pPage, pController, u"cui/ui/wordcompletionpage.ui"_ustr,
1926                  u"WordCompletionPage"_ustr, &rSet)
1927     , m_pAutoCompleteList(nullptr)
1928     , m_nAutoCmpltListCnt(0)
1929     , m_xCBActiv(m_xBuilder->weld_check_button(u"enablewordcomplete"_ustr))
1930     , m_xCBAppendSpace(m_xBuilder->weld_check_button(u"appendspace"_ustr))
1931     , m_xCBAsTip(m_xBuilder->weld_check_button(u"showastip"_ustr))
1932     , m_xCBCollect(m_xBuilder->weld_check_button(u"collectwords"_ustr))
1933     , m_xCBRemoveList(m_xBuilder->weld_check_button(u"whenclosing"_ustr))
1934     , m_xDCBExpandKey(m_xBuilder->weld_combo_box(u"acceptwith"_ustr))
1935     , m_xNFMinWordlen(m_xBuilder->weld_spin_button(u"minwordlen"_ustr))
1936     , m_xNFMaxEntries(m_xBuilder->weld_spin_button(u"maxentries"_ustr))
1937     , m_xLBEntries(m_xBuilder->weld_tree_view(u"entries"_ustr))
1938     , m_xPBEntries(m_xBuilder->weld_button(u"delete"_ustr))
1939 {
1940     //fdo#65595, we need height-for-width support here, but for now we can
1941     //bodge it
1942     Size aPrefSize(m_xCBRemoveList->get_preferred_size());
1943     int nMaxWidth = m_xCBRemoveList->get_approximate_digit_width() * 40;
1944     if (aPrefSize.Width() > nMaxWidth)
1945     {
1946         m_xCBRemoveList->set_label_wrap(true);
1947         m_xCBRemoveList->set_size_request(nMaxWidth, -1);
1948     }
1949 
1950     m_xLBEntries->set_size_request(m_xLBEntries->get_approximate_digit_width() * 30,
1951                                    m_xLBEntries->get_height_rows(10));
1952     m_xLBEntries->set_selection_mode(SelectionMode::Multiple);
1953 
1954     // the defined KEYs
1955     static const sal_uInt16 aKeyCodes[] = {
1956         KEY_END,
1957         KEY_RETURN,
1958         KEY_SPACE,
1959         KEY_RIGHT,
1960         KEY_TAB,
1961         0
1962     };
1963 
1964     for( const sal_uInt16* pKeys = aKeyCodes; *pKeys; ++pKeys )
1965     {
1966         vcl::KeyCode aKCode(*pKeys);
1967         m_xDCBExpandKey->append(OUString::number(static_cast<sal_Int32>(*pKeys)), aKCode.GetName());
1968         if (KEY_RETURN == *pKeys)      // default to RETURN
1969             m_xDCBExpandKey->set_active(std::distance(aKeyCodes, pKeys));
1970     }
1971 
1972     m_xPBEntries->connect_clicked(LINK(this, OfaAutoCompleteTabPage, DeleteHdl));
1973     m_xCBActiv->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl));
1974     m_xCBCollect->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl));
1975     m_xLBEntries->connect_key_release(LINK(this, OfaAutoCompleteTabPage, KeyReleaseHdl));
1976 }
1977 
~OfaAutoCompleteTabPage()1978 OfaAutoCompleteTabPage::~OfaAutoCompleteTabPage()
1979 {
1980 }
1981 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)1982 std::unique_ptr<SfxTabPage> OfaAutoCompleteTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
1983                                                   const SfxItemSet* rSet)
1984 {
1985     return std::make_unique<OfaAutoCompleteTabPage>(pPage, pController, *rSet);
1986 }
1987 
FillItemSet(SfxItemSet *)1988 bool OfaAutoCompleteTabPage::FillItemSet( SfxItemSet* )
1989 {
1990     bool bModified = false, bCheck;
1991     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
1992     SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
1993 
1994     bCheck = m_xCBActiv->get_active();
1995     bModified |= pOpt->bAutoCompleteWords != bCheck;
1996     pOpt->bAutoCompleteWords = bCheck;
1997     bCheck = m_xCBCollect->get_active();
1998     bModified |= pOpt->bAutoCmpltCollectWords != bCheck;
1999     pOpt->bAutoCmpltCollectWords = bCheck;
2000     bCheck = !m_xCBRemoveList->get_active(); // inverted value!
2001     bModified |= pOpt->bAutoCmpltKeepList != bCheck;
2002     pOpt->bAutoCmpltKeepList = bCheck;
2003     bCheck = m_xCBAppendSpace->get_active();
2004     bModified |= pOpt->bAutoCmpltAppendBlank != bCheck;
2005     pOpt->bAutoCmpltAppendBlank = bCheck;
2006     bCheck = m_xCBAsTip->get_active();
2007     bModified |= pOpt->bAutoCmpltShowAsTip != bCheck;
2008     pOpt->bAutoCmpltShowAsTip = bCheck;
2009 
2010     sal_uInt16 nVal = static_cast<sal_uInt16>(m_xNFMinWordlen->get_value());
2011     bModified |= nVal != pOpt->nAutoCmpltWordLen;
2012     pOpt->nAutoCmpltWordLen = nVal;
2013 
2014     sal_uInt32 nList = static_cast<sal_uInt32>(m_xNFMaxEntries->get_value());
2015     bModified |= nList != pOpt->nAutoCmpltListLen;
2016     pOpt->nAutoCmpltListLen = nList;
2017 
2018     const int nPos = m_xDCBExpandKey->get_active();
2019     if (nPos != -1)
2020     {
2021         sal_Int32 nKey = m_xDCBExpandKey->get_id(nPos).toInt32();
2022         bModified |= nKey != pOpt->nAutoCmpltExpandKey;
2023         pOpt->nAutoCmpltExpandKey = static_cast<sal_uInt16>(nKey);
2024     }
2025 
2026     if (m_pAutoCompleteList && m_nAutoCmpltListCnt != m_xLBEntries->n_children())
2027     {
2028         bModified = true;
2029         pOpt->m_pAutoCompleteList = m_pAutoCompleteList;
2030     }
2031     if( bModified )
2032     {
2033         SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
2034         rCfg.SetModified();
2035         rCfg.Commit();
2036     }
2037     return true;
2038 }
2039 
Reset(const SfxItemSet *)2040 void OfaAutoCompleteTabPage::Reset( const SfxItemSet*  )
2041 {
2042     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
2043     SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
2044 
2045     m_xCBActiv->set_active( pOpt->bAutoCompleteWords );
2046     m_xCBCollect->set_active( pOpt->bAutoCmpltCollectWords );
2047     m_xCBRemoveList->set_active( !pOpt->bAutoCmpltKeepList ); //inverted value!
2048     m_xCBAppendSpace->set_active( pOpt->bAutoCmpltAppendBlank );
2049     m_xCBAsTip->set_active( pOpt->bAutoCmpltShowAsTip );
2050 
2051     m_xNFMinWordlen->set_value( pOpt->nAutoCmpltWordLen );
2052     m_xNFMaxEntries->set_value( pOpt->nAutoCmpltListLen );
2053 
2054     // select the specific KeyCode:
2055     {
2056         sal_Int32 nKey = pOpt->nAutoCmpltExpandKey;
2057         for (int n = 0, nCnt = m_xDCBExpandKey->get_count(); n < nCnt; ++n)
2058         {
2059             if (nKey == m_xDCBExpandKey->get_id(n).toInt32())
2060             {
2061                 m_xDCBExpandKey->set_active(n);
2062                 break;
2063             }
2064         }
2065     }
2066 
2067     if (pOpt->m_pAutoCompleteList && !pOpt->m_pAutoCompleteList->empty())
2068     {
2069         m_pAutoCompleteList = const_cast<editeng::SortedAutoCompleteStrings*>(
2070                 pOpt->m_pAutoCompleteList);
2071         pOpt->m_pAutoCompleteList = nullptr;
2072         m_nAutoCmpltListCnt = m_pAutoCompleteList->size();
2073         for (size_t n = 0; n < m_nAutoCmpltListCnt; ++n)
2074         {
2075             const OUString* pStr =
2076                 &(*m_pAutoCompleteList)[n]->GetAutoCompleteString();
2077             OUString sId(weld::toId(pStr));
2078             m_xLBEntries->append(sId, *pStr);
2079         }
2080     }
2081     else
2082     {
2083         m_xLBEntries->set_sensitive(false);
2084         m_xPBEntries->set_sensitive(false);
2085     }
2086 
2087     CheckHdl(*m_xCBActiv);
2088     CheckHdl(*m_xCBCollect);
2089 }
2090 
ActivatePage(const SfxItemSet &)2091 void OfaAutoCompleteTabPage::ActivatePage( const SfxItemSet& )
2092 {
2093     static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage( false );
2094 }
2095 
IMPL_LINK_NOARG(OfaAutoCompleteTabPage,DeleteHdl,weld::Button &,void)2096 IMPL_LINK_NOARG(OfaAutoCompleteTabPage, DeleteHdl, weld::Button&, void)
2097 {
2098     auto rows = m_xLBEntries->get_selected_rows();
2099     std::sort(rows.begin(), rows.end());
2100     while (!rows.empty())
2101     {
2102         sal_Int32 nPos = rows.back();
2103         OUString* pStr = weld::fromId<OUString*>(m_xLBEntries->get_id(nPos));
2104         m_xLBEntries->remove(nPos);
2105         editeng::IAutoCompleteString hack(*pStr); // UGLY
2106         m_pAutoCompleteList->erase(&hack);
2107         rows.pop_back();
2108     }
2109 }
2110 
IMPL_LINK(OfaAutoCompleteTabPage,CheckHdl,weld::Toggleable &,rBox,void)2111 IMPL_LINK(OfaAutoCompleteTabPage, CheckHdl, weld::Toggleable&, rBox, void)
2112 {
2113     bool bEnable = rBox.get_active();
2114     if (&rBox == m_xCBActiv.get())
2115     {
2116         m_xCBAppendSpace->set_sensitive(bEnable);
2117         m_xCBAppendSpace->set_sensitive(bEnable);
2118         m_xCBAsTip->set_sensitive(bEnable);
2119         m_xDCBExpandKey->set_sensitive(bEnable);
2120     }
2121     else if (&rBox == m_xCBCollect.get())
2122         m_xCBRemoveList->set_sensitive(bEnable);
2123 }
2124 
CopyToClipboard() const2125 void OfaAutoCompleteTabPage::CopyToClipboard() const
2126 {
2127     auto rows = m_xLBEntries->get_selected_rows();
2128     if (!m_pAutoCompleteList || rows.empty())
2129         return;
2130 
2131     rtl::Reference<TransferDataContainer> pCntnr = new TransferDataContainer;
2132 
2133     OStringBuffer sData;
2134 
2135     rtl_TextEncoding nEncode = osl_getThreadTextEncoding();
2136 
2137     for (auto a : rows)
2138     {
2139         sData.append(OUStringToOString(m_xLBEntries->get_text(a), nEncode) + SAL_NEWLINE_STRING);
2140     }
2141     pCntnr->CopyByteString( SotClipboardFormatId::STRING, sData.makeStringAndClear() );
2142     pCntnr->CopyToClipboard(m_xLBEntries->get_clipboard());
2143 }
2144 
IMPL_LINK(OfaAutoCompleteTabPage,KeyReleaseHdl,const KeyEvent &,rEvent,bool)2145 IMPL_LINK(OfaAutoCompleteTabPage, KeyReleaseHdl, const KeyEvent&, rEvent, bool)
2146 {
2147     bool bHandled = false;
2148     const vcl::KeyCode& rKeyCode = rEvent.GetKeyCode();
2149     switch (rKeyCode.GetModifier() | rKeyCode.GetCode())
2150     {
2151         case KEY_DELETE:
2152             DeleteHdl(*m_xPBEntries);
2153             bHandled = true;
2154             break;
2155         default:
2156             if (KeyFuncType::COPY == rKeyCode.GetFunction())
2157             {
2158                 CopyToClipboard();
2159                 bHandled = true;
2160             }
2161             break;
2162     }
2163     return bHandled;
2164 }
2165 
2166 // class OfaSmartTagOptionsTabPage ---------------------------------------------
2167 
OfaSmartTagOptionsTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)2168 OfaSmartTagOptionsTabPage::OfaSmartTagOptionsTabPage(weld::Container* pPage, weld::DialogController* pController,
2169                                                      const SfxItemSet& rSet )
2170     : SfxTabPage(pPage, pController, u"cui/ui/smarttagoptionspage.ui"_ustr, u"SmartTagOptionsPage"_ustr, &rSet)
2171     , m_xMainCB(m_xBuilder->weld_check_button(u"main"_ustr))
2172     , m_xSmartTagTypesLB(m_xBuilder->weld_tree_view(u"list"_ustr))
2173     , m_xPropertiesPB(m_xBuilder->weld_button(u"properties"_ustr))
2174 {
2175     m_xSmartTagTypesLB->set_size_request(m_xSmartTagTypesLB->get_approximate_digit_width() * 50,
2176                                          m_xSmartTagTypesLB->get_height_rows(6));
2177 
2178     m_xSmartTagTypesLB->enable_toggle_buttons(weld::ColumnToggleType::Check);
2179 
2180     // set the handlers:
2181     m_xMainCB->connect_toggled(LINK(this, OfaSmartTagOptionsTabPage, CheckHdl));
2182     m_xPropertiesPB->connect_clicked(LINK(this, OfaSmartTagOptionsTabPage, ClickHdl));
2183     m_xSmartTagTypesLB->connect_changed(LINK(this, OfaSmartTagOptionsTabPage, SelectHdl));
2184 }
2185 
~OfaSmartTagOptionsTabPage()2186 OfaSmartTagOptionsTabPage::~OfaSmartTagOptionsTabPage()
2187 {
2188 }
2189 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)2190 std::unique_ptr<SfxTabPage> OfaSmartTagOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
2191 {
2192     return std::make_unique<OfaSmartTagOptionsTabPage>(pPage, pController, *rSet);
2193 }
2194 
2195 namespace {
2196 
2197 /** This struct is used to associate list box entries with smart tag data
2198 */
2199 struct ImplSmartTagLBUserData
2200 {
2201     OUString maSmartTagType;
2202     uno::Reference< smarttags::XSmartTagRecognizer > mxRec;
2203     sal_Int32 mnSmartTagIdx;
2204 
ImplSmartTagLBUserData__anonffeffcef0711::ImplSmartTagLBUserData2205     ImplSmartTagLBUserData( OUString aSmartTagType,
2206                             uno::Reference< smarttags::XSmartTagRecognizer >  xRec,
2207                             sal_Int32 nSmartTagIdx ) :
2208         maSmartTagType(std::move( aSmartTagType )),
2209         mxRec(std::move( xRec )),
2210         mnSmartTagIdx( nSmartTagIdx ) {}
2211 };
2212 
2213 }
2214 
2215 /** Clears m_xSmartTagTypesLB
2216 */
ClearListBox()2217 void OfaSmartTagOptionsTabPage::ClearListBox()
2218 {
2219     const int nCount = m_xSmartTagTypesLB->n_children();
2220     for (int i = 0; i < nCount; ++i)
2221     {
2222         const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(i));
2223         delete pUserData;
2224     }
2225 
2226     m_xSmartTagTypesLB->clear();
2227 }
2228 
2229 /** Inserts items into m_xSmartTagTypesLB
2230 */
FillListBox(const SmartTagMgr & rSmartTagMgr)2231 void OfaSmartTagOptionsTabPage::FillListBox( const SmartTagMgr& rSmartTagMgr )
2232 {
2233     // first we have to clear the list box:
2234     ClearListBox();
2235 
2236     // fill list box:
2237     const sal_uInt32 nNumberOfRecognizers = rSmartTagMgr.NumberOfRecognizers();
2238     const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) );
2239 
2240     for ( sal_uInt32 i = 0; i < nNumberOfRecognizers; ++i )
2241     {
2242         const uno::Reference< smarttags::XSmartTagRecognizer >& xRec = rSmartTagMgr.GetRecognizer(i);
2243 
2244         const OUString aName = xRec->getName( aLocale );
2245         const sal_Int32 nNumberOfSupportedSmartTags = xRec->getSmartTagCount();
2246 
2247         for ( sal_Int32 j = 0; j < nNumberOfSupportedSmartTags; ++j )
2248         {
2249             const OUString aSmartTagType = xRec->getSmartTagName(j);
2250             OUString aSmartTagCaption = rSmartTagMgr.GetSmartTagCaption( aSmartTagType, aLocale );
2251 
2252             if ( aSmartTagCaption.isEmpty() )
2253                 aSmartTagCaption = aSmartTagType;
2254 
2255             const OUString aLBEntry = aSmartTagCaption + " (" + aName + ")";
2256 
2257             m_xSmartTagTypesLB->append();
2258             const int nRow = m_xSmartTagTypesLB->n_children() - 1;
2259             const bool bCheck = rSmartTagMgr.IsSmartTagTypeEnabled( aSmartTagType );
2260             m_xSmartTagTypesLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE);
2261             m_xSmartTagTypesLB->set_text(nRow, aLBEntry, 0);
2262             m_xSmartTagTypesLB->set_id(nRow, weld::toId(new ImplSmartTagLBUserData(aSmartTagType, xRec, j)));
2263         }
2264     }
2265 }
2266 
2267 /** Handler for the push button
2268 */
IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage,ClickHdl,weld::Button &,void)2269 IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, ClickHdl, weld::Button&, void)
2270 {
2271     const int nPos = m_xSmartTagTypesLB->get_selected_index();
2272     const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(nPos));
2273     uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec;
2274     const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx;
2275 
2276     const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) );
2277     if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) )
2278         xRec->displayPropertyPage( nSmartTagIdx, aLocale );
2279 }
2280 
2281 /** Handler for the check box
2282 */
IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage,CheckHdl,weld::Toggleable &,void)2283 IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, CheckHdl, weld::Toggleable&, void)
2284 {
2285     const bool bEnable = m_xMainCB->get_active();
2286     m_xSmartTagTypesLB->set_sensitive(bEnable);
2287     m_xPropertiesPB->set_sensitive(false);
2288 
2289     // if the controls are currently enabled, we still have to check
2290     // if the properties button should be disabled because the currently
2291     // selected smart tag type does not have a properties dialog.
2292     // We do this by calling SelectHdl:
2293     if (bEnable)
2294         SelectHdl(*m_xSmartTagTypesLB);
2295 }
2296 
2297 /** Handler for the list box
2298 */
IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage,SelectHdl,weld::TreeView &,void)2299 IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, SelectHdl, weld::TreeView&, void)
2300 {
2301     const int nPos = m_xSmartTagTypesLB->get_selected_index();
2302     if (nPos == -1)
2303         return;
2304     const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(nPos));
2305     uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec;
2306     const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx;
2307 
2308     const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) );
2309     if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) )
2310         m_xPropertiesPB->set_sensitive(true);
2311     else
2312         m_xPropertiesPB->set_sensitive(false);
2313 }
2314 
2315 /** Propagates the current settings to the smart tag manager.
2316 */
FillItemSet(SfxItemSet *)2317 bool OfaSmartTagOptionsTabPage::FillItemSet( SfxItemSet* )
2318 {
2319     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
2320     SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
2321     SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr;
2322 
2323     // robust!
2324     if ( !pSmartTagMgr )
2325         return false;
2326 
2327     bool bModifiedSmartTagTypes = false;
2328     std::vector< OUString > aDisabledSmartTagTypes;
2329 
2330     const int nCount = m_xSmartTagTypesLB->n_children();
2331 
2332     for (int i = 0; i < nCount; ++i)
2333     {
2334         const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(i));
2335         const bool bChecked = m_xSmartTagTypesLB->get_toggle(i) == TRISTATE_TRUE;
2336         const bool bIsCurrentlyEnabled = pSmartTagMgr->IsSmartTagTypeEnabled( pUserData->maSmartTagType );
2337 
2338         bModifiedSmartTagTypes = bModifiedSmartTagTypes || ( !bChecked != !bIsCurrentlyEnabled );
2339 
2340         if ( !bChecked )
2341             aDisabledSmartTagTypes.push_back( pUserData->maSmartTagType );
2342 
2343         delete pUserData;
2344     }
2345 
2346     const bool bModifiedRecognize = ( !m_xMainCB->get_active() != !pSmartTagMgr->IsLabelTextWithSmartTags() );
2347     if ( bModifiedSmartTagTypes || bModifiedRecognize )
2348     {
2349         bool bLabelTextWithSmartTags = m_xMainCB->get_active();
2350         pSmartTagMgr->WriteConfiguration( bModifiedRecognize     ? &bLabelTextWithSmartTags : nullptr,
2351                                           bModifiedSmartTagTypes ? &aDisabledSmartTagTypes : nullptr );
2352     }
2353 
2354     return true;
2355 }
2356 
2357 /** Sets the controls based on the current settings at SmartTagMgr.
2358 */
Reset(const SfxItemSet *)2359 void OfaSmartTagOptionsTabPage::Reset( const SfxItemSet*  )
2360 {
2361     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
2362     SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags();
2363     const SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr;
2364 
2365     // robust, should not happen!
2366     if ( !pSmartTagMgr )
2367         return;
2368 
2369     FillListBox(*pSmartTagMgr);
2370     m_xSmartTagTypesLB->select(0);
2371     m_xMainCB->set_active(pSmartTagMgr->IsLabelTextWithSmartTags());
2372     CheckHdl(*m_xMainCB);
2373 }
2374 
ActivatePage(const SfxItemSet &)2375 void OfaSmartTagOptionsTabPage::ActivatePage( const SfxItemSet& )
2376 {
2377     static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage( false );
2378 }
2379 
2380 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2381