Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / cui / source / options / optdict.cxx
blob07080a75184ac7ae71a35e4396b46c74152c677f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <editeng/unolingu.hxx>
21 #include <svx/dialmgr.hxx>
22 #include <com/sun/star/frame/XStorable.hpp>
23 #include <com/sun/star/linguistic2/XDictionary.hpp>
24 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
25 #include <comphelper/string.hxx>
26 #include <tools/debug.hxx>
27 #include <unotools/collatorwrapper.hxx>
28 #include <unotools/intlwrapper.hxx>
29 #include <unotools/syslocale.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/weld.hxx>
33 #include <linguistic/misc.hxx>
34 #include <strings.hrc>
35 #include <optdict.hxx>
36 #include <dialmgr.hxx>
37 #include <svx/svxerr.hxx>
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::linguistic2;
42 using namespace linguistic;
44 // static function -------------------------------------------------------
46 static OUString getNormDicEntry_Impl(const OUString &rText)
48 OUString aTmp(comphelper::string::stripEnd(rText, '.'));
49 // non-standard hyphenation
50 if (aTmp.indexOf('[') > -1)
52 OUStringBuffer aTmp2 ( aTmp.getLength() );
53 bool bSkip = false;
54 for (sal_Int32 i = 0; i < aTmp.getLength(); i++)
56 sal_Unicode cTmp = aTmp[i];
57 if (cTmp == '[')
58 bSkip = true;
59 else if (!bSkip)
60 aTmp2.append( cTmp );
61 else if (cTmp == ']')
62 bSkip = false;
64 aTmp = aTmp2.makeStringAndClear();
66 return aTmp.replaceAll("=", "");
69 // Compare Dictionary Entry result
70 enum CDE_RESULT { CDE_EQUAL, CDE_SIMILAR, CDE_DIFFERENT };
72 static CDE_RESULT cmpDicEntry_Impl( const OUString &rText1, const OUString &rText2 )
74 CDE_RESULT eRes = CDE_DIFFERENT;
76 if (rText1 == rText2)
77 eRes = CDE_EQUAL;
78 else
79 { // similar = equal up to trailing '.' and hyphenation positions
80 // marked with '=' and '[' + alternative spelling pattern + ']'
81 if (getNormDicEntry_Impl( rText1 ) == getNormDicEntry_Impl( rText2 ))
82 eRes = CDE_SIMILAR;
85 return eRes;
88 // class SvxNewDictionaryDialog -------------------------------------------
90 SvxNewDictionaryDialog::SvxNewDictionaryDialog(weld::Window* pParent)
91 : GenericDialogController(pParent, "cui/ui/optnewdictionarydialog.ui", "OptNewDictionaryDialog")
92 , m_xNameEdit(m_xBuilder->weld_entry("nameedit"))
93 , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("language")))
94 , m_xExceptBtn(m_xBuilder->weld_check_button("except"))
95 , m_xOKBtn(m_xBuilder->weld_button("ok"))
97 // Prevent creation of dictionary without a name.
98 m_xOKBtn->set_sensitive(false);
100 // install handler
101 m_xNameEdit->connect_changed(LINK(this, SvxNewDictionaryDialog, ModifyHdl_Impl));
102 m_xOKBtn->connect_clicked(LINK(this, SvxNewDictionaryDialog, OKHdl_Impl));
104 // display languages
105 m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::ALL, true, true);
106 m_xLanguageLB->set_active(0);
109 IMPL_LINK_NOARG(SvxNewDictionaryDialog, OKHdl_Impl, weld::Button&, void)
112 // add extension for personal dictionaries
113 OUString sDict = comphelper::string::stripEnd(m_xNameEdit->get_text(), ' ') + ".dic";
115 Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
117 Sequence< Reference< XDictionary > > aDics;
118 if (xDicList.is())
119 aDics = xDicList->getDictionaries();
120 const Reference< XDictionary > *pDic = aDics.getConstArray();
121 sal_Int32 nCount = aDics.getLength();
123 bool bFound = false;
124 sal_Int32 i;
125 for (i = 0; !bFound && i < nCount; ++i )
126 if ( sDict.equalsIgnoreAsciiCase( pDic[i]->getName()) )
127 bFound = true;
129 if ( sDict.indexOf("/") != -1 || sDict.indexOf("\\") != -1 )
131 // Detected an invalid character.
132 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
133 VclMessageType::Info, VclButtonsType::Ok,
134 CuiResId(RID_SVXSTR_OPT_INVALID_DICT_NAME)));
135 xInfoBox->run();
136 m_xNameEdit->grab_focus();
137 return;
140 if ( bFound )
142 // duplicate names?
143 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
144 VclMessageType::Info, VclButtonsType::Ok,
145 CuiResId(RID_SVXSTR_OPT_DOUBLE_DICTS)));
146 xInfoBox->run();
147 m_xNameEdit->grab_focus();
148 return;
151 // create and add
152 LanguageType nLang = m_xLanguageLB->get_active_id();
155 // create new dictionary
156 DictionaryType eType = m_xExceptBtn->get_active() ?
157 DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
158 if (xDicList.is())
160 lang::Locale aLocale( LanguageTag::convertToLocale(nLang) );
161 OUString aURL( linguistic::GetWritableDictionaryURL( sDict ) );
162 m_xNewDic = xDicList->createDictionary(sDict, aLocale, eType, aURL);
163 m_xNewDic->setActive(true);
165 DBG_ASSERT(m_xNewDic.is(), "NULL pointer");
167 catch(...)
169 m_xNewDic = nullptr;
170 // error: couldn't create new dictionary
171 SfxErrorContext aContext( ERRCTX_SVX_LINGU_DICTIONARY, OUString(),
172 m_xDialog.get(), RID_SVXERRCTX, SvxResLocale() );
173 ErrorHandler::HandleError( *new StringErrorInfo(
174 ERRCODE_SVX_LINGU_DICT_NOTWRITEABLE, sDict ) );
175 m_xDialog->response(RET_CANCEL);
178 if (xDicList.is() && m_xNewDic.is())
180 xDicList->addDictionary(m_xNewDic);
182 // refresh list of dictionaries
183 //! dictionaries may have been added/removed elsewhere too.
184 aDics = xDicList->getDictionaries();
187 m_xDialog->response(RET_OK);
190 IMPL_LINK_NOARG(SvxNewDictionaryDialog, ModifyHdl_Impl, weld::Entry&, void)
192 m_xOKBtn->set_sensitive(!m_xNameEdit->get_text().isEmpty());
195 // class SvxEditDictionaryDialog -------------------------------------------
197 SvxEditDictionaryDialog::SvxEditDictionaryDialog(weld::Window* pParent, const OUString& rName)
198 : GenericDialogController(pParent, "cui/ui/editdictionarydialog.ui", "EditDictionaryDialog")
199 , sModify(CuiResId(STR_MODIFY))
200 , bFirstSelect(false)
201 , bDoNothing(false)
202 , bDicIsReadonly(false)
203 , m_xAllDictsLB(m_xBuilder->weld_combo_box("book"))
204 , m_xLangFT(m_xBuilder->weld_label("lang_label"))
205 , m_xLangLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("lang")))
206 , m_xWordED(m_xBuilder->weld_entry("word"))
207 , m_xReplaceFT(m_xBuilder->weld_label("replace_label"))
208 , m_xReplaceED(m_xBuilder->weld_entry("replace"))
209 , m_xSingleColumnLB(m_xBuilder->weld_tree_view("words"))
210 , m_xDoubleColumnLB(m_xBuilder->weld_tree_view("replaces"))
211 , m_xNewReplacePB(m_xBuilder->weld_button("newreplace"))
212 , m_xDeletePB(m_xBuilder->weld_button("delete"))
214 sReplaceFT_Text = m_xReplaceFT->get_label();
215 m_xSingleColumnLB->set_size_request(-1, m_xSingleColumnLB->get_height_rows(8));
216 m_xDoubleColumnLB->set_size_request(-1, m_xDoubleColumnLB->get_height_rows(8));
217 m_pWordsLB = m_xDoubleColumnLB.get();
218 m_xSingleColumnLB->hide();
220 //set to max of both sizes to avoid resizes
221 sNew = m_xNewReplacePB->get_label();
222 auto nNewWidth = m_xNewReplacePB->get_preferred_size().Width();
223 m_xNewReplacePB->set_label(sModify);
224 auto nReplaceWidth = m_xNewReplacePB->get_preferred_size().Width();
225 m_xNewReplacePB->set_label(sNew);
226 m_xNewReplacePB->set_size_request(std::max(nNewWidth, nReplaceWidth), -1);
228 if (LinguMgr::GetDictionaryList().is())
229 aDics = LinguMgr::GetDictionaryList()->getDictionaries();
231 m_xSingleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl));
232 m_xDoubleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl));
234 std::vector<int> aWidths;
235 aWidths.push_back(m_xDoubleColumnLB->get_approximate_digit_width() * 22);
236 m_xDoubleColumnLB->set_column_fixed_widths(aWidths);
238 // install handler
239 m_xNewReplacePB->connect_clicked(
240 LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl));
241 m_xDeletePB->connect_clicked(
242 LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl));
244 m_xLangLB->connect_changed(
245 LINK( this, SvxEditDictionaryDialog, SelectLangHdl_Impl ) );
246 m_xAllDictsLB->connect_changed(
247 LINK( this, SvxEditDictionaryDialog, SelectBookHdl_Impl ) );
249 m_xWordED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
250 m_xReplaceED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
251 m_xWordED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl));
252 m_xReplaceED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl));
254 // fill listbox with all available WB's
255 const Reference< XDictionary > *pDic = aDics.getConstArray();
256 sal_Int32 nCount = aDics.getLength();
258 OUString aLookUpEntry;
259 for ( sal_Int32 i = 0; i < nCount; ++i )
261 Reference< XDictionary > xDic = pDic[i];
262 if (xDic.is())
264 bool bNegative = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
265 OUString aDicName( xDic->getName() );
266 const OUString aTxt( ::GetDicInfoStr( aDicName,
267 LanguageTag( xDic->getLocale() ).getLanguageType(), bNegative ) );
268 m_xAllDictsLB->append_text(aTxt);
270 if (rName == aDicName)
271 aLookUpEntry = aTxt;
275 m_xLangLB->SetLanguageList( SvxLanguageListFlags::ALL, true, true );
277 Link<OUString&,bool> aLink = LINK(this, SvxEditDictionaryDialog, InsertTextHdl);
278 m_xReplaceED->connect_insert_text(aLink);
279 m_xWordED->connect_insert_text(aLink);
281 if ( nCount > 0 )
283 m_xAllDictsLB->set_active_text(aLookUpEntry);
284 int nPos = m_xAllDictsLB->get_active();
286 if (nPos == -1)
288 nPos = 0;
289 m_xAllDictsLB->set_active(nPos);
291 Reference< XDictionary > xDic;
292 if (nPos != -1)
293 xDic.set( aDics.getConstArray()[ nPos ], UNO_QUERY );
294 if (xDic.is())
295 SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() );
297 // check if dictionary is read-only
298 SetDicReadonly_Impl(xDic);
299 bool bEnable = !IsDicReadonly_Impl();
300 m_xNewReplacePB->set_sensitive( false );
301 m_xDeletePB->set_sensitive( false );
302 m_xLangFT->set_sensitive( bEnable );
303 m_xLangLB->set_sensitive( bEnable );
304 ShowWords_Impl( nPos );
306 else
308 m_xNewReplacePB->set_sensitive(false);
309 m_xDeletePB->set_sensitive(false);
312 m_xWordED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl));
313 m_xReplaceED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl));
316 IMPL_LINK_NOARG(SvxEditDictionaryDialog, EntrySizeAllocHdl, const Size&, void)
318 std::vector<int> aWidths;
319 int x, y, width, height;
320 if (m_xReplaceED->get_extents_relative_to(*m_pWordsLB, x, y, width, height))
322 aWidths.push_back(x);
323 m_xDoubleColumnLB->set_column_fixed_widths(aWidths);
327 SvxEditDictionaryDialog::~SvxEditDictionaryDialog()
331 void SvxEditDictionaryDialog::SetDicReadonly_Impl(
332 Reference< XDictionary > const &xDic )
334 // enable or disable new and delete button according to file attributes
335 bDicIsReadonly = true;
336 if (xDic.is())
338 Reference< frame::XStorable > xStor( xDic, UNO_QUERY );
339 if ( !xStor.is() // non persistent dictionary
340 || !xStor->hasLocation() // not yet persistent
341 || !xStor->isReadonly() )
343 bDicIsReadonly = false;
348 void SvxEditDictionaryDialog::SetLanguage_Impl(LanguageType nLanguage)
350 // select language
351 m_xLangLB->set_active_id(nLanguage);
354 int SvxEditDictionaryDialog::GetLBInsertPos(const OUString &rDicWord)
356 IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
357 const CollatorWrapper* pCollator = aIntlWrapper.getCollator();
358 int j;
359 int nCount = m_pWordsLB->n_children();
360 for (j = 0; j < nCount; ++j)
362 OUString aNormEntry( getNormDicEntry_Impl( rDicWord ) );
363 sal_Int32 nCmpRes = pCollator->
364 compareString( aNormEntry, getNormDicEntry_Impl( m_pWordsLB->get_text(j, 0) ) );
365 if (nCmpRes < 0)
366 break;
369 return j;
372 void SvxEditDictionaryDialog::RemoveDictEntry(int nEntry)
374 int nLBPos = m_xAllDictsLB->get_active();
375 if (nEntry != -1 && nLBPos != -1)
377 OUString sTmpShort(m_pWordsLB->get_text(nEntry, 0));
379 Reference<XDictionary> xDic = aDics.getConstArray()[nLBPos];
380 if (xDic->remove(sTmpShort)) // sal_True on success
382 m_pWordsLB->remove(nEntry);
383 SelectHdl(*m_pWordsLB);
388 IMPL_LINK_NOARG(SvxEditDictionaryDialog, SelectBookHdl_Impl, weld::ComboBox&, void)
390 int nPos = m_xAllDictsLB->get_active();
391 if (nPos != -1)
393 m_xNewReplacePB->set_sensitive( false );
394 m_xDeletePB->set_sensitive( false );
395 // display dictionary
396 ShowWords_Impl( nPos );
397 // enable or disable new and delete button according to file attributes
398 Reference< XDictionary > xDic( aDics.getConstArray()[ nPos ], UNO_QUERY );
399 if (xDic.is())
400 SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() );
402 SetDicReadonly_Impl(xDic);
403 bool bEnable = !IsDicReadonly_Impl();
404 m_xLangFT->set_sensitive( bEnable );
405 m_xLangLB->set_sensitive( bEnable );
409 IMPL_LINK_NOARG(SvxEditDictionaryDialog, SelectLangHdl_Impl, weld::ComboBox&, void)
411 int nDicPos = m_xAllDictsLB->get_active();
412 LanguageType nLang = m_xLangLB->get_active_id();
413 Reference< XDictionary > xDic( aDics.getConstArray()[ nDicPos ], UNO_QUERY );
414 LanguageType nOldLang = LanguageTag( xDic->getLocale() ).getLanguageType();
416 if ( nLang != nOldLang )
418 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
419 VclMessageType::Question, VclButtonsType::YesNo,
420 CuiResId(RID_SVXSTR_CONFIRM_SET_LANGUAGE)));
421 OUString sTxt(xBox->get_primary_text());
422 sTxt = sTxt.replaceFirst("%1", m_xAllDictsLB->get_active_text());
423 xBox->set_primary_text(sTxt);
425 if (xBox->run() == RET_YES)
427 xDic->setLocale( LanguageTag::convertToLocale( nLang ) );
428 bool bNegativ = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
430 const OUString sName(
431 ::GetDicInfoStr( xDic->getName(),
432 LanguageTag( xDic->getLocale() ).getLanguageType(),
433 bNegativ ) );
434 m_xAllDictsLB->remove(nDicPos);
435 m_xAllDictsLB->insert_text(nDicPos, sName);
436 m_xAllDictsLB->set_active(nDicPos);
438 else
439 SetLanguage_Impl( nOldLang );
443 void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId )
445 Reference< XDictionary > xDic = aDics.getConstArray()[ nId ];
447 weld::WaitObject aWait(m_xDialog.get());
449 m_xWordED->set_text(OUString());
450 m_xReplaceED->set_text(OUString());
452 bool bIsNegative = xDic->getDictionaryType() != DictionaryType_POSITIVE;
453 bool bLangNone = LanguageTag(
454 xDic->getLocale() ).getLanguageType() == LANGUAGE_NONE;
456 // The label is "Replace By" only in negative dictionaries (forbidden
457 // words), otherwise "Grammar By" in language-specific dictionaries
458 // (where the optional second word is the sample word for
459 // the Hunspell based affixation/compounding of the new dictionary word)
460 if (bIsNegative)
462 m_xReplaceFT->set_label(sReplaceFT_Text);
463 } else if (!bLangNone) {
464 m_xReplaceFT->set_label(CuiResId(RID_SVXSTR_OPT_GRAMMAR_BY));
467 if(bIsNegative || !bLangNone)
469 // make controls for replacement text active
470 if (!m_xReplaceFT->get_visible())
472 m_xReplaceFT->show();
473 m_xReplaceED->show();
474 m_xSingleColumnLB->hide();
475 m_xDoubleColumnLB->show();
476 m_pWordsLB = m_xDoubleColumnLB.get();
479 else
481 // deactivate controls for replacement text
482 if (m_xReplaceFT->get_visible())
484 m_xReplaceFT->hide();
485 m_xReplaceED->hide();
486 m_xDoubleColumnLB->hide();
487 m_xSingleColumnLB->show();
488 m_pWordsLB = m_xSingleColumnLB.get();
492 m_pWordsLB->clear();
494 Sequence< Reference< XDictionaryEntry > > aEntries( xDic->getEntries() );
495 const Reference< XDictionaryEntry > *pEntry = aEntries.getConstArray();
496 sal_Int32 nCount = aEntries.getLength();
497 std::vector<OUString> aSortedDicEntries;
498 aSortedDicEntries.reserve(nCount);
499 for (sal_Int32 i = 0; i < nCount; i++)
501 OUString aStr = pEntry[i]->getDictionaryWord();
502 if(!pEntry[i]->getReplacementText().isEmpty())
504 aStr += "\t" + pEntry[i]->getReplacementText();
506 aSortedDicEntries.push_back(aStr);
509 IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
510 const CollatorWrapper* pCollator = aIntlWrapper.getCollator();
511 std::sort(aSortedDicEntries.begin(), aSortedDicEntries.end(),
512 [&] (OUString const & lhs, OUString const & rhs)
514 sal_Int32 nCmpRes = pCollator->
515 compareString( getNormDicEntry_Impl(lhs), getNormDicEntry_Impl( rhs ) );
516 return nCmpRes < 0;
519 m_pWordsLB->freeze(); // speed up insert
520 int nRow = 0;
521 for (OUString const & rStr : aSortedDicEntries)
523 m_pWordsLB->append_text(rStr.getToken(0, '\t'));
524 if (m_pWordsLB == m_xDoubleColumnLB.get())
526 OUString sReplace = rStr.getToken(1, '\t');
527 m_pWordsLB->set_text(nRow, sReplace, 1);
528 ++nRow;
531 m_pWordsLB->thaw();
533 if (m_pWordsLB->n_children())
535 m_pWordsLB->select(0);
536 m_pWordsLB->set_cursor(0);
537 SelectHdl(*m_pWordsLB);
541 IMPL_LINK(SvxEditDictionaryDialog, SelectHdl, weld::TreeView&, rBox, void)
543 if (bDoNothing)
544 return;
546 int nEntry = rBox.get_selected_index();
548 if(!bFirstSelect)
550 if (nEntry != -1)
552 OUString sTmpShort(rBox.get_text(nEntry, 0));
553 // without this the cursor is always at the beginning of a word, if the text
554 // is set over the ModifyHdl, although you're editing there at the moment
555 if (m_xWordED->get_text() != sTmpShort)
556 m_xWordED->set_text(sTmpShort);
557 if (&rBox == m_xDoubleColumnLB.get())
558 m_xReplaceED->set_text(rBox.get_text(nEntry, 1));
561 else
562 bFirstSelect = false;
564 // entries in the list box should exactly correspond to those from the
565 // dictionary. Thus:
566 m_xNewReplacePB->set_sensitive(false);
567 m_xDeletePB->set_sensitive(nEntry != -1 && !IsDicReadonly_Impl());
570 IMPL_LINK(SvxEditDictionaryDialog, NewDelButtonHdl, weld::Button&, rBtn, void)
572 NewDelHdl(&rBtn);
575 IMPL_LINK(SvxEditDictionaryDialog, NewDelActionHdl, weld::Entry&, rDictEdit, bool)
577 return NewDelHdl(&rDictEdit);
580 bool SvxEditDictionaryDialog::NewDelHdl(const weld::Widget* pBtn)
582 if (pBtn == m_xDeletePB.get())
584 OUString aStr;
586 m_xWordED->set_text(aStr);
587 m_xReplaceED->set_text(aStr);
588 m_xDeletePB->set_sensitive(false);
590 int nEntry = m_pWordsLB->get_selected_index();
591 RemoveDictEntry(nEntry); // remove entry from dic and list-box
593 if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive())
595 int nEntry = m_pWordsLB->get_selected_index();
596 OUString aNewWord(m_xWordED->get_text());
597 OUString sEntry(aNewWord);
598 OUString aReplaceStr(m_xReplaceED->get_text());
600 DictionaryError nAddRes = DictionaryError::UNKNOWN;
601 int nPos = m_xAllDictsLB->get_active();
602 if (nPos != -1 && !aNewWord.isEmpty())
604 DBG_ASSERT(nPos < aDics.getLength(), "invalid dictionary index");
605 Reference< XDictionary > xDic( aDics.getConstArray()[ nPos ], UNO_QUERY );
606 if (xDic.is())
608 // make changes in dic
610 bool bIsNegEntry = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
612 OUString aRplcText;
613 if(!aReplaceStr.isEmpty())
614 aRplcText = aReplaceStr;
616 if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry
617 xDic->remove(m_pWordsLB->get_text(nEntry, 0));
618 // if remove has failed the following add should fail too
619 // and thus a warning message should be triggered...
621 nAddRes = linguistic::AddEntryToDic( xDic,
622 aNewWord, bIsNegEntry,
623 aRplcText, false );
626 if (DictionaryError::NONE != nAddRes)
627 SvxDicError(m_xDialog.get(), nAddRes);
629 if (DictionaryError::NONE == nAddRes && !sEntry.isEmpty())
631 // insert new entry in list-box etc...
632 m_pWordsLB->freeze();
634 if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry
636 m_pWordsLB->set_text(nEntry, sEntry);
637 if (!aReplaceStr.isEmpty())
638 m_pWordsLB->set_text(nEntry, aReplaceStr, 1);
640 else
642 nEntry = GetLBInsertPos(aNewWord);
643 m_pWordsLB->insert_text(nEntry, sEntry);
644 if(!aReplaceStr.isEmpty())
645 m_pWordsLB->set_text(nEntry, aReplaceStr, 1);
648 m_pWordsLB->thaw();
649 m_pWordsLB->scroll_to_row(nEntry);
651 // if the request came from the ReplaceEdit, give focus to the ShortEdit
652 if (m_xReplaceED->has_focus())
653 m_xWordED->grab_focus();
656 else
658 // this can only be an enter in one of the two edit fields
659 // which means EndDialog() - has to be evaluated in KeyInput
660 return false;
662 ModifyHdl(*m_xWordED);
663 return true;
666 IMPL_LINK(SvxEditDictionaryDialog, ModifyHdl, weld::Entry&, rEdt, void)
668 OUString rEntry = rEdt.get_text();
670 sal_Int32 nWordLen = rEntry.getLength();
671 const OUString& rRepString = m_xReplaceED->get_text();
673 bool bEnableNewReplace = false;
674 bool bEnableDelete = false;
675 OUString aNewReplaceText = sNew;
677 if (&rEdt == m_xWordED.get())
679 if(nWordLen>0)
681 bool bFound = false;
682 bool bTmpSelEntry=false;
683 CDE_RESULT eCmpRes = CDE_DIFFERENT;
685 for (int i = 0, nCount = m_pWordsLB->n_children(); i < nCount; ++i)
687 OUString aTestStr(m_pWordsLB->get_text(i, 0));
688 eCmpRes = cmpDicEntry_Impl( rEntry, aTestStr );
689 if(CDE_DIFFERENT != eCmpRes)
691 if(!rRepString.isEmpty())
692 bFirstSelect = true;
693 bDoNothing=true;
694 m_pWordsLB->set_cursor(i);
695 bDoNothing=false;
696 m_xReplaceED->set_text(m_pWordsLB->get_text(i, 1));
698 if (CDE_SIMILAR == eCmpRes)
700 aNewReplaceText = sModify;
701 bEnableNewReplace = true;
703 bFound= true;
704 break;
706 else if(getNormDicEntry_Impl(aTestStr).indexOf(
707 getNormDicEntry_Impl( rEntry ) ) == 0
708 && !bTmpSelEntry)
710 bDoNothing=true;
711 m_pWordsLB->scroll_to_row(i);
712 bDoNothing=false;
713 bTmpSelEntry=true;
715 aNewReplaceText = sNew;
716 bEnableNewReplace = true;
720 if(!bFound)
722 m_pWordsLB->unselect_all();
723 aNewReplaceText = sNew;
724 bEnableNewReplace = true;
726 bEnableDelete = CDE_DIFFERENT != eCmpRes;
728 else if (m_pWordsLB->n_children() > 0)
730 bDoNothing=true;
731 m_pWordsLB->scroll_to_row(0);
732 bDoNothing=false;
735 else if(&rEdt == m_xReplaceED.get())
737 OUString aReplaceText;
738 OUString aWordText;
739 int nFirstSel = m_pWordsLB->get_selected_index();
740 if (nFirstSel != -1) // a m_pWordsLB entry is selected
742 aWordText = m_pWordsLB->get_text(nFirstSel, 0);
743 aReplaceText = m_pWordsLB->get_text(nFirstSel, 1);
745 aNewReplaceText = sModify;
746 bEnableDelete = true;
748 bool bIsChange =
749 CDE_EQUAL != cmpDicEntry_Impl(m_xWordED->get_text(), aWordText)
750 || CDE_EQUAL != cmpDicEntry_Impl(m_xReplaceED->get_text(), aReplaceText);
751 if (!m_xWordED->get_text().isEmpty() && bIsChange)
752 bEnableNewReplace = true;
755 m_xNewReplacePB->set_label(aNewReplaceText);
756 m_xNewReplacePB->set_sensitive(bEnableNewReplace && !IsDicReadonly_Impl());
757 m_xDeletePB->set_sensitive(bEnableDelete && !IsDicReadonly_Impl());
760 IMPL_STATIC_LINK(SvxEditDictionaryDialog, InsertTextHdl, OUString&, rText, bool)
762 rText = rText.replaceAll(" ", "");
763 return true;
766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */