1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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() );
54 for (sal_Int32 i
= 0; i
< aTmp
.getLength(); i
++)
56 sal_Unicode cTmp
= aTmp
[i
];
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
;
79 { // similar = equal up to trailing '.' and hyphenation positions
80 // marked with '=' and '[' + alternative spelling pattern + ']'
81 if (getNormDicEntry_Impl( rText1
) == getNormDicEntry_Impl( rText2
))
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);
101 m_xNameEdit
->connect_changed(LINK(this, SvxNewDictionaryDialog
, ModifyHdl_Impl
));
102 m_xOKBtn
->connect_clicked(LINK(this, SvxNewDictionaryDialog
, OKHdl_Impl
));
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
;
119 aDics
= xDicList
->getDictionaries();
120 const Reference
< XDictionary
> *pDic
= aDics
.getConstArray();
121 sal_Int32 nCount
= aDics
.getLength();
125 for (i
= 0; !bFound
&& i
< nCount
; ++i
)
126 if ( sDict
.equalsIgnoreAsciiCase( pDic
[i
]->getName()) )
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
)));
136 m_xNameEdit
->grab_focus();
143 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(m_xDialog
.get(),
144 VclMessageType::Info
, VclButtonsType::Ok
,
145 CuiResId(RID_SVXSTR_OPT_DOUBLE_DICTS
)));
147 m_xNameEdit
->grab_focus();
152 LanguageType nLang
= m_xLanguageLB
->get_active_id();
155 // create new dictionary
156 DictionaryType eType
= m_xExceptBtn
->get_active() ?
157 DictionaryType_NEGATIVE
: DictionaryType_POSITIVE
;
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");
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)
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
);
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
];
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
)
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
);
283 m_xAllDictsLB
->set_active_text(aLookUpEntry
);
284 int nPos
= m_xAllDictsLB
->get_active();
289 m_xAllDictsLB
->set_active(nPos
);
291 Reference
< XDictionary
> xDic
;
293 xDic
.set( aDics
.getConstArray()[ nPos
], UNO_QUERY
);
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
);
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;
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
)
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();
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) ) );
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();
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
);
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(),
434 m_xAllDictsLB
->remove(nDicPos
);
435 m_xAllDictsLB
->insert_text(nDicPos
, sName
);
436 m_xAllDictsLB
->set_active(nDicPos
);
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)
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();
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();
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
) );
519 m_pWordsLB
->freeze(); // speed up insert
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);
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)
546 int nEntry
= rBox
.get_selected_index();
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));
562 bFirstSelect
= false;
564 // entries in the list box should exactly correspond to those from the
566 m_xNewReplacePB
->set_sensitive(false);
567 m_xDeletePB
->set_sensitive(nEntry
!= -1 && !IsDicReadonly_Impl());
570 IMPL_LINK(SvxEditDictionaryDialog
, NewDelButtonHdl
, weld::Button
&, rBtn
, void)
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())
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
);
608 // make changes in dic
610 bool bIsNegEntry
= xDic
->getDictionaryType() == DictionaryType_NEGATIVE
;
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
,
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);
642 nEntry
= GetLBInsertPos(aNewWord
);
643 m_pWordsLB
->insert_text(nEntry
, sEntry
);
644 if(!aReplaceStr
.isEmpty())
645 m_pWordsLB
->set_text(nEntry
, aReplaceStr
, 1);
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();
658 // this can only be an enter in one of the two edit fields
659 // which means EndDialog() - has to be evaluated in KeyInput
662 ModifyHdl(*m_xWordED
);
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())
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())
694 m_pWordsLB
->set_cursor(i
);
696 m_xReplaceED
->set_text(m_pWordsLB
->get_text(i
, 1));
698 if (CDE_SIMILAR
== eCmpRes
)
700 aNewReplaceText
= sModify
;
701 bEnableNewReplace
= true;
706 else if(getNormDicEntry_Impl(aTestStr
).indexOf(
707 getNormDicEntry_Impl( rEntry
) ) == 0
711 m_pWordsLB
->scroll_to_row(i
);
715 aNewReplaceText
= sNew
;
716 bEnableNewReplace
= true;
722 m_pWordsLB
->unselect_all();
723 aNewReplaceText
= sNew
;
724 bEnableNewReplace
= true;
726 bEnableDelete
= CDE_DIFFERENT
!= eCmpRes
;
728 else if (m_pWordsLB
->n_children() > 0)
731 m_pWordsLB
->scroll_to_row(0);
735 else if(&rEdt
== m_xReplaceED
.get())
737 OUString aReplaceText
;
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;
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(" ", "");
766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */