xref: /aoo42x/main/cui/source/options/optdict.cxx (revision cdf0e10c)
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