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