xref: /trunk/main/cui/source/options/optdict.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cui.hxx"
30 
31 // include ---------------------------------------------------------------
32 #include <tools/shl.hxx>
33 #include <editeng/unolingu.hxx>
34 #include <svx/dlgutil.hxx>
35 #include <sfx2/sfxuno.hxx>
36 #include <svl/eitem.hxx>
37 #include <com/sun/star/frame/XStorable.hpp>
38 #include <comphelper/processfactory.hxx>
39 #include <unotools/intlwrapper.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/msgbox.hxx>
42 #include <svx/dialogs.hrc>
43 
44 #define _SVX_OPTDICT_CXX
45 
46 #include <linguistic/misc.hxx>
47 #include <cuires.hrc>
48 #include "optdict.hrc"
49 #include "optdict.hxx"
50 #include <dialmgr.hxx>
51 #include <svx/svxerr.hxx>
52 
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::linguistic2;
56 
57 // static ----------------------------------------------------------------
58 
59 static const sal_uInt16 nNameLen    = 8;
60 static const short  NOACTDICT   = -1;
61 
62 static long nStaticTabs[]=
63 {
64     2,10,71,120
65 };
66 
67 // static function -------------------------------------------------------
68 
69 static String getNormDicEntry_Impl( const String &rText )
70 {
71     String aTmp( rText );
72     aTmp.EraseTrailingChars( '.' );
73     aTmp.EraseAllChars( '=' );
74     return aTmp;
75 }
76 
77 
78 // Compare Dictionary Entry  result
79 enum CDE_RESULT { CDE_EQUAL, CDE_SIMILAR, CDE_DIFFERENT };
80 
81 static CDE_RESULT cmpDicEntry_Impl( const String &rText1, const String &rText2 )
82 {
83     CDE_RESULT eRes = CDE_DIFFERENT;
84 
85     if (rText1 == rText2)
86         eRes = CDE_EQUAL;
87     else
88     {   // similar = equal up to trailing '.' and hyphenation positions
89         // marked with '='
90         if (getNormDicEntry_Impl( rText1 ) == getNormDicEntry_Impl( rText2 ))
91             eRes = CDE_SIMILAR;
92     }
93 
94     return eRes;
95 }
96 
97 // class SvxNewDictionaryDialog -------------------------------------------
98 
99 SvxNewDictionaryDialog::SvxNewDictionaryDialog( Window* pParent,
100         Reference< XSpellChecker1 >  &xSpl ) :
101 
102     ModalDialog( pParent, CUI_RES( RID_SFXDLG_NEWDICT ) ),
103 
104     aNewDictBox     ( this, CUI_RES( GB_NEWDICT ) ),
105     aNameText       ( this, CUI_RES( FT_DICTNAME ) ),
106     aNameEdit       ( this, CUI_RES( ED_DICTNAME ) ),
107     aLanguageText   ( this, CUI_RES( FT_DICTLANG ) ),
108     aLanguageLB     ( this, CUI_RES( LB_DICTLANG ) ),
109     aExceptBtn      ( this, CUI_RES( BTN_EXCEPT ) ),
110     aOKBtn          ( this, CUI_RES( BTN_NEWDICT_OK ) ),
111     aCancelBtn      ( this, CUI_RES( BTN_NEWDICT_ESC ) ),
112     aHelpBtn        ( this, CUI_RES( BTN_NEWDICT_HLP ) ),
113     xSpell( xSpl )
114 {
115     // Handler installieren
116     aNameEdit.SetModifyHdl(
117         LINK( this, SvxNewDictionaryDialog, ModifyHdl_Impl ) );
118     aOKBtn.SetClickHdl( LINK( this, SvxNewDictionaryDialog, OKHdl_Impl ) );
119 
120     // Sprachen anzeigen
121     aLanguageLB.SetLanguageList( LANG_LIST_ALL, sal_True, sal_True );
122     aLanguageLB.SelectEntryPos(0);
123 
124     aNameText.SetAccessibleRelationMemberOf( &aNewDictBox );
125     aNameEdit.SetAccessibleRelationMemberOf( &aNewDictBox );
126     aLanguageText.SetAccessibleRelationMemberOf( &aNewDictBox );
127     aLanguageLB.SetAccessibleRelationMemberOf( &aNewDictBox );
128 
129     FreeResource();
130 }
131 
132 // -----------------------------------------------------------------------
133 
134 IMPL_LINK( SvxNewDictionaryDialog, OKHdl_Impl, Button *, EMPTYARG )
135 {
136     String sDict = aNameEdit.GetText();
137     sDict.EraseTrailingChars();
138     // add extension for personal dictionaries
139     sDict.AppendAscii(".dic");
140 
141     Reference< XDictionaryList >  xDicList( SvxGetDictionaryList() );
142 
143     Sequence< Reference< XDictionary >  > aDics;
144     if (xDicList.is())
145         aDics = xDicList->getDictionaries();
146     const Reference< XDictionary >  *pDic = aDics.getConstArray();
147     sal_Int32 nCount = (sal_uInt16) aDics.getLength();
148 
149     sal_Bool bFound = sal_False;
150     sal_uInt16 i;
151     for (i = 0; !bFound && i < nCount; ++i )
152         if ( sDict.EqualsIgnoreCaseAscii( String(pDic[i]->getName()) ))
153             bFound = sal_True;
154 
155     if ( bFound )
156     {
157         // Doppelte Namen?
158         InfoBox( this, CUI_RESSTR( RID_SVXSTR_OPT_DOUBLE_DICTS ) ).Execute();
159         aNameEdit.GrabFocus();
160         return 0;
161     }
162 
163     // Erzeugen und hinzufuegen
164     sal_uInt16 nLang = aLanguageLB.GetSelectLanguage();
165     try
166     {
167         // create new dictionary
168         DictionaryType eType = aExceptBtn.IsChecked() ?
169                 DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
170         if (xDicList.is())
171         {
172             lang::Locale aLocale( SvxCreateLocale(nLang) );
173             String aURL( linguistic::GetWritableDictionaryURL( sDict ) );
174             xNewDic = Reference< XDictionary > (
175                     xDicList->createDictionary( sDict, aLocale, eType, aURL ) , UNO_QUERY );
176             xNewDic->setActive( sal_True );
177         }
178         DBG_ASSERT(xNewDic.is(), "NULL pointer");
179     }
180     catch(...)
181     {
182         xNewDic = NULL;
183 
184         // Fehler: konnte neues W"orterbuch nicht anlegen
185         SfxErrorContext aContext( ERRCTX_SVX_LINGU_DICTIONARY, String(),
186             this, RID_SVXERRCTX, &CUI_MGR() );
187         ErrorHandler::HandleError( *new StringErrorInfo(
188                 ERRCODE_SVX_LINGU_DICT_NOTWRITEABLE, sDict ) );
189 
190         EndDialog( RET_CANCEL );
191     }
192 
193     if (xDicList.is() && xNewDic.is())
194     {
195         xDicList->addDictionary( Reference< XDictionary > ( xNewDic, UNO_QUERY ) );
196 
197         // refresh list of dictionaries
198         //! dictionaries may have been added/removed elsewhere too.
199         aDics = xDicList->getDictionaries();
200     }
201     pDic = aDics.getConstArray();
202     nCount = (sal_uInt16) aDics.getLength();
203 
204 
205     EndDialog( RET_OK );
206     return 0;
207 }
208 
209 // -----------------------------------------------------------------------
210 
211 IMPL_LINK_INLINE_START( SvxNewDictionaryDialog, ModifyHdl_Impl, Edit *, EMPTYARG )
212 {
213     if ( aNameEdit.GetText().Len() )
214         aOKBtn.Enable();
215     else
216         aOKBtn.Disable();
217     return 0;
218 }
219 IMPL_LINK_INLINE_END( SvxNewDictionaryDialog, ModifyHdl_Impl, Edit *, EMPTYARG )
220 
221 //==========================================================================
222 //
223 // class SvxEditDictionaryDialog -------------------------------------------
224 //
225 //==========================================================================
226 
227 SvxEditDictionaryDialog::SvxEditDictionaryDialog(
228             Window* pParent,
229             const String& rName,
230             Reference< XSpellChecker1 >  &xSpl ) :
231 
232     ModalDialog( pParent, CUI_RES( RID_SFXDLG_EDITDICT ) ),
233 
234     aBookFT         ( this, CUI_RES( FT_BOOK ) ),
235     aAllDictsLB     ( this, CUI_RES( LB_ALLDICTS ) ),
236     aLangFT         ( this, CUI_RES( FT_DICTLANG ) ),
237     aLangLB         ( this, CUI_RES( LB_DICTLANG ) ),
238 
239     aWordFT         ( this, CUI_RES( FT_WORD ) ),
240     aWordED         ( this, CUI_RES( ED_WORD ) ),
241     aReplaceFT      ( this, CUI_RES( FT_REPLACE ) ),
242     aReplaceED      ( this, CUI_RES( ED_REPLACE ) ),
243     aWordsLB        ( this, CUI_RES( TLB_REPLACE ) ),
244     aNewReplacePB   ( this, CUI_RES( PB_NEW_REPLACE ) ),
245     aDeletePB       ( this, CUI_RES( PB_DELETE_REPLACE ) ),
246     aEditDictsBox   ( this, CUI_RES( GB_EDITDICTS ) ),
247     aHelpBtn        ( this, CUI_RES( BTN_EDITHELP ) ),
248     aCloseBtn       ( this, CUI_RES( BTN_EDITCLOSE ) ),
249     sModify         (CUI_RES(STR_MODIFY)),
250     sNew            (aNewReplacePB.GetText()),
251     aDecoView       ( this),
252     xSpell          ( xSpl ),
253     nOld            ( NOACTDICT ),
254     bFirstSelect    (sal_True),
255     bDoNothing      (sal_False)
256 
257 {
258     if (SvxGetDictionaryList().is())
259         aDics = SvxGetDictionaryList()->getDictionaries();
260 
261     aWordsLB.SetSelectHdl(LINK(this, SvxEditDictionaryDialog, SelectHdl));
262     aWordsLB.SetTabs(nStaticTabs);
263 
264     //! we use an algorithm of our own to insert elements sorted
265     aWordsLB.SetStyle(aWordsLB.GetStyle()|/*WB_SORT|*/WB_HSCROLL|WB_CLIPCHILDREN);
266 
267 
268     nWidth=aWordED.GetSizePixel().Width();
269     // Handler installieren
270     aNewReplacePB.SetClickHdl(
271         LINK( this, SvxEditDictionaryDialog, NewDelHdl));
272     aDeletePB.SetClickHdl(
273         LINK( this, SvxEditDictionaryDialog, NewDelHdl));
274 
275     aLangLB.SetSelectHdl(
276         LINK( this, SvxEditDictionaryDialog, SelectLangHdl_Impl ) );
277     aAllDictsLB.SetSelectHdl(
278         LINK( this, SvxEditDictionaryDialog, SelectBookHdl_Impl ) );
279 
280     aWordED.SetModifyHdl(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
281     aReplaceED.SetModifyHdl(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
282     aWordED.SetActionHdl(LINK(this, SvxEditDictionaryDialog, NewDelHdl));
283     aReplaceED.SetActionHdl(LINK(this, SvxEditDictionaryDialog, NewDelHdl));
284 
285     // Listbox mit allen verfuegbaren WB's fuellen
286     const Reference< XDictionary >  *pDic = aDics.getConstArray();
287     sal_Int32 nCount = aDics.getLength();
288 
289     String aLookUpEntry;
290     for ( sal_Int32 i = 0; i < nCount; ++i )
291     {
292         Reference< XDictionary >  xDic( pDic[i], UNO_QUERY );
293         if (xDic.is())
294         {
295             sal_Bool bNegative = xDic->getDictionaryType() == DictionaryType_NEGATIVE ?
296                                 sal_True : sal_False;
297             String aDicName( xDic->getName() );
298             const String aTxt( ::GetDicInfoStr( aDicName, SvxLocaleToLanguage( xDic->getLocale() ),
299                                                  bNegative ) );
300             aAllDictsLB.InsertEntry( aTxt );
301 
302             if (rName == aDicName)
303                 aLookUpEntry = aTxt;
304         }
305     }
306 
307     aLangLB.SetLanguageList( LANG_LIST_ALL, sal_True, sal_True );
308 
309     aReplaceED.SetSpaces(sal_True);
310     aWordED.SetSpaces(sal_True);
311 
312     if ( nCount > 0 )
313     {
314         aAllDictsLB.SelectEntry( aLookUpEntry );
315         sal_uInt16 nPos = aAllDictsLB.GetSelectEntryPos();
316 
317         if ( nPos == LISTBOX_ENTRY_NOTFOUND )
318         {
319             nPos = 0;
320             aAllDictsLB.SelectEntryPos( nPos );
321         }
322         Reference< XDictionary >  xDic;
323         if (nPos != LISTBOX_ENTRY_NOTFOUND)
324             xDic = Reference< XDictionary > ( aDics.getConstArray()[ nPos ], UNO_QUERY );
325         if (xDic.is())
326             SetLanguage_Impl( SvxLocaleToLanguage( xDic->getLocale() ) );
327 
328         // check if dictionary is read-only
329         SetDicReadonly_Impl(xDic);
330         sal_Bool bEnable = !IsDicReadonly_Impl();
331         aNewReplacePB   .Enable( sal_False );
332         aDeletePB       .Enable( sal_False );
333         aLangFT.Enable( bEnable );
334         aLangLB.Enable( bEnable );
335         ShowWords_Impl( nPos );
336 
337     }
338     else
339     {
340         aNewReplacePB.Disable();
341         aDeletePB    .Disable();
342     }
343     FreeResource();
344 }
345 
346 // -----------------------------------------------------------------------
347 
348 SvxEditDictionaryDialog::~SvxEditDictionaryDialog()
349 {
350 }
351 
352 // -----------------------------------------------------------------------
353 
354 void SvxEditDictionaryDialog::Paint( const Rectangle& rRect )
355 {
356     ModalDialog::Paint(rRect );
357 
358     Rectangle aRect(aEditDictsBox.GetPosPixel(),aEditDictsBox.GetSizePixel());
359 
360     sal_uInt16 nStyle=BUTTON_DRAW_NOFILL;
361     aDecoView.DrawButton( aRect, nStyle);
362 }
363 
364 // -----------------------------------------------------------------------
365 
366 void SvxEditDictionaryDialog::SetDicReadonly_Impl(
367             Reference< XDictionary >  &xDic )
368 {
369     // enable or disable new and delete button according to file attributes
370     bDicIsReadonly = sal_True;
371     if (xDic.is())
372     {
373         Reference< frame::XStorable >  xStor( xDic, UNO_QUERY );
374         if (   !xStor.is()              // non persistent dictionary
375             || !xStor->hasLocation()    // not yet persistent
376             || !xStor->isReadonly() )
377         {
378             bDicIsReadonly = sal_False;
379         }
380     }
381 }
382 
383 // -----------------------------------------------------------------------
384 
385 void SvxEditDictionaryDialog::SetLanguage_Impl( util::Language nLanguage )
386 {
387     // select language
388     aLangLB.SelectLanguage( nLanguage );
389 }
390 
391 sal_uInt16 SvxEditDictionaryDialog::GetLBInsertPos(const String &rDicWord)
392 {
393     sal_uInt16 nPos = USHRT_MAX;
394 
395     IntlWrapper aIntlWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() );
396     const CollatorWrapper* pCollator = aIntlWrapper.getCollator();
397     sal_uInt16 j;
398     for( j = 0; j < aWordsLB.GetEntryCount(); j++ )
399     {
400         SvLBoxEntry* pEntry = aWordsLB.GetEntry(j);
401         DBG_ASSERT( pEntry, "NULL pointer");
402         String aNormEntry( getNormDicEntry_Impl( rDicWord ) );
403         StringCompare eCmpRes = (StringCompare)pCollator->
404             compareString( aNormEntry, getNormDicEntry_Impl( aWordsLB.GetEntryText(pEntry, 0) ) );
405         if( COMPARE_LESS == eCmpRes )
406             break;
407     }
408     if (j < aWordsLB.GetEntryCount())   // entry found?
409         nPos = j;
410 
411     return nPos;
412 }
413 
414 void SvxEditDictionaryDialog::RemoveDictEntry(SvLBoxEntry* pEntry)
415 {
416     sal_uInt16 nLBPos = aAllDictsLB.GetSelectEntryPos();
417 
418     if ( pEntry != NULL && nLBPos != LISTBOX_ENTRY_NOTFOUND )
419     {
420         String sTmpShort(aWordsLB.GetEntryText(pEntry, 0));
421 
422         Reference< XDictionary >  xDic = aDics.getConstArray()[ nLBPos ];
423         if (xDic->remove( sTmpShort ))  // sal_True on success
424         {
425             aWordsLB.GetModel()->Remove(pEntry);
426         }
427     }
428 }
429 
430 // -----------------------------------------------------------------------
431 
432 IMPL_LINK( SvxEditDictionaryDialog, SelectBookHdl_Impl, ListBox *, EMPTYARG )
433 {
434     sal_uInt16 nPos = aAllDictsLB.GetSelectEntryPos();
435 
436     if ( nPos != LISTBOX_ENTRY_NOTFOUND )
437     {
438         aNewReplacePB.Enable( sal_False );
439         aDeletePB    .Enable( sal_False );
440         // Dictionary anzeigen
441         ShowWords_Impl( nPos );
442         // enable or disable new and delete button according to file attributes
443         Reference< XDictionary >  xDic( aDics.getConstArray()[ nPos ], UNO_QUERY );
444         if (xDic.is())
445             SetLanguage_Impl( SvxLocaleToLanguage( xDic->getLocale() ) );
446 
447         SetDicReadonly_Impl(xDic);
448         sal_Bool bEnable = !IsDicReadonly_Impl();
449         aLangFT.Enable( bEnable );
450         aLangLB.Enable( bEnable );
451     }
452     return 0;
453 }
454 
455 // -----------------------------------------------------------------------
456 
457 IMPL_LINK( SvxEditDictionaryDialog, SelectLangHdl_Impl, ListBox *, EMPTYARG )
458 {
459     sal_uInt16 nDicPos = aAllDictsLB.GetSelectEntryPos();
460     sal_uInt16 nLang = aLangLB.GetSelectLanguage();
461     Reference< XDictionary >  xDic( aDics.getConstArray()[ nDicPos ], UNO_QUERY );
462     sal_Int16 nOldLang = SvxLocaleToLanguage( xDic->getLocale() );
463 
464     if ( nLang != nOldLang )
465     {
466         QueryBox aBox( this, CUI_RES( RID_SFXQB_SET_LANGUAGE ) );
467         String sTxt( aBox.GetMessText() );
468         sTxt.SearchAndReplaceAscii( "%1", aAllDictsLB.GetSelectEntry() );
469         aBox.SetMessText( sTxt );
470 
471         if ( aBox.Execute() == RET_YES )
472         {
473             xDic->setLocale( SvxCreateLocale( nLang ) );
474             sal_Bool bNegativ = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
475 
476             const String sName(
477                 ::GetDicInfoStr( xDic->getName(),
478                                  SvxLocaleToLanguage( xDic->getLocale() ),
479                                  bNegativ ) );
480             aAllDictsLB.RemoveEntry( nDicPos );
481             aAllDictsLB.InsertEntry( sName, nDicPos );
482             aAllDictsLB.SelectEntryPos( nDicPos );
483         }
484         else
485             SetLanguage_Impl( nOldLang );
486     }
487     return 1;
488 }
489 
490 // -----------------------------------------------------------------------
491 
492 void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId )
493 {
494     Reference< XDictionary >  xDic = aDics.getConstArray()[ nId ];
495 
496     nOld = nId;
497     EnterWait();
498 
499     String aStr;
500 
501     aWordED.SetText(aStr);
502     aReplaceED.SetText(aStr);
503 
504     if(xDic->getDictionaryType() != DictionaryType_POSITIVE)
505     {
506         nStaticTabs[0]=2;
507 
508         // make controls for replacement text active
509         if(!aReplaceFT.IsVisible())
510         {
511             Size aSize=aWordED.GetSizePixel();
512             aSize.Width()=nWidth;
513             aWordED.SetSizePixel(aSize);
514             aReplaceFT.Show();
515             aReplaceED.Show();
516         }
517     }
518     else
519     {
520         nStaticTabs[0]=1;
521 
522         // deactivate controls for replacement text
523         if(aReplaceFT.IsVisible())
524         {
525             Size aSize=aWordED.GetSizePixel();
526             aSize.Width()=aWordsLB.GetSizePixel().Width();
527             aWordED.SetSizePixel(aSize);
528             aReplaceFT.Hide();
529             aReplaceED.Hide();
530         }
531 
532     }
533 
534     aWordsLB.SetTabs(nStaticTabs);
535     aWordsLB.Clear();
536 
537     Sequence< Reference< XDictionaryEntry >  > aEntries( xDic->getEntries() );
538     const Reference< XDictionaryEntry >  *pEntry = aEntries.getConstArray();
539     sal_Int32 nCount = aEntries.getLength();
540 
541     for (sal_Int32 i = 0;  i < nCount;  i++)
542     {
543         aStr = String(pEntry[i]->getDictionaryWord());
544         sal_uInt16 nPos = GetLBInsertPos( aStr );
545         if(pEntry[i]->isNegative())
546         {
547             aStr += '\t';
548             aStr += String(pEntry[i]->getReplacementText());
549         }
550         aWordsLB.InsertEntry(aStr, 0, sal_False, nPos == USHRT_MAX ?  LIST_APPEND : nPos);
551     }
552 
553     if (aWordsLB.GetEntryCount())
554     {
555         aWordED   .SetText( aWordsLB.GetEntryText(0LU, 0) );
556         aReplaceED.SetText( aWordsLB.GetEntryText(0LU, 1) );
557     }
558 
559     LeaveWait();
560 }
561 
562 // -----------------------------------------------------------------------
563 
564 IMPL_LINK(SvxEditDictionaryDialog, SelectHdl, SvTabListBox*, pBox)
565 {
566     if(!bDoNothing)
567     {
568         if(!bFirstSelect)
569         {
570             SvLBoxEntry* pEntry = pBox->FirstSelected();
571             String sTmpShort(pBox->GetEntryText(pEntry, 0));
572             // wird der Text ueber den ModifyHdl gesetzt, dann steht der Cursor
573             //sonst immer am Wortanfang, obwohl man gerade hier editiert
574             if(aWordED.GetText() != sTmpShort)
575                 aWordED.SetText(sTmpShort);
576             aReplaceED.SetText(pBox->GetEntryText(pEntry, 1));
577         }
578         else
579             bFirstSelect = sal_False;
580 
581         // entries in the list box should exactly correspond to those from the
582         // dictionary. Thus:
583         aNewReplacePB.Enable(sal_False);
584         aDeletePB    .Enable( sal_True && !IsDicReadonly_Impl() );
585     }
586     return 0;
587 };
588 
589 // -----------------------------------------------------------------------
590 
591 IMPL_LINK(SvxEditDictionaryDialog, NewDelHdl, PushButton*, pBtn)
592 {
593     SvLBoxEntry* pEntry = aWordsLB.FirstSelected();
594 
595     if(pBtn == &aDeletePB)
596     {
597         DBG_ASSERT(pEntry, "keine Eintrag selektiert");
598         String aStr;
599 
600         aWordED.SetText(aStr);
601         aReplaceED.SetText(aStr);
602         aDeletePB.Disable();
603 
604         RemoveDictEntry(pEntry);    // remove entry from dic and list-box
605     }
606     if(pBtn == &aNewReplacePB || aNewReplacePB.IsEnabled())
607     {
608         SvLBoxEntry* _pEntry = aWordsLB.FirstSelected();
609         XubString aNewWord(aWordED.GetText());
610         String sEntry(aNewWord);
611         XubString aReplaceStr(aReplaceED.GetText());
612 
613         sal_Int16 nAddRes = DIC_ERR_UNKNOWN;
614         sal_uInt16 nPos = aAllDictsLB.GetSelectEntryPos();
615         if ( nPos != LISTBOX_ENTRY_NOTFOUND && aNewWord.Len() > 0)
616         {
617             DBG_ASSERT(nPos < aDics.getLength(), "invalid dictionary index");
618             Reference< XDictionary >  xDic( aDics.getConstArray()[ nPos ], UNO_QUERY );
619             if (xDic.is())
620             {
621                 // make changes in dic
622 
623                 //! ...IsVisible should reflect wether the dictionary is a negativ
624                 //! or not (hopefully...)
625                 sal_Bool bIsNegEntry = aReplaceFT.IsVisible();
626                 ::rtl::OUString aRplcText;
627                 if(bIsNegEntry)
628                     aRplcText = aReplaceStr;
629 
630                 if (_pEntry) // entry selected in aWordsLB ie action = modify entry
631                     xDic->remove( aWordsLB.GetEntryText( _pEntry, 0 ) );
632                 // if remove has failed the following add should fail too
633                 // and thus a warning message should be triggered...
634 
635                 Reference<XDictionary> aXDictionary(xDic, UNO_QUERY);
636                 nAddRes = linguistic::AddEntryToDic( aXDictionary,
637                             aNewWord, bIsNegEntry,
638                             aRplcText, SvxLocaleToLanguage( xDic->getLocale() ), sal_False );
639             }
640         }
641         if (DIC_ERR_NONE != nAddRes)
642             SvxDicError( this, nAddRes );
643 
644         if(DIC_ERR_NONE == nAddRes && sEntry.Len())
645         {
646             // insert new entry in list-box etc...
647 
648             aWordsLB.SetUpdateMode(sal_False);
649             sal_uInt16 _nPos = USHRT_MAX;
650 
651             if(aReplaceFT.IsVisible())
652             {
653                 sEntry += '\t';
654                 sEntry += aReplaceStr;
655             }
656 
657             SvLBoxEntry* pNewEntry = NULL;
658             if(_pEntry) // entry selected in aWordsLB ie action = modify entry
659             {
660                 aWordsLB.SetEntryText( sEntry, _pEntry );
661                 pNewEntry = _pEntry;
662             }
663             else
664             {
665                 _nPos = GetLBInsertPos( aNewWord );
666                 SvLBoxEntry* pInsEntry = aWordsLB.InsertEntry(sEntry, 0, sal_False,
667                             _nPos == USHRT_MAX ? LIST_APPEND : (sal_uInt32)_nPos);
668                 pNewEntry = pInsEntry;
669             }
670 
671             aWordsLB.MakeVisible( pNewEntry );
672             aWordsLB.SetUpdateMode(sal_True);
673             // falls der Request aus dem ReplaceEdit kam, dann Focus in das ShortEdit setzen
674             if(aReplaceED.HasFocus())
675                 aWordED.GrabFocus();
676         }
677     }
678     else
679     {
680         // das kann nur ein Enter in einem der beiden Edit-Felder sein und das
681         // bedeutet EndDialog() - muss im KeyInput ausgewertet werden
682         return 0;
683     }
684     ModifyHdl(&aWordED);
685     return 1;
686 }
687 
688 // -----------------------------------------------------------------------
689 
690 IMPL_LINK(SvxEditDictionaryDialog, ModifyHdl, Edit*, pEdt)
691 {
692     SvLBoxEntry* pFirstSel = aWordsLB.FirstSelected();
693     String rEntry = pEdt->GetText();
694 
695     xub_StrLen nWordLen=rEntry.Len();
696     const String& rRepString = aReplaceED.GetText();
697 
698     sal_Bool bEnableNewReplace  = sal_False;
699     sal_Bool bEnableDelete      = sal_False;
700     String aNewReplaceText  = sNew;
701 
702     if(pEdt == &aWordED)
703     {
704         if(nWordLen>0)
705         {
706             sal_Bool bFound = sal_False;
707             sal_Bool bTmpSelEntry=sal_False;
708             CDE_RESULT eCmpRes = CDE_DIFFERENT;
709 
710             for(sal_uInt16 i = 0; i < aWordsLB.GetEntryCount(); i++)
711             {
712                 SvLBoxEntry*  pEntry = aWordsLB.GetEntry( i );
713                 String aTestStr( aWordsLB.GetEntryText(pEntry, 0) );
714                 eCmpRes = cmpDicEntry_Impl( rEntry, aTestStr );
715                 if(CDE_DIFFERENT != eCmpRes)
716                 {
717                     if(rRepString.Len())
718                         bFirstSelect = sal_True;
719                     bDoNothing=sal_True;
720                     aWordsLB.SetCurEntry(pEntry);
721                     bDoNothing=sal_False;
722                     pFirstSel = pEntry;
723                     aReplaceED.SetText(aWordsLB.GetEntryText(pEntry, 1));
724 
725                     if (CDE_SIMILAR == eCmpRes)
726                     {
727                         aNewReplaceText = sModify;
728                         bEnableNewReplace = sal_True;
729                     }
730                     bFound= sal_True;
731                     break;
732                 }
733                 else if(getNormDicEntry_Impl(aTestStr).Search(
734                             getNormDicEntry_Impl( rEntry ) ) == 0
735                         && !bTmpSelEntry)
736                 {
737                     bDoNothing=sal_True;
738                     aWordsLB.MakeVisible(pEntry);
739                     bDoNothing=sal_False;
740                     bTmpSelEntry=sal_True;
741 
742                     aNewReplaceText = sNew;
743                     bEnableNewReplace = sal_True;
744                 }
745             }
746 
747             if(!bFound)
748             {
749                 aWordsLB.SelectAll(sal_False);
750                 pFirstSel = 0;
751 
752                 aNewReplaceText = sNew;
753                 bEnableNewReplace = sal_True;
754             }
755             bEnableDelete = CDE_DIFFERENT != eCmpRes;
756         }
757         else if(aWordsLB.GetEntryCount()>0)
758         {
759             SvLBoxEntry*  pEntry = aWordsLB.GetEntry( 0 );
760             bDoNothing=sal_True;
761             aWordsLB.MakeVisible(pEntry);
762             bDoNothing=sal_False;
763         }
764     }
765     else if(pEdt == &aReplaceED)
766     {
767         String aReplaceText;
768         String aWordText;
769         if (pFirstSel)  // a aWordsLB entry is selected
770         {
771             aWordText    = aWordsLB.GetEntryText( pFirstSel, 0 );
772             aReplaceText = aWordsLB.GetEntryText( pFirstSel, 1 );
773 
774             aNewReplaceText = sModify;
775             bEnableDelete = sal_True;
776         }
777         sal_Bool bIsChange =
778                 CDE_EQUAL != cmpDicEntry_Impl(aWordED.GetText(), aWordText)
779              || CDE_EQUAL != cmpDicEntry_Impl(aReplaceED.GetText(), aReplaceText);
780         if (aWordED.GetText().Len()  &&  bIsChange)
781             bEnableNewReplace = sal_True;
782     }
783 
784     aNewReplacePB.SetText( aNewReplaceText );
785     aNewReplacePB.Enable( bEnableNewReplace && !IsDicReadonly_Impl() );
786     aDeletePB    .Enable( bEnableDelete     && !IsDicReadonly_Impl() );
787 
788     return 0;
789 }
790 
791 //=========================================================
792 //SvxDictEdit
793 //=========================================================
794 void SvxDictEdit::KeyInput( const KeyEvent& rKEvt )
795 {
796     const KeyCode aKeyCode = rKEvt.GetKeyCode();
797     const sal_uInt16 nModifier = aKeyCode.GetModifier();
798     if( aKeyCode.GetCode() == KEY_RETURN )
799     {
800         //wird bei Enter nichts getan, dann doch die Basisklasse rufen
801         // um den Dialog zu schliessen
802         if(!nModifier && !aActionLink.Call(this))
803                  Edit::KeyInput(rKEvt);
804     }
805     else if(bSpaces || aKeyCode.GetCode() != KEY_SPACE)
806         Edit::KeyInput(rKEvt);
807 }
808 
809 
810