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 <o3tl/safeint.hxx>
22 #include <svx/dialmgr.hxx>
23 #include <com/sun/star/frame/XStorable.hpp>
24 #include <com/sun/star/linguistic2/XDictionary.hpp>
25 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
26 #include <comphelper/string.hxx>
27 #include <tools/debug.hxx>
28 #include <unotools/collatorwrapper.hxx>
29 #include <unotools/intlwrapper.hxx>
30 #include <unotools/syslocale.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/weld.hxx>
34 #include <linguistic/misc.hxx>
35 #include <strings.hrc>
36 #include <optdict.hxx>
37 #include <dialmgr.hxx>
38 #include <svx/svxerr.hxx>
40 using namespace ::com::sun::star
;
41 using namespace ::com::sun::star::uno
;
42 using namespace ::com::sun::star::linguistic2
;
43 using namespace linguistic
;
45 // static function -------------------------------------------------------
47 static OUString
getNormDicEntry_Impl(std::u16string_view rText
)
49 OUString
aTmp(comphelper::string::stripEnd(rText
, '.'));
50 // non-standard hyphenation
51 if (aTmp
.indexOf('[') > -1)
53 OUStringBuffer
aTmp2 ( aTmp
.getLength() );
55 for (sal_Int32 i
= 0; i
< aTmp
.getLength(); i
++)
57 sal_Unicode cTmp
= aTmp
[i
];
65 aTmp
= aTmp2
.makeStringAndClear();
67 return aTmp
.replaceAll("=", "");
70 // tdf#154499 separate words of a phrase only by a single space,
71 // i.e. trim terminating spaces and replace space sequences with single spaces
72 static OUString
fixSpace(OUString sText
)
79 nLen
= sText
.getLength();
80 sText
= sText
.replaceAll(" ", " ");
82 while ( sText
.getLength() < nLen
);
89 // Compare Dictionary Entry result
90 enum CDE_RESULT
{ CDE_EQUAL
, CDE_SIMILAR
, CDE_DIFFERENT
};
94 static CDE_RESULT
cmpDicEntry_Impl( std::u16string_view rText1
, std::u16string_view rText2
)
96 CDE_RESULT eRes
= CDE_DIFFERENT
;
101 { // similar = equal up to trailing '.' and hyphenation positions
102 // marked with '=' and '[' + alternative spelling pattern + ']'
103 if (getNormDicEntry_Impl( rText1
) == getNormDicEntry_Impl( rText2
))
110 // class SvxNewDictionaryDialog -------------------------------------------
112 SvxNewDictionaryDialog::SvxNewDictionaryDialog(weld::Window
* pParent
)
113 : GenericDialogController(pParent
, "cui/ui/optnewdictionarydialog.ui", "OptNewDictionaryDialog")
114 , m_xNameEdit(m_xBuilder
->weld_entry("nameedit"))
115 , m_xLanguageLB(new SvxLanguageBox(m_xBuilder
->weld_combo_box("language")))
116 , m_xExceptBtn(m_xBuilder
->weld_check_button("except"))
117 , m_xOKBtn(m_xBuilder
->weld_button("ok"))
119 // Prevent creation of dictionary without a name.
120 m_xOKBtn
->set_sensitive(false);
123 m_xNameEdit
->connect_changed(LINK(this, SvxNewDictionaryDialog
, ModifyHdl_Impl
));
124 m_xOKBtn
->connect_clicked(LINK(this, SvxNewDictionaryDialog
, OKHdl_Impl
));
127 m_xLanguageLB
->SetLanguageList(SvxLanguageListFlags::ALL
, true, true);
128 m_xLanguageLB
->set_active(0);
131 IMPL_LINK_NOARG(SvxNewDictionaryDialog
, OKHdl_Impl
, weld::Button
&, void)
134 // add extension for personal dictionaries
135 OUString sDict
= comphelper::string::stripEnd(m_xNameEdit
->get_text(), ' ') + ".dic";
137 Reference
< XSearchableDictionaryList
> xDicList( LinguMgr::GetDictionaryList() );
139 Sequence
< Reference
< XDictionary
> > aDics
;
141 aDics
= xDicList
->getDictionaries();
142 const Reference
< XDictionary
> *pDic
= aDics
.getConstArray();
143 sal_Int32 nCount
= aDics
.getLength();
147 for (i
= 0; !bFound
&& i
< nCount
; ++i
)
148 if ( sDict
.equalsIgnoreAsciiCase( pDic
[i
]->getName()) )
151 if ( sDict
.indexOf("/") != -1 || sDict
.indexOf("\\") != -1 )
153 // Detected an invalid character.
154 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(m_xDialog
.get(),
155 VclMessageType::Info
, VclButtonsType::Ok
,
156 CuiResId(RID_CUISTR_OPT_INVALID_DICT_NAME
)));
158 m_xNameEdit
->grab_focus();
165 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(m_xDialog
.get(),
166 VclMessageType::Info
, VclButtonsType::Ok
,
167 CuiResId(RID_CUISTR_OPT_DOUBLE_DICTS
)));
169 m_xNameEdit
->grab_focus();
174 LanguageType nLang
= m_xLanguageLB
->get_active_id();
177 // create new dictionary
178 DictionaryType eType
= m_xExceptBtn
->get_active() ?
179 DictionaryType_NEGATIVE
: DictionaryType_POSITIVE
;
182 lang::Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
183 OUString
aURL( linguistic::GetWritableDictionaryURL( sDict
) );
184 m_xNewDic
= xDicList
->createDictionary(sDict
, aLocale
, eType
, aURL
);
185 m_xNewDic
->setActive(true);
187 DBG_ASSERT(m_xNewDic
.is(), "NULL pointer");
192 // error: couldn't create new dictionary
193 SfxErrorContext
aContext( ERRCTX_SVX_LINGU_DICTIONARY
, OUString(),
194 m_xDialog
.get(), RID_SVXERRCTX
, SvxResLocale() );
195 ErrorHandler::HandleError( *new StringErrorInfo(
196 ERRCODE_SVX_LINGU_DICT_NOTWRITEABLE
, sDict
) );
197 m_xDialog
->response(RET_CANCEL
);
200 if (xDicList
.is() && m_xNewDic
.is())
202 xDicList
->addDictionary(m_xNewDic
);
204 // refresh list of dictionaries
205 //! dictionaries may have been added/removed elsewhere too.
206 aDics
= xDicList
->getDictionaries();
209 m_xDialog
->response(RET_OK
);
212 IMPL_LINK_NOARG(SvxNewDictionaryDialog
, ModifyHdl_Impl
, weld::Entry
&, void)
214 m_xOKBtn
->set_sensitive(!m_xNameEdit
->get_text().isEmpty());
217 // class SvxEditDictionaryDialog -------------------------------------------
219 SvxEditDictionaryDialog::SvxEditDictionaryDialog(weld::Window
* pParent
, std::u16string_view rName
)
220 : GenericDialogController(pParent
, "cui/ui/editdictionarydialog.ui", "EditDictionaryDialog")
221 , sModify(CuiResId(STR_MODIFY
))
222 , bFirstSelect(false)
224 , bDicIsReadonly(false)
225 , m_xAllDictsLB(m_xBuilder
->weld_combo_box("book"))
226 , m_xLangFT(m_xBuilder
->weld_label("lang_label"))
227 , m_xLangLB(new SvxLanguageBox(m_xBuilder
->weld_combo_box("lang")))
228 , m_xWordED(m_xBuilder
->weld_entry("word"))
229 , m_xReplaceFT(m_xBuilder
->weld_label("replace_label"))
230 , m_xReplaceED(m_xBuilder
->weld_entry("replace"))
231 , m_xSingleColumnLB(m_xBuilder
->weld_tree_view("words"))
232 , m_xDoubleColumnLB(m_xBuilder
->weld_tree_view("replaces"))
233 , m_xNewReplacePB(m_xBuilder
->weld_button("newreplace"))
234 , m_xDeletePB(m_xBuilder
->weld_button("delete"))
236 sReplaceFT_Text
= m_xReplaceFT
->get_label();
237 m_xSingleColumnLB
->set_size_request(-1, m_xSingleColumnLB
->get_height_rows(8));
238 m_xDoubleColumnLB
->set_size_request(-1, m_xDoubleColumnLB
->get_height_rows(8));
239 m_pWordsLB
= m_xDoubleColumnLB
.get();
240 m_xSingleColumnLB
->hide();
242 //set to max of both sizes to avoid resizes
243 sNew
= m_xNewReplacePB
->get_label();
244 auto nNewWidth
= m_xNewReplacePB
->get_preferred_size().Width();
245 m_xNewReplacePB
->set_label(sModify
);
246 auto nReplaceWidth
= m_xNewReplacePB
->get_preferred_size().Width();
247 m_xNewReplacePB
->set_label(sNew
);
248 m_xNewReplacePB
->set_size_request(std::max(nNewWidth
, nReplaceWidth
), -1);
250 if (LinguMgr::GetDictionaryList().is())
251 aDics
= LinguMgr::GetDictionaryList()->getDictionaries();
253 m_xSingleColumnLB
->connect_changed(LINK(this, SvxEditDictionaryDialog
, SelectHdl
));
254 m_xDoubleColumnLB
->connect_changed(LINK(this, SvxEditDictionaryDialog
, SelectHdl
));
256 std::vector
<int> aWidths
258 o3tl::narrowing
<int>(m_xDoubleColumnLB
->get_approximate_digit_width() * 22)
260 m_xDoubleColumnLB
->set_column_fixed_widths(aWidths
);
263 m_xNewReplacePB
->connect_clicked(
264 LINK( this, SvxEditDictionaryDialog
, NewDelButtonHdl
));
265 m_xDeletePB
->connect_clicked(
266 LINK( this, SvxEditDictionaryDialog
, NewDelButtonHdl
));
268 m_xLangLB
->connect_changed(
269 LINK( this, SvxEditDictionaryDialog
, SelectLangHdl_Impl
) );
270 m_xAllDictsLB
->connect_changed(
271 LINK( this, SvxEditDictionaryDialog
, SelectBookHdl_Impl
) );
273 m_xWordED
->connect_changed(LINK(this, SvxEditDictionaryDialog
, ModifyHdl
));
274 m_xReplaceED
->connect_changed(LINK(this, SvxEditDictionaryDialog
, ModifyHdl
));
275 m_xWordED
->connect_activate(LINK(this, SvxEditDictionaryDialog
, NewDelActionHdl
));
276 m_xReplaceED
->connect_activate(LINK(this, SvxEditDictionaryDialog
, NewDelActionHdl
));
278 // fill listbox with all available WB's
279 const Reference
< XDictionary
> *pDic
= aDics
.getConstArray();
280 sal_Int32 nCount
= aDics
.getLength();
282 OUString aLookUpEntry
;
283 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
285 Reference
< XDictionary
> xDic
= pDic
[i
];
288 bool bNegative
= xDic
->getDictionaryType() == DictionaryType_NEGATIVE
;
289 OUString
aDicName( xDic
->getName() );
290 const OUString
aTxt( ::GetDicInfoStr( aDicName
,
291 LanguageTag( xDic
->getLocale() ).getLanguageType(), bNegative
) );
292 m_xAllDictsLB
->append_text(aTxt
);
294 if (rName
== aDicName
)
299 m_xLangLB
->SetLanguageList( SvxLanguageListFlags::ALL
, true, true );
303 m_xAllDictsLB
->set_active_text(aLookUpEntry
);
304 int nPos
= m_xAllDictsLB
->get_active();
309 m_xAllDictsLB
->set_active(nPos
);
311 Reference
< XDictionary
> xDic
;
313 xDic
= aDics
[ nPos
];
315 SetLanguage_Impl( LanguageTag( xDic
->getLocale() ).getLanguageType() );
317 // check if dictionary is read-only
318 SetDicReadonly_Impl(xDic
);
319 bool bEnable
= !IsDicReadonly_Impl();
320 m_xNewReplacePB
->set_sensitive( false );
321 m_xDeletePB
->set_sensitive( false );
322 m_xLangFT
->set_sensitive( bEnable
);
323 m_xLangLB
->set_sensitive( bEnable
);
324 ShowWords_Impl( nPos
);
328 m_xNewReplacePB
->set_sensitive(false);
329 m_xDeletePB
->set_sensitive(false);
332 m_xWordED
->connect_size_allocate(LINK(this, SvxEditDictionaryDialog
, EntrySizeAllocHdl
));
333 m_xReplaceED
->connect_size_allocate(LINK(this, SvxEditDictionaryDialog
, EntrySizeAllocHdl
));
336 IMPL_LINK_NOARG(SvxEditDictionaryDialog
, EntrySizeAllocHdl
, const Size
&, void)
338 std::vector
<int> aWidths
;
339 int x
, y
, width
, height
;
340 if (m_xReplaceED
->get_extents_relative_to(*m_pWordsLB
, x
, y
, width
, height
))
342 aWidths
.push_back(x
);
343 m_xDoubleColumnLB
->set_column_fixed_widths(aWidths
);
347 SvxEditDictionaryDialog::~SvxEditDictionaryDialog()
351 void SvxEditDictionaryDialog::SetDicReadonly_Impl(
352 Reference
< XDictionary
> const &xDic
)
354 // enable or disable new and delete button according to file attributes
355 bDicIsReadonly
= true;
358 Reference
< frame::XStorable
> xStor( xDic
, UNO_QUERY
);
359 if ( !xStor
.is() // non persistent dictionary
360 || !xStor
->hasLocation() // not yet persistent
361 || !xStor
->isReadonly() )
363 bDicIsReadonly
= false;
368 void SvxEditDictionaryDialog::SetLanguage_Impl(LanguageType nLanguage
)
371 m_xLangLB
->set_active_id(nLanguage
);
374 int SvxEditDictionaryDialog::GetLBInsertPos(std::u16string_view rDicWord
)
376 IntlWrapper
aIntlWrapper(SvtSysLocale().GetUILanguageTag());
377 const CollatorWrapper
* pCollator
= aIntlWrapper
.getCollator();
379 int nCount
= m_pWordsLB
->n_children();
380 for (j
= 0; j
< nCount
; ++j
)
382 OUString
aNormEntry( getNormDicEntry_Impl( rDicWord
) );
383 sal_Int32 nCmpRes
= pCollator
->
384 compareString( aNormEntry
, getNormDicEntry_Impl( m_pWordsLB
->get_text(j
, 0) ) );
392 void SvxEditDictionaryDialog::RemoveDictEntry(int nEntry
)
394 int nLBPos
= m_xAllDictsLB
->get_active();
395 if (nEntry
!= -1 && nLBPos
!= -1)
397 OUString
sTmpShort(m_pWordsLB
->get_text(nEntry
, 0));
399 Reference
<XDictionary
> xDic
= aDics
.getConstArray()[nLBPos
];
400 if (xDic
->remove(sTmpShort
)) // sal_True on success
402 m_pWordsLB
->remove(nEntry
);
403 SelectHdl(*m_pWordsLB
);
408 IMPL_LINK_NOARG(SvxEditDictionaryDialog
, SelectBookHdl_Impl
, weld::ComboBox
&, void)
410 int nPos
= m_xAllDictsLB
->get_active();
414 m_xNewReplacePB
->set_sensitive( false );
415 m_xDeletePB
->set_sensitive( false );
416 // display dictionary
417 ShowWords_Impl( nPos
);
418 // enable or disable new and delete button according to file attributes
419 Reference
< XDictionary
> const & xDic
= aDics
[ nPos
];
421 SetLanguage_Impl( LanguageTag( xDic
->getLocale() ).getLanguageType() );
423 SetDicReadonly_Impl(xDic
);
424 bool bEnable
= !IsDicReadonly_Impl();
425 m_xLangFT
->set_sensitive( bEnable
);
426 m_xLangLB
->set_sensitive( bEnable
);
429 IMPL_LINK_NOARG(SvxEditDictionaryDialog
, SelectLangHdl_Impl
, weld::ComboBox
&, void)
431 int nDicPos
= m_xAllDictsLB
->get_active();
432 LanguageType nLang
= m_xLangLB
->get_active_id();
433 Reference
< XDictionary
> const & xDic
= aDics
[ nDicPos
];
434 LanguageType nOldLang
= LanguageTag( xDic
->getLocale() ).getLanguageType();
436 if ( nLang
== nOldLang
)
439 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xDialog
.get(),
440 VclMessageType::Question
, VclButtonsType::YesNo
,
441 CuiResId(RID_CUISTR_CONFIRM_SET_LANGUAGE
)));
442 OUString
sTxt(xBox
->get_primary_text());
443 sTxt
= sTxt
.replaceFirst("%1", m_xAllDictsLB
->get_active_text());
444 xBox
->set_primary_text(sTxt
);
446 if (xBox
->run() == RET_YES
)
448 xDic
->setLocale( LanguageTag::convertToLocale( nLang
) );
449 bool bNegativ
= xDic
->getDictionaryType() == DictionaryType_NEGATIVE
;
451 const OUString
sName(
452 ::GetDicInfoStr( xDic
->getName(),
453 LanguageTag( xDic
->getLocale() ).getLanguageType(),
455 m_xAllDictsLB
->remove(nDicPos
);
456 m_xAllDictsLB
->insert_text(nDicPos
, sName
);
457 m_xAllDictsLB
->set_active(nDicPos
);
460 SetLanguage_Impl( nOldLang
);
463 void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId
)
465 Reference
< XDictionary
> xDic
= aDics
.getConstArray()[ nId
];
467 weld::WaitObject
aWait(m_xDialog
.get());
469 m_xWordED
->set_text(OUString());
470 m_xReplaceED
->set_text(OUString());
472 bool bIsNegative
= xDic
->getDictionaryType() != DictionaryType_POSITIVE
;
473 bool bLangNone
= LanguageTag(
474 xDic
->getLocale() ).getLanguageType() == LANGUAGE_NONE
;
476 // The label is "Replace By" only in negative dictionaries (forbidden
477 // words), otherwise "Grammar By" in language-specific dictionaries
478 // (where the optional second word is the sample word for
479 // the Hunspell based affixation/compounding of the new dictionary word)
482 m_xReplaceFT
->set_label(sReplaceFT_Text
);
483 } else if (!bLangNone
) {
484 m_xReplaceFT
->set_label(CuiResId(RID_CUISTR_OPT_GRAMMAR_BY
));
487 if(bIsNegative
|| !bLangNone
)
489 // make controls for replacement text active
490 if (!m_xReplaceFT
->get_visible())
492 m_xReplaceFT
->show();
493 m_xReplaceED
->show();
494 m_xSingleColumnLB
->hide();
495 m_xDoubleColumnLB
->show();
496 m_pWordsLB
= m_xDoubleColumnLB
.get();
501 // deactivate controls for replacement text
502 if (m_xReplaceFT
->get_visible())
504 m_xReplaceFT
->hide();
505 m_xReplaceED
->hide();
506 m_xDoubleColumnLB
->hide();
507 m_xSingleColumnLB
->show();
508 m_pWordsLB
= m_xSingleColumnLB
.get();
514 Sequence
< Reference
< XDictionaryEntry
> > aEntries( xDic
->getEntries() );
515 const Reference
< XDictionaryEntry
> *pEntry
= aEntries
.getConstArray();
516 sal_Int32 nCount
= aEntries
.getLength();
517 std::vector
<OUString
> aSortedDicEntries
;
518 aSortedDicEntries
.reserve(nCount
);
519 for (sal_Int32 i
= 0; i
< nCount
; i
++)
521 OUString aStr
= pEntry
[i
]->getDictionaryWord();
522 if(!pEntry
[i
]->getReplacementText().isEmpty())
524 aStr
+= "\t" + pEntry
[i
]->getReplacementText();
526 aSortedDicEntries
.push_back(aStr
);
529 IntlWrapper
aIntlWrapper(SvtSysLocale().GetUILanguageTag());
530 const CollatorWrapper
* pCollator
= aIntlWrapper
.getCollator();
531 std::sort(aSortedDicEntries
.begin(), aSortedDicEntries
.end(),
532 [&] (OUString
const & lhs
, OUString
const & rhs
)
534 sal_Int32 nCmpRes
= pCollator
->
535 compareString( getNormDicEntry_Impl(lhs
), getNormDicEntry_Impl( rhs
) );
539 m_pWordsLB
->freeze(); // speed up insert
541 for (OUString
const & rStr
: aSortedDicEntries
)
543 m_pWordsLB
->append_text(rStr
.getToken(0, '\t'));
544 if (m_pWordsLB
== m_xDoubleColumnLB
.get())
546 OUString sReplace
= rStr
.getToken(1, '\t');
547 m_pWordsLB
->set_text(nRow
, sReplace
, 1);
553 if (m_pWordsLB
->n_children())
555 m_pWordsLB
->select(0);
556 m_pWordsLB
->set_cursor(0);
557 SelectHdl(*m_pWordsLB
);
561 IMPL_LINK(SvxEditDictionaryDialog
, SelectHdl
, weld::TreeView
&, rBox
, void)
566 int nEntry
= rBox
.get_selected_index();
572 OUString
sTmpShort(rBox
.get_text(nEntry
, 0));
573 // without this the cursor is always at the beginning of a word, if the text
574 // is set over the ModifyHdl, although you're editing there at the moment
575 if (m_xWordED
->get_text() != sTmpShort
)
576 m_xWordED
->set_text(sTmpShort
);
577 if (&rBox
== m_xDoubleColumnLB
.get())
578 m_xReplaceED
->set_text(rBox
.get_text(nEntry
, 1));
582 bFirstSelect
= false;
584 // entries in the list box should exactly correspond to those from the
586 m_xNewReplacePB
->set_sensitive(false);
587 m_xDeletePB
->set_sensitive(nEntry
!= -1 && !IsDicReadonly_Impl());
590 IMPL_LINK(SvxEditDictionaryDialog
, NewDelButtonHdl
, weld::Button
&, rBtn
, void)
595 IMPL_LINK(SvxEditDictionaryDialog
, NewDelActionHdl
, weld::Entry
&, rDictEdit
, bool)
597 return NewDelHdl(&rDictEdit
);
600 bool SvxEditDictionaryDialog::NewDelHdl(const weld::Widget
* pBtn
)
602 if (pBtn
== m_xDeletePB
.get())
604 m_xWordED
->set_text("");
605 m_xReplaceED
->set_text("");
606 m_xDeletePB
->set_sensitive(false);
608 int nEntry
= m_pWordsLB
->get_selected_index();
609 RemoveDictEntry(nEntry
); // remove entry from dic and list-box
611 if (pBtn
== m_xNewReplacePB
.get() || m_xNewReplacePB
->get_sensitive())
613 int nEntry
= m_pWordsLB
->get_selected_index();
614 OUString
aNewWord(fixSpace(m_xWordED
->get_text()));
615 OUString
sEntry(aNewWord
);
616 OUString
aReplaceStr(fixSpace(m_xReplaceED
->get_text()));
618 DictionaryError nAddRes
= DictionaryError::UNKNOWN
;
619 int nPos
= m_xAllDictsLB
->get_active();
620 if (nPos
!= -1 && !aNewWord
.isEmpty())
622 DBG_ASSERT(nPos
< aDics
.getLength(), "invalid dictionary index");
623 Reference
< XDictionary
> const & xDic
= aDics
[ nPos
];
626 // make changes in dic
628 bool bIsNegEntry
= xDic
->getDictionaryType() == DictionaryType_NEGATIVE
;
631 if(!aReplaceStr
.isEmpty())
632 aRplcText
= aReplaceStr
;
634 if (nEntry
!= -1) // entry selected in m_pWordsLB ie action = modify entry
635 xDic
->remove(m_pWordsLB
->get_text(nEntry
, 0));
636 // if remove has failed the following add should fail too
637 // and thus a warning message should be triggered...
639 nAddRes
= linguistic::AddEntryToDic( xDic
,
640 aNewWord
, bIsNegEntry
,
644 if (DictionaryError::NONE
!= nAddRes
)
645 SvxDicError(m_xDialog
.get(), nAddRes
);
647 if (DictionaryError::NONE
== nAddRes
&& !sEntry
.isEmpty())
649 // insert new entry in list-box etc...
650 m_pWordsLB
->freeze();
652 if (nEntry
!= -1) // entry selected in m_pWordsLB ie action = modify entry
654 m_pWordsLB
->set_text(nEntry
, sEntry
);
655 if (!aReplaceStr
.isEmpty())
656 m_pWordsLB
->set_text(nEntry
, aReplaceStr
, 1);
660 nEntry
= GetLBInsertPos(aNewWord
);
661 m_pWordsLB
->insert_text(nEntry
, sEntry
);
662 if(!aReplaceStr
.isEmpty())
663 m_pWordsLB
->set_text(nEntry
, aReplaceStr
, 1);
667 m_pWordsLB
->scroll_to_row(nEntry
);
669 // if the request came from the ReplaceEdit, give focus to the ShortEdit
670 if (m_xReplaceED
->has_focus())
671 m_xWordED
->grab_focus();
676 // this can only be an enter in one of the two edit fields
677 // which means EndDialog() - has to be evaluated in KeyInput
680 ModifyHdl(*m_xWordED
);
684 IMPL_LINK(SvxEditDictionaryDialog
, ModifyHdl
, weld::Entry
&, rEdt
, void)
686 OUString rEntry
= rEdt
.get_text();
688 sal_Int32 nWordLen
= rEntry
.getLength();
689 const OUString
& rRepString
= fixSpace(m_xReplaceED
->get_text());
691 bool bEnableNewReplace
= false;
692 bool bEnableDelete
= false;
693 OUString aNewReplaceText
= sNew
;
695 if (&rEdt
== m_xWordED
.get())
700 bool bTmpSelEntry
=false;
701 CDE_RESULT eCmpRes
= CDE_DIFFERENT
;
703 bool bDoubleColumn
= m_pWordsLB
== m_xDoubleColumnLB
.get();
705 for (int i
= 0, nCount
= m_pWordsLB
->n_children(); i
< nCount
; ++i
)
707 OUString
aTestStr(m_pWordsLB
->get_text(i
, 0));
708 eCmpRes
= cmpDicEntry_Impl( rEntry
, aTestStr
);
709 if(CDE_DIFFERENT
!= eCmpRes
)
711 if(!rRepString
.isEmpty())
714 m_pWordsLB
->set_cursor(i
);
717 m_xReplaceED
->set_text(m_pWordsLB
->get_text(i
, 1));
719 if (CDE_SIMILAR
== eCmpRes
)
721 aNewReplaceText
= sModify
;
722 bEnableNewReplace
= true;
727 else if(getNormDicEntry_Impl(aTestStr
).indexOf(
728 getNormDicEntry_Impl( rEntry
) ) == 0
732 m_pWordsLB
->scroll_to_row(i
);
736 aNewReplaceText
= sNew
;
737 bEnableNewReplace
= true;
743 m_pWordsLB
->unselect_all();
744 aNewReplaceText
= sNew
;
745 bEnableNewReplace
= true;
747 bEnableDelete
= CDE_DIFFERENT
!= eCmpRes
;
749 else if (m_pWordsLB
->n_children() > 0)
752 m_pWordsLB
->scroll_to_row(0);
756 else if(&rEdt
== m_xReplaceED
.get())
758 OUString aReplaceText
;
760 int nFirstSel
= m_pWordsLB
->get_selected_index();
761 if (nFirstSel
!= -1) // a m_pWordsLB entry is selected
763 aWordText
= m_pWordsLB
->get_text(nFirstSel
, 0);
764 aReplaceText
= m_pWordsLB
->get_text(nFirstSel
, 1);
766 aNewReplaceText
= sModify
;
767 bEnableDelete
= true;
770 CDE_EQUAL
!= cmpDicEntry_Impl(fixSpace(m_xWordED
->get_text()), aWordText
)
771 || CDE_EQUAL
!= cmpDicEntry_Impl(fixSpace(m_xReplaceED
->get_text()), aReplaceText
);
772 if (!fixSpace(m_xWordED
->get_text()).isEmpty() && bIsChange
)
773 bEnableNewReplace
= true;
776 m_xNewReplacePB
->set_label(aNewReplaceText
);
777 m_xNewReplacePB
->set_sensitive(bEnableNewReplace
&& !IsDicReadonly_Impl());
778 m_xDeletePB
->set_sensitive(bEnableDelete
&& !IsDicReadonly_Impl());
781 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */