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