768 lines
26 KiB
C++
768 lines
26 KiB
C++
/* -*- 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 <editeng/unolingu.hxx>
|
|
#include <o3tl/safeint.hxx>
|
|
#include <svx/dialmgr.hxx>
|
|
#include <com/sun/star/frame/XStorable.hpp>
|
|
#include <com/sun/star/linguistic2/XDictionary.hpp>
|
|
#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
|
|
#include <comphelper/string.hxx>
|
|
#include <tools/debug.hxx>
|
|
#include <unotools/collatorwrapper.hxx>
|
|
#include <unotools/intlwrapper.hxx>
|
|
#include <unotools/syslocale.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/weld.hxx>
|
|
|
|
#include <linguistic/misc.hxx>
|
|
#include <strings.hrc>
|
|
#include <optdict.hxx>
|
|
#include <dialmgr.hxx>
|
|
#include <svx/svxerr.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::linguistic2;
|
|
using namespace linguistic;
|
|
|
|
// static function -------------------------------------------------------
|
|
|
|
static OUString getNormDicEntry_Impl(std::u16string_view rText)
|
|
{
|
|
OUString aTmp(comphelper::string::stripEnd(rText, '.'));
|
|
// non-standard hyphenation
|
|
if (aTmp.indexOf('[') > -1)
|
|
{
|
|
OUStringBuffer aTmp2 ( aTmp.getLength() );
|
|
bool bSkip = false;
|
|
for (sal_Int32 i = 0; i < aTmp.getLength(); i++)
|
|
{
|
|
sal_Unicode cTmp = aTmp[i];
|
|
if (cTmp == '[')
|
|
bSkip = true;
|
|
else if (!bSkip)
|
|
aTmp2.append( cTmp );
|
|
else if (cTmp == ']')
|
|
bSkip = false;
|
|
}
|
|
aTmp = aTmp2.makeStringAndClear();
|
|
}
|
|
return aTmp.replaceAll("=", "");
|
|
}
|
|
|
|
// tdf#154499 separate words of a phrase only by a single space,
|
|
// i.e. trim terminating spaces and replace space sequences with single spaces
|
|
static OUString fixSpace(OUString sText)
|
|
{
|
|
sText = sText.trim();
|
|
|
|
sal_Int32 nLen;
|
|
do
|
|
{
|
|
nLen = sText.getLength();
|
|
sText = sText.replaceAll(" ", " ");
|
|
}
|
|
while ( sText.getLength() < nLen );
|
|
|
|
return sText;
|
|
}
|
|
|
|
namespace {
|
|
|
|
// Compare Dictionary Entry result
|
|
enum CDE_RESULT { CDE_EQUAL, CDE_SIMILAR, CDE_DIFFERENT };
|
|
|
|
}
|
|
|
|
static CDE_RESULT cmpDicEntry_Impl( std::u16string_view rText1, std::u16string_view rText2 )
|
|
{
|
|
CDE_RESULT eRes = CDE_DIFFERENT;
|
|
|
|
if (rText1 == rText2)
|
|
eRes = CDE_EQUAL;
|
|
else
|
|
{ // similar = equal up to trailing '.' and hyphenation positions
|
|
// marked with '=' and '[' + alternative spelling pattern + ']'
|
|
if (getNormDicEntry_Impl( rText1 ) == getNormDicEntry_Impl( rText2 ))
|
|
eRes = CDE_SIMILAR;
|
|
}
|
|
|
|
return eRes;
|
|
}
|
|
|
|
// class SvxNewDictionaryDialog -------------------------------------------
|
|
|
|
SvxNewDictionaryDialog::SvxNewDictionaryDialog(weld::Window* pParent)
|
|
: GenericDialogController(pParent, u"cui/ui/optnewdictionarydialog.ui"_ustr, u"OptNewDictionaryDialog"_ustr)
|
|
, m_xNameEdit(m_xBuilder->weld_entry(u"nameedit"_ustr))
|
|
, m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"language"_ustr)))
|
|
, m_xExceptBtn(m_xBuilder->weld_check_button(u"except"_ustr))
|
|
, m_xOKBtn(m_xBuilder->weld_button(u"ok"_ustr))
|
|
{
|
|
// Prevent creation of dictionary without a name.
|
|
m_xOKBtn->set_sensitive(false);
|
|
|
|
// install handler
|
|
m_xNameEdit->connect_changed(LINK(this, SvxNewDictionaryDialog, ModifyHdl_Impl));
|
|
m_xOKBtn->connect_clicked(LINK(this, SvxNewDictionaryDialog, OKHdl_Impl));
|
|
|
|
// display languages
|
|
m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::ALL, true, true);
|
|
m_xLanguageLB->set_active(0);
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SvxNewDictionaryDialog, OKHdl_Impl, weld::Button&, void)
|
|
{
|
|
|
|
// add extension for personal dictionaries
|
|
OUString sDict = comphelper::string::stripEnd(m_xNameEdit->get_text(), ' ') + ".dic";
|
|
|
|
Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
|
|
|
|
if ( sDict.indexOf("/") != -1 || sDict.indexOf("\\") != -1 )
|
|
{
|
|
// Detected an invalid character.
|
|
std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
|
|
VclMessageType::Info, VclButtonsType::Ok,
|
|
CuiResId(RID_CUISTR_OPT_INVALID_DICT_NAME)));
|
|
xInfoBox->run();
|
|
m_xNameEdit->grab_focus();
|
|
return;
|
|
}
|
|
|
|
Sequence< Reference< XDictionary > > aDics;
|
|
if (xDicList.is())
|
|
aDics = xDicList->getDictionaries();
|
|
|
|
if (std::any_of(aDics.begin(), aDics.end(),
|
|
[&sDict](auto& d) { return sDict.equalsIgnoreAsciiCase(d->getName()); }))
|
|
{
|
|
// duplicate names?
|
|
std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
|
|
VclMessageType::Info, VclButtonsType::Ok,
|
|
CuiResId(RID_CUISTR_OPT_DOUBLE_DICTS)));
|
|
xInfoBox->run();
|
|
m_xNameEdit->grab_focus();
|
|
return;
|
|
}
|
|
|
|
// create and add
|
|
LanguageType nLang = m_xLanguageLB->get_active_id();
|
|
try
|
|
{
|
|
// create new dictionary
|
|
DictionaryType eType = m_xExceptBtn->get_active() ?
|
|
DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
|
|
if (xDicList.is())
|
|
{
|
|
lang::Locale aLocale( LanguageTag::convertToLocale(nLang) );
|
|
OUString aURL( linguistic::GetWritableDictionaryURL( sDict ) );
|
|
m_xNewDic = xDicList->createDictionary(sDict, aLocale, eType, aURL);
|
|
m_xNewDic->setActive(true);
|
|
}
|
|
DBG_ASSERT(m_xNewDic.is(), "NULL pointer");
|
|
}
|
|
catch(...)
|
|
{
|
|
m_xNewDic = nullptr;
|
|
// error: couldn't create new dictionary
|
|
SfxErrorContext aContext( ERRCTX_SVX_LINGU_DICTIONARY, OUString(),
|
|
m_xDialog.get(), RID_SVXERRCTX, SvxResLocale() );
|
|
ErrorHandler::HandleError( ErrCodeMsg(
|
|
ERRCODE_SVX_LINGU_DICT_NOTWRITEABLE, sDict ) );
|
|
m_xDialog->response(RET_CANCEL);
|
|
}
|
|
|
|
if (xDicList.is() && m_xNewDic.is())
|
|
{
|
|
xDicList->addDictionary(m_xNewDic);
|
|
|
|
// refresh list of dictionaries
|
|
//! dictionaries may have been added/removed elsewhere too.
|
|
aDics = xDicList->getDictionaries();
|
|
}
|
|
|
|
m_xDialog->response(RET_OK);
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SvxNewDictionaryDialog, ModifyHdl_Impl, weld::Entry&, void)
|
|
{
|
|
m_xOKBtn->set_sensitive(!m_xNameEdit->get_text().isEmpty());
|
|
}
|
|
|
|
// class SvxEditDictionaryDialog -------------------------------------------
|
|
|
|
SvxEditDictionaryDialog::SvxEditDictionaryDialog(weld::Window* pParent, std::u16string_view rName)
|
|
: GenericDialogController(pParent, u"cui/ui/editdictionarydialog.ui"_ustr, u"EditDictionaryDialog"_ustr)
|
|
, sModify(CuiResId(STR_MODIFY))
|
|
, bFirstSelect(false)
|
|
, bDoNothing(false)
|
|
, bDicIsReadonly(false)
|
|
, m_xAllDictsLB(m_xBuilder->weld_combo_box(u"book"_ustr))
|
|
, m_xLangFT(m_xBuilder->weld_label(u"lang_label"_ustr))
|
|
, m_xLangLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"lang"_ustr)))
|
|
, m_xWordED(m_xBuilder->weld_entry(u"word"_ustr))
|
|
, m_xReplaceFT(m_xBuilder->weld_label(u"replace_label"_ustr))
|
|
, m_xReplaceED(m_xBuilder->weld_entry(u"replace"_ustr))
|
|
, m_xSingleColumnLB(m_xBuilder->weld_tree_view(u"words"_ustr))
|
|
, m_xDoubleColumnLB(m_xBuilder->weld_tree_view(u"replaces"_ustr))
|
|
, m_xNewReplacePB(m_xBuilder->weld_button(u"newreplace"_ustr))
|
|
, m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr))
|
|
{
|
|
sReplaceFT_Text = m_xReplaceFT->get_label();
|
|
m_xSingleColumnLB->set_size_request(-1, m_xSingleColumnLB->get_height_rows(8));
|
|
m_xDoubleColumnLB->set_size_request(-1, m_xDoubleColumnLB->get_height_rows(8));
|
|
m_pWordsLB = m_xDoubleColumnLB.get();
|
|
m_xSingleColumnLB->hide();
|
|
|
|
//set to max of both sizes to avoid resizes
|
|
sNew = m_xNewReplacePB->get_label();
|
|
auto nNewWidth = m_xNewReplacePB->get_preferred_size().Width();
|
|
m_xNewReplacePB->set_label(sModify);
|
|
auto nReplaceWidth = m_xNewReplacePB->get_preferred_size().Width();
|
|
m_xNewReplacePB->set_label(sNew);
|
|
m_xNewReplacePB->set_size_request(std::max(nNewWidth, nReplaceWidth), -1);
|
|
|
|
if (LinguMgr::GetDictionaryList().is())
|
|
aDics = LinguMgr::GetDictionaryList()->getDictionaries();
|
|
|
|
m_xSingleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl));
|
|
m_xDoubleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl));
|
|
|
|
std::vector<int> aWidths
|
|
{
|
|
o3tl::narrowing<int>(m_xDoubleColumnLB->get_approximate_digit_width() * 22)
|
|
};
|
|
m_xDoubleColumnLB->set_column_fixed_widths(aWidths);
|
|
|
|
// install handler
|
|
m_xNewReplacePB->connect_clicked(
|
|
LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl));
|
|
m_xDeletePB->connect_clicked(
|
|
LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl));
|
|
|
|
m_xLangLB->connect_changed(
|
|
LINK( this, SvxEditDictionaryDialog, SelectLangHdl_Impl ) );
|
|
m_xAllDictsLB->connect_changed(
|
|
LINK( this, SvxEditDictionaryDialog, SelectBookHdl_Impl ) );
|
|
|
|
m_xWordED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
|
|
m_xReplaceED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
|
|
m_xWordED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl));
|
|
m_xReplaceED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl));
|
|
|
|
// fill listbox with all available WB's
|
|
OUString aLookUpEntry;
|
|
for (auto& xDic : aDics)
|
|
{
|
|
if (xDic.is())
|
|
{
|
|
bool bNegative = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
|
|
OUString aDicName( xDic->getName() );
|
|
const OUString aTxt( ::GetDicInfoStr( aDicName,
|
|
LanguageTag( xDic->getLocale() ).getLanguageType(), bNegative ) );
|
|
m_xAllDictsLB->append_text(aTxt);
|
|
|
|
if (rName == aDicName)
|
|
aLookUpEntry = aTxt;
|
|
}
|
|
}
|
|
|
|
m_xLangLB->SetLanguageList( SvxLanguageListFlags::ALL, true, true );
|
|
|
|
if (aDics.hasElements())
|
|
{
|
|
m_xAllDictsLB->set_active_text(aLookUpEntry);
|
|
int nPos = m_xAllDictsLB->get_active();
|
|
|
|
if (nPos == -1)
|
|
{
|
|
nPos = 0;
|
|
m_xAllDictsLB->set_active(nPos);
|
|
}
|
|
Reference< XDictionary > xDic;
|
|
if (nPos != -1)
|
|
xDic = aDics[ nPos ];
|
|
if (xDic.is())
|
|
SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() );
|
|
|
|
// check if dictionary is read-only
|
|
SetDicReadonly_Impl(xDic);
|
|
bool bEnable = !IsDicReadonly_Impl();
|
|
m_xNewReplacePB->set_sensitive( false );
|
|
m_xDeletePB->set_sensitive( false );
|
|
m_xLangFT->set_sensitive( bEnable );
|
|
m_xLangLB->set_sensitive( bEnable );
|
|
ShowWords_Impl( nPos );
|
|
}
|
|
else
|
|
{
|
|
m_xNewReplacePB->set_sensitive(false);
|
|
m_xDeletePB->set_sensitive(false);
|
|
}
|
|
|
|
m_xWordED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl));
|
|
m_xReplaceED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl));
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SvxEditDictionaryDialog, EntrySizeAllocHdl, const Size&, void)
|
|
{
|
|
std::vector<int> aWidths;
|
|
int x, y, width, height;
|
|
if (m_xReplaceED->get_extents_relative_to(*m_pWordsLB, x, y, width, height))
|
|
{
|
|
aWidths.push_back(x);
|
|
m_xDoubleColumnLB->set_column_fixed_widths(aWidths);
|
|
}
|
|
}
|
|
|
|
SvxEditDictionaryDialog::~SvxEditDictionaryDialog()
|
|
{
|
|
}
|
|
|
|
void SvxEditDictionaryDialog::SetDicReadonly_Impl(
|
|
Reference< XDictionary > const &xDic )
|
|
{
|
|
// enable or disable new and delete button according to file attributes
|
|
bDicIsReadonly = true;
|
|
if (xDic.is())
|
|
{
|
|
Reference< frame::XStorable > xStor( xDic, UNO_QUERY );
|
|
if ( !xStor.is() // non persistent dictionary
|
|
|| !xStor->hasLocation() // not yet persistent
|
|
|| !xStor->isReadonly() )
|
|
{
|
|
bDicIsReadonly = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SvxEditDictionaryDialog::SetLanguage_Impl(LanguageType nLanguage)
|
|
{
|
|
// select language
|
|
m_xLangLB->set_active_id(nLanguage);
|
|
}
|
|
|
|
int SvxEditDictionaryDialog::GetLBInsertPos(std::u16string_view rDicWord)
|
|
{
|
|
IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
|
|
const CollatorWrapper* pCollator = aIntlWrapper.getCollator();
|
|
int j;
|
|
int nCount = m_pWordsLB->n_children();
|
|
for (j = 0; j < nCount; ++j)
|
|
{
|
|
OUString aNormEntry( getNormDicEntry_Impl( rDicWord ) );
|
|
sal_Int32 nCmpRes = pCollator->
|
|
compareString( aNormEntry, getNormDicEntry_Impl( m_pWordsLB->get_text(j, 0) ) );
|
|
if (nCmpRes < 0)
|
|
break;
|
|
}
|
|
|
|
return j;
|
|
}
|
|
|
|
void SvxEditDictionaryDialog::RemoveDictEntry(int nEntry)
|
|
{
|
|
int nLBPos = m_xAllDictsLB->get_active();
|
|
if (nEntry != -1 && nLBPos != -1)
|
|
{
|
|
OUString sTmpShort(m_pWordsLB->get_text(nEntry, 0));
|
|
|
|
Reference<XDictionary> xDic = aDics[nLBPos];
|
|
if (xDic->remove(sTmpShort)) // sal_True on success
|
|
{
|
|
m_pWordsLB->remove(nEntry);
|
|
SelectHdl(*m_pWordsLB);
|
|
}
|
|
}
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SvxEditDictionaryDialog, SelectBookHdl_Impl, weld::ComboBox&, void)
|
|
{
|
|
int nPos = m_xAllDictsLB->get_active();
|
|
if (nPos == -1)
|
|
return;
|
|
|
|
m_xNewReplacePB->set_sensitive( false );
|
|
m_xDeletePB->set_sensitive( false );
|
|
// display dictionary
|
|
ShowWords_Impl( nPos );
|
|
// enable or disable new and delete button according to file attributes
|
|
Reference< XDictionary > const & xDic = aDics[ nPos ];
|
|
if (xDic.is())
|
|
SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() );
|
|
|
|
SetDicReadonly_Impl(xDic);
|
|
bool bEnable = !IsDicReadonly_Impl();
|
|
m_xLangFT->set_sensitive( bEnable );
|
|
m_xLangLB->set_sensitive( bEnable );
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SvxEditDictionaryDialog, SelectLangHdl_Impl, weld::ComboBox&, void)
|
|
{
|
|
int nDicPos = m_xAllDictsLB->get_active();
|
|
LanguageType nLang = m_xLangLB->get_active_id();
|
|
Reference< XDictionary > const & xDic = aDics[ nDicPos ];
|
|
LanguageType nOldLang = LanguageTag( xDic->getLocale() ).getLanguageType();
|
|
|
|
if ( nLang == nOldLang )
|
|
return;
|
|
|
|
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
|
|
VclMessageType::Question, VclButtonsType::YesNo,
|
|
CuiResId(RID_CUISTR_CONFIRM_SET_LANGUAGE)));
|
|
OUString sTxt(xBox->get_primary_text());
|
|
sTxt = sTxt.replaceFirst("%1", m_xAllDictsLB->get_active_text());
|
|
xBox->set_primary_text(sTxt);
|
|
|
|
if (xBox->run() == RET_YES)
|
|
{
|
|
xDic->setLocale( LanguageTag::convertToLocale( nLang ) );
|
|
bool bNegativ = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
|
|
|
|
const OUString sName(
|
|
::GetDicInfoStr( xDic->getName(),
|
|
LanguageTag( xDic->getLocale() ).getLanguageType(),
|
|
bNegativ ) );
|
|
m_xAllDictsLB->remove(nDicPos);
|
|
m_xAllDictsLB->insert_text(nDicPos, sName);
|
|
m_xAllDictsLB->set_active(nDicPos);
|
|
}
|
|
else
|
|
SetLanguage_Impl( nOldLang );
|
|
}
|
|
|
|
void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId )
|
|
{
|
|
Reference<XDictionary> xDic = aDics[nId];
|
|
|
|
weld::WaitObject aWait(m_xDialog.get());
|
|
|
|
m_xWordED->set_text(OUString());
|
|
m_xReplaceED->set_text(OUString());
|
|
|
|
bool bIsNegative = xDic->getDictionaryType() != DictionaryType_POSITIVE;
|
|
bool bLangNone = LanguageTag(
|
|
xDic->getLocale() ).getLanguageType() == LANGUAGE_NONE;
|
|
|
|
// The label is "Replace By" only in negative dictionaries (forbidden
|
|
// words), otherwise "Grammar By" in language-specific dictionaries
|
|
// (where the optional second word is the sample word for
|
|
// the Hunspell based affixation/compounding of the new dictionary word)
|
|
if (bIsNegative)
|
|
{
|
|
m_xReplaceFT->set_label(sReplaceFT_Text);
|
|
} else if (!bLangNone) {
|
|
m_xReplaceFT->set_label(CuiResId(RID_CUISTR_OPT_GRAMMAR_BY));
|
|
}
|
|
|
|
if(bIsNegative || !bLangNone)
|
|
{
|
|
// make controls for replacement text active
|
|
if (!m_xReplaceFT->get_visible())
|
|
{
|
|
m_xReplaceFT->show();
|
|
m_xReplaceED->show();
|
|
m_xSingleColumnLB->hide();
|
|
m_xDoubleColumnLB->show();
|
|
m_pWordsLB = m_xDoubleColumnLB.get();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// deactivate controls for replacement text
|
|
if (m_xReplaceFT->get_visible())
|
|
{
|
|
m_xReplaceFT->hide();
|
|
m_xReplaceED->hide();
|
|
m_xDoubleColumnLB->hide();
|
|
m_xSingleColumnLB->show();
|
|
m_pWordsLB = m_xSingleColumnLB.get();
|
|
}
|
|
}
|
|
|
|
m_pWordsLB->clear();
|
|
|
|
Sequence< Reference< XDictionaryEntry > > aEntries( xDic->getEntries() );
|
|
std::vector<OUString> aSortedDicEntries;
|
|
aSortedDicEntries.reserve(aEntries.getLength());
|
|
for (auto& xDictionaryEntry : aEntries)
|
|
{
|
|
OUString aStr = xDictionaryEntry->getDictionaryWord();
|
|
if (!xDictionaryEntry->getReplacementText().isEmpty())
|
|
{
|
|
aStr += "\t" + xDictionaryEntry->getReplacementText();
|
|
}
|
|
aSortedDicEntries.push_back(aStr);
|
|
}
|
|
|
|
IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
|
|
const CollatorWrapper* pCollator = aIntlWrapper.getCollator();
|
|
std::sort(aSortedDicEntries.begin(), aSortedDicEntries.end(),
|
|
[&] (OUString const & lhs, OUString const & rhs)
|
|
{
|
|
sal_Int32 nCmpRes = pCollator->
|
|
compareString( getNormDicEntry_Impl(lhs), getNormDicEntry_Impl( rhs ) );
|
|
return nCmpRes < 0;
|
|
});
|
|
|
|
m_pWordsLB->freeze(); // speed up insert
|
|
int nRow = 0;
|
|
for (OUString const & rStr : aSortedDicEntries)
|
|
{
|
|
sal_Int32 index = 0;
|
|
m_pWordsLB->append_text(rStr.getToken(0, '\t', index));
|
|
if (index != -1 && m_pWordsLB == m_xDoubleColumnLB.get())
|
|
{
|
|
OUString sReplace = rStr.getToken(0, '\t', index);
|
|
m_pWordsLB->set_text(nRow, sReplace, 1);
|
|
++nRow;
|
|
}
|
|
}
|
|
m_pWordsLB->thaw();
|
|
|
|
if (m_pWordsLB->n_children())
|
|
{
|
|
m_pWordsLB->select(0);
|
|
m_pWordsLB->set_cursor(0);
|
|
SelectHdl(*m_pWordsLB);
|
|
}
|
|
}
|
|
|
|
IMPL_LINK(SvxEditDictionaryDialog, SelectHdl, weld::TreeView&, rBox, void)
|
|
{
|
|
if (bDoNothing)
|
|
return;
|
|
|
|
int nEntry = rBox.get_selected_index();
|
|
|
|
if(!bFirstSelect)
|
|
{
|
|
if (nEntry != -1)
|
|
{
|
|
OUString sTmpShort(rBox.get_text(nEntry, 0));
|
|
// without this the cursor is always at the beginning of a word, if the text
|
|
// is set over the ModifyHdl, although you're editing there at the moment
|
|
if (m_xWordED->get_text() != sTmpShort)
|
|
m_xWordED->set_text(sTmpShort);
|
|
if (&rBox == m_xDoubleColumnLB.get())
|
|
m_xReplaceED->set_text(rBox.get_text(nEntry, 1));
|
|
}
|
|
}
|
|
else
|
|
bFirstSelect = false;
|
|
|
|
// entries in the list box should exactly correspond to those from the
|
|
// dictionary. Thus:
|
|
m_xNewReplacePB->set_sensitive(false);
|
|
m_xDeletePB->set_sensitive(nEntry != -1 && !IsDicReadonly_Impl());
|
|
}
|
|
|
|
IMPL_LINK(SvxEditDictionaryDialog, NewDelButtonHdl, weld::Button&, rBtn, void)
|
|
{
|
|
NewDelHdl(&rBtn);
|
|
}
|
|
|
|
IMPL_LINK(SvxEditDictionaryDialog, NewDelActionHdl, weld::Entry&, rDictEdit, bool)
|
|
{
|
|
return NewDelHdl(&rDictEdit);
|
|
}
|
|
|
|
bool SvxEditDictionaryDialog::NewDelHdl(const weld::Widget* pBtn)
|
|
{
|
|
if (pBtn == m_xDeletePB.get())
|
|
{
|
|
m_xWordED->set_text(u""_ustr);
|
|
m_xReplaceED->set_text(u""_ustr);
|
|
m_xDeletePB->set_sensitive(false);
|
|
|
|
int nEntry = m_pWordsLB->get_selected_index();
|
|
RemoveDictEntry(nEntry); // remove entry from dic and list-box
|
|
}
|
|
if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive())
|
|
{
|
|
int nEntry = m_pWordsLB->get_selected_index();
|
|
OUString aNewWord(fixSpace(m_xWordED->get_text()));
|
|
OUString aReplaceStr(fixSpace(m_xReplaceED->get_text()));
|
|
|
|
DictionaryError nAddRes = DictionaryError::UNKNOWN;
|
|
int nPos = m_xAllDictsLB->get_active();
|
|
if (nPos != -1 && !aNewWord.isEmpty())
|
|
{
|
|
DBG_ASSERT(nPos < aDics.getLength(), "invalid dictionary index");
|
|
Reference< XDictionary > const & xDic = aDics[ nPos ];
|
|
if (xDic.is())
|
|
{
|
|
// make changes in dic
|
|
|
|
bool bIsNegEntry = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
|
|
|
|
OUString aRplcText;
|
|
if(!aReplaceStr.isEmpty())
|
|
aRplcText = aReplaceStr;
|
|
|
|
if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry
|
|
xDic->remove(m_pWordsLB->get_text(nEntry, 0));
|
|
// if remove has failed the following add should fail too
|
|
// and thus a warning message should be triggered...
|
|
|
|
nAddRes = linguistic::AddEntryToDic( xDic,
|
|
aNewWord, bIsNegEntry,
|
|
aRplcText, false );
|
|
}
|
|
}
|
|
if (DictionaryError::NONE != nAddRes)
|
|
SvxDicError(m_xDialog.get(), nAddRes);
|
|
|
|
if (DictionaryError::NONE == nAddRes && !aNewWord.isEmpty())
|
|
{
|
|
// insert new entry in list-box etc...
|
|
m_pWordsLB->freeze();
|
|
|
|
if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry
|
|
{
|
|
m_pWordsLB->set_text(nEntry, aNewWord);
|
|
if (!aReplaceStr.isEmpty())
|
|
m_pWordsLB->set_text(nEntry, aReplaceStr, 1);
|
|
}
|
|
else
|
|
{
|
|
nEntry = GetLBInsertPos(aNewWord);
|
|
m_pWordsLB->insert_text(nEntry, aNewWord);
|
|
if(!aReplaceStr.isEmpty())
|
|
m_pWordsLB->set_text(nEntry, aReplaceStr, 1);
|
|
}
|
|
|
|
m_pWordsLB->thaw();
|
|
m_pWordsLB->scroll_to_row(nEntry);
|
|
|
|
// if the request came from the ReplaceEdit, give focus to the ShortEdit
|
|
if (m_xReplaceED->has_focus())
|
|
m_xWordED->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_xWordED);
|
|
return true;
|
|
}
|
|
|
|
IMPL_LINK(SvxEditDictionaryDialog, ModifyHdl, weld::Entry&, rEdt, void)
|
|
{
|
|
OUString rEntry = rEdt.get_text();
|
|
|
|
sal_Int32 nWordLen = rEntry.getLength();
|
|
const OUString aRepString = fixSpace(m_xReplaceED->get_text());
|
|
|
|
bool bEnableNewReplace = false;
|
|
bool bEnableDelete = false;
|
|
OUString aNewReplaceText = sNew;
|
|
|
|
if (&rEdt == m_xWordED.get())
|
|
{
|
|
if(nWordLen>0)
|
|
{
|
|
bool bFound = false;
|
|
bool bTmpSelEntry=false;
|
|
CDE_RESULT eCmpRes = CDE_DIFFERENT;
|
|
|
|
bool bDoubleColumn = m_pWordsLB == m_xDoubleColumnLB.get();
|
|
|
|
for (int i = 0, nCount = m_pWordsLB->n_children(); i < nCount; ++i)
|
|
{
|
|
OUString aTestStr(m_pWordsLB->get_text(i, 0));
|
|
eCmpRes = cmpDicEntry_Impl( rEntry, aTestStr );
|
|
if(CDE_DIFFERENT != eCmpRes)
|
|
{
|
|
if(!aRepString.isEmpty())
|
|
bFirstSelect = true;
|
|
bDoNothing=true;
|
|
m_pWordsLB->set_cursor(i);
|
|
bDoNothing=false;
|
|
if (bDoubleColumn)
|
|
m_xReplaceED->set_text(m_pWordsLB->get_text(i, 1));
|
|
|
|
if (CDE_SIMILAR == eCmpRes)
|
|
{
|
|
aNewReplaceText = sModify;
|
|
bEnableNewReplace = true;
|
|
}
|
|
bFound= true;
|
|
break;
|
|
}
|
|
else if(getNormDicEntry_Impl(aTestStr).indexOf(
|
|
getNormDicEntry_Impl( rEntry ) ) == 0
|
|
&& !bTmpSelEntry)
|
|
{
|
|
bDoNothing=true;
|
|
m_pWordsLB->scroll_to_row(i);
|
|
bDoNothing=false;
|
|
bTmpSelEntry=true;
|
|
|
|
aNewReplaceText = sNew;
|
|
bEnableNewReplace = true;
|
|
}
|
|
}
|
|
|
|
if(!bFound)
|
|
{
|
|
m_pWordsLB->unselect_all();
|
|
aNewReplaceText = sNew;
|
|
bEnableNewReplace = true;
|
|
}
|
|
bEnableDelete = CDE_DIFFERENT != eCmpRes;
|
|
}
|
|
else if (m_pWordsLB->n_children() > 0)
|
|
{
|
|
bDoNothing=true;
|
|
m_pWordsLB->scroll_to_row(0);
|
|
bDoNothing=false;
|
|
}
|
|
}
|
|
else if(&rEdt == m_xReplaceED.get())
|
|
{
|
|
OUString aReplaceText;
|
|
OUString aWordText;
|
|
int nFirstSel = m_pWordsLB->get_selected_index();
|
|
if (nFirstSel != -1) // a m_pWordsLB entry is selected
|
|
{
|
|
aWordText = m_pWordsLB->get_text(nFirstSel, 0);
|
|
aReplaceText = m_pWordsLB->get_text(nFirstSel, 1);
|
|
|
|
aNewReplaceText = sModify;
|
|
bEnableDelete = true;
|
|
}
|
|
bool bIsChange =
|
|
CDE_EQUAL != cmpDicEntry_Impl(fixSpace(m_xWordED->get_text()), aWordText)
|
|
|| CDE_EQUAL != cmpDicEntry_Impl(fixSpace(m_xReplaceED->get_text()), aReplaceText);
|
|
if (!fixSpace(m_xWordED->get_text()).isEmpty() && bIsChange)
|
|
bEnableNewReplace = true;
|
|
}
|
|
|
|
m_xNewReplacePB->set_label(aNewReplaceText);
|
|
m_xNewReplacePB->set_sensitive(bEnableNewReplace && !IsDicReadonly_Impl());
|
|
m_xDeletePB->set_sensitive(bEnableDelete && !IsDicReadonly_Impl());
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|