diff options
Diffstat (limited to '')
-rw-r--r-- | cui/source/tabpages/autocdlg.cxx | 2379 |
1 files changed, 2379 insertions, 0 deletions
diff --git a/cui/source/tabpages/autocdlg.cxx b/cui/source/tabpages/autocdlg.cxx new file mode 100644 index 0000000000..282e8b5405 --- /dev/null +++ b/cui/source/tabpages/autocdlg.cxx @@ -0,0 +1,2379 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <i18nutil/unicode.hxx> +#include <o3tl/safeint.hxx> +#include <utility> +#include <vcl/event.hxx> +#include <vcl/keycodes.hxx> +#include <vcl/settings.hxx> +#include <vcl/transfer.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewsh.hxx> +#include <unotools/charclass.hxx> +#include <unotools/collatorwrapper.hxx> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/module.hxx> +#include <svl/eitem.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <svx/SmartTagMgr.hxx> +#include <com/sun/star/smarttags/XSmartTagRecognizer.hpp> +#include <rtl/strbuf.hxx> +#include <o3tl/temporary.hxx> +#include <osl/diagnose.h> +#include <tools/debug.hxx> + +#include <autocdlg.hxx> +#include <editeng/acorrcfg.hxx> +#include <editeng/svxacorr.hxx> +#include <cui/cuicharmap.hxx> +#include <strings.hrc> +#include <dialmgr.hxx> +#include <svx/svxids.hrc> + +static LanguageType eLastDialogLanguage = LANGUAGE_SYSTEM; + +using namespace ::com::sun::star::util; +using namespace ::com::sun::star; + +OfaAutoCorrDlg::OfaAutoCorrDlg(weld::Window* pParent, const SfxItemSet* _pSet ) + : SfxTabDialogController(pParent, "cui/ui/autocorrectdialog.ui", "AutoCorrectDialog", _pSet) + , m_xLanguageBox(m_xBuilder->weld_widget("langbox")) + , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("lang"))) +{ + bool bShowSWOptions = false; + bool bOpenSmartTagOptions = false; + + if ( _pSet ) + { + const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(_pSet, SID_AUTO_CORRECT_DLG, false); + if ( pItem && pItem->GetValue() ) + bShowSWOptions = true; + + const SfxBoolItem* pItem2 = SfxItemSet::GetItem<SfxBoolItem>(_pSet, SID_OPEN_SMARTTAGOPTIONS, false); + if ( pItem2 && pItem2->GetValue() ) + bOpenSmartTagOptions = true; + } + + AddTabPage("options", OfaAutocorrOptionsPage::Create, nullptr); + AddTabPage("applypage", OfaSwAutoFmtOptionsPage::Create, nullptr); + AddTabPage("wordcompletion", OfaAutoCompleteTabPage::Create, nullptr); + AddTabPage("smarttags", OfaSmartTagOptionsTabPage::Create, nullptr); + + if (!bShowSWOptions) + { + RemoveTabPage("applypage"); + RemoveTabPage("wordcompletion"); + RemoveTabPage("smarttags"); + } + else + { + // remove smart tag tab page if no extensions are installed + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags& rOpt = pAutoCorrect->GetSwFlags(); + if (!rOpt.pSmartTagMgr || 0 == rOpt.pSmartTagMgr->NumberOfRecognizers()) + RemoveTabPage("smarttags"); + + RemoveTabPage("options"); + } + + AddTabPage("replace", OfaAutocorrReplacePage::Create, nullptr); + AddTabPage("exceptions", OfaAutocorrExceptPage::Create, nullptr); + AddTabPage("localized", OfaQuoteTabPage::Create, nullptr); + + // initialize languages + //! LANGUAGE_NONE is displayed as '[All]' and the LanguageType + //! will be set to LANGUAGE_UNDETERMINED + SvxLanguageListFlags nLangList = SvxLanguageListFlags::WESTERN; + + if( SvtCTLOptions::IsCTLFontEnabled() ) + nLangList |= SvxLanguageListFlags::CTL; + if( SvtCJKOptions::IsCJKFontEnabled() ) + nLangList |= SvxLanguageListFlags::CJK; + m_xLanguageLB->SetLanguageList( nLangList, true, true ); + m_xLanguageLB->set_active_id( LANGUAGE_NONE ); + int nPos = m_xLanguageLB->get_active(); + DBG_ASSERT(nPos != -1, "listbox entry missing" ); + m_xLanguageLB->set_id(nPos, LANGUAGE_UNDETERMINED); + + // Initializing doesn't work for static on linux - therefore here + if (LANGUAGE_SYSTEM == eLastDialogLanguage) + eLastDialogLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); + + LanguageType nSelectLang = LANGUAGE_UNDETERMINED; + nPos = m_xLanguageLB->find_id(eLastDialogLanguage); + if (nPos != -1) + nSelectLang = eLastDialogLanguage; + m_xLanguageLB->set_active_id(nSelectLang); + + m_xLanguageLB->connect_changed(LINK(this, OfaAutoCorrDlg, SelectLanguageHdl)); + + if ( bOpenSmartTagOptions ) + SetCurPageId("smarttags"); +} + +OfaAutoCorrDlg::~OfaAutoCorrDlg() +{ +} + +void OfaAutoCorrDlg::EnableLanguage(bool bEnable) +{ + m_xLanguageBox->set_sensitive(bEnable); +} + +static bool lcl_FindEntry(weld::TreeView& rLB, const OUString& rEntry, + CollatorWrapper const & rCmpClass) +{ + int nCount = rLB.n_children(); + int nSelPos = rLB.get_selected_index(); + for (int i = 0; i < nCount; i++) + { + if (0 == rCmpClass.compareString(rEntry, rLB.get_text(i))) + { + rLB.select(i); + return true; + } + } + if (nSelPos != -1) + rLB.unselect(nSelPos); + return false; +} + +IMPL_LINK_NOARG(OfaAutoCorrDlg, SelectLanguageHdl, weld::ComboBox&, void) +{ + LanguageType eNewLang = m_xLanguageLB->get_active_id(); + // save old settings and fill anew + if(eNewLang == eLastDialogLanguage) + return; + + OUString sPageId = GetCurPageId(); + if (sPageId == "replace") + { + OfaAutocorrReplacePage* pPage = static_cast<OfaAutocorrReplacePage*>(GetTabPage(sPageId)); + assert(pPage); + pPage->SetLanguage(eNewLang); + } + else if (sPageId == "exceptions") + { + OfaAutocorrExceptPage* pPage = static_cast<OfaAutocorrExceptPage*>(GetTabPage(sPageId)); + assert(pPage); + pPage->SetLanguage(eNewLang); + } +} + +OfaAutocorrOptionsPage::OfaAutocorrOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acoroptionspage.ui", "AutocorrectOptionsPage", &rSet) + , m_sInput(CuiResId(RID_CUISTR_USE_REPLACE)) + , m_sDoubleCaps(CuiResId(RID_CUISTR_CPTL_STT_WORD)) + , m_sStartCap(CuiResId(RID_CUISTR_CPTL_STT_SENT)) + , m_sBoldUnderline(CuiResId(RID_CUISTR_BOLD_UNDER)) + , m_sURL(CuiResId(RID_CUISTR_DETECT_URL)) + , m_sDOI(CuiResId(RID_CUISTR_DETECT_DOI)) + , m_sNoDblSpaces(CuiResId(RID_CUISTR_NO_DBL_SPACES)) + , m_sDash(CuiResId(RID_CUISTR_DASH)) + , m_sAccidentalCaps(CuiResId(RID_CUISTR_CORRECT_ACCIDENTAL_CAPS_LOCK)) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklist")) +{ + m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xCheckLB->set_size_request(-1, m_xCheckLB->get_height_rows(10)); +} + +OfaAutocorrOptionsPage::~OfaAutocorrOptionsPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaAutocorrOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutocorrOptionsPage>(pPage, pController, *rSet); +} + +#define CBCOL_FIRST 0 +#define CBCOL_SECOND 1 +#define CBCOL_BOTH 2 + +bool OfaAutocorrOptionsPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + ACFlags nFlags = pAutoCorrect->GetFlags(); + + int nPos = 0; + pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetDOIAttr, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + + bool bReturn = nFlags != pAutoCorrect->GetFlags(); + if(bReturn ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return bReturn; +} + +void OfaAutocorrOptionsPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false); +} + +void OfaAutocorrOptionsPage::InsertEntry(const OUString& rTxt) +{ + m_xCheckLB->append(); + const int nRow = m_xCheckLB->n_children() - 1; + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE); + m_xCheckLB->set_text(nRow, rTxt, 0); +} + +void OfaAutocorrOptionsPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + InsertEntry(m_sInput); + InsertEntry(m_sDoubleCaps); + InsertEntry(m_sStartCap); + InsertEntry(m_sBoldUnderline); + InsertEntry(m_sURL); + InsertEntry(m_sDOI); + InsertEntry(m_sDash); + InsertEntry(m_sNoDblSpaces); + InsertEntry(m_sAccidentalCaps); + + int nPos = 0; + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::SetDOIAttr) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE ); + + m_xCheckLB->thaw(); +} + +/*********************************************************************/ +/* */ +/* helping struct for dUserData of the Checklistbox */ +/* */ +/*********************************************************************/ + +namespace { + +struct ImpUserData +{ + OUString *pString; + vcl::Font *pFont; + + ImpUserData(OUString* pText, vcl::Font* pFnt) + { pString = pText; pFont = pFnt;} +}; + + +/*********************************************************************/ +/* */ +/* dialog for per cent settings */ +/* */ +/*********************************************************************/ + +class OfaAutoFmtPrcntSet : public weld::GenericDialogController +{ + std::unique_ptr<weld::MetricSpinButton> m_xPrcntMF; +public: + explicit OfaAutoFmtPrcntSet(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/percentdialog.ui", "PercentDialog") + , m_xPrcntMF(m_xBuilder->weld_metric_spin_button("margin", FieldUnit::PERCENT)) + { + } + + weld::MetricSpinButton& GetPrcntFld() + { + return *m_xPrcntMF; + } +}; + +/*********************************************************************/ +/* */ +/* use TabPage autoformat */ +/* */ +/*********************************************************************/ + +enum OfaAutoFmtOptions +{ + USE_REPLACE_TABLE, + CORR_UPPER, + BEGIN_UPPER, + BOLD_UNDERLINE, + DETECT_URL, + DETECT_DOI, + REPLACE_DASHES, + DEL_SPACES_AT_STT_END, + DEL_SPACES_BETWEEN_LINES, + IGNORE_DBLSPACE, + CORRECT_CAPS_LOCK, + APPLY_NUMBERING, + APPLY_NUMBERING_AFTER_SPACE, + INSERT_BORDER, + CREATE_TABLE, + REPLACE_STYLES, + DEL_EMPTY_NODE, + REPLACE_USER_COLL, + REPLACE_BULLETS, + MERGE_SINGLE_LINE_PARA +}; + +} + +OfaSwAutoFmtOptionsPage::OfaSwAutoFmtOptionsPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet ) + : SfxTabPage(pPage, pController, "cui/ui/applyautofmtpage.ui", "ApplyAutoFmtPage", &rSet) + , sDeleteEmptyPara(CuiResId(RID_CUISTR_DEL_EMPTY_PARA)) + , sUseReplaceTbl(CuiResId(RID_CUISTR_USE_REPLACE)) + , sCapitalStartWord(CuiResId(RID_CUISTR_CPTL_STT_WORD)) + , sCapitalStartSentence(CuiResId(RID_CUISTR_CPTL_STT_SENT)) + , sUserStyle(CuiResId(RID_CUISTR_USER_STYLE)) + , sBullet(CuiResId(RID_CUISTR_BULLET)) + , sBoldUnder(CuiResId(RID_CUISTR_BOLD_UNDER)) + , sNoDblSpaces(CuiResId(RID_CUISTR_NO_DBL_SPACES)) + , sCorrectCapsLock(CuiResId(RID_CUISTR_CORRECT_ACCIDENTAL_CAPS_LOCK)) + , sDetectURL(CuiResId(RID_CUISTR_DETECT_URL)) + , sDetectDOI(CuiResId(RID_CUISTR_DETECT_DOI)) + , sDash(CuiResId(RID_CUISTR_DASH)) + , sRightMargin(CuiResId(RID_CUISTR_RIGHT_MARGIN)) + , sNum(CuiResId(RID_CUISTR_NUM)) + , sBulletsAfterSpace(CuiResId(RID_SVXSTR_NUM_FORMAT_AFTER_SPACE)) + , sBorder(CuiResId(RID_CUISTR_BORDER)) + , sTable(CuiResId(RID_CUISTR_CREATE_TABLE)) + , sReplaceTemplates(CuiResId(RID_CUISTR_REPLACE_TEMPLATES)) + , sDelSpaceAtSttEnd(CuiResId(RID_CUISTR_DEL_SPACES_AT_STT_END)) + , sDelSpaceBetweenLines(CuiResId(RID_CUISTR_DEL_SPACES_BETWEEN_LINES)) + , nPercent(50) + , m_xCheckLB(m_xBuilder->weld_tree_view("list")) + , m_xEditPB(m_xBuilder->weld_button("edit")) +{ + m_xCheckLB->connect_changed(LINK(this, OfaSwAutoFmtOptionsPage, SelectHdl)); + m_xCheckLB->connect_row_activated(LINK(this, OfaSwAutoFmtOptionsPage, DoubleClickEditHdl)); + + std::vector<int> aWidths + { + o3tl::narrowing<int>(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(0)).Width() * 2), + o3tl::narrowing<int>(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(1)).Width() * 2) + }; + m_xCheckLB->set_column_fixed_widths(aWidths); + + m_xEditPB->connect_clicked(LINK(this, OfaSwAutoFmtOptionsPage, EditHdl)); +} + +void OfaSwAutoFmtOptionsPage::CreateEntry(const OUString& rTxt, sal_uInt16 nCol) +{ + m_xCheckLB->append(); + const int nRow = m_xCheckLB->n_children() - 1; + if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH) + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST); + if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH) + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_text(nRow, rTxt, 2); +} + +OfaSwAutoFmtOptionsPage::~OfaSwAutoFmtOptionsPage() +{ + delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(REPLACE_BULLETS)); + delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(APPLY_NUMBERING)); + delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(MERGE_SINGLE_LINE_PARA)); +} + +std::unique_ptr<SfxTabPage> OfaSwAutoFmtOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<OfaSwAutoFmtOptionsPage>(pPage, pController, *rAttrSet); +} + +bool OfaSwAutoFmtOptionsPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + ACFlags nFlags = pAutoCorrect->GetFlags(); + + bool bCheck = m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAutoCorrect != bCheck; + pOpt->bAutoCorrect = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect, + m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bCapitalStartWord != bCheck; + pOpt->bCapitalStartWord = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord, + m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bCapitalStartSentence != bCheck; + pOpt->bCapitalStartSentence = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence, + m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgWeightUnderl != bCheck; + pOpt->bChgWeightUnderl = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl, + m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_SECOND) == TRISTATE_TRUE); + + pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace, + m_xCheckLB->get_toggle(IGNORE_DBLSPACE, CBCOL_SECOND) == TRISTATE_TRUE); + + pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock, + m_xCheckLB->get_toggle(CORRECT_CAPS_LOCK, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DETECT_URL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bSetINetAttr != bCheck; + pOpt->bSetINetAttr = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr, + m_xCheckLB->get_toggle(DETECT_URL, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DETECT_DOI, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bSetDOIAttr != bCheck; + pOpt->bSetDOIAttr = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetDOIAttr, + m_xCheckLB->get_toggle(DETECT_DOI, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DEL_EMPTY_NODE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bDelEmptyNode != bCheck; + pOpt->bDelEmptyNode = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_USER_COLL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgUserColl != bCheck; + pOpt->bChgUserColl = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_BULLETS, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgEnumNum != bCheck; + pOpt->bChgEnumNum = bCheck; + bModified |= aBulletFont != pOpt->aBulletFont; + pOpt->aBulletFont = aBulletFont; + bModified |= sBulletChar != OUString(&pOpt->cBullet, 1); + pOpt->cBullet = sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0))); + + bModified |= aByInputBulletFont != pOpt->aByInputBulletFont; + bModified |= sByInputBulletChar != OUString(&pOpt->cByInputBullet, 1); + pOpt->aByInputBulletFont = aByInputBulletFont; + pOpt->cByInputBullet = sByInputBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0))); + + bCheck = m_xCheckLB->get_toggle(MERGE_SINGLE_LINE_PARA, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bRightMargin != bCheck; + pOpt->bRightMargin = bCheck; + bModified |= nPercent != pOpt->nRightMargin; + pOpt->nRightMargin = static_cast<sal_uInt8>(nPercent); + + bCheck = m_xCheckLB->get_toggle(APPLY_NUMBERING, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bSetNumRule != bCheck; + pOpt->bSetNumRule = bCheck; + + bCheck = m_xCheckLB->get_toggle(APPLY_NUMBERING_AFTER_SPACE, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bSetNumRuleAfterSpace != bCheck; + pOpt->bSetNumRuleAfterSpace = bCheck; + + bCheck = m_xCheckLB->get_toggle(INSERT_BORDER, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bSetBorder != bCheck; + pOpt->bSetBorder = bCheck; + + bCheck = m_xCheckLB->get_toggle(CREATE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bCreateTable != bCheck; + pOpt->bCreateTable = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_STYLES, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bReplaceStyles != bCheck; + pOpt->bReplaceStyles = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgToEnEmDash != bCheck; + pOpt->bChgToEnEmDash = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash, + m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatDelSpacesAtSttEnd != bCheck; + pOpt->bAFormatDelSpacesAtSttEnd = bCheck; + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatByInpDelSpacesAtSttEnd != bCheck; + pOpt->bAFormatByInpDelSpacesAtSttEnd = bCheck; + + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatDelSpacesBetweenLines != bCheck; + pOpt->bAFormatDelSpacesBetweenLines = bCheck; + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatByInpDelSpacesBetweenLines != bCheck; + pOpt->bAFormatByInpDelSpacesBetweenLines = bCheck; + + if(bModified || nFlags != pAutoCorrect->GetFlags()) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + + return true; +} + +void OfaSwAutoFmtOptionsPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false); +} + +void OfaSwAutoFmtOptionsPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + aBulletFont = pOpt->aBulletFont; + sBulletChar = OUString(&pOpt->cBullet, 1); + + aByInputBulletFont = pOpt->aByInputBulletFont; + sByInputBulletChar = OUString(&pOpt->cByInputBullet, 1); + + nPercent = pOpt->nRightMargin; + sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag()); + + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + // The following entries have to be inserted in the same order + // as in the OfaAutoFmtOptions-enum! + CreateEntry(sUseReplaceTbl, CBCOL_BOTH ); + CreateEntry(sCapitalStartWord, CBCOL_BOTH ); + CreateEntry(sCapitalStartSentence, CBCOL_BOTH ); + CreateEntry(sBoldUnder, CBCOL_BOTH ); + CreateEntry(sDetectURL, CBCOL_BOTH ); + CreateEntry(sDetectDOI, CBCOL_BOTH ); + CreateEntry(sDash, CBCOL_BOTH ); + CreateEntry(sDelSpaceAtSttEnd, CBCOL_BOTH ); + CreateEntry(sDelSpaceBetweenLines, CBCOL_BOTH ); + + CreateEntry(sNoDblSpaces, CBCOL_SECOND); + CreateEntry(sCorrectCapsLock, CBCOL_SECOND); + CreateEntry(sNum.replaceFirst("%1", sBulletChar), CBCOL_SECOND); + CreateEntry(sBulletsAfterSpace, CBCOL_SECOND); + CreateEntry(sBorder, CBCOL_SECOND); + CreateEntry(sTable, CBCOL_SECOND); + CreateEntry(sReplaceTemplates, CBCOL_SECOND); + CreateEntry(sDeleteEmptyPara, CBCOL_FIRST ); + CreateEntry(sUserStyle, CBCOL_FIRST ); + CreateEntry(sBullet.replaceFirst("%1", sByInputBulletChar), CBCOL_FIRST); + CreateEntry(sRightMargin.replaceFirst("%1", sMargin), CBCOL_FIRST); + + m_xCheckLB->set_toggle(USE_REPLACE_TABLE, pOpt->bAutoCorrect ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(USE_REPLACE_TABLE, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CORR_UPPER, pOpt->bCapitalStartWord ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(CORR_UPPER, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(BEGIN_UPPER, pOpt->bCapitalStartSentence ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(BEGIN_UPPER, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(BOLD_UNDERLINE, pOpt->bChgWeightUnderl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(BOLD_UNDERLINE, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DETECT_URL, pOpt->bSetINetAttr ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DETECT_URL, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DETECT_DOI, pOpt->bSetDOIAttr ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DETECT_DOI, bool(nFlags & ACFlags::SetDOIAttr) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(REPLACE_DASHES, pOpt->bChgToEnEmDash ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_DASHES, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatByInpDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatByInpDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(IGNORE_DBLSPACE, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CORRECT_CAPS_LOCK, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(APPLY_NUMBERING, pOpt->bSetNumRule ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(APPLY_NUMBERING_AFTER_SPACE, pOpt->bSetNumRuleAfterSpace ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(INSERT_BORDER, pOpt->bSetBorder ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CREATE_TABLE, pOpt->bCreateTable ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(REPLACE_STYLES, pOpt->bReplaceStyles ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_EMPTY_NODE, pOpt->bDelEmptyNode ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_USER_COLL, pOpt->bChgUserColl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_BULLETS, pOpt->bChgEnumNum ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(MERGE_SINGLE_LINE_PARA, pOpt->bRightMargin ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + + ImpUserData* pUserData = new ImpUserData(&sBulletChar, &aBulletFont); + OUString sId(weld::toId(pUserData)); + m_xCheckLB->set_id(REPLACE_BULLETS, sId); + + pUserData = new ImpUserData(&sMargin, nullptr); + sId = weld::toId(pUserData); + m_xCheckLB->set_id(MERGE_SINGLE_LINE_PARA, sId); + + ImpUserData* pUserData2 = new ImpUserData(&sByInputBulletChar, &aByInputBulletFont); + sId = weld::toId(pUserData2); + m_xCheckLB->set_id(APPLY_NUMBERING, sId); + + m_xCheckLB->thaw(); +} + +IMPL_LINK(OfaSwAutoFmtOptionsPage, SelectHdl, weld::TreeView&, rBox, void) +{ + m_xEditPB->set_sensitive(rBox.get_selected_id().toInt64() != 0); +} + +IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, DoubleClickEditHdl, weld::TreeView&, bool) +{ + EditHdl(*m_xEditPB); + return true; +} + +IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, EditHdl, weld::Button&, void) +{ + int nSelEntryPos = m_xCheckLB->get_selected_index(); + if (nSelEntryPos == REPLACE_BULLETS || nSelEntryPos == APPLY_NUMBERING) + { + SvxCharacterMap aMapDlg(GetFrameWeld(), nullptr, nullptr); + ImpUserData* pUserData = weld::fromId<ImpUserData*>(m_xCheckLB->get_id(nSelEntryPos)); + aMapDlg.SetCharFont(*pUserData->pFont); + aMapDlg.SetChar( (*pUserData->pString)[0] ); + if (RET_OK == aMapDlg.run()) + { + const vcl::Font& aFont(aMapDlg.GetCharFont()); + *pUserData->pFont = aFont; + sal_UCS4 aChar = aMapDlg.GetChar(); + // using the UCS4 constructor + OUString aOUStr( &aChar, 1 ); + *pUserData->pString = aOUStr; + if (nSelEntryPos == REPLACE_BULLETS) + m_xCheckLB->set_text(nSelEntryPos, sNum.replaceFirst("%1", aOUStr), 2); + else + m_xCheckLB->set_text(nSelEntryPos, sBullet.replaceFirst("%1", aOUStr), 2); + } + } + else if( MERGE_SINGLE_LINE_PARA == nSelEntryPos ) + { + // dialog for per cent settings + OfaAutoFmtPrcntSet aDlg(GetFrameWeld()); + aDlg.GetPrcntFld().set_value(nPercent, FieldUnit::PERCENT); + if (aDlg.run() == RET_OK) + { + nPercent = static_cast<sal_uInt16>(aDlg.GetPrcntFld().get_value(FieldUnit::PERCENT)); + sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag()); + m_xCheckLB->set_text(nSelEntryPos, sRightMargin.replaceFirst("%1", sMargin), 2); + } + } +} + + +OfaAutocorrReplacePage::OfaAutocorrReplacePage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acorreplacepage.ui", "AcorReplacePage", &rSet) + , maCompareClass(comphelper::getProcessComponentContext()) + , eLang(eLastDialogLanguage) + , bHasSelectionText(false) + , bFirstSelect(true) + , bReplaceEditChanged(false) + , bSWriter(true) + , m_xTextOnlyCB(m_xBuilder->weld_check_button("textonly")) + , m_xShortED(m_xBuilder->weld_entry("origtext")) + , m_xReplaceED(m_xBuilder->weld_entry("newtext")) + , m_xReplaceTLB(m_xBuilder->weld_tree_view("tabview")) + , m_xNewReplacePB(m_xBuilder->weld_button("new")) + , m_xReplacePB(m_xBuilder->weld_button("replace")) + , m_xDeleteReplacePB(m_xBuilder->weld_button("delete")) + , m_xButtonBox(m_xBuilder->weld_container("buttonbox")) +{ + sNew = m_xNewReplacePB->get_label(); + sModify = m_xReplacePB->get_label(); + + // lock down the width of the button box to its max + // desired width + auto nMaxWidth = m_xButtonBox->get_preferred_size().Width(); + m_xButtonBox->set_size_request(nMaxWidth, -1); + m_xReplacePB->hide(); + + // tdf#125348 set some small but fixed initial width size, final width will + // depend on the size of the entry boxes + m_xReplaceTLB->set_size_request(42, m_xReplaceTLB->get_height_rows(10)); + + SfxModule *pMod = SfxApplication::GetModule(SfxToolsModule::Writer); + bSWriter = pMod == SfxModule::GetActiveModule(); + + LanguageTag aLanguageTag( eLastDialogLanguage ); + maCompareClass.loadDefaultCollator( aLanguageTag.getLocale(), 0 ); + pCharClass.reset( new CharClass( std::move(aLanguageTag) ) ); + + auto nColWidth = m_xReplaceTLB->get_approximate_digit_width() * 32; + m_aReplaceFixedWidths.push_back(nColWidth); + m_aReplaceFixedWidths.push_back(nColWidth); + + m_xReplaceTLB->connect_changed( LINK(this, OfaAutocorrReplacePage, SelectHdl) ); + m_xNewReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) ); + m_xDeleteReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) ); + m_xShortED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) ); + m_xReplaceED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) ); + m_xShortED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) ); + m_xReplaceED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) ); + m_xShortED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl)); + m_xReplaceED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl)); +} + +OfaAutocorrReplacePage::~OfaAutocorrReplacePage() +{ + aDoubleStringTable.clear(); + aChangesTable.clear(); + + pCharClass.reset(); +} + +std::unique_ptr<SfxTabPage> OfaAutocorrReplacePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutocorrReplacePage>(pPage, pController, *rSet); +} + +void OfaAutocorrReplacePage::ActivatePage( const SfxItemSet& ) +{ + if(eLang != eLastDialogLanguage) + SetLanguage(eLastDialogLanguage); + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(true); +} + +DeactivateRC OfaAutocorrReplacePage::DeactivatePage( SfxItemSet* ) +{ + return DeactivateRC::LeavePage; +} + +bool OfaAutocorrReplacePage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + + for (StringChangeTable::reverse_iterator it = aChangesTable.rbegin(); it != aChangesTable.rend(); ++it) + { + LanguageType eCurrentLang = it->first; + StringChangeList& rStringChangeList = it->second; + std::vector<SvxAutocorrWord> aDeleteWords; + std::vector<SvxAutocorrWord> aNewWords; + + aDeleteWords.reserve( rStringChangeList.aDeletedEntries.size() ); + for (const DoubleString & deleteEntry : rStringChangeList.aDeletedEntries) + { + SvxAutocorrWord aDeleteWord( deleteEntry.sShort, deleteEntry.sLong ); + aDeleteWords.push_back( aDeleteWord ); + } + + aNewWords.reserve( rStringChangeList.aNewEntries.size() ); + for (const DoubleString & newEntry : rStringChangeList.aNewEntries) + { + //fdo#67697 if the user data is set then we want to retain the + //source formatting of the entry, so don't use the optimized + //text-only MakeCombinedChanges for this entry + bool bKeepSourceFormatting = newEntry.pUserData == &bHasSelectionText; + if (bKeepSourceFormatting) + { + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + pAutoCorrect->PutText(newEntry.sShort, *pSh, eCurrentLang); + continue; + } + + SvxAutocorrWord aNewWord( newEntry.sShort, newEntry.sLong ); + aNewWords.push_back( aNewWord ); + } + pAutoCorrect->MakeCombinedChanges( aNewWords, aDeleteWords, eCurrentLang ); + } + aChangesTable.clear(); + return false; +} + +void OfaAutocorrReplacePage::RefillReplaceBox(bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage) +{ + eLang = eNewLanguage; + if(bFromReset) + { + aDoubleStringTable.clear(); + aChangesTable.clear(); + } + else + { + DoubleStringArray* pArray; + if(aDoubleStringTable.find(eOldLanguage) != aDoubleStringTable.end()) + { + pArray = &aDoubleStringTable[eOldLanguage]; + pArray->clear(); + } + else + { + pArray = &aDoubleStringTable[eOldLanguage]; // create new array + } + + m_xReplaceTLB->all_foreach([this, &pArray](weld::TreeIter& rIter) { + pArray->push_back(DoubleString(m_xReplaceTLB->get_text(rIter, 0), + m_xReplaceTLB->get_text(rIter, 1))); + DoubleString& rDouble = pArray->back(); + rDouble.pUserData = weld::fromId<void*>(m_xReplaceTLB->get_id(rIter)); + return false; + }); + } + + if( !bSWriter ) + aFormatText.clear(); + + if (aDoubleStringTable.find(eLang) != aDoubleStringTable.end()) + { + DoubleStringArray& rArray = aDoubleStringTable[eNewLanguage]; + + m_xReplaceTLB->bulk_insert_for_each(rArray.size(), [this, &rArray](weld::TreeIter& rIter, int nIndex) { + DoubleString &rDouble = rArray[nIndex]; + bool bTextOnly = nullptr == rDouble.pUserData; + // formatted text is only in Writer + if (bSWriter || bTextOnly) + { + if (!bTextOnly) + { + // that means: with format info or even with selection text + OUString sId = weld::toId(rDouble.pUserData); + m_xReplaceTLB->set_id(rIter, sId); + } + m_xReplaceTLB->set_text(rIter, rDouble.sShort, 0); + m_xReplaceTLB->set_text(rIter, rDouble.sLong, 1); + } + else + { + aFormatText.insert(rDouble.sShort); + } + }, nullptr, &m_aReplaceFixedWidths); + } + else + { + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxAutocorrWordList* pWordList = pAutoCorrect->LoadAutocorrWordList(eLang); + const SvxAutocorrWordList::AutocorrWordSetType & rContent = pWordList->getSortedContent(); + m_xReplaceTLB->bulk_insert_for_each(rContent.size(), [this, rContent](weld::TreeIter& rIter, int nIndex) { + auto const& elem = rContent[nIndex]; + bool bTextOnly = elem.IsTextOnly(); + // formatted text is only in Writer + if (bSWriter || bTextOnly) + { + if (!bTextOnly) + { + // that means: with format info or even with selection text + OUString sId = weld::toId(m_xTextOnlyCB.get()); + m_xReplaceTLB->set_id(rIter, sId); + } + m_xReplaceTLB->set_text(rIter, elem.GetShort(), 0); + m_xReplaceTLB->set_text(rIter, elem.GetLong(), 1); + } + else + { + aFormatText.insert(elem.GetShort()); + } + }, nullptr, &m_aReplaceFixedWidths); + m_xNewReplacePB->set_sensitive(false); + m_xDeleteReplacePB->set_sensitive(false); + } + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (pViewShell && pViewShell->HasSelection()) + { + bHasSelectionText = true; + const OUString sSelection( pViewShell->GetSelectionText() ); + m_xReplaceED->set_text(sSelection); + m_xTextOnlyCB->set_active(!bSWriter); + m_xTextOnlyCB->set_sensitive(bSWriter && !sSelection.isEmpty()); + } + else + { + m_xTextOnlyCB->set_active(true); + m_xTextOnlyCB->set_sensitive(false); + } +} + +void OfaAutocorrReplacePage::Reset( const SfxItemSet* ) +{ + RefillReplaceBox(true, eLang, eLang); + m_xShortED->grab_focus(); +} + +void OfaAutocorrReplacePage::SetLanguage(LanguageType eSet) +{ + //save old settings and refill + if(eSet != eLang) + { + RefillReplaceBox(false, eLang, eSet); + eLastDialogLanguage = eSet; + + LanguageTag aLanguageTag( eLastDialogLanguage ); + maCompareClass = CollatorWrapper( comphelper::getProcessComponentContext() ); + maCompareClass.loadDefaultCollator( aLanguageTag.getLocale(), 0 ); + pCharClass.reset( new CharClass( std::move(aLanguageTag) ) ); + ModifyHdl(*m_xShortED); + } +} + +IMPL_LINK(OfaAutocorrReplacePage, SelectHdl, weld::TreeView&, rBox, void) +{ + if(!bFirstSelect || !bHasSelectionText) + { + int nEntry = rBox.get_selected_index(); + OUString sTmpShort(rBox.get_text(nEntry, 0)); + // if the text is set via ModifyHdl, the cursor is always at the beginning + // of a word, although you're editing here + bool bSameContent = 0 == maCompareClass.compareString(sTmpShort, m_xShortED->get_text()); + int nStartPos, nEndPos; + m_xShortED->get_selection_bounds(nStartPos, nEndPos); + if (m_xShortED->get_text() != sTmpShort) + { + m_xShortED->set_text(sTmpShort); + // if it was only a different notation, the selection has to be set again + if (bSameContent) + { + m_xShortED->select_region(nStartPos, nEndPos); + } + } + m_xReplaceED->set_text(rBox.get_text(nEntry, 1)); + // with UserData there is a Formatinfo + m_xTextOnlyCB->set_active(rBox.get_id(nEntry).isEmpty()); + } + else + { + bFirstSelect = false; + } + + m_xNewReplacePB->set_sensitive(false); + m_xDeleteReplacePB->set_sensitive(true); +}; + +void OfaAutocorrReplacePage::NewEntry(const OUString& sShort, const OUString& sLong, bool bKeepSourceFormatting) +{ + DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; + for (size_t i = 0; i < rNewArray.size(); i++) + { + if (rNewArray[i].sShort == sShort) + { + rNewArray.erase(rNewArray.begin() + i); + break; + } + } + + DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; + for (size_t i = 0; i < rDeletedArray.size(); i++) + { + if (rDeletedArray[i].sShort == sShort) + { + rDeletedArray.erase(rDeletedArray.begin() + i); + break; + } + } + + DoubleString aNewString(sShort, sLong); + rNewArray.push_back(aNewString); + if (bKeepSourceFormatting) + rNewArray.back().pUserData = &bHasSelectionText; +} + +void OfaAutocorrReplacePage::DeleteEntry(const OUString& sShort, const OUString& sLong) +{ + DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; + for (size_t i = 0; i < rNewArray.size(); i++) + { + if (rNewArray[i].sShort == sShort) + { + rNewArray.erase(rNewArray.begin() + i); + break; + } + } + + DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; + for (size_t i = 0; i < rDeletedArray.size(); i++) + { + if (rDeletedArray[i].sShort == sShort) + { + rDeletedArray.erase(rDeletedArray.begin() + i); + break; + } + } + + DoubleString aDeletedString(sShort, sLong); + rDeletedArray.push_back(aDeletedString); +} + +IMPL_LINK(OfaAutocorrReplacePage, NewDelButtonHdl, weld::Button&, rBtn, void) +{ + NewDelHdl(&rBtn); +} + +IMPL_LINK(OfaAutocorrReplacePage, NewDelActionHdl, weld::Entry&, rEdit, bool) +{ + return NewDelHdl(&rEdit); +} + +IMPL_LINK_NOARG(OfaAutocorrReplacePage, EntrySizeAllocHdl, const Size&, void) +{ + m_aReplaceFixedWidths.clear(); + int x, y, width, height; + if (m_xReplaceED->get_extents_relative_to(*m_xReplaceTLB, x, y, width, height)) + { + m_aReplaceFixedWidths.push_back(x); + m_aReplaceFixedWidths.push_back(width - 1); + m_xReplaceTLB->set_column_fixed_widths(m_aReplaceFixedWidths); + } +} + +bool OfaAutocorrReplacePage::NewDelHdl(const weld::Widget* pBtn) +{ + int nEntry = m_xReplaceTLB->get_selected_index(); + if (pBtn == m_xDeleteReplacePB.get()) + { + DBG_ASSERT( nEntry != -1, "no entry selected" ); + if (nEntry != -1) + { + DeleteEntry(m_xReplaceTLB->get_text(nEntry, 0), m_xReplaceTLB->get_text(nEntry, 1)); + m_xReplaceTLB->remove(nEntry); + ModifyHdl(*m_xShortED); + return true; + } + } + + if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive()) + { + OUString sEntry(m_xShortED->get_text()); + if (!sEntry.isEmpty() && (!m_xReplaceED->get_text().isEmpty() || + ( bHasSelectionText && bSWriter ) )) + { + bool bKeepSourceFormatting = !bReplaceEditChanged && !m_xTextOnlyCB->get_active(); + + NewEntry(m_xShortED->get_text(), m_xReplaceED->get_text(), bKeepSourceFormatting); + m_xReplaceTLB->freeze(); + int nPos = -1; + if (nEntry != -1) + { + nPos = nEntry; + m_xReplaceTLB->remove(nEntry); + } + else + { + int j; + int nCount = m_xReplaceTLB->n_children(); + for (j = 0; j < nCount; ++j) + { + if (0 >= maCompareClass.compareString(sEntry, m_xReplaceTLB->get_text(j, 0))) + break; + } + nPos = j; + } + + OUString sId; + if (bKeepSourceFormatting) + { + sId = weld::toId(&bHasSelectionText); // new formatted text + } + + m_xReplaceTLB->insert(nPos, sEntry, &sId, nullptr, nullptr); + m_xReplaceTLB->set_text(nPos, m_xReplaceED->get_text(), 1); + m_xReplaceTLB->thaw(); + m_xReplaceTLB->scroll_to_row(nPos); + // if the request came from the ReplaceEdit, give focus to the ShortEdit + if (m_xReplaceED->has_focus()) + { + m_xShortED->grab_focus(); + } + } + } + else + { + // this can only be an enter in one of the two edit fields + // which means EndDialog() - has to be evaluated in KeyInput + return false; + } + ModifyHdl(*m_xShortED); + return true; +} + +IMPL_LINK(OfaAutocorrReplacePage, ModifyHdl, weld::Entry&, rEdt, void) +{ + std::unique_ptr<weld::TreeIter> xFirstSel(m_xReplaceTLB->make_iterator()); + bool bFirstSelIterSet = m_xReplaceTLB->get_selected(xFirstSel.get()); + bool bShort = &rEdt == m_xShortED.get(); + const OUString rEntry = rEdt.get_text(); + const OUString rRepString = m_xReplaceED->get_text(); + OUString aWordStr(pCharClass->lowercase(rEntry)); + + if(bShort) + { + if(!rEntry.isEmpty()) + { + bool bFound = false; + bool bTmpSelEntry=false; + + m_xReplaceTLB->all_foreach([this, &rEntry, &rRepString, &bFound, + &bTmpSelEntry, &bFirstSelIterSet, + &xFirstSel, &aWordStr](weld::TreeIter& rIter){ + OUString aTestStr = m_xReplaceTLB->get_text(rIter, 0); + if( maCompareClass.compareString(rEntry, aTestStr ) == 0 ) + { + if (!rRepString.isEmpty()) + bFirstSelect = true; + m_xReplaceTLB->set_cursor(rIter); + m_xReplaceTLB->copy_iterator(rIter, *xFirstSel); + bFirstSelIterSet = true; + m_xNewReplacePB->set_label(sModify); + bFound = true; + return true; + } + else + { + aTestStr = pCharClass->lowercase( aTestStr ); + if( aTestStr.startsWith(aWordStr) && !bTmpSelEntry ) + { + m_xReplaceTLB->scroll_to_row(rIter); + bTmpSelEntry = true; + } + } + return false; + }); + if( !bFound ) + { + m_xReplaceTLB->select(-1); + bFirstSelIterSet = false; + m_xNewReplacePB->set_label(sNew); + if( bReplaceEditChanged ) + m_xTextOnlyCB->set_sensitive(false); + } + m_xDeleteReplacePB->set_sensitive(bFound); + } + else if (m_xReplaceTLB->n_children() > 0) + { + m_xReplaceTLB->scroll_to_row(0); + } + + } + else if( !bShort ) + { + bReplaceEditChanged = true; + if (bFirstSelIterSet) + { + m_xNewReplacePB->set_label(sModify); + } + } + + const OUString& rShortTxt = m_xShortED->get_text(); + bool bEnableNew = !rShortTxt.isEmpty() && + ( !rRepString.isEmpty() || + ( bHasSelectionText && bSWriter )) && + ( !bFirstSelIterSet || rRepString != + m_xReplaceTLB->get_text(*xFirstSel, 1) ); + if( bEnableNew ) + { + for (auto const& elem : aFormatText) + { + if(elem == rShortTxt) + { + bEnableNew = false; + break; + } + } + } + m_xNewReplacePB->set_sensitive(bEnableNew); +} + +static bool lcl_FindInArray(std::vector<OUString>& rStrings, std::u16string_view rString) +{ + for (auto const& elem : rStrings) + { + if(elem == rString) + { + return true; + } + } + return false; +} + +OfaAutocorrExceptPage::OfaAutocorrExceptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acorexceptpage.ui", "AcorExceptPage", &rSet) + , maCompareClass(comphelper::getProcessComponentContext()) + , eLang(eLastDialogLanguage) + , m_xAbbrevED(m_xBuilder->weld_entry("abbrev")) + , m_xAbbrevLB(m_xBuilder->weld_tree_view("abbrevlist")) + , m_xNewAbbrevPB(m_xBuilder->weld_button("newabbrev")) + , m_xDelAbbrevPB(m_xBuilder->weld_button("delabbrev")) + , m_xAutoAbbrevCB(m_xBuilder->weld_check_button("autoabbrev")) + , m_xDoubleCapsED(m_xBuilder->weld_entry("double")) + , m_xDoubleCapsLB(m_xBuilder->weld_tree_view("doublelist")) + , m_xNewDoublePB(m_xBuilder->weld_button("newdouble")) + , m_xDelDoublePB(m_xBuilder->weld_button("deldouble")) + , m_xAutoCapsCB(m_xBuilder->weld_check_button("autodouble")) +{ + m_xAbbrevLB->make_sorted(); + m_xAbbrevLB->set_size_request(-1, m_xAbbrevLB->get_height_rows(6)); + + m_xDoubleCapsLB->make_sorted(); + m_xDoubleCapsLB->set_size_request(-1, m_xDoubleCapsLB->get_height_rows(6)); + + css::lang::Locale aLcl( LanguageTag::convertToLocale(eLastDialogLanguage )); + maCompareClass.loadDefaultCollator( aLcl, 0 ); + + m_xNewAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xDelAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xNewDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xDelDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + + m_xAbbrevLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl)); + m_xDoubleCapsLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl)); + m_xAbbrevED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl)); + m_xDoubleCapsED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl)); + + m_xAbbrevED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl)); + m_xDoubleCapsED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl)); +} + +OfaAutocorrExceptPage::~OfaAutocorrExceptPage() +{ + aStringsTable.clear(); +} + +std::unique_ptr<SfxTabPage> OfaAutocorrExceptPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutocorrExceptPage>(pPage, pController, *rSet); +} + +void OfaAutocorrExceptPage::ActivatePage( const SfxItemSet& ) +{ + if(eLang != eLastDialogLanguage) + SetLanguage(eLastDialogLanguage); + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(true); +} + +DeactivateRC OfaAutocorrExceptPage::DeactivatePage( SfxItemSet* ) +{ + return DeactivateRC::LeavePage; +} + +bool OfaAutocorrExceptPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + for(StringsTable::reverse_iterator it1 = aStringsTable.rbegin(); it1 != aStringsTable.rend(); ++it1) + { + LanguageType eCurLang = it1->first; + StringsArrays& rArrays = it1->second; + if(eCurLang != eLang) // current language is treated later + { + SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWordStartExceptList(eCurLang); + + if(pWrdList) + { + size_t nCount = pWrdList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pWrdList)[ --i ]; + + if( !lcl_FindInArray(rArrays.aDoubleCapsStrings, aString)) + { + pWrdList->erase_at(i); + } + } + + for (auto const& elem : rArrays.aDoubleCapsStrings) + { + pWrdList->insert(elem); + } + pAutoCorrect->SaveWordStartExceptList(eCurLang); + } + + SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eCurLang); + + if(pCplList) + { + size_t nCount = pCplList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pCplList)[ --i ]; + if( !lcl_FindInArray(rArrays.aAbbrevStrings, aString)) + { + pCplList->erase_at(i); + } + } + + for (auto const& elem : rArrays.aAbbrevStrings) + { + pCplList->insert(elem); + } + + pAutoCorrect->SaveCplSttExceptList(eCurLang); + } + } + } + aStringsTable.clear(); + + SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWordStartExceptList(eLang); + + if(pWrdList) + { + size_t nCount = pWrdList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pWrdList)[ --i ]; + if (m_xDoubleCapsLB->find_text(aString) == -1) + { + pWrdList->erase_at(i); + } + } + nCount = m_xDoubleCapsLB->n_children(); + for( i = 0; i < nCount; ++i ) + { + pWrdList->insert(m_xDoubleCapsLB->get_text(i)); + } + pAutoCorrect->SaveWordStartExceptList(eLang); + } + + SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eLang); + + if(pCplList) + { + size_t nCount = pCplList->size(); + for( size_t i = nCount; i; ) + { + OUString aString = (*pCplList)[ --i ]; + if (m_xAbbrevLB->find_text(aString) == -1) + { + pCplList->erase_at(i); + } + } + sal_Int32 nAbbrevCount = m_xAbbrevLB->n_children(); + for( sal_Int32 ia = 0; ia < nAbbrevCount; ++ia ) + { + pCplList->insert(m_xAbbrevLB->get_text(ia)); + } + pAutoCorrect->SaveCplSttExceptList(eLang); + } + if (m_xAutoAbbrevCB->get_state_changed_from_saved()) + pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordCplSttLst, m_xAutoAbbrevCB->get_active()); + if (m_xAutoCapsCB->get_state_changed_from_saved()) + pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordWordStartLst, m_xAutoCapsCB->get_active()); + return false; +} + +void OfaAutocorrExceptPage::SetLanguage(LanguageType eSet) +{ + if(eLang != eSet) + { + // save old settings and fill anew + RefillReplaceBoxes(false, eLang, eSet); + eLastDialogLanguage = eSet; + maCompareClass = CollatorWrapper( comphelper::getProcessComponentContext() ); + maCompareClass.loadDefaultCollator( LanguageTag::convertToLocale( eLastDialogLanguage ), 0 ); + ModifyHdl(*m_xAbbrevED); + ModifyHdl(*m_xDoubleCapsED); + } +} + +void OfaAutocorrExceptPage::RefillReplaceBoxes(bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage) +{ + eLang = eNewLanguage; + if(bFromReset) + { + aStringsTable.clear(); + } + else + { + StringsArrays* pArrays; + if(aStringsTable.find(eOldLanguage) != aStringsTable.end()) + { + pArrays = &aStringsTable[eOldLanguage]; + pArrays->aAbbrevStrings.clear(); + pArrays->aDoubleCapsStrings.clear(); + } + else + { + pArrays = &aStringsTable[eOldLanguage]; // create new array + } + + sal_Int32 i, nCount; + nCount = m_xAbbrevLB->n_children(); + for(i = 0; i < nCount; i++) + pArrays->aAbbrevStrings.push_back(m_xAbbrevLB->get_text(i)); + + nCount = m_xDoubleCapsLB->n_children(); + for(i = 0; i < nCount; i++) + pArrays->aDoubleCapsStrings.push_back(m_xDoubleCapsLB->get_text(i)); + } + m_xDoubleCapsLB->clear(); + m_xAbbrevLB->clear(); + m_xAbbrevED->set_text(""); + m_xDoubleCapsED->set_text(""); + + if(aStringsTable.find(eLang) != aStringsTable.end()) + { + StringsArrays& rArrays = aStringsTable[eLang]; + for (auto const& elem : rArrays.aAbbrevStrings) + m_xAbbrevLB->append_text(elem); + + for (auto const& elem : rArrays.aDoubleCapsStrings) + m_xDoubleCapsLB->append_text(elem); + } + else + { + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const SvStringsISortDtor* pCplList = pAutoCorrect->GetCplSttExceptList(eLang); + const SvStringsISortDtor* pWrdList = pAutoCorrect->GetWordStartExceptList(eLang); + size_t i; + for( i = 0; i < pCplList->size(); i++ ) + { + m_xAbbrevLB->append_text((*pCplList)[i]); + } + for( i = 0; i < pWrdList->size(); i++ ) + { + m_xDoubleCapsLB->append_text((*pWrdList)[i]); + } + } +} + +void OfaAutocorrExceptPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + RefillReplaceBoxes(true, eLang, eLang); + m_xAutoAbbrevCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordCplSttLst)); + m_xAutoCapsCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordWordStartLst)); + m_xAutoAbbrevCB->save_state(); + m_xAutoCapsCB->save_state(); +} + +IMPL_LINK(OfaAutocorrExceptPage, NewDelButtonHdl, weld::Button&, rBtn, void) +{ + NewDelHdl(&rBtn); +} + +IMPL_LINK(OfaAutocorrExceptPage, NewDelActionHdl, weld::Entry&, rEdit, bool) +{ + return NewDelHdl(&rEdit); +} + +bool OfaAutocorrExceptPage::NewDelHdl(const weld::Widget* pBtn) +{ + if ((pBtn == m_xNewAbbrevPB.get() || pBtn == m_xAbbrevED.get()) + && !m_xAbbrevED->get_text().isEmpty() && m_xNewAbbrevPB->get_sensitive()) + { + m_xAbbrevLB->append_text(m_xAbbrevED->get_text()); + ModifyHdl(*m_xAbbrevED); + } + else if(pBtn == m_xDelAbbrevPB.get()) + { + m_xAbbrevLB->remove_text(m_xAbbrevED->get_text()); + ModifyHdl(*m_xAbbrevED); + } + else if((pBtn == m_xNewDoublePB.get() || pBtn == m_xDoubleCapsED.get() ) + && !m_xDoubleCapsED->get_text().isEmpty() && m_xNewDoublePB->get_sensitive()) + { + m_xDoubleCapsLB->append_text(m_xDoubleCapsED->get_text()); + ModifyHdl(*m_xDoubleCapsED); + } + else if (pBtn == m_xDelDoublePB.get()) + { + m_xDoubleCapsLB->remove_text(m_xDoubleCapsED->get_text()); + ModifyHdl(*m_xDoubleCapsED); + } + else + { + // we didn't do anything, if this was because of 'activate' in an + // entry then let it continue to close the dialog like the replace + // page does + return false; + } + return true; +} + +IMPL_LINK(OfaAutocorrExceptPage, SelectHdl, weld::TreeView&, rBox, void) +{ + if (&rBox == m_xAbbrevLB.get()) + { + m_xAbbrevED->set_text(rBox.get_selected_text()); + m_xNewAbbrevPB->set_sensitive(false); + m_xDelAbbrevPB->set_sensitive(true); + } + else + { + m_xDoubleCapsED->set_text(rBox.get_selected_text()); + m_xNewDoublePB->set_sensitive(false); + m_xDelDoublePB->set_sensitive(true); + } +} + +IMPL_LINK(OfaAutocorrExceptPage, ModifyHdl, weld::Entry&, rEdt, void) +{ + const OUString& sEntry = rEdt.get_text(); + bool bEntryLen = !sEntry.isEmpty(); + if (&rEdt == m_xAbbrevED.get()) + { + bool bSame = lcl_FindEntry(*m_xAbbrevLB, sEntry, maCompareClass); + if(bSame && sEntry != m_xAbbrevLB->get_selected_text()) + rEdt.set_text(m_xAbbrevLB->get_selected_text()); + m_xNewAbbrevPB->set_sensitive(!bSame && bEntryLen); + m_xDelAbbrevPB->set_sensitive(bSame && bEntryLen); + } + else + { + bool bSame = lcl_FindEntry(*m_xDoubleCapsLB, sEntry, maCompareClass); + if(bSame && sEntry != m_xDoubleCapsLB->get_selected_text()) + rEdt.set_text(m_xDoubleCapsLB->get_selected_text()); + m_xNewDoublePB->set_sensitive(!bSame && bEntryLen); + m_xDelDoublePB->set_sensitive(bSame && bEntryLen); + } +} + +namespace { + +enum OfaQuoteOptions +{ + ADD_NONBRK_SPACE, + REPLACE_1ST, + TRANSLITERATE_RTL, + REPLACE_ANGLE_QUOTES +}; + +} + +void OfaQuoteTabPage::CreateEntry(weld::TreeView& rCheckLB, const OUString& rTxt, sal_uInt16 nCol, sal_uInt16 nTextCol) +{ + rCheckLB.append(); + const int nRow = rCheckLB.n_children() - 1; + if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH) + rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST); + if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH) + rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND); + rCheckLB.set_text(nRow, rTxt, nTextCol); +} + +OfaQuoteTabPage::OfaQuoteTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/applylocalizedpage.ui", "ApplyLocalizedPage", &rSet) + , sNonBrkSpace(CuiResId(RID_CUISTR_NON_BREAK_SPACE)) + , sOrdinal(CuiResId(RID_CUISTR_ORDINAL)) + , sTransliterateRTL(CuiResId(RID_CUISTR_OLD_HUNGARIAN)) + , sAngleQuotes(CuiResId(RID_CUISTR_ANGLE_QUOTES)) + , cSglStartQuote(0) + , cSglEndQuote(0) + , cStartQuote(0) + , cEndQuote(0) + , m_xSingleTypoCB(m_xBuilder->weld_check_button("singlereplace")) + , m_xSglStartQuotePB(m_xBuilder->weld_button("startsingle")) + , m_xSglStartExFT(m_xBuilder->weld_label("singlestartex")) + , m_xSglEndQuotePB(m_xBuilder->weld_button("endsingle")) + , m_xSglEndExFT(m_xBuilder->weld_label("singleendex")) + , m_xSglStandardPB(m_xBuilder->weld_button("defaultsingle")) + , m_xDoubleTypoCB(m_xBuilder->weld_check_button("doublereplace")) + , m_xDblStartQuotePB(m_xBuilder->weld_button("startdouble")) + , m_xDblStartExFT(m_xBuilder->weld_label("doublestartex")) + , m_xDblEndQuotePB(m_xBuilder->weld_button("enddouble")) + , m_xDblEndExFT(m_xBuilder->weld_label("doubleendex")) + , m_xDblStandardPB(m_xBuilder->weld_button("defaultdouble")) + , m_sStandard(m_xSglStartExFT->get_label()) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklist")) + , m_xSwCheckLB(m_xBuilder->weld_tree_view("list")) +{ + m_xSwCheckLB->set_size_request(m_xSwCheckLB->get_approximate_digit_width() * 50, + m_xSwCheckLB->get_height_rows(6)); + + bool bShowSWOptions = false; + + const SfxBoolItem* pItem = rSet.GetItem<SfxBoolItem>(SID_AUTO_CORRECT_DLG, false); + if ( pItem && pItem->GetValue() ) + bShowSWOptions = true; + + if ( bShowSWOptions ) + { + std::vector<int> aWidths + { + o3tl::narrowing<int>(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(0)).Width() * 2), + o3tl::narrowing<int>(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(1)).Width() * 2) + }; + m_xSwCheckLB->set_column_fixed_widths(aWidths); + m_xCheckLB->hide(); + } + else + { + m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xSwCheckLB->hide(); + } + + m_xDblStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xDblEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xSglStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xSglEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xDblStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl)); + m_xSglStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl)); +} + +OfaQuoteTabPage::~OfaQuoteTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaQuoteTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<OfaQuoteTabPage>(pPage, pController, *rAttrSet); +} + +bool OfaQuoteTabPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + + ACFlags nFlags = pAutoCorrect->GetFlags(); + + if (m_xCheckLB->get_visible()) + { + int nPos = 0; + pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + } + + bool bModified = false; + if (m_xSwCheckLB->get_visible()) + { + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + bool bCheck = m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAddNonBrkSpace != bCheck; + pOpt->bAddNonBrkSpace = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace, + m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgOrdinalNumber != bCheck; + pOpt->bChgOrdinalNumber = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, + m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bTransliterateRTL != bCheck; + pOpt->bTransliterateRTL = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, + m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgAngleQuotes != bCheck; + pOpt->bChgAngleQuotes = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, + m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_SECOND) == TRISTATE_TRUE); + } + + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgQuotes, m_xDoubleTypoCB->get_active()); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgSglQuotes, m_xSingleTypoCB->get_active()); + bool bReturn = nFlags != pAutoCorrect->GetFlags(); + if(cStartQuote != pAutoCorrect->GetStartDoubleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cStartQuote); //TODO + pAutoCorrect->SetStartDoubleQuote(cUCS2); + } + if(cEndQuote != pAutoCorrect->GetEndDoubleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cEndQuote); //TODO + pAutoCorrect->SetEndDoubleQuote(cUCS2); + } + if(cSglStartQuote != pAutoCorrect->GetStartSingleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cSglStartQuote); //TODO + pAutoCorrect->SetStartSingleQuote(cUCS2); + } + if(cSglEndQuote != pAutoCorrect->GetEndSingleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cSglEndQuote); //TODO + pAutoCorrect->SetEndSingleQuote(cUCS2); + } + + if( bModified || bReturn ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return bReturn; +} + +void OfaQuoteTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false); +} + +void OfaQuoteTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + // Initialize the Sw options + if (m_xSwCheckLB->get_visible()) + { + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + m_xSwCheckLB->freeze(); + m_xSwCheckLB->clear(); + + CreateEntry(*m_xSwCheckLB, sNonBrkSpace, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sOrdinal, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sTransliterateRTL, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sAngleQuotes, CBCOL_BOTH, 2); + + m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, pOpt->bAddNonBrkSpace ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(REPLACE_1ST, pOpt->bChgOrdinalNumber ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(REPLACE_1ST, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, pOpt->bTransliterateRTL ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, pOpt->bChgAngleQuotes ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + + m_xSwCheckLB->thaw(); + } + + // Initialize the non Sw options + if (m_xCheckLB->get_visible()) + { + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + int nPos = 0; + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sNonBrkSpace, 0); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sOrdinal, 0); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sTransliterateRTL, 0); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sAngleQuotes, 0); + + m_xCheckLB->thaw(); + } + + // Initialize the quote stuffs + m_xDoubleTypoCB->set_active(bool(nFlags & ACFlags::ChgQuotes)); + m_xSingleTypoCB->set_active(bool(nFlags & ACFlags::ChgSglQuotes)); + m_xDoubleTypoCB->save_state(); + m_xSingleTypoCB->save_state(); + + cStartQuote = pAutoCorrect->GetStartDoubleQuote(); + cEndQuote = pAutoCorrect->GetEndDoubleQuote(); + cSglStartQuote = pAutoCorrect->GetStartSingleQuote(); + cSglEndQuote = pAutoCorrect->GetEndSingleQuote(); + + m_xSglStartExFT->set_label(ChangeStringExt_Impl(cSglStartQuote)); + m_xSglEndExFT->set_label(ChangeStringExt_Impl(cSglEndQuote)); + m_xDblStartExFT->set_label(ChangeStringExt_Impl(cStartQuote)); + m_xDblEndExFT->set_label(ChangeStringExt_Impl(cEndQuote)); +} + +#define SGL_START 0 +#define DBL_START 1 +#define SGL_END 2 +#define DBL_END 3 + + +IMPL_LINK(OfaQuoteTabPage, QuoteHdl, weld::Button&, rBtn, void) +{ + sal_uInt16 nMode = SGL_START; + if (&rBtn == m_xSglEndQuotePB.get()) + nMode = SGL_END; + else if (&rBtn == m_xDblStartQuotePB.get()) + nMode = DBL_START; + else if (&rBtn == m_xDblEndQuotePB.get()) + nMode = DBL_END; + // start character selection dialog + SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr); + aMap.SetCharFont( OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT, + LANGUAGE_ENGLISH_US, GetDefaultFontFlags::OnlyOne )); + aMap.set_title(nMode < SGL_END ? CuiResId(RID_CUISTR_STARTQUOTE) : CuiResId(RID_CUISTR_ENDQUOTE)); + sal_UCS4 cDlg; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + LanguageType eLang = Application::GetSettings().GetLanguageTag().getLanguageType(); + switch( nMode ) + { + case SGL_START: + cDlg = cSglStartQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\'', true, eLang); + break; + case SGL_END: + cDlg = cSglEndQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\'', false, eLang); + break; + case DBL_START: + cDlg = cStartQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\"', true, eLang); + break; + case DBL_END: + cDlg = cEndQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\"', false, eLang); + break; + default: + OSL_FAIL("svx::OfaQuoteTabPage::QuoteHdl(), how to initialize cDlg?" ); + cDlg = 0; + break; + + } + aMap.SetChar( cDlg ); + aMap.DisableFontSelection(); + if (aMap.run() != RET_OK) + return; + + sal_UCS4 cNewChar = aMap.GetChar(); + switch( nMode ) + { + case SGL_START: + cSglStartQuote = cNewChar; + m_xSglStartExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case SGL_END: + cSglEndQuote = cNewChar; + m_xSglEndExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case DBL_START: + cStartQuote = cNewChar; + m_xDblStartExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case DBL_END: + cEndQuote = cNewChar; + m_xDblEndExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + } +} + +IMPL_LINK(OfaQuoteTabPage, StdQuoteHdl, weld::Button&, rBtn, void) +{ + if (&rBtn == m_xDblStandardPB.get()) + { + cStartQuote = 0; + m_xDblStartExFT->set_label(ChangeStringExt_Impl(0)); + cEndQuote = 0; + m_xDblEndExFT->set_label(ChangeStringExt_Impl(0)); + + } + else + { + cSglStartQuote = 0; + m_xSglStartExFT->set_label(ChangeStringExt_Impl(0)); + cSglEndQuote = 0; + m_xSglEndExFT->set_label(ChangeStringExt_Impl(0)); + } +} + +OUString OfaQuoteTabPage::ChangeStringExt_Impl( sal_UCS4 cChar ) +{ + if (!cChar) + return m_sStandard; + + // convert codepoint value to unicode-hex string + sal_UCS4 aStrCodes[32] = { 0, ' ', '(', 'U', '+', '0' }; + aStrCodes[0] = cChar; + int nFullLen = 5; + int nHexLen = 4; + while( (cChar >> (4*nHexLen)) != 0 ) + ++nHexLen; + for( int i = nHexLen; --i >= 0;) + { + sal_UCS4 cHexDigit = ((cChar >> (4*i)) & 0x0f) + '0'; + if( cHexDigit > '9' ) + cHexDigit += 'A' - ('9' + 1); + aStrCodes[ nFullLen++ ] = cHexDigit; + } + aStrCodes[ nFullLen++ ] = ')'; + // using the new UCS4 constructor + OUString aOUStr( aStrCodes, nFullLen ); + return aOUStr; +} + +OfaAutoCompleteTabPage::OfaAutoCompleteTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/wordcompletionpage.ui", + "WordCompletionPage", &rSet) + , m_pAutoCompleteList(nullptr) + , m_nAutoCmpltListCnt(0) + , m_xCBActiv(m_xBuilder->weld_check_button("enablewordcomplete")) + , m_xCBAppendSpace(m_xBuilder->weld_check_button("appendspace")) + , m_xCBAsTip(m_xBuilder->weld_check_button("showastip")) + , m_xCBCollect(m_xBuilder->weld_check_button("collectwords")) + , m_xCBRemoveList(m_xBuilder->weld_check_button("whenclosing")) + , m_xDCBExpandKey(m_xBuilder->weld_combo_box("acceptwith")) + , m_xNFMinWordlen(m_xBuilder->weld_spin_button("minwordlen")) + , m_xNFMaxEntries(m_xBuilder->weld_spin_button("maxentries")) + , m_xLBEntries(m_xBuilder->weld_tree_view("entries")) + , m_xPBEntries(m_xBuilder->weld_button("delete")) +{ + //fdo#65595, we need height-for-width support here, but for now we can + //bodge it + Size aPrefSize(m_xCBRemoveList->get_preferred_size()); + int nMaxWidth = m_xCBRemoveList->get_approximate_digit_width() * 40; + if (aPrefSize.Width() > nMaxWidth) + { + m_xCBRemoveList->set_label_wrap(true); + m_xCBRemoveList->set_size_request(nMaxWidth, -1); + } + + m_xLBEntries->set_size_request(m_xLBEntries->get_approximate_digit_width() * 30, + m_xLBEntries->get_height_rows(10)); + m_xLBEntries->set_selection_mode(SelectionMode::Multiple); + + // the defined KEYs + static const sal_uInt16 aKeyCodes[] = { + KEY_END, + KEY_RETURN, + KEY_SPACE, + KEY_RIGHT, + KEY_TAB, + 0 + }; + + for( const sal_uInt16* pKeys = aKeyCodes; *pKeys; ++pKeys ) + { + vcl::KeyCode aKCode(*pKeys); + m_xDCBExpandKey->append(OUString::number(static_cast<sal_Int32>(*pKeys)), aKCode.GetName()); + if (KEY_RETURN == *pKeys) // default to RETURN + m_xDCBExpandKey->set_active(std::distance(aKeyCodes, pKeys)); + } + + m_xPBEntries->connect_clicked(LINK(this, OfaAutoCompleteTabPage, DeleteHdl)); + m_xCBActiv->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl)); + m_xCBCollect->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl)); + m_xLBEntries->connect_key_release(LINK(this, OfaAutoCompleteTabPage, KeyReleaseHdl)); +} + +OfaAutoCompleteTabPage::~OfaAutoCompleteTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaAutoCompleteTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutoCompleteTabPage>(pPage, pController, *rSet); +} + +bool OfaAutoCompleteTabPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false, bCheck; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + bCheck = m_xCBActiv->get_active(); + bModified |= pOpt->bAutoCompleteWords != bCheck; + pOpt->bAutoCompleteWords = bCheck; + bCheck = m_xCBCollect->get_active(); + bModified |= pOpt->bAutoCmpltCollectWords != bCheck; + pOpt->bAutoCmpltCollectWords = bCheck; + bCheck = !m_xCBRemoveList->get_active(); // inverted value! + bModified |= pOpt->bAutoCmpltKeepList != bCheck; + pOpt->bAutoCmpltKeepList = bCheck; + bCheck = m_xCBAppendSpace->get_active(); + bModified |= pOpt->bAutoCmpltAppendBlank != bCheck; + pOpt->bAutoCmpltAppendBlank = bCheck; + bCheck = m_xCBAsTip->get_active(); + bModified |= pOpt->bAutoCmpltShowAsTip != bCheck; + pOpt->bAutoCmpltShowAsTip = bCheck; + + sal_uInt16 nVal = static_cast<sal_uInt16>(m_xNFMinWordlen->get_value()); + bModified |= nVal != pOpt->nAutoCmpltWordLen; + pOpt->nAutoCmpltWordLen = nVal; + + sal_uInt32 nList = static_cast<sal_uInt32>(m_xNFMaxEntries->get_value()); + bModified |= nList != pOpt->nAutoCmpltListLen; + pOpt->nAutoCmpltListLen = nList; + + const int nPos = m_xDCBExpandKey->get_active(); + if (nPos != -1) + { + sal_Int32 nKey = m_xDCBExpandKey->get_id(nPos).toInt32(); + bModified |= nKey != pOpt->nAutoCmpltExpandKey; + pOpt->nAutoCmpltExpandKey = static_cast<sal_uInt16>(nKey); + } + + if (m_pAutoCompleteList && m_nAutoCmpltListCnt != m_xLBEntries->n_children()) + { + bModified = true; + pOpt->m_pAutoCompleteList = m_pAutoCompleteList; + } + if( bModified ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return true; +} + +void OfaAutoCompleteTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + m_xCBActiv->set_active( pOpt->bAutoCompleteWords ); + m_xCBCollect->set_active( pOpt->bAutoCmpltCollectWords ); + m_xCBRemoveList->set_active( !pOpt->bAutoCmpltKeepList ); //inverted value! + m_xCBAppendSpace->set_active( pOpt->bAutoCmpltAppendBlank ); + m_xCBAsTip->set_active( pOpt->bAutoCmpltShowAsTip ); + + m_xNFMinWordlen->set_value( pOpt->nAutoCmpltWordLen ); + m_xNFMaxEntries->set_value( pOpt->nAutoCmpltListLen ); + + // select the specific KeyCode: + { + sal_Int32 nKey = pOpt->nAutoCmpltExpandKey; + for (int n = 0, nCnt = m_xDCBExpandKey->get_count(); n < nCnt; ++n) + { + if (nKey == m_xDCBExpandKey->get_id(n).toInt32()) + { + m_xDCBExpandKey->set_active(n); + break; + } + } + } + + if (pOpt->m_pAutoCompleteList && !pOpt->m_pAutoCompleteList->empty()) + { + m_pAutoCompleteList = const_cast<editeng::SortedAutoCompleteStrings*>( + pOpt->m_pAutoCompleteList); + pOpt->m_pAutoCompleteList = nullptr; + m_nAutoCmpltListCnt = m_pAutoCompleteList->size(); + for (size_t n = 0; n < m_nAutoCmpltListCnt; ++n) + { + const OUString* pStr = + &(*m_pAutoCompleteList)[n]->GetAutoCompleteString(); + OUString sId(weld::toId(pStr)); + m_xLBEntries->append(sId, *pStr); + } + } + else + { + m_xLBEntries->set_sensitive(false); + m_xPBEntries->set_sensitive(false); + } + + CheckHdl(*m_xCBActiv); + CheckHdl(*m_xCBCollect); +} + +void OfaAutoCompleteTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage( false ); +} + +IMPL_LINK_NOARG(OfaAutoCompleteTabPage, DeleteHdl, weld::Button&, void) +{ + auto rows = m_xLBEntries->get_selected_rows(); + std::sort(rows.begin(), rows.end()); + while (!rows.empty()) + { + sal_Int32 nPos = rows.back(); + OUString* pStr = weld::fromId<OUString*>(m_xLBEntries->get_id(nPos)); + m_xLBEntries->remove(nPos); + editeng::IAutoCompleteString hack(*pStr); // UGLY + m_pAutoCompleteList->erase(&hack); + rows.pop_back(); + } +} + +IMPL_LINK(OfaAutoCompleteTabPage, CheckHdl, weld::Toggleable&, rBox, void) +{ + bool bEnable = rBox.get_active(); + if (&rBox == m_xCBActiv.get()) + { + m_xCBAppendSpace->set_sensitive(bEnable); + m_xCBAppendSpace->set_sensitive(bEnable); + m_xCBAsTip->set_sensitive(bEnable); + m_xDCBExpandKey->set_sensitive(bEnable); + } + else if (&rBox == m_xCBCollect.get()) + m_xCBRemoveList->set_sensitive(bEnable); +} + +void OfaAutoCompleteTabPage::CopyToClipboard() const +{ + auto rows = m_xLBEntries->get_selected_rows(); + if (!m_pAutoCompleteList || rows.empty()) + return; + + rtl::Reference<TransferDataContainer> pCntnr = new TransferDataContainer; + + OStringBuffer sData; + + rtl_TextEncoding nEncode = osl_getThreadTextEncoding(); + + for (auto a : rows) + { + sData.append(OUStringToOString(m_xLBEntries->get_text(a), nEncode) + SAL_NEWLINE_STRING); + } + pCntnr->CopyByteString( SotClipboardFormatId::STRING, sData.makeStringAndClear() ); + pCntnr->CopyToClipboard(m_xLBEntries->get_clipboard()); +} + +IMPL_LINK(OfaAutoCompleteTabPage, KeyReleaseHdl, const KeyEvent&, rEvent, bool) +{ + bool bHandled = false; + const vcl::KeyCode& rKeyCode = rEvent.GetKeyCode(); + switch (rKeyCode.GetModifier() | rKeyCode.GetCode()) + { + case KEY_DELETE: + DeleteHdl(*m_xPBEntries); + bHandled = true; + break; + default: + if (KeyFuncType::COPY == rKeyCode.GetFunction()) + { + CopyToClipboard(); + bHandled = true; + } + break; + } + return bHandled; +} + +// class OfaSmartTagOptionsTabPage --------------------------------------------- + +OfaSmartTagOptionsTabPage::OfaSmartTagOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet ) + : SfxTabPage(pPage, pController, "cui/ui/smarttagoptionspage.ui", "SmartTagOptionsPage", &rSet) + , m_xMainCB(m_xBuilder->weld_check_button("main")) + , m_xSmartTagTypesLB(m_xBuilder->weld_tree_view("list")) + , m_xPropertiesPB(m_xBuilder->weld_button("properties")) +{ + m_xSmartTagTypesLB->set_size_request(m_xSmartTagTypesLB->get_approximate_digit_width() * 50, + m_xSmartTagTypesLB->get_height_rows(6)); + + m_xSmartTagTypesLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + + // set the handlers: + m_xMainCB->connect_toggled(LINK(this, OfaSmartTagOptionsTabPage, CheckHdl)); + m_xPropertiesPB->connect_clicked(LINK(this, OfaSmartTagOptionsTabPage, ClickHdl)); + m_xSmartTagTypesLB->connect_changed(LINK(this, OfaSmartTagOptionsTabPage, SelectHdl)); +} + +OfaSmartTagOptionsTabPage::~OfaSmartTagOptionsTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaSmartTagOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<OfaSmartTagOptionsTabPage>(pPage, pController, *rSet); +} + +namespace { + +/** This struct is used to associate list box entries with smart tag data +*/ +struct ImplSmartTagLBUserData +{ + OUString maSmartTagType; + uno::Reference< smarttags::XSmartTagRecognizer > mxRec; + sal_Int32 mnSmartTagIdx; + + ImplSmartTagLBUserData( OUString aSmartTagType, + uno::Reference< smarttags::XSmartTagRecognizer > xRec, + sal_Int32 nSmartTagIdx ) : + maSmartTagType(std::move( aSmartTagType )), + mxRec(std::move( xRec )), + mnSmartTagIdx( nSmartTagIdx ) {} +}; + +} + +/** Clears m_xSmartTagTypesLB +*/ +void OfaSmartTagOptionsTabPage::ClearListBox() +{ + const int nCount = m_xSmartTagTypesLB->n_children(); + for (int i = 0; i < nCount; ++i) + { + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(i)); + delete pUserData; + } + + m_xSmartTagTypesLB->clear(); +} + +/** Inserts items into m_xSmartTagTypesLB +*/ +void OfaSmartTagOptionsTabPage::FillListBox( const SmartTagMgr& rSmartTagMgr ) +{ + // first we have to clear the list box: + ClearListBox(); + + // fill list box: + const sal_uInt32 nNumberOfRecognizers = rSmartTagMgr.NumberOfRecognizers(); + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + + for ( sal_uInt32 i = 0; i < nNumberOfRecognizers; ++i ) + { + const uno::Reference< smarttags::XSmartTagRecognizer >& xRec = rSmartTagMgr.GetRecognizer(i); + + const OUString aName = xRec->getName( aLocale ); + const sal_Int32 nNumberOfSupportedSmartTags = xRec->getSmartTagCount(); + + for ( sal_Int32 j = 0; j < nNumberOfSupportedSmartTags; ++j ) + { + const OUString aSmartTagType = xRec->getSmartTagName(j); + OUString aSmartTagCaption = rSmartTagMgr.GetSmartTagCaption( aSmartTagType, aLocale ); + + if ( aSmartTagCaption.isEmpty() ) + aSmartTagCaption = aSmartTagType; + + const OUString aLBEntry = aSmartTagCaption + " (" + aName + ")"; + + m_xSmartTagTypesLB->append(); + const int nRow = m_xSmartTagTypesLB->n_children() - 1; + const bool bCheck = rSmartTagMgr.IsSmartTagTypeEnabled( aSmartTagType ); + m_xSmartTagTypesLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xSmartTagTypesLB->set_text(nRow, aLBEntry, 0); + m_xSmartTagTypesLB->set_id(nRow, weld::toId(new ImplSmartTagLBUserData(aSmartTagType, xRec, j))); + } + } +} + +/** Handler for the push button +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, ClickHdl, weld::Button&, void) +{ + const int nPos = m_xSmartTagTypesLB->get_selected_index(); + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(nPos)); + uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec; + const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx; + + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) ) + xRec->displayPropertyPage( nSmartTagIdx, aLocale ); +} + +/** Handler for the check box +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, CheckHdl, weld::Toggleable&, void) +{ + const bool bEnable = m_xMainCB->get_active(); + m_xSmartTagTypesLB->set_sensitive(bEnable); + m_xPropertiesPB->set_sensitive(false); + + // if the controls are currently enabled, we still have to check + // if the properties button should be disabled because the currently + // selected smart tag type does not have a properties dialog. + // We do this by calling SelectHdl: + if (bEnable) + SelectHdl(*m_xSmartTagTypesLB); +} + +/** Handler for the list box +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, SelectHdl, weld::TreeView&, void) +{ + const int nPos = m_xSmartTagTypesLB->get_selected_index(); + if (nPos == -1) + return; + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(nPos)); + uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec; + const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx; + + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) ) + m_xPropertiesPB->set_sensitive(true); + else + m_xPropertiesPB->set_sensitive(false); +} + +/** Propagates the current settings to the smart tag manager. +*/ +bool OfaSmartTagOptionsTabPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr; + + // robust! + if ( !pSmartTagMgr ) + return false; + + bool bModifiedSmartTagTypes = false; + std::vector< OUString > aDisabledSmartTagTypes; + + const int nCount = m_xSmartTagTypesLB->n_children(); + + for (int i = 0; i < nCount; ++i) + { + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(i)); + const bool bChecked = m_xSmartTagTypesLB->get_toggle(i) == TRISTATE_TRUE; + const bool bIsCurrentlyEnabled = pSmartTagMgr->IsSmartTagTypeEnabled( pUserData->maSmartTagType ); + + bModifiedSmartTagTypes = bModifiedSmartTagTypes || ( !bChecked != !bIsCurrentlyEnabled ); + + if ( !bChecked ) + aDisabledSmartTagTypes.push_back( pUserData->maSmartTagType ); + + delete pUserData; + } + + const bool bModifiedRecognize = ( !m_xMainCB->get_active() != !pSmartTagMgr->IsLabelTextWithSmartTags() ); + if ( bModifiedSmartTagTypes || bModifiedRecognize ) + { + bool bLabelTextWithSmartTags = m_xMainCB->get_active(); + pSmartTagMgr->WriteConfiguration( bModifiedRecognize ? &bLabelTextWithSmartTags : nullptr, + bModifiedSmartTagTypes ? &aDisabledSmartTagTypes : nullptr ); + } + + return true; +} + +/** Sets the controls based on the current settings at SmartTagMgr. +*/ +void OfaSmartTagOptionsTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + const SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr; + + // robust, should not happen! + if ( !pSmartTagMgr ) + return; + + FillListBox(*pSmartTagMgr); + m_xSmartTagTypesLB->select(0); + m_xMainCB->set_active(pSmartTagMgr->IsLabelTextWithSmartTags()); + CheckHdl(*m_xMainCB); +} + +void OfaSmartTagOptionsTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage( false ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |