xref: /aoo42x/main/cui/source/options/optlingu.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 
33 #include <vcl/msgbox.hxx>
34 #include <vcl/field.hxx>
35 #include <vcl/fixed.hxx>
36 #include <tools/shl.hxx>
37 #include <tools/dynary.hxx>
38 #include <i18npool/mslangid.hxx>
39 #include <unotools/lingucfg.hxx>
40 #include <editeng/unolingu.hxx>
41 #include <svx/dlgutil.hxx>
42 #include <linguistic/lngprops.hxx>
43 #include <linguistic/misc.hxx>
44 #include <sfx2/sfxuno.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <tools/urlobj.hxx>
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <comphelper/processfactory.hxx>
49 #include <com/sun/star/linguistic2/XSpellChecker.hpp>
50 #include <com/sun/star/linguistic2/XProofreader.hpp>
51 #include <com/sun/star/linguistic2/XHyphenator.hpp>
52 #include <com/sun/star/linguistic2/XThesaurus.hpp>
53 #include <com/sun/star/linguistic2/XAvailableLocales.hpp>
54 #include <com/sun/star/lang/XServiceDisplayName.hpp>
55 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
56 #include <com/sun/star/linguistic2/DictionaryListEvent.hpp>
57 #include <com/sun/star/linguistic2/XDictionaryListEventListener.hpp>
58 #include <com/sun/star/linguistic2/XDictionaryList.hpp>
59 #include <com/sun/star/frame/XStorable.hpp>
60 #include <com/sun/star/ucb/CommandAbortedException.hpp>
61 #include <com/sun/star/system/XSystemShellExecute.hpp>
62 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
63 #include <unotools/extendedsecurityoptions.hxx>
64 #include <svtools/svlbox.hxx>
65 #include <svl/eitem.hxx>
66 #include <svl/intitem.hxx>
67 #include <sfx2/viewfrm.hxx>
68 #include <vcl/svapp.hxx>
69 #define _SVX_OPTLINGU_CXX
70 #include "optlingu.hrc"
71 
72 #include <svx/svxdlg.hxx>
73 #include <editeng/optitems.hxx>
74 #include "optlingu.hxx"
75 #include <dialmgr.hxx>
76 #include <cuires.hrc>
77 #include "helpid.hrc"
78 
79 #include <ucbhelper/content.hxx>
80 
81 #include <vector>
82 #include <map>
83 
84 
85 using namespace ::ucbhelper;
86 using namespace ::rtl;
87 using namespace ::com::sun::star;
88 using namespace ::com::sun::star::lang;
89 using namespace ::com::sun::star::uno;
90 using namespace ::com::sun::star::linguistic2;
91 using namespace ::com::sun::star::beans;
92 namespace css = com::sun::star;
93 
94 #define C2U(cChar) OUString::createFromAscii(cChar)
95 #define SVX_MAX_USERDICTS 20
96 #define CBCOL_FIRST		0
97 #define CBCOL_SECOND	1
98 #define CBCOL_BOTH		2
99 
100 static const sal_Char cSpell[]   = SN_SPELLCHECKER;
101 static const sal_Char cGrammar[] = SN_GRAMMARCHECKER;
102 static const sal_Char cHyph[]    = SN_HYPHENATOR;
103 static const sal_Char cThes[]    = SN_THESAURUS;
104 
105 // static ----------------------------------------------------------------
106 
107 static Sequence< sal_Int16 > lcl_LocaleSeqToLangSeq( const Sequence< Locale > &rSeq )
108 {
109     sal_Int32 nLen = rSeq.getLength();
110     Sequence< sal_Int16 > aRes( nLen );
111     sal_Int16 *pRes = aRes.getArray();
112     const Locale *pSeq = rSeq.getConstArray();
113     for (sal_Int32 i = 0;  i < nLen;  ++i)
114     {
115         pRes[i] = SvxLocaleToLanguage( pSeq[i] );
116     }
117     return aRes;
118 }
119 
120 
121 static sal_Bool lcl_SeqHasLang( const Sequence< sal_Int16 > &rSeq, sal_Int16 nLang )
122 {
123     sal_Int32 nLen = rSeq.getLength();
124     const sal_Int16 *pLang = rSeq.getConstArray();
125     sal_Int32 nPos = -1;
126     for (sal_Int32 i = 0;  i < nLen  &&  nPos < 0;  ++i)
127     {
128         if (nLang == pLang[i])
129             nPos = i;
130     }
131     return nPos < 0 ? sal_False : sal_True;
132 }
133 
134 
135 static sal_Int32 lcl_SeqGetEntryPos(
136 	const Sequence< OUString > &rSeq, const OUString &rEntry )
137 {
138 	sal_Int32 i;
139 	sal_Int32 nLen = rSeq.getLength();
140 	const OUString *pItem = rSeq.getConstArray();
141 	for (i = 0;  i < nLen;  ++i)
142 	{
143 		if (rEntry == pItem[i])
144 			break;
145 	}
146     return i < nLen ? i : -1;
147 }
148 
149 static void lcl_OpenURL( const ::rtl::OUString& rURL )
150 {
151     if ( rURL.getLength() > 0 )
152     {
153         try
154         {
155             uno::Reference< lang::XMultiServiceFactory > xSMGR =
156                 ::comphelper::getProcessServiceFactory();
157             uno::Reference< css::system::XSystemShellExecute > xSystemShell(
158                 xSMGR->createInstance( ::rtl::OUString(
159                     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SystemShellExecute" ) ) ),
160                 uno::UNO_QUERY_THROW );
161             if ( xSystemShell.is() )
162                 xSystemShell->execute( rURL, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS );
163         }
164         catch( const uno::Exception& e )
165         {
166              OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
167                 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
168         }
169     }
170 }
171 
172 /*--------------------------------------------------
173 --------------------------------------------------*/
174 
175 static const sal_uInt16 nNameLen = 8;
176 
177 static sal_uInt16 pRanges[] =
178 {
179 	SID_ATTR_SPELL,
180 	SID_ATTR_SPELL,
181 	0
182 };
183 
184 sal_Bool KillFile_Impl( const String& rURL )
185 {
186 	sal_Bool bRet = sal_True;
187 	try
188 	{
189 		Content aCnt( rURL, uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
190 		aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
191 	}
192 	catch( ::com::sun::star::ucb::CommandAbortedException& )
193 	{
194 		DBG_ERRORFILE( "KillFile: CommandAbortedException" );
195 		bRet = sal_False;
196 	}
197 	catch( ... )
198 	{
199 		DBG_ERRORFILE( "KillFile: Any other exception" );
200 		bRet = sal_False;
201 	}
202 
203 	return bRet;
204 }
205 /* -----------------------------27.11.00 14:07--------------------------------
206 
207  ---------------------------------------------------------------------------*/
208 // 0x 0p 0t 0c nn
209 // p: 1 -> parent
210 // t: 1 -> spell, 2 -> hyph, 3 -> thes, 4 -> grammar
211 // c: 1 -> checked 0 -> unchecked
212 // n: index
213 
214 #define TYPE_SPELL      (sal_uInt8)1
215 #define TYPE_GRAMMAR    (sal_uInt8)2
216 #define TYPE_HYPH       (sal_uInt8)3
217 #define TYPE_THES       (sal_uInt8)4
218 
219 class ModuleUserData_Impl
220 {
221 	sal_Bool bParent;
222 	sal_Bool bIsChecked;
223 	sal_uInt8 nType;
224 	sal_uInt8 nIndex;
225 	String	sImplName;
226 
227 public:
228 	ModuleUserData_Impl( String sImpName, sal_Bool bIsParent, sal_Bool bChecked, sal_uInt8 nSetType, sal_uInt8 nSetIndex ) :
229 		bParent(bIsParent),
230 		bIsChecked(bChecked),
231 		nType(nSetType),
232 		nIndex(nSetIndex),
233 		sImplName(sImpName)
234 		{
235 		}
236 	sal_Bool IsParent() const {return bParent;}
237 	sal_uInt8 GetType() const {return nType;}
238 	sal_Bool IsChecked() const {return bIsChecked;}
239 	sal_uInt8 GetIndex() const {return nIndex;}
240 	void SetIndex(sal_uInt8 nSet)  {nIndex = nSet;}
241 	const String& GetImplName() const {return sImplName;}
242 
243 };
244 
245 /*--------------------------------------------------
246 --------------------------------------------------*/
247 //
248 // User for user-dictionaries (XDictionary interface)
249 //
250 class DicUserData
251 {
252 	sal_uLong	nVal;
253 
254 public:
255 	DicUserData( sal_uLong nUserData ) : nVal( nUserData ) {}
256 	DicUserData( sal_uInt16 nEID,
257 				 sal_Bool bChecked, sal_Bool bEditable, sal_Bool bDeletable );
258 
259 	sal_uLong	GetUserData() const			{ return nVal; }
260 	sal_uInt16	GetEntryId() const			{ return (sal_uInt16)(nVal >> 16); }
261 	sal_Bool	IsChecked() const			{ return (sal_Bool)(nVal >>  8) & 0x01; }
262 	sal_Bool	IsEditable() const			{ return (sal_Bool)(nVal >>  9) & 0x01; }
263 	sal_Bool	IsDeletable() const			{ return (sal_Bool)(nVal >> 10) & 0x01; }
264 
265 	void	SetChecked( sal_Bool bVal );
266 };
267 
268 
269 DicUserData::DicUserData(
270 		sal_uInt16 nEID,
271 		sal_Bool bChecked, sal_Bool bEditable, sal_Bool bDeletable )
272 {
273 	DBG_ASSERT( nEID < 65000, "Entry Id out of range" );
274 	nVal =  ((sal_uLong)(0xFFFF & nEID)			<< 16) |
275 			((sal_uLong)(bChecked ? 1 : 0)		<<  8) |
276 			((sal_uLong)(bEditable ? 1 : 0)		<<  9) |
277 			((sal_uLong)(bDeletable ? 1 : 0)	<< 10);
278 }
279 
280 
281 void DicUserData::SetChecked( sal_Bool bVal )
282 {
283 	nVal &= ~(1UL << 8);
284 	nVal |=  (sal_uLong)(bVal ? 1 : 0) << 8;
285 }
286 
287 
288 // class BrwString_Impl -------------------------------------------------
289 
290 void lcl_SetCheckButton( SvLBoxEntry* pEntry, sal_Bool bCheck )
291 {
292 	SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
293 
294 	DBG_ASSERT(pItem,"SetCheckButton:Item not found");
295 	if (((SvLBoxItem*)pItem)->IsA() == SV_ITEM_ID_LBOXBUTTON)
296 	{
297 		if (bCheck)
298 			pItem->SetStateChecked();
299 		else
300 			pItem->SetStateUnchecked();
301 		//InvalidateEntry( pEntry );
302 	}
303 }
304 
305 
306 class BrwStringDic_Impl : public SvLBoxString
307 {
308 public:
309 
310 	BrwStringDic_Impl( SvLBoxEntry* pEntry, sal_uInt16 nFlags,
311 		const String& rStr ) : SvLBoxString( pEntry, nFlags, rStr ) {}
312 
313 	virtual void Paint( const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags,
314 											SvLBoxEntry* pEntry);
315 };
316 
317 void BrwStringDic_Impl::Paint( const Point& rPos, SvLBox& rDev, sal_uInt16,
318 	SvLBoxEntry* pEntry )
319 {
320 	ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
321 	Point aPos(rPos);
322 	Font aOldFont( rDev.GetFont());
323 	if(pData->IsParent())
324 	{
325 		Font aFont( aOldFont );
326 		aFont.SetWeight( WEIGHT_BOLD );
327 		rDev.SetFont( aFont );
328 		aPos.X() = 0;
329 	}
330 	else
331 		aPos.X() += 5;
332 	rDev.DrawText( aPos, GetText() );
333 	rDev.SetFont( aOldFont );
334 }
335 
336 
337 /*--------------------------------------------------
338 --------------------------------------------------*/
339 
340 class OptionsBreakSet : public ModalDialog
341 {
342 	OKButton 		aOKPB;
343 	CancelButton	aCancelPB;
344     FixedLine       aValFL;
345 	NumericField	aValNF;
346 
347 public:
348 	OptionsBreakSet(Window* pParent, int nRID) :
349 			ModalDialog(pParent, CUI_RES(RID_SVXDLG_LNG_ED_NUM_PREBREAK )),
350 			aOKPB		(this, CUI_RES(BT_OK_PREBREAK)),
351 			aCancelPB	(this, CUI_RES(BT_CANCEL_PREBREAK)),
352             aValFL      (this, CUI_RES(FL_NUMVAL_PREBREAK)),
353 			aValNF		(this, CUI_RES(ED_PREBREAK))
354 	{
355 		DBG_ASSERT( STR_NUM_PRE_BREAK_DLG   == nRID	||
356 					STR_NUM_POST_BREAK_DLG  == nRID	||
357 					STR_NUM_MIN_WORDLEN_DLG == nRID, "unexpected RID" );
358 
359 		if (nRID != -1)
360             aValFL.SetText( String( CUI_RES(nRID) ) );
361 		FreeResource();
362 	}
363 
364 	NumericField& 	GetNumericFld()	{ return aValNF; }
365 };
366 
367 
368 /*--------------------------------------------------
369 	Entry IDs for options listbox of dialog
370 --------------------------------------------------*/
371 
372 enum EID_OPTIONS
373 {
374     EID_SPELL_AUTO,
375     EID_GRAMMAR_AUTO,
376 	EID_CAPITAL_WORDS,
377 	EID_WORDS_WITH_DIGITS,
378 	EID_CAPITALIZATION,
379 	EID_SPELL_SPECIAL,
380 	EID_NUM_MIN_WORDLEN,
381 	EID_NUM_PRE_BREAK,
382 	EID_NUM_POST_BREAK,
383 	EID_HYPH_AUTO,
384 	EID_HYPH_SPECIAL
385 };
386 
387 //! this array must have an entry for every value of EID_OPTIONS.
388 //  It is used to get the respective property name.
389 static const char * aEidToPropName[] =
390 {
391     UPN_IS_SPELL_AUTO,				// EID_SPELL_AUTO
392     UPN_IS_GRAMMAR_AUTO,            // EID_GRAMMAR_AUTO
393 	UPN_IS_SPELL_UPPER_CASE,		// EID_CAPITAL_WORDS
394 	UPN_IS_SPELL_WITH_DIGITS,		// EID_WORDS_WITH_DIGITS
395 	UPN_IS_SPELL_CAPITALIZATION,    // EID_CAPITALIZATION
396 	UPN_IS_SPELL_SPECIAL,			// EID_SPELL_SPECIAL
397 	UPN_HYPH_MIN_WORD_LENGTH,		// EID_NUM_MIN_WORDLEN,
398 	UPN_HYPH_MIN_LEADING,			// EID_NUM_PRE_BREAK
399 	UPN_HYPH_MIN_TRAILING,			// EID_NUM_POST_BREAK
400 	UPN_IS_HYPH_AUTO,				// EID_HYPH_AUTO
401 	UPN_IS_HYPH_SPECIAL				// EID_HYPH_SPECIAL
402 };
403 
404 
405 static inline String lcl_GetPropertyName( EID_OPTIONS eEntryId )
406 {
407 	DBG_ASSERT( (unsigned int) eEntryId < sizeof(aEidToPropName) / sizeof(aEidToPropName[0]), "index out of range" );
408 	return String::CreateFromAscii( aEidToPropName[ (int) eEntryId ] );
409 }
410 
411 // class OptionsUserData -------------------------------------------------
412 
413 class OptionsUserData
414 {
415 	sal_uLong	nVal;
416 
417 	void	SetModified();
418 
419 public:
420 	OptionsUserData( sal_uLong nUserData ) : nVal( nUserData ) {}
421 	OptionsUserData( sal_uInt16 nEID,
422 					 sal_Bool bHasNV, sal_uInt16 nNumVal,
423 					 sal_Bool bCheckable, sal_Bool bChecked );
424 
425 	sal_uLong	GetUserData() const			{ return nVal; }
426 	sal_uInt16	GetEntryId() const			{ return (sal_uInt16)(nVal >> 16); }
427 	sal_Bool	HasNumericValue() const		{ return (sal_Bool)(nVal >> 10) & 0x01; }
428 	sal_uInt16	GetNumericValue() const		{ return (sal_uInt16)(nVal & 0xFF); }
429 	sal_Bool	IsChecked() const			{ return (sal_Bool)(nVal >> 8) & 0x01; }
430 	sal_Bool	IsCheckable() const			{ return (sal_Bool)(nVal >> 9) & 0x01; }
431 	sal_Bool	IsModified() const			{ return (sal_Bool)(nVal >> 11) & 0x01; }
432 
433 	void	SetChecked( sal_Bool bVal );
434 	void	SetNumericValue( sal_uInt8 nNumVal );
435 };
436 
437 OptionsUserData::OptionsUserData( sal_uInt16 nEID,
438 		sal_Bool bHasNV, sal_uInt16 nNumVal,
439 		sal_Bool bCheckable, sal_Bool bChecked )
440 {
441 	DBG_ASSERT( nEID < 65000, "Entry Id out of range" );
442 	DBG_ASSERT( nNumVal < 256, "value out of range" );
443 	nVal =  ((sal_uLong)(0xFFFF & nEID)			<< 16) |
444 			((sal_uLong)(bHasNV ? 1 : 0)		<< 10) |
445 			((sal_uLong)(bCheckable ? 1 : 0)	<<  9) |
446 			((sal_uLong)(bChecked ? 1 : 0)		<<  8) |
447 			((sal_uLong)(0xFF & nNumVal));
448 }
449 
450 void OptionsUserData::SetChecked( sal_Bool bVal )
451 {
452 	if (IsCheckable()  &&  (IsChecked() != bVal))
453 	{
454 		nVal &= ~(1UL << 8);
455 		nVal |=  (sal_uLong)(bVal ? 1 : 0) << 8;
456 		SetModified();
457 	}
458 }
459 
460 void OptionsUserData::SetNumericValue( sal_uInt8 nNumVal )
461 {
462 //	DBG_ASSERT( nNumVal < 256, "value out of range" );
463 	if (HasNumericValue()  &&  (GetNumericValue() != nNumVal))
464 	{
465 		nVal &= 0xffffff00;
466 		nVal |= (nNumVal);
467 		SetModified();
468 	}
469 }
470 
471 void OptionsUserData::SetModified()
472 {
473 	nVal |=  (sal_uLong)1 << 11;
474 }
475 
476 // class BrwString_Impl -------------------------------------------------
477 
478 class BrwString_Impl : public SvLBoxString
479 {
480 public:
481 
482 	BrwString_Impl( SvLBoxEntry* pEntry, sal_uInt16 nFlags,
483 		const String& rStr ) : SvLBoxString( pEntry, nFlags, rStr ) {}
484 
485 	virtual void Paint( const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags,
486 											SvLBoxEntry* pEntry);
487 };
488 
489 void BrwString_Impl::Paint( const Point& rPos, SvLBox& rDev, sal_uInt16,
490 	SvLBoxEntry* pEntry )
491 {
492 	Point aPos(rPos);
493 	aPos.X() += 20;
494 	rDev.DrawText( aPos, GetText() );
495 	if(pEntry->GetUserData())
496 	{
497 		Point aNewPos(aPos);
498 		aNewPos.X() += rDev.GetTextWidth(GetText());
499 		Font aOldFont( rDev.GetFont());
500 		Font aFont( aOldFont );
501 		aFont.SetWeight( WEIGHT_BOLD );
502 
503 //		sal_Bool bFett = sal_True;
504 //		sal_uInt16 nPos = 0;
505 		//??? das untere byte aus dem user data in string wandeln
506 		OptionsUserData aData( (sal_uLong) pEntry->GetUserData() );
507 		if(aData.HasNumericValue())
508 		{
509 			String sTxt( ' ' );
510 			sTxt +=  String::CreateFromInt32( aData.GetNumericValue() );
511 			rDev.SetFont( aFont );
512 			rDev.DrawText( aNewPos, sTxt );
513 		}
514 
515 //			if( STRING_NOTFOUND != nPos )
516 //				aNewPos.X() += rDev.GetTextWidth( sTxt );
517 
518 		rDev.SetFont( aOldFont );
519 	}
520 }
521 
522 // ServiceInfo_Impl ----------------------------------------------------
523 
524 struct ServiceInfo_Impl
525 {
526 	OUString					sDisplayName;
527 	OUString					sSpellImplName;
528 	OUString					sHyphImplName;
529 	OUString					sThesImplName;
530     OUString                    sGrammarImplName;
531     uno::Reference< XSpellChecker >     xSpell;
532     uno::Reference< XHyphenator >       xHyph;
533     uno::Reference< XThesaurus >        xThes;
534     uno::Reference< XProofreader >   	xGrammar;
535 	sal_Bool						bConfigured;
536 
537     ServiceInfo_Impl() : bConfigured(sal_False) {}
538 };
539 
540 typedef std::vector< ServiceInfo_Impl >                             ServiceInfoArr;
541 typedef std::map< sal_Int16 /*LanguageType*/, Sequence< OUString > >    LangImplNameTable;
542 
543 
544 // SvxLinguData_Impl ----------------------------------------------------
545 
546 class SvxLinguData_Impl
547 {
548     //contains services and implementation names sorted by implementation names
549 	ServiceInfoArr			   			aDisplayServiceArr;
550     sal_uLong                               nDisplayServices;
551 
552     Sequence< Locale >                  aAllServiceLocales;
553     LangImplNameTable                   aCfgSpellTable;
554     LangImplNameTable                   aCfgHyphTable;
555     LangImplNameTable                   aCfgThesTable;
556     LangImplNameTable                   aCfgGrammarTable;
557     uno::Reference< XMultiServiceFactory >   xMSF;
558     uno::Reference< XLinguServiceManager >   xLinguSrvcMgr;
559 
560 
561     sal_Bool    AddRemove( Sequence< OUString > &rConfigured,
562                            const OUString &rImplName, sal_Bool bAdd );
563 
564 public:
565 	SvxLinguData_Impl();
566     SvxLinguData_Impl( const SvxLinguData_Impl &rData );
567 	~SvxLinguData_Impl();
568 
569     SvxLinguData_Impl & operator = (const SvxLinguData_Impl &rData);
570 
571     uno::Reference<XLinguServiceManager> &   GetManager() { return xLinguSrvcMgr; }
572 
573     void SetChecked( const Sequence< OUString > &rConfiguredServices );
574     void Reconfigure( const OUString &rDisplayName, sal_Bool bEnable );
575 
576     const Sequence<Locale> &    GetAllSupportedLocales() { return aAllServiceLocales; }
577 
578     const LangImplNameTable &   GetSpellTable() const   { return aCfgSpellTable; }
579     LangImplNameTable &         GetSpellTable()         { return aCfgSpellTable; }
580     const LangImplNameTable &   GetHyphTable() const    { return aCfgHyphTable; }
581     LangImplNameTable &         GetHyphTable()          { return aCfgHyphTable; }
582     const LangImplNameTable &   GetThesTable() const    { return aCfgThesTable; }
583     LangImplNameTable &         GetThesTable()          { return aCfgThesTable; }
584     const LangImplNameTable &   GetGrammarTable() const { return aCfgGrammarTable; }
585     LangImplNameTable &         GetGrammarTable()       { return aCfgGrammarTable; }
586 
587     const ServiceInfoArr &      GetDisplayServiceArray() const  { return aDisplayServiceArr; }
588     ServiceInfoArr &            GetDisplayServiceArray()        { return aDisplayServiceArr; }
589 
590     const sal_uLong &   GetDisplayServiceCount() const          { return nDisplayServices; }
591     void            SetDisplayServiceCount( sal_uLong nVal )    { nDisplayServices = nVal; }
592 
593     // returns the list of service implementation names for the specified
594     // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in
595     // the proper order for the SvxEditModulesDlg (the ones from the
596     // configuration (keeping that order!) first and then the other ones.
597     // I.e. the ones available but not configured in arbitrary order).
598     // They available ones may contain names that do not(!) support that
599     // language.
600     Sequence< OUString > GetSortedImplNames( sal_Int16 nLang, sal_uInt8 nType );
601 
602     ServiceInfo_Impl * GetInfoByImplName( const OUString &rSvcImplName );
603 };
604 
605 
606 sal_Int32 lcl_SeqGetIndex( const Sequence< OUString > &rSeq, const OUString &rTxt )
607 {
608     sal_Int32 nRes = -1;
609     sal_Int32 nLen = rSeq.getLength();
610     const OUString *pString = rSeq.getConstArray();
611     for (sal_Int32 i = 0;  i < nLen  &&  nRes == -1;  ++i)
612     {
613         if (pString[i] == rTxt)
614             nRes = i;
615     }
616     return nRes;
617 }
618 
619 
620 Sequence< OUString > SvxLinguData_Impl::GetSortedImplNames( sal_Int16 nLang, sal_uInt8 nType )
621 {
622     LangImplNameTable *pTable = 0;
623     switch (nType)
624     {
625         case TYPE_SPELL     : pTable = &aCfgSpellTable; break;
626         case TYPE_HYPH      : pTable = &aCfgHyphTable; break;
627         case TYPE_THES      : pTable = &aCfgThesTable; break;
628         case TYPE_GRAMMAR   : pTable = &aCfgGrammarTable; break;
629     }
630     Sequence< OUString > aRes;
631     if (pTable->count( nLang ))
632         aRes = (*pTable)[ nLang ];      // add configured services
633     sal_Int32 nIdx = aRes.getLength();
634     DBG_ASSERT( (sal_Int32) nDisplayServices >= nIdx, "size mismatch" );
635     aRes.realloc( nDisplayServices );
636     OUString *pRes = aRes.getArray();
637 
638     // add not configured services
639     for (sal_Int32 i = 0;  i < (sal_Int32) nDisplayServices;  ++i)
640     {
641         const ServiceInfo_Impl &rInfo = aDisplayServiceArr[ i ];
642         OUString aImplName;
643         switch (nType)
644         {
645             case TYPE_SPELL     : aImplName = rInfo.sSpellImplName; break;
646             case TYPE_HYPH      : aImplName = rInfo.sHyphImplName; break;
647             case TYPE_THES      : aImplName = rInfo.sThesImplName; break;
648             case TYPE_GRAMMAR   : aImplName = rInfo.sGrammarImplName; break;
649         }
650 
651         if (aImplName.getLength()  &&  (lcl_SeqGetIndex( aRes, aImplName) == -1))    // name not yet added
652         {
653 			DBG_ASSERT( nIdx < aRes.getLength(), "index out of range" );
654 			if (nIdx < aRes.getLength())
655                 pRes[ nIdx++ ] = aImplName;
656         }
657     }
658     // don't forget to put aRes back to its actual size just in case you allocated too much
659     // since all of the names may have already been added
660     // otherwise you get duplicate entries in the edit dialog
661     aRes.realloc( nIdx );
662     return aRes;
663 }
664 
665 
666 ServiceInfo_Impl * SvxLinguData_Impl::GetInfoByImplName( const OUString &rSvcImplName )
667 {
668     ServiceInfo_Impl* pInfo = 0;
669     for (sal_uLong i = 0;  i < nDisplayServices  &&  !pInfo;  ++i)
670     {
671         ServiceInfo_Impl &rTmp = aDisplayServiceArr[ i ];
672         if (rTmp.sSpellImplName == rSvcImplName ||
673             rTmp.sHyphImplName  == rSvcImplName ||
674             rTmp.sThesImplName  == rSvcImplName ||
675             rTmp.sGrammarImplName == rSvcImplName)
676             pInfo = &rTmp;
677     }
678     return pInfo;
679 }
680 
681 
682 //-----------------------------------------------------------------------------
683 
684 void lcl_MergeLocales(Sequence< Locale >& aAllLocales, const Sequence< Locale >& rAdd)
685 {
686 	const Locale* pAdd = rAdd.getConstArray();
687 	Sequence<Locale> aLocToAdd(rAdd.getLength());
688 	const Locale* pAllLocales = aAllLocales.getConstArray();
689 	Locale* pLocToAdd = aLocToAdd.getArray();
690 	sal_Int32 nFound = 0;
691 	sal_Int32 i;
692 	for(i = 0; i < rAdd.getLength(); i++)
693 	{
694 		sal_Bool bFound = sal_False;
695 		for(sal_Int32 j = 0; j < aAllLocales.getLength() && !bFound; j++)
696 		{
697 			bFound = pAdd[i].Language == pAllLocales[j].Language &&
698 				pAdd[i].Country == pAllLocales[j].Country;
699 		}
700 		if(!bFound)
701 		{
702 			pLocToAdd[nFound++] = pAdd[i];
703 		}
704 	}
705 	sal_Int32 nLength = aAllLocales.getLength();
706 	aAllLocales.realloc( nLength + nFound);
707 	Locale* pAllLocales2 = aAllLocales.getArray();
708 	for(i = 0; i < nFound; i++)
709 		pAllLocales2[nLength++] = pLocToAdd[i];
710 }
711 /* -----------------------------27.11.00 16:48--------------------------------
712 
713  ---------------------------------------------------------------------------*/
714 void lcl_MergeDisplayArray(
715         SvxLinguData_Impl &rData,
716         const ServiceInfo_Impl &rToAdd )
717 {
718     sal_uLong nCnt = 0;
719 
720     ServiceInfoArr &rSvcInfoArr = rData.GetDisplayServiceArray();
721     sal_uLong nEntries = rData.GetDisplayServiceCount();
722 
723     ServiceInfo_Impl* pEntry;
724     for (sal_uLong i = 0;  i < nEntries;  ++i)
725 	{
726         pEntry = &rSvcInfoArr[i];
727         if (pEntry  &&  pEntry->sDisplayName == rToAdd.sDisplayName)
728 		{
729             if(rToAdd.xSpell.is())
730 			{
731                 DBG_ASSERT( !pEntry->xSpell.is() &&
732                             pEntry->sSpellImplName.getLength() == 0,
733                             "merge conflict" );
734                 pEntry->sSpellImplName = rToAdd.sSpellImplName;
735                 pEntry->xSpell = rToAdd.xSpell;
736 			}
737             if(rToAdd.xGrammar.is())
738             {
739                 DBG_ASSERT( !pEntry->xGrammar.is() &&
740                             pEntry->sGrammarImplName.getLength() == 0,
741                             "merge conflict" );
742                 pEntry->sGrammarImplName = rToAdd.sGrammarImplName;
743                 pEntry->xGrammar = rToAdd.xGrammar;
744             }
745             if(rToAdd.xHyph.is())
746 			{
747                 DBG_ASSERT( !pEntry->xHyph.is() &&
748                             pEntry->sHyphImplName.getLength() == 0,
749                             "merge conflict" );
750                 pEntry->sHyphImplName = rToAdd.sHyphImplName;
751                 pEntry->xHyph = rToAdd.xHyph;
752 			}
753             if(rToAdd.xThes.is())
754 			{
755                 DBG_ASSERT( !pEntry->xThes.is() &&
756                             pEntry->sThesImplName.getLength() == 0,
757                             "merge conflict" );
758                 pEntry->sThesImplName = rToAdd.sThesImplName;
759                 pEntry->xThes = rToAdd.xThes;
760 			}
761 			return ;
762 		}
763         ++nCnt;
764 	}
765     rData.GetDisplayServiceArray().push_back( rToAdd );
766     rData.SetDisplayServiceCount( nCnt + 1 );
767 }
768 /* -----------------------------26.11.00 18:07--------------------------------
769 
770  ---------------------------------------------------------------------------*/
771 SvxLinguData_Impl::SvxLinguData_Impl() :
772     nDisplayServices    (0)
773 {
774 	xMSF = ::comphelper::getProcessServiceFactory();
775 	uno::Reference < XInterface > xI = xMSF->createInstance(
776 		C2U( "com.sun.star.linguistic2.LinguServiceManager" ) );
777 	xLinguSrvcMgr = uno::Reference<XLinguServiceManager>(xI, UNO_QUERY);
778 	DBG_ASSERT(xLinguSrvcMgr.is(), "No linguistic service available!");
779 	if(xLinguSrvcMgr.is())
780 	{
781 		Locale aCurrentLocale;
782 	    LanguageType eLang = Application::GetSettings().GetLanguage();
783 		SvxLanguageToLocale(aCurrentLocale, eLang);
784 		Sequence<Any> aArgs(2);//second arguments has to be empty!
785 		aArgs.getArray()[0] <<= SvxGetLinguPropertySet();
786 
787 		//read spell checker
788 		Sequence< OUString > aSpellNames = xLinguSrvcMgr->getAvailableServices(
789 						C2U(cSpell),	Locale() );
790 		const OUString* pSpellNames = aSpellNames.getConstArray();
791 
792 		sal_Int32 nIdx;
793 		for(nIdx = 0; nIdx < aSpellNames.getLength(); nIdx++)
794 		{
795             ServiceInfo_Impl aInfo;
796             aInfo.sSpellImplName = pSpellNames[nIdx];
797             aInfo.xSpell = uno::Reference<XSpellChecker>(
798                             xMSF->createInstanceWithArguments(aInfo.sSpellImplName, aArgs), UNO_QUERY);
799 
800             uno::Reference<XServiceDisplayName> xDispName(aInfo.xSpell, UNO_QUERY);
801             if(xDispName.is())
802                 aInfo.sDisplayName = xDispName->getServiceDisplayName( aCurrentLocale );
803 
804             const Sequence< Locale > aLocales( aInfo.xSpell->getLocales() );
805             //! suppress display of entries with no supported languages (see feature 110994)
806             if (aLocales.getLength())
807             {
808                 lcl_MergeLocales( aAllServiceLocales, aLocales );
809                 lcl_MergeDisplayArray( *this, aInfo );
810             }
811         }
812 
813         //read grammar checker
814         Sequence< OUString > aGrammarNames = xLinguSrvcMgr->getAvailableServices(
815                         C2U(cGrammar), Locale() );
816         const OUString* pGrammarNames = aGrammarNames.getConstArray();
817         for(nIdx = 0; nIdx < aGrammarNames.getLength(); nIdx++)
818         {
819             ServiceInfo_Impl aInfo;
820             aInfo.sGrammarImplName = pGrammarNames[nIdx];
821             aInfo.xGrammar = uno::Reference<XProofreader>(
822                             xMSF->createInstanceWithArguments(aInfo.sGrammarImplName, aArgs), UNO_QUERY);
823 
824             uno::Reference<XServiceDisplayName> xDispName(aInfo.xGrammar, UNO_QUERY);
825             if(xDispName.is())
826                 aInfo.sDisplayName = xDispName->getServiceDisplayName( aCurrentLocale );
827 
828             const Sequence< Locale > aLocales( aInfo.xGrammar->getLocales() );
829             //! suppress display of entries with no supported languages (see feature 110994)
830             if (aLocales.getLength())
831             {
832                 lcl_MergeLocales( aAllServiceLocales, aLocales );
833                 lcl_MergeDisplayArray( *this, aInfo );
834             }
835         }
836 
837 		//read hyphenator
838 		Sequence< OUString > aHyphNames = xLinguSrvcMgr->getAvailableServices(
839 						C2U(cHyph),	Locale() );
840 		const OUString* pHyphNames = aHyphNames.getConstArray();
841 		for(nIdx = 0; nIdx < aHyphNames.getLength(); nIdx++)
842 		{
843             ServiceInfo_Impl aInfo;
844             aInfo.sHyphImplName = pHyphNames[nIdx];
845             aInfo.xHyph = uno::Reference<XHyphenator>(
846                             xMSF->createInstanceWithArguments(aInfo.sHyphImplName, aArgs), UNO_QUERY);
847 
848             uno::Reference<XServiceDisplayName> xDispName(aInfo.xHyph, UNO_QUERY);
849             if(xDispName.is())
850                 aInfo.sDisplayName = xDispName->getServiceDisplayName( aCurrentLocale );
851 
852             const Sequence< Locale > aLocales( aInfo.xHyph->getLocales() );
853             //! suppress display of entries with no supported languages (see feature 110994)
854             if (aLocales.getLength())
855             {
856                 lcl_MergeLocales( aAllServiceLocales, aLocales );
857                 lcl_MergeDisplayArray( *this, aInfo );
858             }
859 		}
860 
861 		//read thesauri
862 		Sequence< OUString > aThesNames = xLinguSrvcMgr->getAvailableServices(
863 						C2U(cThes),		Locale() );
864 		const OUString* pThesNames = aThesNames.getConstArray();
865 		for(nIdx = 0; nIdx < aThesNames.getLength(); nIdx++)
866 		{
867             ServiceInfo_Impl aInfo;
868             aInfo.sThesImplName = pThesNames[nIdx];
869             aInfo.xThes = uno::Reference<XThesaurus>(
870                             xMSF->createInstanceWithArguments(aInfo.sThesImplName, aArgs), UNO_QUERY);
871 
872             uno::Reference<XServiceDisplayName> xDispName(aInfo.xThes, UNO_QUERY);
873             if(xDispName.is())
874                 aInfo.sDisplayName = xDispName->getServiceDisplayName( aCurrentLocale );
875 
876             const Sequence< Locale > aLocales( aInfo.xThes->getLocales() );
877             //! suppress display of entries with no supported languages (see feature 110994)
878             if (aLocales.getLength())
879             {
880                 lcl_MergeLocales( aAllServiceLocales, aLocales );
881                 lcl_MergeDisplayArray( *this, aInfo );
882             }
883 		}
884 
885         Sequence< OUString > aCfgSvcs;
886 		const Locale* pAllLocales = aAllServiceLocales.getConstArray();
887 		for(sal_Int32 nLocale = 0; nLocale < aAllServiceLocales.getLength(); nLocale++)
888 		{
889             sal_Int16 nLang = SvxLocaleToLanguage( pAllLocales[nLocale] );
890 
891             aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(C2U(cSpell), pAllLocales[nLocale]);
892             SetChecked( aCfgSvcs );
893             if (aCfgSvcs.getLength())
894                 aCfgSpellTable[ nLang ] = aCfgSvcs;
895 
896             aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(C2U(cGrammar), pAllLocales[nLocale]);
897             SetChecked( aCfgSvcs );
898             if (aCfgSvcs.getLength())
899                 aCfgGrammarTable[ nLang ] = aCfgSvcs;
900 
901             aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(C2U(cHyph), pAllLocales[nLocale]);
902             SetChecked( aCfgSvcs );
903             if (aCfgSvcs.getLength())
904                 aCfgHyphTable[ nLang ] = aCfgSvcs;
905 
906             aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(C2U(cThes), pAllLocales[nLocale]);
907             SetChecked( aCfgSvcs );
908             if (aCfgSvcs.getLength())
909                 aCfgThesTable[ nLang ] = aCfgSvcs;
910 		}
911 	}
912 }
913 /* -----------------------------22.05.01 10:43--------------------------------
914 
915 ---------------------------------------------------------------------------*/
916 SvxLinguData_Impl::SvxLinguData_Impl( const SvxLinguData_Impl &rData ) :
917     aDisplayServiceArr  (rData.aDisplayServiceArr),
918     nDisplayServices    (rData.nDisplayServices),
919     aAllServiceLocales  (rData.aAllServiceLocales),
920     aCfgSpellTable      (rData.aCfgSpellTable),
921     aCfgHyphTable       (rData.aCfgHyphTable),
922     aCfgThesTable       (rData.aCfgThesTable),
923     aCfgGrammarTable    (rData.aCfgGrammarTable),
924     xMSF                (rData.xMSF),
925     xLinguSrvcMgr       (rData.xLinguSrvcMgr)
926 {
927 }
928 /* -----------------------------22.05.01 10:43--------------------------------
929 
930  ---------------------------------------------------------------------------*/
931 SvxLinguData_Impl & SvxLinguData_Impl::operator = (const SvxLinguData_Impl &rData)
932 {
933     xMSF                = rData.xMSF;
934     xLinguSrvcMgr       = rData.xLinguSrvcMgr;
935     aAllServiceLocales  = rData.aAllServiceLocales;
936     aCfgSpellTable      = rData.aCfgSpellTable;
937     aCfgHyphTable       = rData.aCfgHyphTable;
938     aCfgThesTable       = rData.aCfgThesTable;
939     aCfgGrammarTable    = rData.aCfgGrammarTable;
940     aDisplayServiceArr  = rData.aDisplayServiceArr;
941     nDisplayServices    = rData.nDisplayServices;
942     return *this;
943 }
944 /* -----------------------------26.11.00 18:08--------------------------------
945 
946  ---------------------------------------------------------------------------*/
947 SvxLinguData_Impl::~SvxLinguData_Impl()
948 {
949 }
950 /* -----------------------------26.11.00 19:42--------------------------------
951 
952  ---------------------------------------------------------------------------*/
953 void SvxLinguData_Impl::SetChecked(const Sequence<OUString>& rConfiguredServices)
954 {
955 	const OUString* pConfiguredServices = rConfiguredServices.getConstArray();
956 	for(sal_Int32 n = 0; n < rConfiguredServices.getLength(); n++)
957 	{
958         ServiceInfo_Impl* pEntry;
959         for (sal_uLong i = 0;  i < nDisplayServices;  ++i)
960 		{
961             pEntry = &aDisplayServiceArr[i];
962             if (pEntry  &&  !pEntry->bConfigured)
963             {
964                 const OUString &rSrvcImplName = pConfiguredServices[n];
965                 if (rSrvcImplName.getLength()  &&
966                     (pEntry->sSpellImplName == rSrvcImplName  ||
967                         pEntry->sGrammarImplName  == rSrvcImplName  ||
968                         pEntry->sHyphImplName  == rSrvcImplName  ||
969                         pEntry->sThesImplName  == rSrvcImplName))
970                 {
971                     pEntry->bConfigured = sal_True;
972                     break;
973                 }
974             }
975 		}
976 	}
977 }
978 /* -----------------------------26.11.00 20:43--------------------------------
979 
980  ---------------------------------------------------------------------------*/
981 
982 sal_Bool SvxLinguData_Impl::AddRemove(
983             Sequence< OUString > &rConfigured,
984             const OUString &rImplName, sal_Bool bAdd )
985 {
986     sal_Bool bRet = sal_False;  // modified?
987 
988     sal_Int32 nEntries = rConfigured.getLength();
989     sal_Int32 nPos = lcl_SeqGetEntryPos(rConfigured, rImplName);
990     if (bAdd  &&  nPos < 0)         // add new entry
991     {
992         rConfigured.realloc( ++nEntries );
993         OUString *pConfigured = rConfigured.getArray();
994         pConfigured = rConfigured.getArray();
995         pConfigured[nEntries - 1] = rImplName;
996         bRet = sal_True;
997     }
998     else if (!bAdd  &&  nPos >= 0)  // remove existing entry
999     {
1000         OUString *pConfigured = rConfigured.getArray();
1001         for (sal_Int32 i = nPos;  i < nEntries - 1;  ++i)
1002             pConfigured[i] = pConfigured[i + 1];
1003         rConfigured.realloc(--nEntries);
1004         bRet = sal_True;
1005     }
1006 
1007 	return bRet;
1008 }
1009 
1010 
1011 void SvxLinguData_Impl::Reconfigure( const OUString &rDisplayName, sal_Bool bEnable )
1012 {
1013     DBG_ASSERT( rDisplayName.getLength(), "empty DisplayName" );
1014 
1015     ServiceInfo_Impl *pInfo = 0;
1016     ServiceInfo_Impl *pTmp  = 0;
1017     for (sal_uLong i = 0;  i < nDisplayServices;  ++i)
1018     {
1019         pTmp = &aDisplayServiceArr[i];
1020         if (pTmp  &&  pTmp->sDisplayName == rDisplayName)
1021         {
1022             pInfo = pTmp;
1023             break;
1024         }
1025     }
1026     DBG_ASSERT( pInfo, "DisplayName entry not found" );
1027     if (pInfo)
1028     {
1029         pInfo->bConfigured = bEnable;
1030 
1031         Sequence< Locale > aLocales;
1032         const Locale *pLocale = 0;
1033         sal_Int32 nLocales = 0;
1034         sal_Int32 i;
1035 
1036         // update configured spellchecker entries
1037         if (pInfo->xSpell.is())
1038         {
1039             aLocales = pInfo->xSpell->getLocales();
1040             pLocale = aLocales.getConstArray();
1041             nLocales = aLocales.getLength();
1042             for (i = 0;  i < nLocales;  ++i)
1043             {
1044                 sal_Int16 nLang = SvxLocaleToLanguage( pLocale[i] );
1045                 if (!aCfgSpellTable.count( nLang ) && bEnable)
1046                     aCfgSpellTable[ nLang ] = Sequence< OUString >();
1047                 if (aCfgSpellTable.count( nLang ))
1048                     AddRemove( aCfgSpellTable[ nLang ], pInfo->sSpellImplName, bEnable );
1049             }
1050         }
1051 
1052         // update configured grammar checker entries
1053         if (pInfo->xGrammar.is())
1054         {
1055             aLocales = pInfo->xGrammar->getLocales();
1056             pLocale = aLocales.getConstArray();
1057             nLocales = aLocales.getLength();
1058             for (i = 0;  i < nLocales;  ++i)
1059             {
1060                 sal_Int16 nLang = SvxLocaleToLanguage( pLocale[i] );
1061                 if (!aCfgGrammarTable.count( nLang ) && bEnable)
1062                     aCfgGrammarTable[ nLang ] = Sequence< OUString >();
1063                 if (aCfgGrammarTable.count( nLang ))
1064                     AddRemove( aCfgGrammarTable[ nLang ], pInfo->sGrammarImplName, bEnable );
1065             }
1066         }
1067 
1068         // update configured hyphenator entries
1069         if (pInfo->xHyph.is())
1070         {
1071             aLocales = pInfo->xHyph->getLocales();
1072             pLocale = aLocales.getConstArray();
1073             nLocales = aLocales.getLength();
1074             for (i = 0;  i < nLocales;  ++i)
1075             {
1076                 sal_Int16 nLang = SvxLocaleToLanguage( pLocale[i] );
1077                 if (!aCfgHyphTable.count( nLang ) && bEnable)
1078                     aCfgHyphTable[ nLang ] = Sequence< OUString >();
1079                 if (aCfgHyphTable.count( nLang ))
1080                     AddRemove( aCfgHyphTable[ nLang ], pInfo->sHyphImplName, bEnable );
1081             }
1082         }
1083 
1084         // update configured spellchecker entries
1085         if (pInfo->xThes.is())
1086         {
1087             aLocales = pInfo->xThes->getLocales();
1088             pLocale = aLocales.getConstArray();
1089             nLocales = aLocales.getLength();
1090             for (i = 0;  i < nLocales;  ++i)
1091             {
1092                 sal_Int16 nLang = SvxLocaleToLanguage( pLocale[i] );
1093                 if (!aCfgThesTable.count( nLang ) && bEnable)
1094                     aCfgThesTable[ nLang ] = Sequence< OUString >();
1095                 if (aCfgThesTable.count( nLang ))
1096                     AddRemove( aCfgThesTable[ nLang ], pInfo->sThesImplName, bEnable );
1097             }
1098         }
1099     }
1100 }
1101 
1102 
1103 // class SvxLinguTabPage -------------------------------------------------
1104 
1105 #define CBCOL_FIRST		0
1106 #define CBCOL_SECOND	1
1107 #define CBCOL_BOTH		2
1108 
1109 SvxLinguTabPage::SvxLinguTabPage( Window* pParent,
1110 								  const SfxItemSet& rSet ):
1111 
1112 	SfxTabPage( pParent, CUI_RES( RID_SFXPAGE_LINGU ), rSet ),
1113 
1114     aLinguisticFL       ( this, CUI_RES( FL_LINGUISTIC ) ),
1115 	aLinguModulesFT		( this, CUI_RES( FT_LINGU_MODULES ) ),
1116 	aLinguModulesCLB	( this, CUI_RES( CLB_LINGU_MODULES ) ),
1117 	aLinguModulesEditPB	( this, CUI_RES( PB_LINGU_MODULES_EDIT ) ),
1118     aLinguDicsFT        ( this, CUI_RES( FT_LINGU_DICS ) ),
1119     aLinguDicsCLB       ( this, CUI_RES( CLB_LINGU_DICS ) ),
1120     aLinguDicsNewPB     ( this, CUI_RES( PB_LINGU_DICS_NEW_DIC ) ),
1121     aLinguDicsEditPB    ( this, CUI_RES( PB_LINGU_DICS_EDIT_DIC ) ),
1122     aLinguDicsDelPB     ( this, CUI_RES( PB_LINGU_DICS_DEL_DIC ) ),
1123 	aLinguOptionsFT		( this, CUI_RES( FT_LINGU_OPTIONS ) ),
1124 	aLinguOptionsCLB	( this, CUI_RES( CLB_LINGU_OPTIONS ) ),
1125     aLinguOptionsEditPB ( this, CUI_RES( PB_LINGU_OPTIONS_EDIT ) ),
1126     aMoreDictsLink      ( this, CUI_RES( FT_LINGU_OPTIONS_MOREDICTS ) ),
1127 	sCapitalWords		( CUI_RES( STR_CAPITAL_WORDS ) ),
1128 	sWordsWithDigits	( CUI_RES( STR_WORDS_WITH_DIGITS ) ),
1129 	sCapitalization		( CUI_RES( STR_CAPITALIZATION ) ),
1130 	sSpellSpecial		( CUI_RES( STR_SPELL_SPECIAL ) ),
1131 	sSpellAuto			( CUI_RES( STR_SPELL_AUTO ) ),
1132     sGrammarAuto        ( CUI_RES( STR_GRAMMAR_AUTO ) ),
1133 	sNumMinWordlen  	( CUI_RES( STR_NUM_MIN_WORDLEN ) ),
1134 	sNumPreBreak		( CUI_RES( STR_NUM_PRE_BREAK ) ),
1135 	sNumPostBreak		( CUI_RES( STR_NUM_POST_BREAK ) ),
1136 	sHyphAuto			( CUI_RES( STR_HYPH_AUTO ) ),
1137 	sHyphSpecial		( CUI_RES( STR_HYPH_SPECIAL ) ),
1138 
1139 	pLinguData			( NULL )
1140 {
1141 	pCheckButtonData = NULL;
1142 
1143     aLinguModulesCLB.SetStyle( aLinguModulesCLB.GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
1144 	aLinguModulesCLB.SetHelpId(HID_CLB_LINGU_MODULES );
1145 	aLinguModulesCLB.SetHighlightRange();
1146 	aLinguModulesCLB.SetSelectHdl( LINK( this, SvxLinguTabPage, SelectHdl_Impl ));
1147     aLinguModulesCLB.SetDoubleClickHdl(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl));
1148     aLinguModulesCLB.SetCheckButtonHdl(LINK(this, SvxLinguTabPage, BoxCheckButtonHdl_Impl));
1149 
1150 	aLinguModulesEditPB.SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1151 	aLinguOptionsEditPB.SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1152 
1153     aLinguDicsCLB.SetStyle( aLinguDicsCLB.GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
1154     aLinguDicsCLB.SetHelpId(HID_CLB_EDIT_MODULES_DICS );
1155     aLinguDicsCLB.SetHighlightRange();
1156     aLinguDicsCLB.SetSelectHdl( LINK( this, SvxLinguTabPage, SelectHdl_Impl ));
1157     aLinguDicsCLB.SetCheckButtonHdl(LINK(this, SvxLinguTabPage, BoxCheckButtonHdl_Impl));
1158 
1159     aLinguDicsNewPB.SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1160     aLinguDicsEditPB.SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1161     aLinguDicsDelPB.SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1162 
1163     aLinguOptionsCLB.SetStyle( aLinguOptionsCLB.GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
1164 	aLinguOptionsCLB.SetHelpId(HID_CLB_LINGU_OPTIONS );
1165 	aLinguOptionsCLB.SetHighlightRange();
1166 	aLinguOptionsCLB.SetSelectHdl( LINK( this, SvxLinguTabPage, SelectHdl_Impl ));
1167     aLinguOptionsCLB.SetDoubleClickHdl(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl));
1168 
1169     if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
1170             != SvtExtendedSecurityOptions::OPEN_NEVER )
1171     {
1172         aMoreDictsLink.SetURL( String(
1173             RTL_CONSTASCII_STRINGPARAM( "http://extensions.services.openoffice.org/dictionary?cid=926386" ) ) );
1174         aMoreDictsLink.SetClickHdl( LINK( this, SvxLinguTabPage, OpenURLHdl_Impl ) );
1175     }
1176     else
1177         aMoreDictsLink.Hide();
1178 
1179 	String sAccessibleNameModuleEdit( CUI_RES( STR_LINGU_MODULES_EDIT ) );
1180 	String sAccessibleNameDicsEdit	( CUI_RES( STR_LINGU_DICS_EDIT_DIC ) );
1181 	String sAccessibleNameOptionEdit( CUI_RES( STR_LINGU_OPTIONS_EDIT ) );
1182 
1183 	aLinguModulesEditPB.SetAccessibleName(sAccessibleNameModuleEdit);
1184 	aLinguDicsEditPB.SetAccessibleName(sAccessibleNameDicsEdit);
1185 	aLinguOptionsEditPB.SetAccessibleName(sAccessibleNameOptionEdit);
1186 
1187     // force recalculation of hash value used for checking the need of updating
1188     // because new dictionaries might be installed / downloaded.
1189     //! Thus it needs to be called now since it may infuence the supported languages
1190     //! to be reported AND the found user-dictionaries(!) as well.
1191     SvxLinguConfigUpdate::UpdateAll( sal_True );
1192 
1193     xProp = uno::Reference< XPropertySet >( SvxGetLinguPropertySet(), UNO_QUERY );
1194 	xDicList = uno::Reference< XDictionaryList >( SvxGetDictionaryList(), UNO_QUERY );
1195 	if (xDicList.is())
1196 	{
1197         // keep references to all **currently** available dictionaries,
1198         // since the diclist may get changed meanwhile (e.g. through the API).
1199         // We want the dialog to operate on the same set of dictionaries it
1200         // was started with.
1201         // Also we have to take care to not loose the last reference when
1202         // someone else removes a dictionary from the list.
1203         // removed dics will be replaced by NULL new entries be added to the end
1204         // Thus we may use indizes as consistent references.
1205         aDics = xDicList->getDictionaries();
1206 
1207         UpdateDicBox_Impl();
1208 	}
1209 	else
1210 	{
1211         aLinguDicsFT.Disable();
1212         aLinguDicsCLB.Disable();
1213         aLinguDicsNewPB.Disable();
1214         aLinguDicsEditPB.Disable();
1215         aLinguDicsDelPB.Disable();
1216 	}
1217 
1218 	const SfxSpellCheckItem* pItem = 0;
1219 	SfxItemState eItemState = SFX_ITEM_UNKNOWN;
1220 
1221 	eItemState = rSet.GetItemState( GetWhich( SID_ATTR_SPELL ),
1222 									sal_False, (const SfxPoolItem**)&pItem );
1223 
1224 	// handelt es sich um ein Default-Item?
1225 	if ( eItemState == SFX_ITEM_DEFAULT )
1226 		pItem = (const SfxSpellCheckItem*)&(rSet.Get( GetWhich( SID_ATTR_SPELL ) ) );
1227 	else if ( eItemState == SFX_ITEM_DONTCARE )
1228 		pItem = NULL;
1229 
1230 	FreeResource();
1231 }
1232 
1233 // -----------------------------------------------------------------------
1234 
1235 SvxLinguTabPage::~SvxLinguTabPage()
1236 {
1237 	if (pLinguData)
1238 		delete pLinguData;
1239 }
1240 
1241 //------------------------------------------------------------------------
1242 
1243 //nicht �berladen wegschmeissen
1244 sal_uInt16* SvxLinguTabPage::GetRanges()
1245 {
1246 	//TL???
1247 	return pRanges;
1248 }
1249 
1250 //------------------------------------------------------------------------
1251 
1252 SfxTabPage* SvxLinguTabPage::Create( Window* pParent,
1253 									 const SfxItemSet& rAttrSet )
1254 {
1255 	return ( new SvxLinguTabPage( pParent, rAttrSet ) );
1256 }
1257 
1258 //------------------------------------------------------------------------
1259 
1260 Any lcl_Bool2Any(sal_Bool bVal)
1261 {
1262 	Any aRet(&bVal, ::getBooleanCppuType());
1263 	return aRet;
1264 }
1265 
1266 
1267 sal_Bool lcl_Bool2Any(Any& rVal)
1268 {
1269 	return *(sal_Bool*)rVal.getValue();
1270 }
1271 
1272 
1273 sal_Bool SvxLinguTabPage::FillItemSet( SfxItemSet& rCoreSet )
1274 {
1275 	sal_Bool bModified = sal_True; // !!!!
1276 
1277 	// if not HideGroups was called with GROUP_MODULES...
1278 	if (aLinguModulesCLB.IsVisible())
1279 	{
1280         DBG_ASSERT( pLinguData, "pLinguData not yet initialized" );
1281         if (!pLinguData)
1282             pLinguData = new SvxLinguData_Impl;
1283 
1284         LangImplNameTable::const_iterator aIt;
1285 
1286         // update spellchecker configuration entries
1287         const LangImplNameTable *pTable = &pLinguData->GetSpellTable();
1288         for (aIt = pTable->begin();  aIt != pTable->end();  ++aIt)
1289         {
1290             sal_Int16 nLang = aIt->first;
1291             const Sequence< OUString > aImplNames( aIt->second );
1292 #if OSL_DEBUG_LEVEL > 1
1293             const OUString *pTmpStr;
1294             pTmpStr = aImplNames.getConstArray();
1295 #endif
1296             uno::Reference< XLinguServiceManager > xMgr( pLinguData->GetManager() );
1297             Locale aLocale( SvxCreateLocale(nLang) );
1298             if (xMgr.is())
1299                 xMgr->setConfiguredServices( C2U(cSpell), aLocale, aImplNames );
1300         }
1301 
1302         // update grammar checker configuration entries
1303         pTable = &pLinguData->GetGrammarTable();
1304         for (aIt = pTable->begin();  aIt != pTable->end();  ++aIt)
1305         {
1306             sal_Int16 nLang = aIt->first;
1307             const Sequence< OUString > aImplNames( aIt->second );
1308 #if OSL_DEBUG_LEVEL > 1
1309             const OUString *pTmpStr;
1310             pTmpStr = aImplNames.getConstArray();
1311 #endif
1312             uno::Reference< XLinguServiceManager > xMgr( pLinguData->GetManager() );
1313             Locale aLocale( SvxCreateLocale(nLang) );
1314             if (xMgr.is())
1315                 xMgr->setConfiguredServices( C2U(cGrammar), aLocale, aImplNames );
1316         }
1317 
1318         // update hyphenator configuration entries
1319         pTable = &pLinguData->GetHyphTable();
1320         for (aIt = pTable->begin();  aIt != pTable->end();  ++aIt)
1321         {
1322             sal_Int16 nLang = aIt->first;
1323             const Sequence< OUString > aImplNames( aIt->second );
1324 #if OSL_DEBUG_LEVEL > 1
1325             const OUString *pTmpStr;
1326             pTmpStr = aImplNames.getConstArray();
1327 #endif
1328             uno::Reference< XLinguServiceManager > xMgr( pLinguData->GetManager() );
1329             Locale aLocale( SvxCreateLocale(nLang) );
1330             if (xMgr.is())
1331                 xMgr->setConfiguredServices( C2U(cHyph), aLocale, aImplNames );
1332         }
1333 
1334         // update thesaurus configuration entries
1335         pTable = &pLinguData->GetThesTable();
1336         for (aIt = pTable->begin();  aIt != pTable->end();  ++aIt)
1337         {
1338             sal_Int16 nLang = aIt->first;
1339             const Sequence< OUString > aImplNames( aIt->second );
1340 #if OSL_DEBUG_LEVEL > 1
1341             const OUString *pTmpStr;
1342             pTmpStr = aImplNames.getConstArray();
1343 #endif
1344             uno::Reference< XLinguServiceManager > xMgr( pLinguData->GetManager() );
1345             Locale aLocale( SvxCreateLocale(nLang) );
1346             if (xMgr.is())
1347                 xMgr->setConfiguredServices( C2U(cThes), aLocale, aImplNames );
1348         }
1349 	}
1350 
1351 
1352     //
1353     // activate dictionaries according to checkbox state
1354     //
1355     Sequence< OUString > aActiveDics;
1356     sal_Int32 nActiveDics = 0;
1357     sal_uLong nEntries = aLinguDicsCLB.GetEntryCount();
1358     for (sal_uLong i = 0;  i < nEntries;  ++i)
1359     {
1360         sal_Int32 nDics = aDics.getLength();
1361 //        const uno::Reference< XDictionary > *pDic = aDics.getConstArray();
1362 
1363         aActiveDics.realloc( nDics );
1364         OUString *pActiveDic = aActiveDics.getArray();
1365 
1366         SvLBoxEntry *pEntry = aLinguDicsCLB.GetEntry( i );
1367         if (pEntry)
1368         {
1369             DicUserData aData( (sal_uLong)pEntry->GetUserData() );
1370             if (aData.GetEntryId() < nDics)
1371             {
1372                 sal_Bool bChecked = aLinguDicsCLB.IsChecked( (sal_uInt16) i );
1373                 uno::Reference< XDictionary > xDic( aDics.getConstArray()[ i ] );
1374                 if (xDic.is())
1375                 {
1376                     if (SvxGetIgnoreAllList() == xDic)
1377                         bChecked = sal_True;
1378                     xDic->setActive( bChecked );
1379 
1380                     if (bChecked)
1381                     {
1382                         String aDicName( xDic->getName() );
1383                         pActiveDic[ nActiveDics++ ] = aDicName;
1384                     }
1385                 }
1386             }
1387         }
1388     }
1389     //
1390     aActiveDics.realloc( nActiveDics );
1391     Any aTmp;
1392     aTmp <<= aActiveDics;
1393     SvtLinguConfig aLngCfg;
1394     aLngCfg.SetProperty( UPH_ACTIVE_DICTIONARIES, aTmp );
1395 
1396 
1397     nEntries = aLinguOptionsCLB.GetEntryCount();
1398     for (sal_uInt16 j = 0;  j < nEntries;  ++j)
1399 	{
1400 		SvLBoxEntry *pEntry = aLinguOptionsCLB.GetEntry( j );
1401 
1402 		OptionsUserData aData( (sal_uLong)pEntry->GetUserData() );
1403 		String aPropName( lcl_GetPropertyName( (EID_OPTIONS) aData.GetEntryId() ) );
1404 
1405 		Any aAny;
1406 		if (aData.IsCheckable())
1407 		{
1408 			sal_Bool bChecked = aLinguOptionsCLB.IsChecked( j );
1409 			aAny <<= bChecked;
1410 		}
1411 		else if (aData.HasNumericValue())
1412 		{
1413 			sal_Int16 nVal = aData.GetNumericValue();
1414 			aAny <<= nVal;
1415 		}
1416 
1417 		if (xProp.is())
1418 			xProp->setPropertyValue( aPropName, aAny );
1419 		aLngCfg.SetProperty( aPropName, aAny );
1420 	}
1421 
1422 	SvLBoxEntry *pPreBreakEntry  = aLinguOptionsCLB.GetEntry( (sal_uInt16) EID_NUM_PRE_BREAK );
1423 	SvLBoxEntry *pPostBreakEntry = aLinguOptionsCLB.GetEntry( (sal_uInt16) EID_NUM_POST_BREAK );
1424 	DBG_ASSERT( pPreBreakEntry, "NULL Pointer" );
1425 	DBG_ASSERT( pPostBreakEntry, "NULL Pointer" );
1426 	if (pPreBreakEntry && pPostBreakEntry)
1427 	{
1428 		OptionsUserData aPreBreakData( (sal_uLong)pPreBreakEntry->GetUserData() );
1429 		OptionsUserData aPostBreakData( (sal_uLong)pPostBreakEntry->GetUserData() );
1430 		if ( aPreBreakData.IsModified() || aPostBreakData.IsModified() )
1431 		{
1432 			SfxHyphenRegionItem aHyp( GetWhich( SID_ATTR_HYPHENREGION ) );
1433 			aHyp.GetMinLead()  = (sal_uInt8) aPreBreakData.GetNumericValue();
1434 			aHyp.GetMinTrail() = (sal_uInt8) aPostBreakData.GetNumericValue();
1435 			rCoreSet.Put( aHyp );
1436 		}
1437 	}
1438 
1439 
1440     // automatic spell checking
1441 	sal_Bool bNewAutoCheck = aLinguOptionsCLB.IsChecked( (sal_uInt16) EID_SPELL_AUTO );
1442 	const SfxPoolItem* pOld = GetOldItem( rCoreSet, SID_AUTOSPELL_CHECK );
1443 	if ( !pOld || ( (SfxBoolItem*)pOld )->GetValue() != bNewAutoCheck )
1444 	{
1445 		rCoreSet.Put( SfxBoolItem( GetWhich( SID_AUTOSPELL_CHECK ),
1446 								bNewAutoCheck ) );
1447 		bModified |= sal_True;
1448 	}
1449 
1450 	return bModified;
1451 }
1452 
1453 // ----------------------------------------------------------------------
1454 
1455 sal_uLong SvxLinguTabPage::GetDicUserData( const uno::Reference< XDictionary > &rxDic, sal_uInt16 nIdx )
1456 {
1457     sal_uLong nRes = 0;
1458     DBG_ASSERT( rxDic.is(), "dictionary not supplied" );
1459     if (rxDic.is())
1460     {
1461         uno::Reference< frame::XStorable > xStor( rxDic, UNO_QUERY );
1462 
1463 //        sal_uLong nUserData = 0;
1464         sal_Bool bChecked = rxDic->isActive();
1465         sal_Bool bEditable = !xStor.is() || !xStor->isReadonly();
1466         sal_Bool bDeletable = bEditable;
1467 //        sal_Bool bNegativ = rxDic->getDictionaryType() == DictionaryType_NEGATIVE;
1468 
1469         nRes = DicUserData( nIdx,
1470                 bChecked, bEditable, bDeletable ).GetUserData();
1471     }
1472     return nRes;
1473 }
1474 
1475 
1476 void SvxLinguTabPage::AddDicBoxEntry(
1477         const uno::Reference< XDictionary > &rxDic,
1478         sal_uInt16 nIdx )
1479 {
1480     aLinguDicsCLB.SetUpdateMode(sal_False);
1481 
1482     String aTxt( ::GetDicInfoStr( rxDic->getName(),
1483                         SvxLocaleToLanguage( rxDic->getLocale() ),
1484                         DictionaryType_NEGATIVE == rxDic->getDictionaryType() ) );
1485     aLinguDicsCLB.InsertEntry( aTxt, (sal_uInt16)LISTBOX_APPEND );  // append at end
1486     SvLBoxEntry* pEntry = aLinguDicsCLB.GetEntry( aLinguDicsCLB.GetEntryCount() - 1 );
1487     DBG_ASSERT( pEntry, "failed to add entry" );
1488     if (pEntry)
1489     {
1490         DicUserData aData( GetDicUserData( rxDic, nIdx ) );
1491         pEntry->SetUserData( (void *) aData.GetUserData() );
1492         lcl_SetCheckButton( pEntry, aData.IsChecked() );
1493     }
1494 
1495     aLinguDicsCLB.SetUpdateMode(sal_True);
1496 }
1497 
1498 // ----------------------------------------------------------------------
1499 
1500 void SvxLinguTabPage::UpdateDicBox_Impl()
1501 {
1502     aLinguDicsCLB.SetUpdateMode(sal_False);
1503     aLinguDicsCLB.Clear();
1504 
1505 	sal_Int32 nDics	 = aDics.getLength();
1506 	const uno::Reference< XDictionary > *pDic = aDics.getConstArray();
1507 	for (sal_Int32 i = 0;  i < nDics;  ++i)
1508 	{
1509 		const uno::Reference< XDictionary > &rDic = pDic[i];
1510 		if (rDic.is())
1511             AddDicBoxEntry( rDic, (sal_uInt16)i );
1512 	}
1513 
1514     aLinguDicsCLB.SetUpdateMode(sal_True);
1515 }
1516 
1517 // ----------------------------------------------------------------------
1518 
1519 void SvxLinguTabPage::UpdateModulesBox_Impl()
1520 {
1521     if (pLinguData)
1522     {
1523         const ServiceInfoArr &rAllDispSrvcArr = pLinguData->GetDisplayServiceArray();
1524         const sal_uLong nDispSrvcCount = pLinguData->GetDisplayServiceCount();
1525 
1526         aLinguModulesCLB.Clear();
1527 
1528         for (sal_uInt16 i = 0;  i < nDispSrvcCount;  ++i)
1529         {
1530             const ServiceInfo_Impl &rInfo = rAllDispSrvcArr[i];
1531             aLinguModulesCLB.InsertEntry( rInfo.sDisplayName, (sal_uInt16)LISTBOX_APPEND );
1532             SvLBoxEntry* pEntry = aLinguModulesCLB.GetEntry(i);
1533             pEntry->SetUserData( (void *) &rInfo );
1534             aLinguModulesCLB.CheckEntryPos( i, rInfo.bConfigured );
1535         }
1536         aLinguModulesEditPB.Enable( nDispSrvcCount > 0 );
1537     }
1538 }
1539 
1540 //------------------------------------------------------------------------
1541 
1542 void SvxLinguTabPage::Reset( const SfxItemSet& rSet )
1543 {
1544 	// if not HideGroups was called with GROUP_MODULES...
1545 	if (aLinguModulesCLB.IsVisible())
1546 	{
1547 		if (!pLinguData)
1548 			pLinguData = new SvxLinguData_Impl;
1549         UpdateModulesBox_Impl();
1550 	}
1551 
1552 
1553 	//
1554 	//	get data from configuration
1555 	//
1556 
1557 	SvtLinguConfig aLngCfg;
1558 
1559 	aLinguOptionsCLB.SetUpdateMode(sal_False);
1560 	aLinguOptionsCLB.Clear();
1561 
1562 	SvLBoxTreeList *pModel = aLinguOptionsCLB.GetModel();
1563 	SvLBoxEntry* pEntry = NULL;
1564 
1565 	sal_Int16 nVal = 0;
1566 	sal_Bool  bVal  = sal_False;
1567 	sal_uLong nUserData = 0;
1568 
1569     pEntry = CreateEntry( sSpellAuto,		CBCOL_FIRST );
1570 	aLngCfg.GetProperty( C2U(UPN_IS_SPELL_AUTO) ) >>= bVal;
1571 	const SfxPoolItem* pItem = GetItem( rSet, SID_AUTOSPELL_CHECK );
1572 	if (pItem)
1573 		bVal = ((SfxBoolItem *) pItem)->GetValue();
1574 	nUserData = OptionsUserData( EID_SPELL_AUTO, sal_False, 0, sal_True, bVal).GetUserData();
1575 	pEntry->SetUserData( (void *)nUserData );
1576 	pModel->Insert( pEntry );
1577 	lcl_SetCheckButton( pEntry, bVal );
1578 
1579     pEntry = CreateEntry( sGrammarAuto,       CBCOL_FIRST );
1580     aLngCfg.GetProperty( C2U(UPN_IS_GRAMMAR_AUTO) ) >>= bVal;
1581 //    const SfxPoolItem* pItem = GetItem( rSet, SID_AUTOSPELL_CHECK );
1582 //    if (pItem)
1583 //        bVal = ((SfxBoolItem *) pItem)->GetValue();
1584     nUserData = OptionsUserData( EID_GRAMMAR_AUTO, sal_False, 0, sal_True, bVal).GetUserData();
1585     pEntry->SetUserData( (void *)nUserData );
1586     pModel->Insert( pEntry );
1587     lcl_SetCheckButton( pEntry, bVal );
1588 
1589 	pEntry = CreateEntry( sCapitalWords,	CBCOL_FIRST );
1590 	aLngCfg.GetProperty( C2U(UPN_IS_SPELL_UPPER_CASE) ) >>= bVal;
1591 	nUserData = OptionsUserData( EID_CAPITAL_WORDS, sal_False, 0, sal_True, bVal).GetUserData();
1592 	pEntry->SetUserData( (void *)nUserData );
1593 	pModel->Insert( pEntry );
1594 	lcl_SetCheckButton( pEntry, bVal );
1595 
1596 	pEntry = CreateEntry( sWordsWithDigits,	CBCOL_FIRST );
1597 	aLngCfg.GetProperty( C2U(UPN_IS_SPELL_WITH_DIGITS) ) >>= bVal;
1598 	nUserData = OptionsUserData( EID_WORDS_WITH_DIGITS, sal_False, 0, sal_True, bVal).GetUserData();
1599 	pEntry->SetUserData( (void *)nUserData );
1600 	pModel->Insert( pEntry );
1601 	lcl_SetCheckButton( pEntry, bVal );
1602 
1603 	pEntry = CreateEntry( sCapitalization,	CBCOL_FIRST );
1604 	aLngCfg.GetProperty( C2U(UPN_IS_SPELL_CAPITALIZATION) ) >>= bVal;
1605 	nUserData = OptionsUserData( EID_CAPITALIZATION, sal_False, 0, sal_True, bVal).GetUserData();
1606 	pEntry->SetUserData( (void *)nUserData );
1607 	pModel->Insert( pEntry );
1608 	lcl_SetCheckButton( pEntry, bVal );
1609 
1610 	pEntry = CreateEntry( sSpellSpecial,	CBCOL_FIRST );
1611 	aLngCfg.GetProperty( C2U(UPN_IS_SPELL_SPECIAL) ) >>= bVal;
1612 	nUserData = OptionsUserData( EID_SPELL_SPECIAL, sal_False, 0, sal_True, bVal).GetUserData();
1613 	pEntry->SetUserData( (void *)nUserData );
1614 	pModel->Insert( pEntry );
1615 	lcl_SetCheckButton( pEntry, bVal );
1616 
1617 	pEntry = CreateEntry( sNumMinWordlen,	CBCOL_SECOND );
1618 	aLngCfg.GetProperty( C2U(UPN_HYPH_MIN_WORD_LENGTH) ) >>= nVal;
1619 	nUserData = OptionsUserData( EID_NUM_MIN_WORDLEN, sal_True, (sal_uInt16)nVal, sal_False, sal_False).GetUserData();
1620 	pEntry->SetUserData( (void *)nUserData );
1621 	pModel->Insert( pEntry );
1622 
1623 	const SfxHyphenRegionItem *pHyp = NULL;
1624 	sal_uInt16 nWhich = GetWhich( SID_ATTR_HYPHENREGION );
1625     if ( rSet.GetItemState( nWhich, sal_False ) == SFX_ITEM_SET )
1626 		pHyp = &( (const SfxHyphenRegionItem &) rSet.Get( nWhich ) );
1627 
1628 	pEntry = CreateEntry( sNumPreBreak,		CBCOL_SECOND );
1629 	aLngCfg.GetProperty( C2U(UPN_HYPH_MIN_LEADING) ) >>= nVal;
1630 	if (pHyp)
1631 		nVal = (sal_Int16) pHyp->GetMinLead();
1632 	nUserData = OptionsUserData( EID_NUM_PRE_BREAK, sal_True, (sal_uInt16)nVal, sal_False, sal_False).GetUserData();
1633 	pEntry->SetUserData( (void *)nUserData );
1634 	pModel->Insert( pEntry );
1635 
1636 	pEntry = CreateEntry( sNumPostBreak,	CBCOL_SECOND );
1637 	aLngCfg.GetProperty( C2U(UPN_HYPH_MIN_TRAILING) ) >>= nVal;
1638 	if (pHyp)
1639 		nVal = (sal_Int16) pHyp->GetMinTrail();
1640 	nUserData = OptionsUserData( EID_NUM_POST_BREAK, sal_True, (sal_uInt16)nVal, sal_False, sal_False).GetUserData();
1641 	pEntry->SetUserData( (void *)nUserData );
1642 	pModel->Insert( pEntry );
1643 
1644 	pEntry = CreateEntry( sHyphAuto,		CBCOL_FIRST );
1645 	aLngCfg.GetProperty( C2U(UPN_IS_HYPH_AUTO) ) >>= bVal;
1646 	nUserData = OptionsUserData( EID_HYPH_AUTO, sal_False, 0, sal_True, bVal).GetUserData();
1647 	pEntry->SetUserData( (void *)nUserData );
1648 	pModel->Insert( pEntry );
1649 	lcl_SetCheckButton( pEntry, bVal );
1650 
1651 	pEntry = CreateEntry( sHyphSpecial,		CBCOL_FIRST );
1652 	aLngCfg.GetProperty( C2U(UPN_IS_HYPH_SPECIAL) ) >>= bVal;
1653 	nUserData = OptionsUserData( EID_HYPH_SPECIAL, sal_False, 0, sal_True, bVal).GetUserData();
1654 	pEntry->SetUserData( (void *)nUserData );
1655 	pModel->Insert( pEntry );
1656 	lcl_SetCheckButton( pEntry, bVal );
1657 
1658 	aLinguOptionsCLB.SetUpdateMode(sal_True);
1659 }
1660 
1661 // -----------------------------------------------------------------------
1662 
1663 IMPL_LINK( SvxLinguTabPage, BoxDoubleClickHdl_Impl, SvTreeListBox *, pBox )
1664 {
1665     if (pBox == &aLinguModulesCLB)
1666     {
1667         //! in order to avoid a bug causing a GPF when double clicking
1668         //! on a module entry and exiting the "Edit Modules" dialog
1669         //! after that.
1670         Application::PostUserEvent( LINK(
1671                     this, SvxLinguTabPage, PostDblClickHdl_Impl ) );
1672     }
1673     else if (pBox == &aLinguOptionsCLB)
1674     {
1675         ClickHdl_Impl(&aLinguOptionsEditPB);
1676     }
1677     return 0;
1678 }
1679 
1680 // -----------------------------------------------------------------------
1681 
1682 IMPL_LINK( SvxLinguTabPage, PostDblClickHdl_Impl, SvTreeListBox *, EMPTYARG )
1683 {
1684     ClickHdl_Impl(&aLinguModulesEditPB);
1685 	return 0;
1686 }
1687 
1688 // -----------------------------------------------------------------------
1689 
1690 IMPL_LINK( SvxLinguTabPage, OpenURLHdl_Impl, svt::FixedHyperlink *, EMPTYARG )
1691 {
1692     ::rtl::OUString sURL( aMoreDictsLink.GetURL() );
1693     lcl_OpenURL( sURL );
1694     return 0;
1695 }
1696 
1697 // -----------------------------------------------------------------------
1698 
1699 IMPL_LINK( SvxLinguTabPage, BoxCheckButtonHdl_Impl, SvTreeListBox *, pBox )
1700 {
1701     if (pBox == &aLinguModulesCLB)
1702     {
1703         DBG_ASSERT( pLinguData, "NULL pointer, LinguData missing" );
1704         sal_uInt16 nPos = aLinguModulesCLB.GetSelectEntryPos();
1705         if (nPos != LISTBOX_ENTRY_NOTFOUND  &&  pLinguData)
1706         {
1707             pLinguData->Reconfigure( aLinguModulesCLB.GetText( nPos ),
1708                                      aLinguModulesCLB.IsChecked( nPos ) );
1709         }
1710     }
1711     else if (pBox == &aLinguDicsCLB)
1712     {
1713         sal_uInt16 nPos = aLinguDicsCLB.GetSelectEntryPos();
1714         if (nPos != LISTBOX_ENTRY_NOTFOUND)
1715         {
1716             const uno::Reference< XDictionary > &rDic = aDics.getConstArray()[ nPos ];
1717             if (SvxGetIgnoreAllList() == rDic)
1718             {
1719                 SvLBoxEntry* pEntry = aLinguDicsCLB.GetEntry( nPos );
1720                 if (pEntry)
1721                     lcl_SetCheckButton( pEntry, sal_True );
1722             }
1723         }
1724     }
1725 	return 0;
1726 }
1727 
1728 // -----------------------------------------------------------------------
1729 
1730 IMPL_LINK( SvxLinguTabPage, ClickHdl_Impl, PushButton *, pBtn )
1731 {
1732 	if (&aLinguModulesEditPB == pBtn)
1733 	{
1734 		if (!pLinguData)
1735 			pLinguData = new SvxLinguData_Impl;
1736 
1737         SvxLinguData_Impl   aOldLinguData( *pLinguData );
1738         SvxEditModulesDlg   aDlg( this, *pLinguData );
1739         if (aDlg.Execute() != RET_OK)
1740             *pLinguData = aOldLinguData;
1741 
1742         // evaluate new status of 'bConfigured' flag
1743         sal_uLong nLen = pLinguData->GetDisplayServiceCount();
1744         for (sal_uLong i = 0;  i < nLen;  ++i)
1745             pLinguData->GetDisplayServiceArray()[i].bConfigured = sal_False;
1746         const Locale* pAllLocales = pLinguData->GetAllSupportedLocales().getConstArray();
1747         sal_Int32 nLocales = pLinguData->GetAllSupportedLocales().getLength();
1748         for (sal_Int32 k = 0;  k < nLocales;  ++k)
1749 		{
1750             sal_Int16 nLang = SvxLocaleToLanguage( pAllLocales[k] );
1751             if (pLinguData->GetSpellTable().count( nLang ))
1752                 pLinguData->SetChecked( pLinguData->GetSpellTable()[ nLang ] );
1753             if (pLinguData->GetGrammarTable().count( nLang ))
1754                 pLinguData->SetChecked( pLinguData->GetGrammarTable()[ nLang ] );
1755             if (pLinguData->GetHyphTable().count( nLang ))
1756                 pLinguData->SetChecked( pLinguData->GetHyphTable()[ nLang ] );
1757             if (pLinguData->GetThesTable().count( nLang ))
1758                 pLinguData->SetChecked( pLinguData->GetThesTable()[ nLang ] );
1759 		}
1760 
1761         // show new status of modules
1762         UpdateModulesBox_Impl();
1763 	}
1764     else if (&aLinguDicsNewPB == pBtn)
1765 	{
1766         uno::Reference< XSpellChecker1 > xSpellChecker1;
1767 		SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1768 		if(pFact)
1769 		{
1770 			AbstractSvxNewDictionaryDialog* aDlg = pFact->CreateSvxNewDictionaryDialog( this, xSpellChecker1, RID_SFXDLG_NEWDICT );
1771             DBG_ASSERT(aDlg, "Dialogdiet fail!");
1772 			uno::Reference< XDictionary >  xNewDic;
1773             if ( aDlg->Execute() == RET_OK )
1774                 xNewDic = uno::Reference< XDictionary >( aDlg->GetNewDictionary(), UNO_QUERY );
1775 			if ( xNewDic.is() )
1776 			{
1777 				// add new dics to the end
1778 				sal_Int32 nLen = aDics.getLength();
1779 				aDics.realloc( nLen + 1 );
1780 
1781 				aDics.getArray()[ nLen ] = xNewDic;
1782 
1783 				AddDicBoxEntry( xNewDic, (sal_uInt16) nLen );
1784 			}
1785 			delete aDlg; //add by CHINA001
1786 		}
1787 	}
1788     else if (&aLinguDicsEditPB == pBtn)
1789 	{
1790         SvLBoxEntry *pEntry = aLinguDicsCLB.GetCurEntry();
1791 		if (pEntry)
1792 		{
1793 			DicUserData aData( (sal_uLong) pEntry->GetUserData() );
1794 			sal_uInt16 nDicPos = aData.GetEntryId();
1795 			sal_Int32 nDics = aDics.getLength();
1796 			if (nDicPos < nDics)
1797 			{
1798 				uno::Reference< XDictionary > xDic;
1799 				xDic = aDics.getConstArray()[ nDicPos ];
1800 				if (xDic.is())
1801 				{
1802                     uno::Reference< XSpellChecker1 > xSpellChecker1;
1803 					SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1804 					if(pFact)
1805 					{
1806 						VclAbstractDialog* aDlg = pFact->CreateSvxEditDictionaryDialog( this, xDic->getName(), xSpellChecker1, RID_SFXDLG_EDITDICT );
1807                         DBG_ASSERT(aDlg, "Dialogdiet fail!");
1808                         aDlg->Execute();
1809                         delete aDlg;
1810 					}
1811 				}
1812 			}
1813 		}
1814 	}
1815     else if (&aLinguDicsDelPB == pBtn)
1816 	{
1817 		if ( RET_NO ==
1818 		 	QueryBox( this, CUI_RES( RID_SFXQB_DELDICT ) ).Execute() )
1819 			return 0;
1820 
1821         SvLBoxEntry *pEntry = aLinguDicsCLB.GetCurEntry();
1822 		if (pEntry)
1823 		{
1824 			DicUserData aData( (sal_uLong) pEntry->GetUserData() );
1825 			sal_uInt16 nDicPos = aData.GetEntryId();
1826 			sal_Int32 nDics = aDics.getLength();
1827 			if (nDicPos < nDics)
1828 			{
1829 				uno::Reference< XDictionary > xDic;
1830 				xDic = aDics.getConstArray()[ nDicPos ];
1831 				if (xDic.is())
1832 				{
1833 					if (SvxGetIgnoreAllList() == xDic)
1834 						xDic->clear();
1835 					else
1836 					{
1837 						if (xDicList.is())
1838 							xDicList->removeDictionary( xDic );
1839 
1840 						uno::Reference< frame::XStorable > xStor( xDic, UNO_QUERY );
1841 						if ( xStor->hasLocation() && !xStor->isReadonly() )
1842 						{
1843 							String sURL = xStor->getLocation();
1844 							INetURLObject aObj(sURL);
1845 							DBG_ASSERT( aObj.GetProtocol() == INET_PROT_FILE,
1846 									"non-file URLs cannot be deleted" );
1847 							if ( aObj.GetProtocol() == INET_PROT_FILE )
1848 							{
1849 								KillFile_Impl( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
1850 							}
1851 						}
1852 
1853                         aDics.getArray()[ nDicPos ] = 0;
1854 
1855                         // remove entry from checklistbox
1856                         sal_uLong nCnt = aLinguDicsCLB.GetEntryCount();
1857                         for (sal_uLong i = 0;  i < nCnt;  ++i)
1858                         {
1859                             SvLBoxEntry *pDicEntry = aLinguDicsCLB.GetEntry( i );
1860                             DBG_ASSERT( pDicEntry, "missing entry" );
1861                             if (pDicEntry)
1862                             {
1863                                 DicUserData aDicData( (sal_uLong) pDicEntry->GetUserData() );
1864                                 if (aDicData.GetEntryId() == nDicPos )
1865                                 {
1866                                     aLinguDicsCLB.RemoveEntry( (sal_uInt16) i );
1867                                     break;
1868                                 }
1869                             }
1870                         }
1871                         DBG_ASSERT( nCnt > aLinguDicsCLB.GetEntryCount(),
1872                                 "remove failed ?");
1873 					}
1874 				}
1875 			}
1876 		}
1877 	}
1878 	else if (&aLinguOptionsEditPB == pBtn)
1879 	{
1880 		SvLBoxEntry *pEntry = aLinguOptionsCLB.GetCurEntry();
1881 		DBG_ASSERT( pEntry, "no entry selected" );
1882 		if (pEntry)
1883 		{
1884 			long nVal = -1;
1885 			OptionsUserData aData( (sal_uLong)pEntry->GetUserData() );
1886 			if(aData.HasNumericValue())
1887 			{
1888 				int nRID = -1;
1889 				switch (aData.GetEntryId())
1890 				{
1891 					case EID_NUM_PRE_BREAK	: nRID = STR_NUM_PRE_BREAK_DLG; break;
1892 					case EID_NUM_POST_BREAK	: nRID = STR_NUM_POST_BREAK_DLG; break;
1893 					case EID_NUM_MIN_WORDLEN: nRID = STR_NUM_MIN_WORDLEN_DLG; break;
1894 					default:
1895 						DBG_ERROR( "unexpected case" );
1896 				}
1897 
1898 				OptionsBreakSet aDlg( this, nRID );
1899                 aDlg.GetNumericFld().SetValue( aData.GetNumericValue() );
1900 				if (RET_OK == aDlg.Execute() )
1901 				{
1902 					nVal = static_cast<long>(aDlg.GetNumericFld().GetValue());
1903 					if (-1 != nVal && aData.GetNumericValue() != nVal)
1904 					{
1905 						aData.SetNumericValue( (sal_uInt8)nVal ); //! sets IsModified !
1906 						pEntry->SetUserData( (void *) aData.GetUserData() );
1907 						aLinguOptionsCLB.Invalidate();
1908 					}
1909 				}
1910 			}
1911 		}
1912 	}
1913 	else
1914 	{
1915 		DBG_ERROR( "pBtn unexpected value" );
1916 	}
1917 
1918 	return 0;
1919 }
1920 
1921 // -----------------------------------------------------------------------
1922 
1923 IMPL_LINK( SvxLinguTabPage, SelectHdl_Impl, SvxCheckListBox *, pBox )
1924 {
1925 	if (&aLinguModulesCLB == pBox)
1926 	{
1927 	}
1928     else if (&aLinguDicsCLB == pBox)
1929 	{
1930 		SvLBoxEntry *pEntry = pBox->GetCurEntry();
1931 		if (pEntry)
1932 		{
1933 			DicUserData aData( (sal_uLong) pEntry->GetUserData() );
1934 
1935 			// always allow to edit (i.e. at least view the content of the dictionary)
1936             aLinguDicsEditPB.Enable( true/*aData.IsEditable()*/ );
1937             aLinguDicsDelPB .Enable( aData.IsDeletable() );
1938 		}
1939 	}
1940 	else if (&aLinguOptionsCLB == pBox)
1941 	{
1942 		SvLBoxEntry *pEntry = pBox->GetCurEntry();
1943 		if (pEntry)
1944 		{
1945 			OptionsUserData aData( (sal_uLong) pEntry->GetUserData() );
1946 			aLinguOptionsEditPB.Enable( aData.HasNumericValue() );
1947 		}
1948 	}
1949 	else
1950 	{
1951 		DBG_ERROR( "pBox unexpected value" );
1952 	}
1953 
1954 	return 0;
1955 }
1956 
1957 // -----------------------------------------------------------------------
1958 
1959 SvLBoxEntry* SvxLinguTabPage::CreateEntry( String& rTxt, sal_uInt16 nCol )
1960 {
1961 	SvLBoxEntry* pEntry = new SvLBoxEntry;
1962 
1963 	if( !pCheckButtonData )
1964 		pCheckButtonData = new SvLBoxButtonData( &aLinguOptionsCLB );
1965 
1966 	String sEmpty;
1967 	if (CBCOL_FIRST == nCol)
1968 		pEntry->AddItem( new SvLBoxButton( pEntry, SvLBoxButtonKind_enabledCheckbox, 0, pCheckButtonData ) );
1969 	if (CBCOL_SECOND == nCol)
1970 		pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty) );	// Leerspalte
1971 	pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0));	// Sonst Puff!
1972 	pEntry->AddItem( new BrwString_Impl( pEntry, 0, rTxt ) );
1973 
1974 	return pEntry;
1975 }
1976 
1977 // -----------------------------------------------------------------------
1978 
1979 void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp )
1980 {
1981 	if ( 0 != ( GROUP_MODULES & nGrp ) )
1982 	{
1983 		aLinguModulesFT.Hide();
1984 		aLinguModulesCLB.Hide();
1985 		aLinguModulesEditPB.Hide();
1986 
1987         // reposition / resize remaining controls
1988         long nDeltaY = aLinguDicsFT.GetPosPixel().Y() -
1989                        aLinguModulesFT.GetPosPixel().Y();
1990         DBG_ASSERT( nDeltaY >= 0, "move/resize value is negative" );
1991         Point   aPos;
1992         //
1993         aPos = aLinguDicsFT.GetPosPixel();
1994         aPos.Y() -= nDeltaY;
1995         aLinguDicsFT.SetPosPixel( aPos );
1996         aPos = aLinguDicsCLB.GetPosPixel();
1997         aPos.Y() -= nDeltaY;
1998         aLinguDicsCLB.SetPosPixel( aPos );
1999         aPos = aLinguDicsNewPB.GetPosPixel();
2000         aPos.Y() -= nDeltaY;
2001         aLinguDicsNewPB.SetPosPixel( aPos );
2002         aPos = aLinguDicsEditPB.GetPosPixel();
2003         aPos.Y() -= nDeltaY;
2004         aLinguDicsEditPB.SetPosPixel( aPos );
2005         aPos = aLinguDicsDelPB.GetPosPixel();
2006         aPos.Y() -= nDeltaY;
2007         aLinguDicsDelPB.SetPosPixel( aPos );
2008         //
2009         aPos = aLinguOptionsFT.GetPosPixel();
2010         aPos.Y() -= nDeltaY;
2011         aLinguOptionsFT.SetPosPixel( aPos );
2012         aPos = aLinguOptionsCLB.GetPosPixel();
2013         aPos.Y() -= nDeltaY;
2014         aLinguOptionsCLB.SetPosPixel( aPos );
2015         aPos = aLinguOptionsEditPB.GetPosPixel();
2016         aPos.Y() -= nDeltaY;
2017         aLinguOptionsEditPB.SetPosPixel( aPos );
2018         //
2019         Size aSize( aLinguOptionsCLB.GetSizePixel() );
2020         aSize.Height() += nDeltaY;
2021         aLinguOptionsCLB.SetSizePixel( aSize );
2022 
2023         if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
2024                 != SvtExtendedSecurityOptions::OPEN_NEVER )
2025         {
2026             aSize = GetOutputSizePixel();
2027             aSize.Height() += ( aMoreDictsLink.GetSizePixel().Height() * 11 / 8 );
2028             SetSizePixel( aSize );
2029             aMoreDictsLink.Show();
2030         }
2031 	}
2032 }
2033 /*--------------------------------------------------
2034 --------------------------------------------------*/
2035 
2036 SvxEditModulesDlg::SvxEditModulesDlg(Window* pParent, SvxLinguData_Impl& rData) :
2037     ModalDialog( pParent, CUI_RES(RID_SVXDLG_EDIT_MODULES ) ),
2038     aModulesFL      ( this, CUI_RES( FL_EDIT_MODULES_OPTIONS ) ),
2039     aLanguageFT     ( this, CUI_RES( FT_EDIT_MODULES_LANGUAGE ) ),
2040     aLanguageLB     ( this, CUI_RES( LB_EDIT_MODULES_LANGUAGE ), sal_False ),
2041     aModulesCLB     ( this, CUI_RES( CLB_EDIT_MODULES_MODULES ) ),
2042     aPrioUpPB       ( this, CUI_RES( PB_EDIT_MODULES_PRIO_UP ) ),
2043     aPrioDownPB     ( this, CUI_RES( PB_EDIT_MODULES_PRIO_DOWN ) ),
2044     aBackPB         ( this, CUI_RES( PB_EDIT_MODULES_PRIO_BACK ) ),
2045     aMoreDictsLink  ( this, CUI_RES( FT_EDIT_MODULES_NEWDICTSLINK ) ),
2046     aButtonsFL      ( this, CUI_RES( FL_EDIT_MODULES_BUTTONS ) ),
2047     aHelpPB         ( this, CUI_RES( PB_HELP ) ),
2048     aClosePB        ( this, CUI_RES( PB_OK ) ),
2049     sSpell          (       CUI_RES( ST_SPELL ) ),
2050     sHyph           (       CUI_RES( ST_HYPH ) ),
2051     sThes           (       CUI_RES( ST_THES ) ),
2052     sGrammar        (       CUI_RES( ST_GRAMMAR ) ),
2053     rLinguData      ( rData )
2054 {
2055 	pCheckButtonData = NULL;
2056 	FreeResource();
2057 
2058     pDefaultLinguData = new SvxLinguData_Impl( rLinguData );
2059 
2060 	aModulesCLB.SetStyle( aModulesCLB.GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
2061 	aModulesCLB.SetHighlightRange();
2062 	aModulesCLB.SetHelpId(HID_CLB_EDIT_MODULES_MODULES );
2063 	aModulesCLB.SetSelectHdl( LINK( this, SvxEditModulesDlg, SelectHdl_Impl ));
2064     aModulesCLB.SetCheckButtonHdl( LINK( this, SvxEditModulesDlg, BoxCheckButtonHdl_Impl) );
2065 
2066     aClosePB   .SetClickHdl( LINK( this, SvxEditModulesDlg, ClickHdl_Impl ));
2067     aPrioUpPB  .SetClickHdl( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
2068 	aPrioDownPB.SetClickHdl( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
2069     aBackPB    .SetClickHdl( LINK( this, SvxEditModulesDlg, BackHdl_Impl ));
2070     // in case of not installed language modules
2071     aPrioUpPB  .Enable( sal_False );
2072     aPrioDownPB.Enable( sal_False );
2073 
2074     if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
2075             != SvtExtendedSecurityOptions::OPEN_NEVER )
2076     {
2077         aMoreDictsLink.SetURL( String(
2078             RTL_CONSTASCII_STRINGPARAM( "http://extensions.services.openoffice.org/dictionary?cid=926386" ) ) );
2079         aMoreDictsLink.SetClickHdl( LINK( this, SvxEditModulesDlg, OpenURLHdl_Impl ) );
2080     }
2081     else
2082     {
2083         aMoreDictsLink.Hide();
2084         long nPos = aMoreDictsLink.GetPosPixel().Y() + aMoreDictsLink.GetSizePixel().Height();
2085         Size aSize = aModulesCLB.GetSizePixel();
2086         aSize.Height() += ( nPos - ( aModulesCLB.GetPosPixel().Y() + aSize.Height() ) );
2087         aModulesCLB.SetSizePixel( aSize );
2088     }
2089 
2090     //
2091     //fill language box
2092     //
2093     Sequence< sal_Int16 > aAvailLang;
2094     uno::Reference< XAvailableLocales > xAvail( rLinguData.GetManager(), UNO_QUERY );
2095     if (xAvail.is())
2096     {
2097         aAvailLang = lcl_LocaleSeqToLangSeq(
2098                         xAvail->getAvailableLocales( C2U(cSpell) ) );
2099     }
2100     const Sequence< Locale >& rLoc = rLinguData.GetAllSupportedLocales();
2101 	const Locale* pLocales = rLoc.getConstArray();
2102 	aLanguageLB.Clear();
2103 	for(long i = 0; i < rLoc.getLength(); i++)
2104 	{
2105         sal_Int16 nLang = SvxLocaleToLanguage( pLocales[i] );
2106         aLanguageLB.InsertLanguage( nLang, lcl_SeqHasLang( aAvailLang, nLang ) );
2107 	}
2108 	LanguageType eSysLang = MsLangId::getSystemLanguage();
2109 	aLanguageLB.SelectLanguage( eSysLang );
2110 	if(!aLanguageLB.IsLanguageSelected( eSysLang ) )
2111 		aLanguageLB.SelectEntryPos(0);
2112 
2113 	aLanguageLB.SetSelectHdl( LINK( this, SvxEditModulesDlg, LangSelectHdl_Impl ));
2114 	LangSelectHdl_Impl(&aLanguageLB);
2115 }
2116 
2117 
2118 SvxEditModulesDlg::~SvxEditModulesDlg()
2119 {
2120     delete pDefaultLinguData;
2121 }
2122 
2123 
2124 SvLBoxEntry* SvxEditModulesDlg::CreateEntry( String& rTxt, sal_uInt16 nCol )
2125 {
2126 	SvLBoxEntry* pEntry = new SvLBoxEntry;
2127 	if( !pCheckButtonData )
2128 	{
2129 		pCheckButtonData = new SvLBoxButtonData( &aModulesCLB );
2130         pCheckButtonData->SetLink( aModulesCLB.GetCheckButtonHdl() );
2131 	}
2132 
2133 	String sEmpty;
2134 	if (CBCOL_FIRST == nCol)
2135 		pEntry->AddItem( new SvLBoxButton( pEntry, SvLBoxButtonKind_enabledCheckbox, 0, pCheckButtonData ) );
2136 	if (CBCOL_SECOND == nCol)
2137 		pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty) );	// Leerspalte
2138 	pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0));	// Sonst Puff!
2139 	pEntry->AddItem( new BrwStringDic_Impl( pEntry, 0, rTxt ) );
2140 
2141 	return pEntry;
2142 }
2143 
2144 /* ---------------------------------------------------------------------------
2145 
2146  ---------------------------------------------------------------------------*/
2147 IMPL_LINK( SvxEditModulesDlg, SelectHdl_Impl, SvxCheckListBox *, pBox )
2148 {
2149 	if (&aModulesCLB == pBox)
2150 	{
2151 		sal_Bool bDisableUp = sal_True;
2152 		sal_Bool bDisableDown = sal_True;
2153 		SvLBoxEntry *pEntry = pBox->GetCurEntry();
2154 		if (pEntry)
2155 		{
2156 			ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
2157 			if(!pData->IsParent() && pData->GetType() != TYPE_HYPH)
2158 			{
2159 				sal_uInt16	nCurPos = pBox->GetSelectEntryPos();
2160 				if(nCurPos < pBox->GetEntryCount() - 1)
2161 				{
2162 					bDisableDown = ((ModuleUserData_Impl*)pBox->
2163 							GetEntry(nCurPos + 1)->GetUserData())->IsParent();
2164 				}
2165 				if(nCurPos > 1)
2166 				{
2167             					bDisableUp = ((ModuleUserData_Impl*)pBox->
2168 							GetEntry(nCurPos - 1)->GetUserData())->IsParent();
2169 				}
2170 			}
2171 			aPrioUpPB.Enable(!bDisableUp);
2172 			aPrioDownPB.Enable(!bDisableDown);
2173 		}
2174 	}
2175 	else
2176 	{
2177 		DBG_ERROR( "pBox unexpected value" );
2178 	}
2179 
2180 	return 0;
2181 }
2182 /* -----------------------------28.05.01 11:00--------------------------------
2183 
2184  ---------------------------------------------------------------------------*/
2185 IMPL_LINK( SvxEditModulesDlg, BoxCheckButtonHdl_Impl, SvTreeListBox *, pBox )
2186 {
2187 //    if (pBox == (SvTreeListBox *) &aModulesCLB)
2188 //    {
2189         pBox = &aModulesCLB;
2190 		SvLBoxEntry *pCurEntry = pBox->GetCurEntry();
2191 		if (pCurEntry)
2192 		{
2193 			ModuleUserData_Impl* pData = (ModuleUserData_Impl *)
2194 												pCurEntry->GetUserData();
2195 			if (!pData->IsParent()  &&  pData->GetType() == TYPE_HYPH)
2196 			{
2197 				// make hyphenator checkboxes function as radio-buttons
2198 				// (at most one box may be checked)
2199 				SvLBoxEntry *pEntry = pBox->First();
2200 				while (pEntry)
2201 				{
2202 					pData = (ModuleUserData_Impl *) pEntry->GetUserData();
2203 					if (!pData->IsParent()  &&
2204 						 pData->GetType() == TYPE_HYPH  &&
2205 						 pEntry != pCurEntry)
2206 					{
2207 						lcl_SetCheckButton( pEntry, sal_False );
2208 						pBox->InvalidateEntry( pEntry );
2209 					}
2210 					pEntry = pBox->Next( pEntry );
2211 				}
2212 			}
2213 		}
2214 //    }
2215 	return 0;
2216 }
2217 /* -----------------------------27.11.00 14:00--------------------------------
2218 
2219  ---------------------------------------------------------------------------*/
2220 OUString lcl_GetServiceName(sal_uInt8 nType)
2221 {
2222 	switch(nType)
2223 	{
2224         case  TYPE_SPELL    : return C2U(cSpell);
2225         case  TYPE_GRAMMAR  : return C2U(cGrammar);
2226         case  TYPE_HYPH     : return C2U(cHyph);
2227         case  TYPE_THES     : return C2U(cThes);
2228 	}
2229 	return OUString();
2230 }
2231 
2232 
2233 IMPL_LINK( SvxEditModulesDlg, LangSelectHdl_Impl, ListBox *, pBox )
2234 {
2235 	LanguageType  eCurLanguage = aLanguageLB.GetSelectLanguage();
2236 	static Locale aLastLocale;
2237 	Locale aCurLocale;
2238 	SvxLanguageToLocale(aCurLocale, eCurLanguage);
2239 	SvLBoxTreeList *pModel = aModulesCLB.GetModel();
2240 //	uno::Reference<XLinguServiceManager>&   xMgr = rLinguData.GetManager();
2241 
2242     if (pBox)
2243 	{
2244         // save old probably changed settings
2245         // before switching to new language entries
2246 
2247         sal_Int16 nLang = SvxLocaleToLanguage( aLastLocale );
2248 
2249 		sal_Int32 nStart = 0, nLocalIndex = 0;
2250         Sequence< OUString > aChange;
2251 		sal_Bool bChanged = sal_False;
2252 		for(sal_uInt16 i = 0; i < aModulesCLB.GetEntryCount(); i++)
2253 		{
2254 			SvLBoxEntry *pEntry = aModulesCLB.GetEntry(i);
2255 			ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
2256 			if(pData->IsParent())
2257 			{
2258 				if(bChanged)
2259 				{
2260                     LangImplNameTable *pTable = 0;
2261                     sal_uInt8 nType = pData->GetType();
2262                     switch (nType - 1)
2263                     {
2264                         case  TYPE_SPELL    : pTable = &rLinguData.GetSpellTable(); break;
2265                         case  TYPE_GRAMMAR  : pTable = &rLinguData.GetGrammarTable();  break;
2266                         case  TYPE_HYPH     : pTable = &rLinguData.GetHyphTable();  break;
2267                         case  TYPE_THES     : pTable = &rLinguData.GetThesTable();  break;
2268                     }
2269                     if (pTable)
2270                     {
2271                         aChange.realloc(nStart);
2272                         (*pTable)[ nLang ] = aChange;
2273                     }
2274 				}
2275 				nLocalIndex = nStart = 0;
2276 				aChange.realloc(aModulesCLB.GetEntryCount());
2277 				bChanged = sal_False;
2278 			}
2279 			else
2280 			{
2281 				OUString* pChange = aChange.getArray();
2282 				pChange[nStart] = pData->GetImplName();
2283 				bChanged |= pData->GetIndex() != nLocalIndex ||
2284 					pData->IsChecked() != aModulesCLB.IsChecked(i);
2285 				if(aModulesCLB.IsChecked(i))
2286 					nStart++;
2287 				++nLocalIndex;
2288 			}
2289 		}
2290 		if(bChanged)
2291 		{
2292 			aChange.realloc(nStart);
2293             rLinguData.GetThesTable()[ nLang ] = aChange;
2294 		}
2295 	}
2296 
2297 	for(sal_uLong i = 0; i < aModulesCLB.GetEntryCount(); i++)
2298 		delete (ModuleUserData_Impl*)aModulesCLB.GetEntry(i)->GetUserData();
2299 
2300     //
2301     // display entries for new selected language
2302     //
2303 	aModulesCLB.Clear();
2304 	if(LANGUAGE_DONTKNOW != eCurLanguage)
2305 	{
2306 //		sal_Int32 nEntryPos = 1;
2307 
2308         sal_uLong n;
2309         ServiceInfo_Impl* pInfo;
2310 
2311         //
2312         // spellchecker entries
2313         //
2314 		SvLBoxEntry* pEntry = CreateEntry( sSpell,	CBCOL_SECOND );
2315         ModuleUserData_Impl* pUserData = new ModuleUserData_Impl(
2316                                          String(), sal_True, sal_False, TYPE_SPELL, 0 );
2317 		pEntry->SetUserData( (void *)pUserData );
2318 		pModel->Insert( pEntry );
2319         //
2320         Sequence< OUString > aNames( rLinguData.GetSortedImplNames( eCurLanguage, TYPE_SPELL ) );
2321         const OUString *pName = aNames.getConstArray();
2322         sal_uLong nNames = (sal_uLong) aNames.getLength();
2323 		sal_Int32 nLocalIndex = 0;	// index relative to parent
2324         for (n = 0;  n < nNames;  ++n)
2325 		{
2326 			OUString aImplName;
2327 			sal_Bool	 bIsSuppLang = sal_False;
2328 
2329             pInfo = rLinguData.GetInfoByImplName( pName[n] );
2330 			if (pInfo)
2331 			{
2332 				bIsSuppLang = pInfo->xSpell.is()  &&
2333 							  pInfo->xSpell->hasLocale( aCurLocale );
2334 				aImplName = pInfo->sSpellImplName;
2335 			}
2336             if (aImplName.getLength() && bIsSuppLang)
2337 			{
2338                 String aTxt( pInfo->sDisplayName );
2339                 SvLBoxEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2340 
2341                 LangImplNameTable &rTable = rLinguData.GetSpellTable();
2342                 const bool bHasLang = rTable.count( eCurLanguage );
2343 				if (!bHasLang)
2344 				{
2345 					DBG_WARNING( "language entry missing" );	// only relevant if all languages found should be supported
2346 				}
2347                 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2348                 lcl_SetCheckButton( pNewEntry, bCheck );
2349                 pUserData = new ModuleUserData_Impl( aImplName, sal_False,
2350                                         bCheck, TYPE_SPELL, (sal_uInt8)nLocalIndex++ );
2351                 pNewEntry->SetUserData( (void *)pUserData );
2352                 pModel->Insert( pNewEntry );
2353 			}
2354 		}
2355 
2356         //
2357         // grammar checker entries
2358         //
2359         pEntry = CreateEntry( sGrammar,    CBCOL_SECOND );
2360         pUserData = new ModuleUserData_Impl( String(), sal_True, sal_False, TYPE_GRAMMAR, 0 );
2361         pEntry->SetUserData( (void *)pUserData );
2362         pModel->Insert( pEntry );
2363         //
2364         aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_GRAMMAR );
2365         pName = aNames.getConstArray();
2366         nNames = (sal_uLong) aNames.getLength();
2367         nLocalIndex = 0;
2368         for (n = 0;  n < nNames;  ++n)
2369         {
2370             OUString aImplName;
2371             sal_Bool     bIsSuppLang = sal_False;
2372 
2373             pInfo = rLinguData.GetInfoByImplName( pName[n] );
2374             if (pInfo)
2375             {
2376                 bIsSuppLang = pInfo->xGrammar.is()  &&
2377                               pInfo->xGrammar->hasLocale( aCurLocale );
2378                 aImplName = pInfo->sGrammarImplName;
2379             }
2380             if (aImplName.getLength() && bIsSuppLang)
2381             {
2382                 String aTxt( pInfo->sDisplayName );
2383                 SvLBoxEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2384 
2385                 LangImplNameTable &rTable = rLinguData.GetGrammarTable();
2386                 const bool bHasLang = rTable.count( eCurLanguage );
2387                 if (!bHasLang)
2388                 {
2389                     DBG_WARNING( "language entry missing" );    // only relevant if all languages found should be supported
2390                 }
2391                 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2392                 lcl_SetCheckButton( pNewEntry, bCheck );
2393                 pUserData = new ModuleUserData_Impl( aImplName, sal_False,
2394                                         bCheck, TYPE_GRAMMAR, (sal_uInt8)nLocalIndex++ );
2395                 pNewEntry->SetUserData( (void *)pUserData );
2396                 pModel->Insert( pNewEntry );
2397             }
2398         }
2399 
2400         //
2401         // hyphenator entries
2402         //
2403 		pEntry = CreateEntry( sHyph,	CBCOL_SECOND );
2404 		pUserData = new ModuleUserData_Impl( String(), sal_True, sal_False, TYPE_HYPH, 0 );
2405 		pEntry->SetUserData( (void *)pUserData );
2406 		pModel->Insert( pEntry );
2407         //
2408         aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_HYPH );
2409         pName = aNames.getConstArray();
2410         nNames = (sal_uLong) aNames.getLength();
2411 		nLocalIndex = 0;
2412         for (n = 0;  n < nNames;  ++n)
2413 		{
2414 			OUString aImplName;
2415 			sal_Bool	 bIsSuppLang = sal_False;
2416 
2417             pInfo = rLinguData.GetInfoByImplName( pName[n] );
2418 			if (pInfo)
2419 			{
2420 				bIsSuppLang = pInfo->xHyph.is()  &&
2421 							  pInfo->xHyph->hasLocale( aCurLocale );
2422 				aImplName = pInfo->sHyphImplName;
2423 			}
2424             if (aImplName.getLength() && bIsSuppLang)
2425 			{
2426                 String aTxt( pInfo->sDisplayName );
2427                 SvLBoxEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2428 
2429                 LangImplNameTable &rTable = rLinguData.GetHyphTable();
2430                 const bool bHasLang = rTable.count( eCurLanguage );
2431 				if (!bHasLang)
2432 				{
2433 					DBG_WARNING( "language entry missing" );	// only relevant if all languages found should be supported
2434 				}
2435                 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2436                 lcl_SetCheckButton( pNewEntry, bCheck );
2437                 pUserData = new ModuleUserData_Impl( aImplName, sal_False,
2438                                         bCheck, TYPE_HYPH, (sal_uInt8)nLocalIndex++ );
2439                 pNewEntry->SetUserData( (void *)pUserData );
2440                 pModel->Insert( pNewEntry );
2441 			}
2442 		}
2443 
2444         //
2445         // thesaurus entries
2446         //
2447 		pEntry = CreateEntry( sThes,	CBCOL_SECOND );
2448 		pUserData = new ModuleUserData_Impl( String(), sal_True, sal_False, TYPE_THES, 0 );
2449 		pEntry->SetUserData( (void *)pUserData );
2450 		pModel->Insert( pEntry );
2451         //
2452         aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_THES );
2453         pName = aNames.getConstArray();
2454         nNames = (sal_uLong) aNames.getLength();
2455 		nLocalIndex = 0;
2456         for (n = 0;  n < nNames;  ++n)
2457 		{
2458 			OUString aImplName;
2459 			sal_Bool	 bIsSuppLang = sal_False;
2460 
2461             pInfo = rLinguData.GetInfoByImplName( pName[n] );
2462 			if (pInfo)
2463 			{
2464 				bIsSuppLang = pInfo->xThes.is()  &&
2465 							  pInfo->xThes->hasLocale( aCurLocale );
2466 				aImplName = pInfo->sThesImplName;
2467 			}
2468             if (aImplName.getLength() && bIsSuppLang)
2469 			{
2470                 String aTxt( pInfo->sDisplayName );
2471                 SvLBoxEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2472 
2473                 LangImplNameTable &rTable = rLinguData.GetThesTable();
2474                 const bool bHasLang = rTable.count( eCurLanguage );
2475 				if (!bHasLang)
2476 				{
2477 					DBG_WARNING( "language entry missing" );	// only relevant if all languages found should be supported
2478 				}
2479                 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2480                 lcl_SetCheckButton( pNewEntry, bCheck );
2481                 pUserData = new ModuleUserData_Impl( aImplName, sal_False,
2482                                         bCheck, TYPE_THES, (sal_uInt8)nLocalIndex++ );
2483                 pNewEntry->SetUserData( (void *)pUserData );
2484                 pModel->Insert( pNewEntry );
2485 			}
2486 		}
2487 	}
2488 	aLastLocale.Language = aCurLocale.Language;
2489 	aLastLocale.Country = aCurLocale.Country;
2490 	return 0;
2491 }
2492 /* -----------------------------27.11.00 19:50--------------------------------
2493 
2494  ---------------------------------------------------------------------------*/
2495 IMPL_LINK( SvxEditModulesDlg, UpDownHdl_Impl, PushButton *, pBtn )
2496 {
2497 	sal_Bool bUp = &aPrioUpPB == pBtn;
2498 	sal_uInt16	nCurPos = aModulesCLB.GetSelectEntryPos();
2499     SvLBoxEntry* pEntry;
2500     if (nCurPos != LISTBOX_ENTRY_NOTFOUND  &&
2501         0 != (pEntry = aModulesCLB.GetEntry(nCurPos)))
2502     {
2503         aModulesCLB.SetUpdateMode(sal_False);
2504         SvLBoxTreeList *pModel = aModulesCLB.GetModel();
2505 
2506         ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
2507         String aStr(aModulesCLB.GetEntryText(pEntry));
2508         SvLBoxEntry* pToInsert = CreateEntry( aStr, CBCOL_FIRST );
2509         pToInsert->SetUserData( (void *)pData);
2510         sal_Bool bIsChecked = aModulesCLB.IsChecked(nCurPos);
2511 
2512         pModel->Remove(pEntry);
2513 
2514         sal_uInt16 nDestPos = bUp ? nCurPos - 1 : nCurPos + 1;
2515         pModel->Insert(pToInsert, nDestPos);
2516         aModulesCLB.CheckEntryPos(nDestPos, bIsChecked );
2517         aModulesCLB.SelectEntryPos(nDestPos );
2518         SelectHdl_Impl(&aModulesCLB);
2519         aModulesCLB.SetUpdateMode(sal_True);
2520     }
2521 	return 0;
2522 }
2523 /* ---------------------------------------------------------------------------
2524 
2525  ---------------------------------------------------------------------------*/
2526 IMPL_LINK( SvxEditModulesDlg, ClickHdl_Impl, PushButton *, pBtn )
2527 {
2528 	if (&aClosePB == pBtn)
2529 	{
2530 		// store language config
2531 		LangSelectHdl_Impl(&aLanguageLB);
2532 		EndDialog( RET_OK );
2533 	}
2534 	else
2535 	{
2536 		DBG_ERROR( "pBtn unexpected value" );
2537 	}
2538 
2539 	return 0;
2540 }
2541 /* -----------------------------27.11.00 20:31--------------------------------
2542 
2543  ---------------------------------------------------------------------------*/
2544 IMPL_LINK( SvxEditModulesDlg, BackHdl_Impl, PushButton *, EMPTYARG )
2545 {
2546     rLinguData = *pDefaultLinguData;
2547 	LangSelectHdl_Impl(0);
2548 	return 0;
2549 }
2550 
2551 // -----------------------------------------------------------------------
2552 
2553 IMPL_LINK( SvxEditModulesDlg, OpenURLHdl_Impl, svt::FixedHyperlink *, EMPTYARG )
2554 {
2555     ::rtl::OUString sURL( aMoreDictsLink.GetURL() );
2556     lcl_OpenURL( sURL );
2557     return 0;
2558 }
2559 
2560