Bump version to 4.3-4
[LibreOffice.git] / cui / source / options / optlingu.cxx
blob6168506a864d8262dc300cb6dae008c6bb78f6c0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/msgbox.hxx>
21 #include <vcl/field.hxx>
22 #include <vcl/fixed.hxx>
23 #include <vcl/settings.hxx>
24 #include <tools/shl.hxx>
25 #include <i18nlangtag/mslangid.hxx>
26 #include <unotools/lingucfg.hxx>
27 #include <editeng/unolingu.hxx>
28 #include <svx/dlgutil.hxx>
29 #include <linguistic/lngprops.hxx>
30 #include <linguistic/misc.hxx>
31 #include <sfx2/sfxuno.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <tools/urlobj.hxx>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <comphelper/processfactory.hxx>
36 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
37 #include <com/sun/star/linguistic2/XSpellChecker.hpp>
38 #include <com/sun/star/linguistic2/XProofreader.hpp>
39 #include <com/sun/star/linguistic2/XHyphenator.hpp>
40 #include <com/sun/star/linguistic2/XThesaurus.hpp>
41 #include <com/sun/star/linguistic2/XAvailableLocales.hpp>
42 #include <com/sun/star/lang/XServiceDisplayName.hpp>
43 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
44 #include <com/sun/star/linguistic2/DictionaryListEvent.hpp>
45 #include <com/sun/star/linguistic2/XDictionaryListEventListener.hpp>
46 #include <com/sun/star/linguistic2/XDictionaryList.hpp>
47 #include <com/sun/star/frame/XStorable.hpp>
48 #include <com/sun/star/ucb/CommandAbortedException.hpp>
49 #include <com/sun/star/system/SystemShellExecute.hpp>
50 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
51 #include <unotools/extendedsecurityoptions.hxx>
52 #include <svtools/treelistbox.hxx>
53 #include "svtools/treelistentry.hxx"
54 #include <svtools/langhelp.hxx>
55 #include <svl/eitem.hxx>
56 #include <svl/intitem.hxx>
57 #include <sfx2/viewfrm.hxx>
58 #include <vcl/svapp.hxx>
60 #include <svx/svxdlg.hxx>
61 #include <editeng/optitems.hxx>
62 #include "optlingu.hxx"
63 #include <dialmgr.hxx>
64 #include <cuires.hrc>
65 #include "helpid.hrc"
67 #include <ucbhelper/content.hxx>
69 #include <vector>
70 #include <map>
73 using namespace ::ucbhelper;
74 using namespace ::rtl;
75 using namespace ::com::sun::star;
76 using namespace ::com::sun::star::lang;
77 using namespace ::com::sun::star::uno;
78 using namespace ::com::sun::star::linguistic2;
79 using namespace ::com::sun::star::beans;
81 #define CBCOL_FIRST 0
82 #define CBCOL_SECOND 1
84 static const sal_Char cSpell[] = SN_SPELLCHECKER;
85 static const sal_Char cGrammar[] = SN_GRAMMARCHECKER;
86 static const sal_Char cHyph[] = SN_HYPHENATOR;
87 static const sal_Char cThes[] = SN_THESAURUS;
89 // static ----------------------------------------------------------------
91 static Sequence< sal_Int16 > lcl_LocaleSeqToLangSeq( const Sequence< Locale > &rSeq )
93 sal_Int32 nLen = rSeq.getLength();
94 Sequence< sal_Int16 > aRes( nLen );
95 sal_Int16 *pRes = aRes.getArray();
96 const Locale *pSeq = rSeq.getConstArray();
97 for (sal_Int32 i = 0; i < nLen; ++i)
99 pRes[i] = LanguageTag::convertToLanguageType( pSeq[i] );
101 return aRes;
105 static bool lcl_SeqHasLang( const Sequence< sal_Int16 > &rSeq, sal_Int16 nLang )
107 sal_Int32 nLen = rSeq.getLength();
108 const sal_Int16 *pLang = rSeq.getConstArray();
109 sal_Int32 nPos = -1;
110 for (sal_Int32 i = 0; i < nLen && nPos < 0; ++i)
112 if (nLang == pLang[i])
113 nPos = i;
115 return nPos >= 0;
119 static sal_Int32 lcl_SeqGetEntryPos(
120 const Sequence< OUString > &rSeq, const OUString &rEntry )
122 sal_Int32 i;
123 sal_Int32 nLen = rSeq.getLength();
124 const OUString *pItem = rSeq.getConstArray();
125 for (i = 0; i < nLen; ++i)
127 if (rEntry == pItem[i])
128 break;
130 return i < nLen ? i : -1;
133 static void lcl_OpenURL( const OUString& _sURL )
135 if ( !_sURL.isEmpty() )
137 OUString sURL = _sURL;
138 localizeWebserviceURI(sURL);
141 uno::Reference< uno::XComponentContext > xContext =
142 ::comphelper::getProcessComponentContext();
143 uno::Reference< css::system::XSystemShellExecute > xSystemShell(
144 css::system::SystemShellExecute::create(xContext) );
145 xSystemShell->execute( sURL, OUString(), css::system::SystemShellExecuteFlags::URIS_ONLY );
147 catch( const uno::Exception& e )
149 OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
150 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
155 static const sal_uInt16 pRanges[] =
157 SID_ATTR_SPELL,
158 SID_ATTR_SPELL,
162 bool KillFile_Impl( const OUString& rURL )
164 bool bRet = true;
167 Content aCnt( rURL, uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
168 aCnt.executeCommand( OUString("delete"), makeAny( true ) );
170 catch( ::com::sun::star::ucb::CommandAbortedException& )
172 SAL_WARN( "cui.options", "KillFile: CommandAbortedException" );
173 bRet = false;
175 catch( ... )
177 SAL_WARN( "cui.options", "KillFile: Any other exception" );
178 bRet = false;
181 return bRet;
184 // 0x 0p 0t 0c nn
185 // p: 1 -> parent
186 // t: 1 -> spell, 2 -> hyph, 3 -> thes, 4 -> grammar
187 // c: 1 -> checked 0 -> unchecked
188 // n: index
190 #define TYPE_SPELL (sal_uInt8)1
191 #define TYPE_GRAMMAR (sal_uInt8)2
192 #define TYPE_HYPH (sal_uInt8)3
193 #define TYPE_THES (sal_uInt8)4
195 class ModuleUserData_Impl
197 bool bParent;
198 bool bIsChecked;
199 sal_uInt8 nType;
200 sal_uInt8 nIndex;
201 OUString sImplName;
203 public:
204 ModuleUserData_Impl( const OUString& sImpName, bool bIsParent, bool bChecked, sal_uInt8 nSetType, sal_uInt8 nSetIndex ) :
205 bParent(bIsParent),
206 bIsChecked(bChecked),
207 nType(nSetType),
208 nIndex(nSetIndex),
209 sImplName(sImpName)
212 bool IsParent() const {return bParent;}
213 sal_uInt8 GetType() const {return nType;}
214 bool IsChecked() const {return bIsChecked;}
215 sal_uInt8 GetIndex() const {return nIndex;}
216 const OUString& GetImplName() const {return sImplName;}
221 // User for user-dictionaries (XDictionary interface)
223 class DicUserData
225 sal_uLong nVal;
227 public:
228 DicUserData( sal_uLong nUserData ) : nVal( nUserData ) {}
229 DicUserData( sal_uInt16 nEID,
230 bool bChecked, bool bEditable, bool bDeletable );
232 sal_uLong GetUserData() const { return nVal; }
233 sal_uInt16 GetEntryId() const { return (sal_uInt16)(nVal >> 16); }
234 bool IsChecked() const { return (bool)((nVal >> 8) & 0x01); }
235 bool IsDeletable() const { return (bool)((nVal >> 10) & 0x01); }
239 DicUserData::DicUserData(
240 sal_uInt16 nEID,
241 bool bChecked, bool bEditable, bool bDeletable )
243 DBG_ASSERT( nEID < 65000, "Entry Id out of range" );
244 nVal = ((sal_uLong)(0xFFFF & nEID) << 16) |
245 ((sal_uLong)(bChecked ? 1 : 0) << 8) |
246 ((sal_uLong)(bEditable ? 1 : 0) << 9) |
247 ((sal_uLong)(bDeletable ? 1 : 0) << 10);
251 // class BrwString_Impl -------------------------------------------------
253 static void lcl_SetCheckButton( SvTreeListEntry* pEntry, bool bCheck )
255 SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
257 DBG_ASSERT(pItem,"SetCheckButton:Item not found");
258 if (pItem->GetType() == SV_ITEM_ID_LBOXBUTTON)
260 if (bCheck)
261 pItem->SetStateChecked();
262 else
263 pItem->SetStateUnchecked();
268 class BrwStringDic_Impl : public SvLBoxString
270 public:
272 BrwStringDic_Impl( SvTreeListEntry* pEntry, sal_uInt16 nFlags,
273 const OUString& rStr ) : SvLBoxString( pEntry, nFlags, rStr ) {}
275 virtual void Paint(
276 const Point& rPos, SvTreeListBox& rOutDev, const SvViewDataEntry* pView, const SvTreeListEntry* pEntry) SAL_OVERRIDE;
279 void BrwStringDic_Impl::Paint(
280 const Point& rPos, SvTreeListBox& rDev, const SvViewDataEntry* /*pView*/,
281 const SvTreeListEntry* pEntry)
283 ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
284 Point aPos(rPos);
285 Font aOldFont( rDev.GetFont());
286 if(pData->IsParent())
288 Font aFont( aOldFont );
289 aFont.SetWeight( WEIGHT_BOLD );
290 rDev.SetFont( aFont );
291 aPos.X() = 0;
293 else
294 aPos.X() += 5;
295 rDev.DrawText( aPos, GetText() );
296 rDev.SetFont( aOldFont );
299 /*--------------------------------------------------
300 Entry IDs for options listbox of dialog
301 --------------------------------------------------*/
303 enum EID_OPTIONS
305 EID_SPELL_AUTO,
306 EID_GRAMMAR_AUTO,
307 EID_CAPITAL_WORDS,
308 EID_WORDS_WITH_DIGITS,
309 EID_SPELL_SPECIAL,
310 EID_NUM_MIN_WORDLEN,
311 EID_NUM_PRE_BREAK,
312 EID_NUM_POST_BREAK,
313 EID_HYPH_AUTO,
314 EID_HYPH_SPECIAL
317 //! this array must have an entry for every value of EID_OPTIONS.
318 // It is used to get the respective property name.
319 static const char * aEidToPropName[] =
321 UPN_IS_SPELL_AUTO, // EID_SPELL_AUTO
322 UPN_IS_GRAMMAR_AUTO, // EID_GRAMMAR_AUTO
323 UPN_IS_SPELL_UPPER_CASE, // EID_CAPITAL_WORDS
324 UPN_IS_SPELL_WITH_DIGITS, // EID_WORDS_WITH_DIGITS
325 UPN_IS_SPELL_SPECIAL, // EID_SPELL_SPECIAL
326 UPN_HYPH_MIN_WORD_LENGTH, // EID_NUM_MIN_WORDLEN,
327 UPN_HYPH_MIN_LEADING, // EID_NUM_PRE_BREAK
328 UPN_HYPH_MIN_TRAILING, // EID_NUM_POST_BREAK
329 UPN_IS_HYPH_AUTO, // EID_HYPH_AUTO
330 UPN_IS_HYPH_SPECIAL // EID_HYPH_SPECIAL
333 static inline OUString lcl_GetPropertyName( EID_OPTIONS eEntryId )
335 DBG_ASSERT( (unsigned int) eEntryId < SAL_N_ELEMENTS(aEidToPropName), "index out of range" );
336 return OUString::createFromAscii( aEidToPropName[ (int) eEntryId ] );
339 class OptionsBreakSet : public ModalDialog
341 VclFrame* m_pBeforeFrame;
342 VclFrame* m_pAfterFrame;
343 VclFrame* m_pMinimalFrame;
344 NumericField* m_pBreakNF;
346 public:
347 OptionsBreakSet(Window* pParent, sal_uInt16 nRID)
348 : ModalDialog(pParent, "BreakNumberOption",
349 "cui/ui/breaknumberoption.ui")
350 , m_pBreakNF(NULL)
352 get(m_pBeforeFrame, "beforeframe");
353 get(m_pAfterFrame, "afterframe");
354 get(m_pMinimalFrame, "miniframe");
356 assert(EID_NUM_PRE_BREAK == nRID ||
357 EID_NUM_POST_BREAK == nRID ||
358 EID_NUM_MIN_WORDLEN == nRID); //unexpected ID
360 if (nRID == EID_NUM_PRE_BREAK)
362 m_pBeforeFrame->Show();
363 get(m_pBreakNF, "beforebreak");
365 else if(nRID == EID_NUM_POST_BREAK)
367 m_pAfterFrame->Show();
368 get(m_pBreakNF, "afterbreak");
370 else if(nRID == EID_NUM_MIN_WORDLEN)
372 m_pMinimalFrame->Show();
373 get(m_pBreakNF, "wordlength");
377 NumericField& GetNumericFld()
379 return *m_pBreakNF;
383 // class OptionsUserData -------------------------------------------------
385 class OptionsUserData
387 sal_uLong nVal;
389 void SetModified();
391 public:
392 OptionsUserData( sal_uLong nUserData ) : nVal( nUserData ) {}
393 OptionsUserData( sal_uInt16 nEID,
394 bool bHasNV, sal_uInt16 nNumVal,
395 bool bCheckable, bool bChecked );
397 sal_uLong GetUserData() const { return nVal; }
398 sal_uInt16 GetEntryId() const { return (sal_uInt16)(nVal >> 16); }
399 bool HasNumericValue() const { return (bool)((nVal >> 10) & 0x01); }
400 sal_uInt16 GetNumericValue() const { return (sal_uInt16)(nVal & 0xFF); }
401 bool IsCheckable() const { return (bool)((nVal >> 9) & 0x01); }
402 bool IsModified() const { return (bool)((nVal >> 11) & 0x01); }
404 void SetNumericValue( sal_uInt8 nNumVal );
407 OptionsUserData::OptionsUserData( sal_uInt16 nEID,
408 bool bHasNV, sal_uInt16 nNumVal,
409 bool bCheckable, bool bChecked )
411 DBG_ASSERT( nEID < 65000, "Entry Id out of range" );
412 DBG_ASSERT( nNumVal < 256, "value out of range" );
413 nVal = ((sal_uLong)(0xFFFF & nEID) << 16) |
414 ((sal_uLong)(bHasNV ? 1 : 0) << 10) |
415 ((sal_uLong)(bCheckable ? 1 : 0) << 9) |
416 ((sal_uLong)(bChecked ? 1 : 0) << 8) |
417 ((sal_uLong)(0xFF & nNumVal));
420 void OptionsUserData::SetNumericValue( sal_uInt8 nNumVal )
422 if (HasNumericValue() && (GetNumericValue() != nNumVal))
424 nVal &= 0xffffff00;
425 nVal |= (nNumVal);
426 SetModified();
430 void OptionsUserData::SetModified()
432 nVal |= (sal_uLong)1 << 11;
435 // class BrwString_Impl -------------------------------------------------
437 class BrwString_Impl : public SvLBoxString
439 public:
441 BrwString_Impl( SvTreeListEntry* pEntry, sal_uInt16 nFlags,
442 const OUString& rStr ) : SvLBoxString( pEntry, nFlags, rStr ) {}
444 virtual void Paint(
445 const Point& rPos, SvTreeListBox& rOutDev, const SvViewDataEntry* pView, const SvTreeListEntry* pEntry) SAL_OVERRIDE;
448 void BrwString_Impl::Paint(
449 const Point& rPos, SvTreeListBox& rDev, const SvViewDataEntry* /*pView*/,
450 const SvTreeListEntry* pEntry)
452 Point aPos(rPos);
453 aPos.X() += 20;
454 rDev.DrawText( aPos, GetText() );
455 if(pEntry->GetUserData())
457 Point aNewPos(aPos);
458 aNewPos.X() += rDev.GetTextWidth(GetText());
459 Font aOldFont( rDev.GetFont());
460 Font aFont( aOldFont );
461 aFont.SetWeight( WEIGHT_BOLD );
463 //??? convert the lower byte from the user date into a string
464 OptionsUserData aData( (sal_uLong) pEntry->GetUserData() );
465 if(aData.HasNumericValue())
467 OUStringBuffer sTxt;
468 sTxt.append(' ').append(static_cast<sal_Int32>(aData.GetNumericValue()));
469 rDev.SetFont( aFont );
470 rDev.DrawText( aNewPos, sTxt.makeStringAndClear() );
473 rDev.SetFont( aOldFont );
477 // ServiceInfo_Impl ----------------------------------------------------
479 struct ServiceInfo_Impl
481 OUString sDisplayName;
482 OUString sSpellImplName;
483 OUString sHyphImplName;
484 OUString sThesImplName;
485 OUString sGrammarImplName;
486 uno::Reference< XSpellChecker > xSpell;
487 uno::Reference< XHyphenator > xHyph;
488 uno::Reference< XThesaurus > xThes;
489 uno::Reference< XProofreader > xGrammar;
490 bool bConfigured;
492 ServiceInfo_Impl() : bConfigured(false) {}
495 typedef std::vector< ServiceInfo_Impl > ServiceInfoArr;
496 typedef std::map< sal_Int16 /*LanguageType*/, Sequence< OUString > > LangImplNameTable;
499 // SvxLinguData_Impl ----------------------------------------------------
501 class SvxLinguData_Impl
503 //contains services and implementation names sorted by implementation names
504 ServiceInfoArr aDisplayServiceArr;
505 sal_uLong nDisplayServices;
507 Sequence< Locale > aAllServiceLocales;
508 LangImplNameTable aCfgSpellTable;
509 LangImplNameTable aCfgHyphTable;
510 LangImplNameTable aCfgThesTable;
511 LangImplNameTable aCfgGrammarTable;
512 uno::Reference< XLinguServiceManager2 > xLinguSrvcMgr;
515 bool AddRemove( Sequence< OUString > &rConfigured,
516 const OUString &rImplName, bool bAdd );
518 public:
519 SvxLinguData_Impl();
520 SvxLinguData_Impl( const SvxLinguData_Impl &rData );
521 ~SvxLinguData_Impl();
523 SvxLinguData_Impl & operator = (const SvxLinguData_Impl &rData);
525 uno::Reference<XLinguServiceManager2> & GetManager() { return xLinguSrvcMgr; }
527 void SetChecked( const Sequence< OUString > &rConfiguredServices );
528 void Reconfigure( const OUString &rDisplayName, bool bEnable );
530 const Sequence<Locale> & GetAllSupportedLocales() const { return aAllServiceLocales; }
532 LangImplNameTable & GetSpellTable() { return aCfgSpellTable; }
533 LangImplNameTable & GetHyphTable() { return aCfgHyphTable; }
534 LangImplNameTable & GetThesTable() { return aCfgThesTable; }
535 LangImplNameTable & GetGrammarTable() { return aCfgGrammarTable; }
537 ServiceInfoArr & GetDisplayServiceArray() { return aDisplayServiceArr; }
539 const sal_uLong & GetDisplayServiceCount() const { return nDisplayServices; }
540 void SetDisplayServiceCount( sal_uLong nVal ) { nDisplayServices = nVal; }
542 // returns the list of service implementation names for the specified
543 // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in
544 // the proper order for the SvxEditModulesDlg (the ones from the
545 // configuration (keeping that order!) first and then the other ones.
546 // I.e. the ones available but not configured in arbitrary order).
547 // They available ones may contain names that do not(!) support that
548 // language.
549 Sequence< OUString > GetSortedImplNames( sal_Int16 nLang, sal_uInt8 nType );
551 ServiceInfo_Impl * GetInfoByImplName( const OUString &rSvcImplName );
555 static sal_Int32 lcl_SeqGetIndex( const Sequence< OUString > &rSeq, const OUString &rTxt )
557 sal_Int32 nRes = -1;
558 sal_Int32 nLen = rSeq.getLength();
559 const OUString *pString = rSeq.getConstArray();
560 for (sal_Int32 i = 0; i < nLen && nRes == -1; ++i)
562 if (pString[i] == rTxt)
563 nRes = i;
565 return nRes;
569 Sequence< OUString > SvxLinguData_Impl::GetSortedImplNames( sal_Int16 nLang, sal_uInt8 nType )
571 LangImplNameTable *pTable = 0;
572 switch (nType)
574 case TYPE_SPELL : pTable = &aCfgSpellTable; break;
575 case TYPE_HYPH : pTable = &aCfgHyphTable; break;
576 case TYPE_THES : pTable = &aCfgThesTable; break;
577 case TYPE_GRAMMAR : pTable = &aCfgGrammarTable; break;
579 Sequence< OUString > aRes;
580 if (!pTable)
582 SAL_WARN( "cui.options", "unknown linguistic type" );
583 return aRes;
585 if (pTable->count( nLang ))
586 aRes = (*pTable)[ nLang ]; // add configured services
587 sal_Int32 nIdx = aRes.getLength();
588 DBG_ASSERT( (sal_Int32) nDisplayServices >= nIdx, "size mismatch" );
589 aRes.realloc( nDisplayServices );
590 OUString *pRes = aRes.getArray();
592 // add not configured services
593 for (sal_Int32 i = 0; i < (sal_Int32) nDisplayServices; ++i)
595 const ServiceInfo_Impl &rInfo = aDisplayServiceArr[ i ];
596 OUString aImplName;
597 switch (nType)
599 case TYPE_SPELL : aImplName = rInfo.sSpellImplName; break;
600 case TYPE_HYPH : aImplName = rInfo.sHyphImplName; break;
601 case TYPE_THES : aImplName = rInfo.sThesImplName; break;
602 case TYPE_GRAMMAR : aImplName = rInfo.sGrammarImplName; break;
605 if (!aImplName.isEmpty() && (lcl_SeqGetIndex( aRes, aImplName) == -1)) // name not yet added
607 DBG_ASSERT( nIdx < aRes.getLength(), "index out of range" );
608 if (nIdx < aRes.getLength())
609 pRes[ nIdx++ ] = aImplName;
612 // don't forget to put aRes back to its actual size just in case you allocated too much
613 // since all of the names may have already been added
614 // otherwise you get duplicate entries in the edit dialog
615 aRes.realloc( nIdx );
616 return aRes;
620 ServiceInfo_Impl * SvxLinguData_Impl::GetInfoByImplName( const OUString &rSvcImplName )
622 ServiceInfo_Impl* pInfo = 0;
623 for (sal_uLong i = 0; i < nDisplayServices && !pInfo; ++i)
625 ServiceInfo_Impl &rTmp = aDisplayServiceArr[ i ];
626 if (rTmp.sSpellImplName == rSvcImplName ||
627 rTmp.sHyphImplName == rSvcImplName ||
628 rTmp.sThesImplName == rSvcImplName ||
629 rTmp.sGrammarImplName == rSvcImplName)
630 pInfo = &rTmp;
632 return pInfo;
638 static void lcl_MergeLocales(Sequence< Locale >& aAllLocales, const Sequence< Locale >& rAdd)
640 const Locale* pAdd = rAdd.getConstArray();
641 Sequence<Locale> aLocToAdd(rAdd.getLength());
642 const Locale* pAllLocales = aAllLocales.getConstArray();
643 Locale* pLocToAdd = aLocToAdd.getArray();
644 sal_Int32 nFound = 0;
645 sal_Int32 i;
646 for(i = 0; i < rAdd.getLength(); i++)
648 bool bFound = false;
649 for(sal_Int32 j = 0; j < aAllLocales.getLength() && !bFound; j++)
651 bFound = pAdd[i].Language == pAllLocales[j].Language &&
652 pAdd[i].Country == pAllLocales[j].Country &&
653 pAdd[i].Variant == pAllLocales[j].Variant;
655 if(!bFound)
657 pLocToAdd[nFound++] = pAdd[i];
660 sal_Int32 nLength = aAllLocales.getLength();
661 aAllLocales.realloc( nLength + nFound);
662 Locale* pAllLocales2 = aAllLocales.getArray();
663 for(i = 0; i < nFound; i++)
664 pAllLocales2[nLength++] = pLocToAdd[i];
667 static void lcl_MergeDisplayArray(
668 SvxLinguData_Impl &rData,
669 const ServiceInfo_Impl &rToAdd )
671 sal_uLong nCnt = 0;
673 ServiceInfoArr &rSvcInfoArr = rData.GetDisplayServiceArray();
674 sal_uLong nEntries = rData.GetDisplayServiceCount();
676 ServiceInfo_Impl* pEntry;
677 for (sal_uLong i = 0; i < nEntries; ++i)
679 pEntry = &rSvcInfoArr[i];
680 if (pEntry && pEntry->sDisplayName == rToAdd.sDisplayName)
682 if(rToAdd.xSpell.is())
684 DBG_ASSERT( !pEntry->xSpell.is() &&
685 pEntry->sSpellImplName.isEmpty(),
686 "merge conflict" );
687 pEntry->sSpellImplName = rToAdd.sSpellImplName;
688 pEntry->xSpell = rToAdd.xSpell;
690 if(rToAdd.xGrammar.is())
692 DBG_ASSERT( !pEntry->xGrammar.is() &&
693 pEntry->sGrammarImplName.isEmpty(),
694 "merge conflict" );
695 pEntry->sGrammarImplName = rToAdd.sGrammarImplName;
696 pEntry->xGrammar = rToAdd.xGrammar;
698 if(rToAdd.xHyph.is())
700 DBG_ASSERT( !pEntry->xHyph.is() &&
701 pEntry->sHyphImplName.isEmpty(),
702 "merge conflict" );
703 pEntry->sHyphImplName = rToAdd.sHyphImplName;
704 pEntry->xHyph = rToAdd.xHyph;
706 if(rToAdd.xThes.is())
708 DBG_ASSERT( !pEntry->xThes.is() &&
709 pEntry->sThesImplName.isEmpty(),
710 "merge conflict" );
711 pEntry->sThesImplName = rToAdd.sThesImplName;
712 pEntry->xThes = rToAdd.xThes;
714 return ;
716 ++nCnt;
718 rData.GetDisplayServiceArray().push_back( rToAdd );
719 rData.SetDisplayServiceCount( nCnt + 1 );
722 SvxLinguData_Impl::SvxLinguData_Impl() :
723 nDisplayServices (0)
725 uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
726 xLinguSrvcMgr = LinguServiceManager::create(xContext);
728 const Locale& rCurrentLocale = Application::GetSettings().GetLanguageTag().getLocale();
729 Sequence<Any> aArgs(2);//second arguments has to be empty!
730 aArgs.getArray()[0] <<= SvxGetLinguPropertySet();
732 //read spell checker
733 Sequence< OUString > aSpellNames = xLinguSrvcMgr->getAvailableServices(
734 cSpell, Locale() );
735 const OUString* pSpellNames = aSpellNames.getConstArray();
737 sal_Int32 nIdx;
738 for(nIdx = 0; nIdx < aSpellNames.getLength(); nIdx++)
740 ServiceInfo_Impl aInfo;
741 aInfo.sSpellImplName = pSpellNames[nIdx];
742 aInfo.xSpell = uno::Reference<XSpellChecker>(
743 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sSpellImplName, aArgs, xContext), UNO_QUERY);
745 uno::Reference<XServiceDisplayName> xDispName(aInfo.xSpell, UNO_QUERY);
746 if(xDispName.is())
747 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
749 const Sequence< Locale > aLocales( aInfo.xSpell->getLocales() );
750 //! suppress display of entries with no supported languages (see feature 110994)
751 if (aLocales.getLength())
753 lcl_MergeLocales( aAllServiceLocales, aLocales );
754 lcl_MergeDisplayArray( *this, aInfo );
758 //read grammar checker
759 Sequence< OUString > aGrammarNames = xLinguSrvcMgr->getAvailableServices(
760 cGrammar, Locale() );
761 const OUString* pGrammarNames = aGrammarNames.getConstArray();
762 for(nIdx = 0; nIdx < aGrammarNames.getLength(); nIdx++)
764 ServiceInfo_Impl aInfo;
765 aInfo.sGrammarImplName = pGrammarNames[nIdx];
766 aInfo.xGrammar = uno::Reference<XProofreader>(
767 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sGrammarImplName, aArgs, xContext), UNO_QUERY);
769 uno::Reference<XServiceDisplayName> xDispName(aInfo.xGrammar, UNO_QUERY);
770 if(xDispName.is())
771 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
773 const Sequence< Locale > aLocales( aInfo.xGrammar->getLocales() );
774 //! suppress display of entries with no supported languages (see feature 110994)
775 if (aLocales.getLength())
777 lcl_MergeLocales( aAllServiceLocales, aLocales );
778 lcl_MergeDisplayArray( *this, aInfo );
782 //read hyphenator
783 Sequence< OUString > aHyphNames = xLinguSrvcMgr->getAvailableServices(
784 cHyph, Locale() );
785 const OUString* pHyphNames = aHyphNames.getConstArray();
786 for(nIdx = 0; nIdx < aHyphNames.getLength(); nIdx++)
788 ServiceInfo_Impl aInfo;
789 aInfo.sHyphImplName = pHyphNames[nIdx];
790 aInfo.xHyph = uno::Reference<XHyphenator>(
791 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sHyphImplName, aArgs, xContext), UNO_QUERY);
793 uno::Reference<XServiceDisplayName> xDispName(aInfo.xHyph, UNO_QUERY);
794 if(xDispName.is())
795 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
797 const Sequence< Locale > aLocales( aInfo.xHyph->getLocales() );
798 //! suppress display of entries with no supported languages (see feature 110994)
799 if (aLocales.getLength())
801 lcl_MergeLocales( aAllServiceLocales, aLocales );
802 lcl_MergeDisplayArray( *this, aInfo );
806 //read thesauri
807 Sequence< OUString > aThesNames = xLinguSrvcMgr->getAvailableServices(
808 cThes, Locale() );
809 const OUString* pThesNames = aThesNames.getConstArray();
810 for(nIdx = 0; nIdx < aThesNames.getLength(); nIdx++)
812 ServiceInfo_Impl aInfo;
813 aInfo.sThesImplName = pThesNames[nIdx];
814 aInfo.xThes = uno::Reference<XThesaurus>(
815 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sThesImplName, aArgs, xContext), UNO_QUERY);
817 uno::Reference<XServiceDisplayName> xDispName(aInfo.xThes, UNO_QUERY);
818 if(xDispName.is())
819 aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale );
821 const Sequence< Locale > aLocales( aInfo.xThes->getLocales() );
822 //! suppress display of entries with no supported languages (see feature 110994)
823 if (aLocales.getLength())
825 lcl_MergeLocales( aAllServiceLocales, aLocales );
826 lcl_MergeDisplayArray( *this, aInfo );
830 Sequence< OUString > aCfgSvcs;
831 const Locale* pAllLocales = aAllServiceLocales.getConstArray();
832 for(sal_Int32 nLocale = 0; nLocale < aAllServiceLocales.getLength(); nLocale++)
834 sal_Int16 nLang = LanguageTag::convertToLanguageType( pAllLocales[nLocale] );
836 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cSpell, pAllLocales[nLocale]);
837 SetChecked( aCfgSvcs );
838 if (aCfgSvcs.getLength())
839 aCfgSpellTable[ nLang ] = aCfgSvcs;
841 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cGrammar, pAllLocales[nLocale]);
842 SetChecked( aCfgSvcs );
843 if (aCfgSvcs.getLength())
844 aCfgGrammarTable[ nLang ] = aCfgSvcs;
846 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cHyph, pAllLocales[nLocale]);
847 SetChecked( aCfgSvcs );
848 if (aCfgSvcs.getLength())
849 aCfgHyphTable[ nLang ] = aCfgSvcs;
851 aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cThes, pAllLocales[nLocale]);
852 SetChecked( aCfgSvcs );
853 if (aCfgSvcs.getLength())
854 aCfgThesTable[ nLang ] = aCfgSvcs;
858 SvxLinguData_Impl::SvxLinguData_Impl( const SvxLinguData_Impl &rData ) :
859 aDisplayServiceArr (rData.aDisplayServiceArr),
860 nDisplayServices (rData.nDisplayServices),
861 aAllServiceLocales (rData.aAllServiceLocales),
862 aCfgSpellTable (rData.aCfgSpellTable),
863 aCfgHyphTable (rData.aCfgHyphTable),
864 aCfgThesTable (rData.aCfgThesTable),
865 aCfgGrammarTable (rData.aCfgGrammarTable),
866 xLinguSrvcMgr (rData.xLinguSrvcMgr)
870 SvxLinguData_Impl & SvxLinguData_Impl::operator = (const SvxLinguData_Impl &rData)
872 xLinguSrvcMgr = rData.xLinguSrvcMgr;
873 aAllServiceLocales = rData.aAllServiceLocales;
874 aCfgSpellTable = rData.aCfgSpellTable;
875 aCfgHyphTable = rData.aCfgHyphTable;
876 aCfgThesTable = rData.aCfgThesTable;
877 aCfgGrammarTable = rData.aCfgGrammarTable;
878 aDisplayServiceArr = rData.aDisplayServiceArr;
879 nDisplayServices = rData.nDisplayServices;
880 return *this;
883 SvxLinguData_Impl::~SvxLinguData_Impl()
887 void SvxLinguData_Impl::SetChecked(const Sequence<OUString>& rConfiguredServices)
889 const OUString* pConfiguredServices = rConfiguredServices.getConstArray();
890 for(sal_Int32 n = 0; n < rConfiguredServices.getLength(); n++)
892 ServiceInfo_Impl* pEntry;
893 for (sal_uLong i = 0; i < nDisplayServices; ++i)
895 pEntry = &aDisplayServiceArr[i];
896 if (pEntry && !pEntry->bConfigured)
898 const OUString &rSrvcImplName = pConfiguredServices[n];
899 if (!rSrvcImplName.isEmpty() &&
900 (pEntry->sSpellImplName == rSrvcImplName ||
901 pEntry->sGrammarImplName == rSrvcImplName ||
902 pEntry->sHyphImplName == rSrvcImplName ||
903 pEntry->sThesImplName == rSrvcImplName))
905 pEntry->bConfigured = true;
906 break;
913 bool SvxLinguData_Impl::AddRemove(
914 Sequence< OUString > &rConfigured,
915 const OUString &rImplName, bool bAdd )
917 bool bRet = false; // modified?
919 sal_Int32 nEntries = rConfigured.getLength();
920 sal_Int32 nPos = lcl_SeqGetEntryPos(rConfigured, rImplName);
921 if (bAdd && nPos < 0) // add new entry
923 rConfigured.realloc( ++nEntries );
924 OUString *pConfigured = rConfigured.getArray();
925 pConfigured[nEntries - 1] = rImplName;
926 bRet = true;
928 else if (!bAdd && nPos >= 0) // remove existing entry
930 OUString *pConfigured = rConfigured.getArray();
931 for (sal_Int32 i = nPos; i < nEntries - 1; ++i)
932 pConfigured[i] = pConfigured[i + 1];
933 rConfigured.realloc(--nEntries);
934 bRet = true;
937 return bRet;
941 void SvxLinguData_Impl::Reconfigure( const OUString &rDisplayName, bool bEnable )
943 DBG_ASSERT( !rDisplayName.isEmpty(), "empty DisplayName" );
945 ServiceInfo_Impl *pInfo = 0;
946 ServiceInfo_Impl *pTmp = 0;
947 for (sal_uLong i = 0; i < nDisplayServices; ++i)
949 pTmp = &aDisplayServiceArr[i];
950 if (pTmp && pTmp->sDisplayName == rDisplayName)
952 pInfo = pTmp;
953 break;
956 DBG_ASSERT( pInfo, "DisplayName entry not found" );
957 if (pInfo)
959 pInfo->bConfigured = bEnable;
961 Sequence< Locale > aLocales;
962 const Locale *pLocale = 0;
963 sal_Int32 nLocales = 0;
964 sal_Int32 i;
966 // update configured spellchecker entries
967 if (pInfo->xSpell.is())
969 aLocales = pInfo->xSpell->getLocales();
970 pLocale = aLocales.getConstArray();
971 nLocales = aLocales.getLength();
972 for (i = 0; i < nLocales; ++i)
974 sal_Int16 nLang = LanguageTag::convertToLanguageType( pLocale[i] );
975 if (!aCfgSpellTable.count( nLang ) && bEnable)
976 aCfgSpellTable[ nLang ] = Sequence< OUString >();
977 if (aCfgSpellTable.count( nLang ))
978 AddRemove( aCfgSpellTable[ nLang ], pInfo->sSpellImplName, bEnable );
982 // update configured grammar checker entries
983 if (pInfo->xGrammar.is())
985 aLocales = pInfo->xGrammar->getLocales();
986 pLocale = aLocales.getConstArray();
987 nLocales = aLocales.getLength();
988 for (i = 0; i < nLocales; ++i)
990 sal_Int16 nLang = LanguageTag::convertToLanguageType( pLocale[i] );
991 if (!aCfgGrammarTable.count( nLang ) && bEnable)
992 aCfgGrammarTable[ nLang ] = Sequence< OUString >();
993 if (aCfgGrammarTable.count( nLang ))
994 AddRemove( aCfgGrammarTable[ nLang ], pInfo->sGrammarImplName, bEnable );
998 // update configured hyphenator entries
999 if (pInfo->xHyph.is())
1001 aLocales = pInfo->xHyph->getLocales();
1002 pLocale = aLocales.getConstArray();
1003 nLocales = aLocales.getLength();
1004 for (i = 0; i < nLocales; ++i)
1006 sal_Int16 nLang = LanguageTag::convertToLanguageType( pLocale[i] );
1007 if (!aCfgHyphTable.count( nLang ) && bEnable)
1008 aCfgHyphTable[ nLang ] = Sequence< OUString >();
1009 if (aCfgHyphTable.count( nLang ))
1010 AddRemove( aCfgHyphTable[ nLang ], pInfo->sHyphImplName, bEnable );
1014 // update configured spellchecker entries
1015 if (pInfo->xThes.is())
1017 aLocales = pInfo->xThes->getLocales();
1018 pLocale = aLocales.getConstArray();
1019 nLocales = aLocales.getLength();
1020 for (i = 0; i < nLocales; ++i)
1022 sal_Int16 nLang = LanguageTag::convertToLanguageType( pLocale[i] );
1023 if (!aCfgThesTable.count( nLang ) && bEnable)
1024 aCfgThesTable[ nLang ] = Sequence< OUString >();
1025 if (aCfgThesTable.count( nLang ))
1026 AddRemove( aCfgThesTable[ nLang ], pInfo->sThesImplName, bEnable );
1033 // class SvxLinguTabPage -------------------------------------------------
1035 SvxLinguTabPage::SvxLinguTabPage( Window* pParent, const SfxItemSet& rSet ) :
1036 SfxTabPage(pParent, "OptLinguPage", "cui/ui/optlingupage.ui", rSet),
1038 sCapitalWords (CUI_RES(RID_SVXSTR_CAPITAL_WORDS)),
1039 sWordsWithDigits(CUI_RES(RID_SVXSTR_WORDS_WITH_DIGITS)),
1040 sSpellSpecial (CUI_RES(RID_SVXSTR_SPELL_SPECIAL)),
1041 sSpellAuto (CUI_RES(RID_SVXSTR_SPELL_AUTO)),
1042 sGrammarAuto (CUI_RES(RID_SVXSTR_GRAMMAR_AUTO)),
1043 sNumMinWordlen (CUI_RES(RID_SVXSTR_NUM_MIN_WORDLEN)),
1044 sNumPreBreak (CUI_RES(RID_SVXSTR_NUM_PRE_BREAK)),
1045 sNumPostBreak (CUI_RES(RID_SVXSTR_NUM_POST_BREAK)),
1046 sHyphAuto (CUI_RES(RID_SVXSTR_HYPH_AUTO)),
1047 sHyphSpecial (CUI_RES(RID_SVXSTR_HYPH_SPECIAL)),
1049 pLinguData(NULL)
1051 get(m_pLinguModulesFT, "lingumodulesft");
1052 get(m_pLinguModulesCLB, "lingumodules");
1053 get(m_pLinguModulesEditPB, "lingumodulesedit");
1054 get(m_pLinguDicsFT, "lingudictsft");
1055 get(m_pLinguDicsCLB, "lingudicts");
1056 get(m_pLinguDicsNewPB, "lingudictsnew");
1057 get(m_pLinguDicsEditPB, "lingudictsedit");
1058 get(m_pLinguDicsDelPB, "lingudictsdelete");
1059 get(m_pLinguOptionsCLB, "linguoptions");
1060 get(m_pLinguOptionsEditPB, "linguoptionsedit");
1061 get(m_pMoreDictsLink, "moredictslink");
1063 m_pLinguModulesCLB->set_height_request(m_pLinguModulesCLB->GetTextHeight() * 3);
1064 m_pLinguDicsCLB->set_height_request(m_pLinguDicsCLB->GetTextHeight() * 5);
1065 m_pLinguOptionsCLB->set_height_request(m_pLinguOptionsCLB->GetTextHeight() * 5);
1067 pCheckButtonData = NULL;
1069 m_pLinguModulesCLB->SetStyle( m_pLinguModulesCLB->GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
1070 m_pLinguModulesCLB->SetHighlightRange();
1071 m_pLinguModulesCLB->SetSelectHdl( LINK( this, SvxLinguTabPage, SelectHdl_Impl ));
1072 m_pLinguModulesCLB->SetDoubleClickHdl(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl));
1073 m_pLinguModulesCLB->SetCheckButtonHdl(LINK(this, SvxLinguTabPage, BoxCheckButtonHdl_Impl));
1075 m_pLinguModulesEditPB->SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1076 m_pLinguOptionsEditPB->SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1078 m_pLinguDicsCLB->SetStyle( m_pLinguDicsCLB->GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
1079 m_pLinguDicsCLB->SetHighlightRange();
1080 m_pLinguDicsCLB->SetSelectHdl( LINK( this, SvxLinguTabPage, SelectHdl_Impl ));
1081 m_pLinguDicsCLB->SetCheckButtonHdl(LINK(this, SvxLinguTabPage, BoxCheckButtonHdl_Impl));
1083 m_pLinguDicsNewPB->SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1084 m_pLinguDicsEditPB->SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1085 m_pLinguDicsDelPB->SetClickHdl( LINK( this, SvxLinguTabPage, ClickHdl_Impl ));
1087 m_pLinguOptionsCLB->SetStyle( m_pLinguOptionsCLB->GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
1088 m_pLinguOptionsCLB->SetHighlightRange();
1089 m_pLinguOptionsCLB->SetSelectHdl( LINK( this, SvxLinguTabPage, SelectHdl_Impl ));
1090 m_pLinguOptionsCLB->SetDoubleClickHdl(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl));
1092 if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
1093 != SvtExtendedSecurityOptions::OPEN_NEVER )
1095 m_pMoreDictsLink->SetClickHdl( LINK( this, SvxLinguTabPage, OpenURLHdl_Impl ) );
1097 else
1098 m_pMoreDictsLink->Hide();
1100 OUString sAccessibleNameModuleEdit(CUI_RES(RID_SVXSTR_LINGU_MODULES_EDIT));
1101 OUString sAccessibleNameDicsEdit (CUI_RES(RID_SVXSTR_LINGU_DICS_EDIT_DIC));
1102 OUString sAccessibleNameOptionEdit(CUI_RES(RID_SVXSTR_LINGU_OPTIONS_EDIT));
1104 m_pLinguModulesEditPB->SetAccessibleName(sAccessibleNameModuleEdit);
1105 m_pLinguDicsEditPB->SetAccessibleName(sAccessibleNameDicsEdit);
1106 m_pLinguOptionsEditPB->SetAccessibleName(sAccessibleNameOptionEdit);
1108 xProp = SvxGetLinguPropertySet();
1109 xDicList = uno::Reference< XDictionaryList >( SvxGetDictionaryList(), UNO_QUERY );
1110 if (xDicList.is())
1112 // keep references to all **currently** available dictionaries,
1113 // since the diclist may get changed meanwhile (e.g. through the API).
1114 // We want the dialog to operate on the same set of dictionaries it
1115 // was started with.
1116 // Also we have to take care to not lose the last reference when
1117 // someone else removes a dictionary from the list.
1118 // removed dics will be replaced by NULL new entries be added to the end
1119 // Thus we may use indices as consistent references.
1120 aDics = xDicList->getDictionaries();
1122 UpdateDicBox_Impl();
1124 else
1126 m_pLinguDicsFT->Disable();
1127 m_pLinguDicsCLB->Disable();
1128 m_pLinguDicsNewPB->Disable();
1129 m_pLinguDicsEditPB->Disable();
1130 m_pLinguDicsDelPB->Disable();
1134 SvxLinguTabPage::~SvxLinguTabPage()
1136 if (pLinguData)
1137 delete pLinguData;
1142 // don't throw away overloaded
1143 const sal_uInt16* SvxLinguTabPage::GetRanges()
1145 //TL???
1146 return pRanges;
1151 SfxTabPage* SvxLinguTabPage::Create( Window* pParent,
1152 const SfxItemSet& rAttrSet )
1154 return ( new SvxLinguTabPage( pParent, rAttrSet ) );
1159 bool SvxLinguTabPage::FillItemSet( SfxItemSet& rCoreSet )
1161 bool bModified = true; // !!!!
1163 // if not HideGroups was called with GROUP_MODULES...
1164 if (m_pLinguModulesCLB->IsVisible())
1166 DBG_ASSERT( pLinguData, "pLinguData not yet initialized" );
1167 if (!pLinguData)
1168 pLinguData = new SvxLinguData_Impl;
1170 LangImplNameTable::const_iterator aIt;
1172 // update spellchecker configuration entries
1173 const LangImplNameTable *pTable = &pLinguData->GetSpellTable();
1174 for (aIt = pTable->begin(); aIt != pTable->end(); ++aIt)
1176 sal_Int16 nLang = aIt->first;
1177 const Sequence< OUString > aImplNames( aIt->second );
1178 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
1179 Locale aLocale( LanguageTag::convertToLocale(nLang) );
1180 if (xMgr.is())
1181 xMgr->setConfiguredServices( cSpell, aLocale, aImplNames );
1184 // update grammar checker configuration entries
1185 pTable = &pLinguData->GetGrammarTable();
1186 for (aIt = pTable->begin(); aIt != pTable->end(); ++aIt)
1188 sal_Int16 nLang = aIt->first;
1189 const Sequence< OUString > aImplNames( aIt->second );
1190 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
1191 Locale aLocale( LanguageTag::convertToLocale(nLang) );
1192 if (xMgr.is())
1193 xMgr->setConfiguredServices( cGrammar, aLocale, aImplNames );
1196 // update hyphenator configuration entries
1197 pTable = &pLinguData->GetHyphTable();
1198 for (aIt = pTable->begin(); aIt != pTable->end(); ++aIt)
1200 sal_Int16 nLang = aIt->first;
1201 const Sequence< OUString > aImplNames( aIt->second );
1202 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
1203 Locale aLocale( LanguageTag::convertToLocale(nLang) );
1204 if (xMgr.is())
1205 xMgr->setConfiguredServices( cHyph, aLocale, aImplNames );
1208 // update thesaurus configuration entries
1209 pTable = &pLinguData->GetThesTable();
1210 for (aIt = pTable->begin(); aIt != pTable->end(); ++aIt)
1212 sal_Int16 nLang = aIt->first;
1213 const Sequence< OUString > aImplNames( aIt->second );
1214 uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() );
1215 Locale aLocale( LanguageTag::convertToLocale(nLang) );
1216 if (xMgr.is())
1217 xMgr->setConfiguredServices( cThes, aLocale, aImplNames );
1223 // activate dictionaries according to checkbox state
1225 Sequence< OUString > aActiveDics;
1226 sal_Int32 nActiveDics = 0;
1227 sal_uLong nEntries = m_pLinguDicsCLB->GetEntryCount();
1228 for (sal_uLong i = 0; i < nEntries; ++i)
1230 sal_Int32 nDics = aDics.getLength();
1232 aActiveDics.realloc( nDics );
1233 OUString *pActiveDic = aActiveDics.getArray();
1235 SvTreeListEntry *pEntry = m_pLinguDicsCLB->GetEntry( i );
1236 if (pEntry)
1238 DicUserData aData( (sal_uLong)pEntry->GetUserData() );
1239 if (aData.GetEntryId() < nDics)
1241 bool bChecked = m_pLinguDicsCLB->IsChecked( i );
1242 uno::Reference< XDictionary > xDic( aDics.getConstArray()[ i ] );
1243 if (xDic.is())
1245 if (SvxGetIgnoreAllList() == xDic)
1246 bChecked = true;
1247 xDic->setActive( bChecked );
1249 if (bChecked)
1251 OUString aDicName( xDic->getName() );
1252 pActiveDic[ nActiveDics++ ] = aDicName;
1259 aActiveDics.realloc( nActiveDics );
1260 Any aTmp;
1261 aTmp <<= aActiveDics;
1262 SvtLinguConfig aLngCfg;
1263 aLngCfg.SetProperty( UPH_ACTIVE_DICTIONARIES, aTmp );
1266 nEntries = m_pLinguOptionsCLB->GetEntryCount();
1267 for (sal_uLong j = 0; j < nEntries; ++j)
1269 SvTreeListEntry *pEntry = m_pLinguOptionsCLB->GetEntry( j );
1271 OptionsUserData aData( (sal_uLong)pEntry->GetUserData() );
1272 OUString aPropName( lcl_GetPropertyName( (EID_OPTIONS) aData.GetEntryId() ) );
1274 Any aAny;
1275 if (aData.IsCheckable())
1277 bool bChecked = m_pLinguOptionsCLB->IsChecked( j );
1278 aAny <<= bChecked;
1280 else if (aData.HasNumericValue())
1282 sal_Int16 nVal = aData.GetNumericValue();
1283 aAny <<= nVal;
1286 if (xProp.is())
1287 xProp->setPropertyValue( aPropName, aAny );
1288 aLngCfg.SetProperty( aPropName, aAny );
1291 SvTreeListEntry *pPreBreakEntry = m_pLinguOptionsCLB->GetEntry( (sal_uLong) EID_NUM_PRE_BREAK );
1292 SvTreeListEntry *pPostBreakEntry = m_pLinguOptionsCLB->GetEntry( (sal_uLong) EID_NUM_POST_BREAK );
1293 DBG_ASSERT( pPreBreakEntry, "NULL Pointer" );
1294 DBG_ASSERT( pPostBreakEntry, "NULL Pointer" );
1295 if (pPreBreakEntry && pPostBreakEntry)
1297 OptionsUserData aPreBreakData( (sal_uLong)pPreBreakEntry->GetUserData() );
1298 OptionsUserData aPostBreakData( (sal_uLong)pPostBreakEntry->GetUserData() );
1299 if ( aPreBreakData.IsModified() || aPostBreakData.IsModified() )
1301 SfxHyphenRegionItem aHyp( GetWhich( SID_ATTR_HYPHENREGION ) );
1302 aHyp.GetMinLead() = (sal_uInt8) aPreBreakData.GetNumericValue();
1303 aHyp.GetMinTrail() = (sal_uInt8) aPostBreakData.GetNumericValue();
1304 rCoreSet.Put( aHyp );
1309 // automatic spell checking
1310 bool bNewAutoCheck = m_pLinguOptionsCLB->IsChecked( (sal_uLong) EID_SPELL_AUTO );
1311 const SfxPoolItem* pOld = GetOldItem( rCoreSet, SID_AUTOSPELL_CHECK );
1312 if ( !pOld || ( (SfxBoolItem*)pOld )->GetValue() != bNewAutoCheck )
1314 rCoreSet.Put( SfxBoolItem( GetWhich( SID_AUTOSPELL_CHECK ),
1315 bNewAutoCheck ) );
1316 bModified |= true;
1319 return bModified;
1324 sal_uLong SvxLinguTabPage::GetDicUserData( const uno::Reference< XDictionary > &rxDic, sal_uInt16 nIdx )
1326 sal_uLong nRes = 0;
1327 DBG_ASSERT( rxDic.is(), "dictionary not supplied" );
1328 if (rxDic.is())
1330 uno::Reference< frame::XStorable > xStor( rxDic, UNO_QUERY );
1332 bool bChecked = rxDic->isActive();
1333 bool bEditable = !xStor.is() || !xStor->isReadonly();
1334 bool bDeletable = bEditable;
1336 nRes = DicUserData( nIdx,
1337 bChecked, bEditable, bDeletable ).GetUserData();
1339 return nRes;
1343 void SvxLinguTabPage::AddDicBoxEntry(
1344 const uno::Reference< XDictionary > &rxDic,
1345 sal_uInt16 nIdx )
1347 m_pLinguDicsCLB->SetUpdateMode(false);
1349 OUString aTxt( ::GetDicInfoStr( rxDic->getName(),
1350 LanguageTag( rxDic->getLocale() ).getLanguageType(),
1351 DictionaryType_NEGATIVE == rxDic->getDictionaryType() ) );
1352 m_pLinguDicsCLB->InsertEntry( aTxt, TREELIST_APPEND ); // append at end
1353 SvTreeListEntry* pEntry = m_pLinguDicsCLB->GetEntry( m_pLinguDicsCLB->GetEntryCount() - 1 );
1354 DBG_ASSERT( pEntry, "failed to add entry" );
1355 if (pEntry)
1357 DicUserData aData( GetDicUserData( rxDic, nIdx ) );
1358 pEntry->SetUserData( (void *) aData.GetUserData() );
1359 lcl_SetCheckButton( pEntry, aData.IsChecked() );
1362 m_pLinguDicsCLB->SetUpdateMode(true);
1367 void SvxLinguTabPage::UpdateDicBox_Impl()
1369 m_pLinguDicsCLB->SetUpdateMode(false);
1370 m_pLinguDicsCLB->Clear();
1372 sal_Int32 nDics = aDics.getLength();
1373 const uno::Reference< XDictionary > *pDic = aDics.getConstArray();
1374 for (sal_Int32 i = 0; i < nDics; ++i)
1376 const uno::Reference< XDictionary > &rDic = pDic[i];
1377 if (rDic.is())
1378 AddDicBoxEntry( rDic, (sal_uInt16)i );
1381 m_pLinguDicsCLB->SetUpdateMode(true);
1386 void SvxLinguTabPage::UpdateModulesBox_Impl()
1388 if (pLinguData)
1390 const ServiceInfoArr &rAllDispSrvcArr = pLinguData->GetDisplayServiceArray();
1391 const sal_uLong nDispSrvcCount = pLinguData->GetDisplayServiceCount();
1393 m_pLinguModulesCLB->Clear();
1395 for (sal_uLong i = 0; i < nDispSrvcCount; ++i)
1397 const ServiceInfo_Impl &rInfo = rAllDispSrvcArr[i];
1398 m_pLinguModulesCLB->InsertEntry( rInfo.sDisplayName, TREELIST_APPEND );
1399 SvTreeListEntry* pEntry = m_pLinguModulesCLB->GetEntry(i);
1400 pEntry->SetUserData( (void *) &rInfo );
1401 m_pLinguModulesCLB->CheckEntryPos( i, rInfo.bConfigured );
1403 m_pLinguModulesEditPB->Enable( nDispSrvcCount > 0 );
1409 void SvxLinguTabPage::Reset( const SfxItemSet& rSet )
1411 // if not HideGroups was called with GROUP_MODULES...
1412 if (m_pLinguModulesCLB->IsVisible())
1414 if (!pLinguData)
1415 pLinguData = new SvxLinguData_Impl;
1416 UpdateModulesBox_Impl();
1421 // get data from configuration
1424 SvtLinguConfig aLngCfg;
1426 m_pLinguOptionsCLB->SetUpdateMode(false);
1427 m_pLinguOptionsCLB->Clear();
1429 SvTreeList *pModel = m_pLinguOptionsCLB->GetModel();
1430 SvTreeListEntry* pEntry = NULL;
1432 sal_Int16 nVal = 0;
1433 bool bVal = false;
1434 sal_uLong nUserData = 0;
1436 pEntry = CreateEntry( sSpellAuto, CBCOL_FIRST );
1437 aLngCfg.GetProperty( UPN_IS_SPELL_AUTO ) >>= bVal;
1438 const SfxPoolItem* pItem = GetItem( rSet, SID_AUTOSPELL_CHECK );
1439 if (pItem)
1440 bVal = ((SfxBoolItem *) pItem)->GetValue();
1441 nUserData = OptionsUserData( EID_SPELL_AUTO, false, 0, true, bVal).GetUserData();
1442 pEntry->SetUserData( (void *)nUserData );
1443 pModel->Insert( pEntry );
1444 lcl_SetCheckButton( pEntry, bVal );
1446 pEntry = CreateEntry( sGrammarAuto, CBCOL_FIRST );
1447 aLngCfg.GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bVal;
1448 nUserData = OptionsUserData( EID_GRAMMAR_AUTO, false, 0, true, bVal).GetUserData();
1449 pEntry->SetUserData( (void *)nUserData );
1450 pModel->Insert( pEntry );
1451 lcl_SetCheckButton( pEntry, bVal );
1453 pEntry = CreateEntry( sCapitalWords, CBCOL_FIRST );
1454 aLngCfg.GetProperty( UPN_IS_SPELL_UPPER_CASE ) >>= bVal;
1455 nUserData = OptionsUserData( EID_CAPITAL_WORDS, false, 0, true, bVal).GetUserData();
1456 pEntry->SetUserData( (void *)nUserData );
1457 pModel->Insert( pEntry );
1458 lcl_SetCheckButton( pEntry, bVal );
1460 pEntry = CreateEntry( sWordsWithDigits, CBCOL_FIRST );
1461 aLngCfg.GetProperty( UPN_IS_SPELL_WITH_DIGITS ) >>= bVal;
1462 nUserData = OptionsUserData( EID_WORDS_WITH_DIGITS, false, 0, true, bVal).GetUserData();
1463 pEntry->SetUserData( (void *)nUserData );
1464 pModel->Insert( pEntry );
1465 lcl_SetCheckButton( pEntry, bVal );
1467 pEntry = CreateEntry( sSpellSpecial, CBCOL_FIRST );
1468 aLngCfg.GetProperty( UPN_IS_SPELL_SPECIAL ) >>= bVal;
1469 nUserData = OptionsUserData( EID_SPELL_SPECIAL, false, 0, true, bVal).GetUserData();
1470 pEntry->SetUserData( (void *)nUserData );
1471 pModel->Insert( pEntry );
1472 lcl_SetCheckButton( pEntry, bVal );
1474 pEntry = CreateEntry( sNumMinWordlen, CBCOL_SECOND );
1475 aLngCfg.GetProperty( UPN_HYPH_MIN_WORD_LENGTH ) >>= nVal;
1476 nUserData = OptionsUserData( EID_NUM_MIN_WORDLEN, true, (sal_uInt16)nVal, false, false).GetUserData();
1477 pEntry->SetUserData( (void *)nUserData );
1478 pModel->Insert( pEntry );
1480 const SfxHyphenRegionItem *pHyp = NULL;
1481 sal_uInt16 nWhich = GetWhich( SID_ATTR_HYPHENREGION );
1482 if ( rSet.GetItemState( nWhich, false ) == SFX_ITEM_SET )
1483 pHyp = &( (const SfxHyphenRegionItem &) rSet.Get( nWhich ) );
1485 pEntry = CreateEntry( sNumPreBreak, CBCOL_SECOND );
1486 aLngCfg.GetProperty( UPN_HYPH_MIN_LEADING ) >>= nVal;
1487 if (pHyp)
1488 nVal = (sal_Int16) pHyp->GetMinLead();
1489 nUserData = OptionsUserData( EID_NUM_PRE_BREAK, true, (sal_uInt16)nVal, false, false).GetUserData();
1490 pEntry->SetUserData( (void *)nUserData );
1491 pModel->Insert( pEntry );
1493 pEntry = CreateEntry( sNumPostBreak, CBCOL_SECOND );
1494 aLngCfg.GetProperty( UPN_HYPH_MIN_TRAILING ) >>= nVal;
1495 if (pHyp)
1496 nVal = (sal_Int16) pHyp->GetMinTrail();
1497 nUserData = OptionsUserData( EID_NUM_POST_BREAK, true, (sal_uInt16)nVal, false, false).GetUserData();
1498 pEntry->SetUserData( (void *)nUserData );
1499 pModel->Insert( pEntry );
1501 pEntry = CreateEntry( sHyphAuto, CBCOL_FIRST );
1502 aLngCfg.GetProperty( UPN_IS_HYPH_AUTO ) >>= bVal;
1503 nUserData = OptionsUserData( EID_HYPH_AUTO, false, 0, true, bVal).GetUserData();
1504 pEntry->SetUserData( (void *)nUserData );
1505 pModel->Insert( pEntry );
1506 lcl_SetCheckButton( pEntry, bVal );
1508 pEntry = CreateEntry( sHyphSpecial, CBCOL_FIRST );
1509 aLngCfg.GetProperty( UPN_IS_HYPH_SPECIAL ) >>= bVal;
1510 nUserData = OptionsUserData( EID_HYPH_SPECIAL, false, 0, true, bVal).GetUserData();
1511 pEntry->SetUserData( (void *)nUserData );
1512 pModel->Insert( pEntry );
1513 lcl_SetCheckButton( pEntry, bVal );
1515 m_pLinguOptionsCLB->SetUpdateMode(true);
1520 IMPL_LINK( SvxLinguTabPage, BoxDoubleClickHdl_Impl, SvTreeListBox *, pBox )
1522 if (pBox == m_pLinguModulesCLB)
1524 //! in order to avoid a bug causing a GPF when double clicking
1525 //! on a module entry and exiting the "Edit Modules" dialog
1526 //! after that.
1527 Application::PostUserEvent( LINK(
1528 this, SvxLinguTabPage, PostDblClickHdl_Impl ) );
1530 else if (pBox == m_pLinguOptionsCLB)
1532 ClickHdl_Impl(m_pLinguOptionsEditPB);
1534 return 0;
1539 IMPL_LINK_NOARG(SvxLinguTabPage, PostDblClickHdl_Impl)
1541 ClickHdl_Impl(m_pLinguModulesEditPB);
1542 return 0;
1547 IMPL_LINK_NOARG(SvxLinguTabPage, OpenURLHdl_Impl)
1549 OUString sURL( m_pMoreDictsLink->GetURL() );
1550 lcl_OpenURL( sURL );
1551 return 0;
1556 IMPL_LINK( SvxLinguTabPage, BoxCheckButtonHdl_Impl, SvTreeListBox *, pBox )
1558 if (pBox == m_pLinguModulesCLB)
1560 DBG_ASSERT( pLinguData, "NULL pointer, LinguData missing" );
1561 sal_uLong nPos = m_pLinguModulesCLB->GetSelectEntryPos();
1562 if (nPos != TREELIST_ENTRY_NOTFOUND && pLinguData)
1564 pLinguData->Reconfigure( m_pLinguModulesCLB->GetText( nPos ),
1565 m_pLinguModulesCLB->IsChecked( nPos ) );
1568 else if (pBox == m_pLinguDicsCLB)
1570 sal_uLong nPos = m_pLinguDicsCLB->GetSelectEntryPos();
1571 if (nPos != TREELIST_ENTRY_NOTFOUND)
1573 const uno::Reference< XDictionary > &rDic = aDics.getConstArray()[ nPos ];
1574 if (SvxGetIgnoreAllList() == rDic)
1576 SvTreeListEntry* pEntry = m_pLinguDicsCLB->GetEntry( nPos );
1577 if (pEntry)
1578 lcl_SetCheckButton( pEntry, true );
1582 return 0;
1587 IMPL_LINK( SvxLinguTabPage, ClickHdl_Impl, PushButton *, pBtn )
1589 if (m_pLinguModulesEditPB == pBtn)
1591 if (!pLinguData)
1592 pLinguData = new SvxLinguData_Impl;
1594 SvxLinguData_Impl aOldLinguData( *pLinguData );
1595 SvxEditModulesDlg aDlg( this, *pLinguData );
1596 if (aDlg.Execute() != RET_OK)
1597 *pLinguData = aOldLinguData;
1599 // evaluate new status of 'bConfigured' flag
1600 sal_uLong nLen = pLinguData->GetDisplayServiceCount();
1601 for (sal_uLong i = 0; i < nLen; ++i)
1602 pLinguData->GetDisplayServiceArray()[i].bConfigured = false;
1603 const Locale* pAllLocales = pLinguData->GetAllSupportedLocales().getConstArray();
1604 sal_Int32 nLocales = pLinguData->GetAllSupportedLocales().getLength();
1605 for (sal_Int32 k = 0; k < nLocales; ++k)
1607 sal_Int16 nLang = LanguageTag::convertToLanguageType( pAllLocales[k] );
1608 if (pLinguData->GetSpellTable().count( nLang ))
1609 pLinguData->SetChecked( pLinguData->GetSpellTable()[ nLang ] );
1610 if (pLinguData->GetGrammarTable().count( nLang ))
1611 pLinguData->SetChecked( pLinguData->GetGrammarTable()[ nLang ] );
1612 if (pLinguData->GetHyphTable().count( nLang ))
1613 pLinguData->SetChecked( pLinguData->GetHyphTable()[ nLang ] );
1614 if (pLinguData->GetThesTable().count( nLang ))
1615 pLinguData->SetChecked( pLinguData->GetThesTable()[ nLang ] );
1618 // show new status of modules
1619 UpdateModulesBox_Impl();
1621 else if (m_pLinguDicsNewPB == pBtn)
1623 uno::Reference< XSpellChecker1 > xSpellChecker1;
1624 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1625 if(pFact)
1627 AbstractSvxNewDictionaryDialog* aDlg = pFact->CreateSvxNewDictionaryDialog( this, xSpellChecker1 );
1628 DBG_ASSERT(aDlg, "Dialogdiet fail!");
1629 uno::Reference< XDictionary > xNewDic;
1630 if ( aDlg->Execute() == RET_OK )
1631 xNewDic = uno::Reference< XDictionary >( aDlg->GetNewDictionary(), UNO_QUERY );
1632 if ( xNewDic.is() )
1634 // add new dics to the end
1635 sal_Int32 nLen = aDics.getLength();
1636 aDics.realloc( nLen + 1 );
1638 aDics.getArray()[ nLen ] = xNewDic;
1640 AddDicBoxEntry( xNewDic, (sal_uInt16) nLen );
1642 delete aDlg;
1645 else if (m_pLinguDicsEditPB == pBtn)
1647 SvTreeListEntry *pEntry = m_pLinguDicsCLB->GetCurEntry();
1648 if (pEntry)
1650 DicUserData aData( (sal_uLong) pEntry->GetUserData() );
1651 sal_uInt16 nDicPos = aData.GetEntryId();
1652 sal_Int32 nDics = aDics.getLength();
1653 if (nDicPos < nDics)
1655 uno::Reference< XDictionary > xDic;
1656 xDic = aDics.getConstArray()[ nDicPos ];
1657 if (xDic.is())
1659 uno::Reference< XSpellChecker1 > xSpellChecker1;
1660 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1661 if(pFact)
1663 VclAbstractDialog* aDlg = pFact->CreateSvxEditDictionaryDialog( this, xDic->getName(), xSpellChecker1, RID_SFXDLG_EDITDICT );
1664 DBG_ASSERT(aDlg, "Dialogdiet fail!");
1665 aDlg->Execute();
1666 delete aDlg;
1672 else if (m_pLinguDicsDelPB == pBtn)
1674 MessageDialog aQuery(this, "QueryDeleteDictionaryDialog",
1675 "cui/ui/querydeletedictionarydialog.ui");
1676 if (RET_NO == aQuery.Execute())
1677 return 0;
1679 SvTreeListEntry *pEntry = m_pLinguDicsCLB->GetCurEntry();
1680 if (pEntry)
1682 DicUserData aData( (sal_uLong) pEntry->GetUserData() );
1683 sal_uInt16 nDicPos = aData.GetEntryId();
1684 sal_Int32 nDics = aDics.getLength();
1685 if (nDicPos < nDics)
1687 uno::Reference< XDictionary > xDic;
1688 xDic = aDics.getConstArray()[ nDicPos ];
1689 if (xDic.is())
1691 if (SvxGetIgnoreAllList() == xDic)
1692 xDic->clear();
1693 else
1695 if (xDicList.is())
1696 xDicList->removeDictionary( xDic );
1698 uno::Reference< frame::XStorable > xStor( xDic, UNO_QUERY );
1699 if ( xStor->hasLocation() && !xStor->isReadonly() )
1701 OUString sURL = xStor->getLocation();
1702 INetURLObject aObj(sURL);
1703 DBG_ASSERT( aObj.GetProtocol() == INET_PROT_FILE,
1704 "non-file URLs cannot be deleted" );
1705 if ( aObj.GetProtocol() == INET_PROT_FILE )
1707 KillFile_Impl( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
1711 aDics.getArray()[ nDicPos ] = 0;
1713 // remove entry from checklistbox
1714 sal_uLong nCnt = m_pLinguDicsCLB->GetEntryCount();
1715 for (sal_uLong i = 0; i < nCnt; ++i)
1717 SvTreeListEntry *pDicEntry = m_pLinguDicsCLB->GetEntry( i );
1718 DBG_ASSERT( pDicEntry, "missing entry" );
1719 if (pDicEntry)
1721 DicUserData aDicData( (sal_uLong) pDicEntry->GetUserData() );
1722 if (aDicData.GetEntryId() == nDicPos )
1724 m_pLinguDicsCLB->RemoveEntry( i );
1725 break;
1729 DBG_ASSERT( nCnt > m_pLinguDicsCLB->GetEntryCount(),
1730 "remove failed ?");
1736 else if (m_pLinguOptionsEditPB == pBtn)
1738 SvTreeListEntry *pEntry = m_pLinguOptionsCLB->GetCurEntry();
1739 DBG_ASSERT( pEntry, "no entry selected" );
1740 if (pEntry)
1742 OptionsUserData aData( (sal_uLong)pEntry->GetUserData() );
1743 if(aData.HasNumericValue())
1745 sal_uInt16 nRID = aData.GetEntryId();
1746 OptionsBreakSet aDlg( this, nRID );
1747 aDlg.GetNumericFld().SetValue( aData.GetNumericValue() );
1748 if (RET_OK == aDlg.Execute() )
1750 long nVal = static_cast<long>(aDlg.GetNumericFld().GetValue());
1751 if (-1 != nVal && aData.GetNumericValue() != nVal)
1753 aData.SetNumericValue( (sal_uInt8)nVal ); //! sets IsModified !
1754 pEntry->SetUserData( (void *) aData.GetUserData() );
1755 m_pLinguOptionsCLB->Invalidate();
1761 else
1763 OSL_FAIL( "pBtn unexpected value" );
1766 return 0;
1771 IMPL_LINK( SvxLinguTabPage, SelectHdl_Impl, SvxCheckListBox *, pBox )
1773 if (m_pLinguModulesCLB == pBox)
1776 else if (m_pLinguDicsCLB == pBox)
1778 SvTreeListEntry *pEntry = pBox->GetCurEntry();
1779 if (pEntry)
1781 DicUserData aData( (sal_uLong) pEntry->GetUserData() );
1783 // always allow to edit (i.e. at least view the content of the dictionary)
1784 m_pLinguDicsEditPB->Enable( true/*aData.IsEditable()*/ );
1785 m_pLinguDicsDelPB->Enable( aData.IsDeletable() );
1788 else if (m_pLinguOptionsCLB == pBox)
1790 SvTreeListEntry *pEntry = pBox->GetCurEntry();
1791 if (pEntry)
1793 OptionsUserData aData( (sal_uLong) pEntry->GetUserData() );
1794 m_pLinguOptionsEditPB->Enable( aData.HasNumericValue() );
1797 else
1799 OSL_FAIL( "pBox unexpected value" );
1802 return 0;
1807 SvTreeListEntry* SvxLinguTabPage::CreateEntry( OUString& rTxt, sal_uInt16 nCol )
1809 SvTreeListEntry* pEntry = new SvTreeListEntry;
1811 if( !pCheckButtonData )
1812 pCheckButtonData = new SvLBoxButtonData(m_pLinguOptionsCLB);
1814 OUString sEmpty;
1815 if (CBCOL_FIRST == nCol)
1816 pEntry->AddItem( new SvLBoxButton( pEntry, SvLBoxButtonKind_enabledCheckbox, 0, pCheckButtonData ) );
1817 if (CBCOL_SECOND == nCol)
1818 pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty) ); // empty column
1819 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), false));
1820 pEntry->AddItem( new BrwString_Impl( pEntry, 0, rTxt ) );
1822 return pEntry;
1827 void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp )
1829 if ( 0 != ( GROUP_MODULES & nGrp ) )
1831 m_pLinguModulesFT->Hide();
1832 m_pLinguModulesCLB->Hide();
1833 m_pLinguModulesEditPB->Hide();
1835 if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
1836 != SvtExtendedSecurityOptions::OPEN_NEVER )
1838 m_pMoreDictsLink->Show();
1843 SvxEditModulesDlg::SvxEditModulesDlg(Window* pParent, SvxLinguData_Impl& rData)
1844 : ModalDialog( pParent, "EditModulesDialog",
1845 "cui/ui/editmodulesdialog.ui")
1846 , sSpell(CUI_RES(RID_SVXSTR_SPELL))
1847 , sHyph(CUI_RES(RID_SVXSTR_HYPH))
1848 , sThes(CUI_RES(RID_SVXSTR_THES))
1849 , sGrammar(CUI_RES(RID_SVXSTR_GRAMMAR))
1850 , rLinguData(rData)
1852 get(m_pClosePB, "close");
1853 get(m_pMoreDictsLink, "moredictslink");
1854 get(m_pBackPB, "back");
1855 get(m_pPrioDownPB, "down");
1856 get(m_pPrioUpPB, "up");
1857 get(m_pModulesCLB, "lingudicts");
1858 Size aListSize(m_pModulesCLB->LogicToPixel(Size(166, 120), MAP_APPFONT));
1859 m_pModulesCLB->set_height_request(aListSize.Height());
1860 m_pModulesCLB->set_width_request(aListSize.Width());
1861 get(m_pLanguageLB, "language");
1862 m_pLanguageLB->SetStyle(m_pLanguageLB->GetStyle() | WB_SORT);
1864 pCheckButtonData = NULL;
1866 pDefaultLinguData = new SvxLinguData_Impl( rLinguData );
1868 m_pModulesCLB->SetStyle( m_pModulesCLB->GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_FORCE_MAKEVISIBLE );
1869 m_pModulesCLB->SetHighlightRange();
1870 m_pModulesCLB->SetSelectHdl( LINK( this, SvxEditModulesDlg, SelectHdl_Impl ));
1871 m_pModulesCLB->SetCheckButtonHdl( LINK( this, SvxEditModulesDlg, BoxCheckButtonHdl_Impl) );
1873 m_pClosePB->SetClickHdl( LINK( this, SvxEditModulesDlg, ClickHdl_Impl ));
1874 m_pPrioUpPB->SetClickHdl( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
1875 m_pPrioDownPB->SetClickHdl( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl ));
1876 m_pBackPB->SetClickHdl( LINK( this, SvxEditModulesDlg, BackHdl_Impl ));
1877 // in case of not installed language modules
1878 m_pPrioUpPB->Enable( false );
1879 m_pPrioDownPB->Enable( false );
1881 if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
1882 != SvtExtendedSecurityOptions::OPEN_NEVER )
1884 m_pMoreDictsLink->SetClickHdl( LINK( this, SvxEditModulesDlg, OpenURLHdl_Impl ) );
1886 else
1888 m_pMoreDictsLink->Hide();
1891 //fill language box
1892 Sequence< sal_Int16 > aAvailLang;
1893 uno::Reference< XAvailableLocales > xAvail( rLinguData.GetManager(), UNO_QUERY );
1894 if (xAvail.is())
1896 aAvailLang = lcl_LocaleSeqToLangSeq(
1897 xAvail->getAvailableLocales( cSpell ) );
1899 const Sequence< Locale >& rLoc = rLinguData.GetAllSupportedLocales();
1900 const Locale* pLocales = rLoc.getConstArray();
1901 m_pLanguageLB->Clear();
1902 for(long i = 0; i < rLoc.getLength(); i++)
1904 sal_Int16 nLang = LanguageTag::convertToLanguageType( pLocales[i] );
1905 m_pLanguageLB->InsertLanguage( nLang, lcl_SeqHasLang( aAvailLang, nLang ) );
1907 LanguageType eSysLang = MsLangId::getSystemLanguage();
1908 m_pLanguageLB->SelectLanguage( eSysLang );
1909 if(!m_pLanguageLB->IsLanguageSelected( eSysLang ) )
1910 m_pLanguageLB->SelectEntryPos(0);
1912 m_pLanguageLB->SetSelectHdl( LINK( this, SvxEditModulesDlg, LangSelectHdl_Impl ));
1913 LangSelectHdl_Impl(m_pLanguageLB);
1917 SvxEditModulesDlg::~SvxEditModulesDlg()
1919 delete pDefaultLinguData;
1923 SvTreeListEntry* SvxEditModulesDlg::CreateEntry( OUString& rTxt, sal_uInt16 nCol )
1925 SvTreeListEntry* pEntry = new SvTreeListEntry;
1926 if( !pCheckButtonData )
1928 pCheckButtonData = new SvLBoxButtonData(m_pModulesCLB);
1929 pCheckButtonData->SetLink( m_pModulesCLB->GetCheckButtonHdl() );
1932 OUString sEmpty;
1933 if (CBCOL_FIRST == nCol)
1934 pEntry->AddItem( new SvLBoxButton( pEntry, SvLBoxButtonKind_enabledCheckbox, 0, pCheckButtonData ) );
1935 if (CBCOL_SECOND == nCol)
1936 pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty) ); // empty column
1937 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), false));
1938 pEntry->AddItem( new BrwStringDic_Impl( pEntry, 0, rTxt ) );
1940 return pEntry;
1943 IMPL_LINK( SvxEditModulesDlg, SelectHdl_Impl, SvxCheckListBox *, pBox )
1945 if (m_pModulesCLB == pBox)
1947 bool bDisableUp = true;
1948 bool bDisableDown = true;
1949 SvTreeListEntry *pEntry = pBox->GetCurEntry();
1950 if (pEntry)
1952 ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
1953 if(!pData->IsParent() && pData->GetType() != TYPE_HYPH)
1955 sal_uLong nCurPos = pBox->GetSelectEntryPos();
1956 if(nCurPos < pBox->GetEntryCount() - 1)
1958 bDisableDown = ((ModuleUserData_Impl*)pBox->
1959 GetEntry(nCurPos + 1)->GetUserData())->IsParent();
1961 if(nCurPos > 1)
1963 bDisableUp = ((ModuleUserData_Impl*)pBox->
1964 GetEntry(nCurPos - 1)->GetUserData())->IsParent();
1967 m_pPrioUpPB->Enable(!bDisableUp);
1968 m_pPrioDownPB->Enable(!bDisableDown);
1971 else
1973 OSL_FAIL( "pBox unexpected value" );
1976 return 0;
1979 IMPL_LINK( SvxEditModulesDlg, BoxCheckButtonHdl_Impl, SvTreeListBox *, pBox )
1981 pBox = m_pModulesCLB;
1982 SvTreeListEntry *pCurEntry = pBox->GetCurEntry();
1983 if (pCurEntry)
1985 ModuleUserData_Impl* pData = (ModuleUserData_Impl *)
1986 pCurEntry->GetUserData();
1987 if (!pData->IsParent() && pData->GetType() == TYPE_HYPH)
1989 // make hyphenator checkboxes function as radio-buttons
1990 // (at most one box may be checked)
1991 SvTreeListEntry *pEntry = pBox->First();
1992 while (pEntry)
1994 pData = (ModuleUserData_Impl *) pEntry->GetUserData();
1995 if (!pData->IsParent() &&
1996 pData->GetType() == TYPE_HYPH &&
1997 pEntry != pCurEntry)
1999 lcl_SetCheckButton( pEntry, false );
2000 pBox->InvalidateEntry( pEntry );
2002 pEntry = pBox->Next( pEntry );
2006 return 0;
2009 IMPL_LINK( SvxEditModulesDlg, LangSelectHdl_Impl, ListBox *, pBox )
2011 LanguageType eCurLanguage = m_pLanguageLB->GetSelectLanguage();
2012 static Locale aLastLocale;
2013 Locale aCurLocale( LanguageTag::convertToLocale( eCurLanguage));
2014 SvTreeList *pModel = m_pModulesCLB->GetModel();
2016 if (pBox)
2018 // save old probably changed settings
2019 // before switching to new language entries
2021 sal_Int16 nLang = LanguageTag::convertToLanguageType( aLastLocale );
2023 sal_Int32 nStart = 0, nLocalIndex = 0;
2024 Sequence< OUString > aChange;
2025 bool bChanged = false;
2026 for(sal_uLong i = 0; i < m_pModulesCLB->GetEntryCount(); i++)
2028 SvTreeListEntry *pEntry = m_pModulesCLB->GetEntry(i);
2029 ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
2030 if(pData->IsParent())
2032 if(bChanged)
2034 LangImplNameTable *pTable = 0;
2035 sal_uInt8 nType = pData->GetType();
2036 switch (nType - 1)
2038 case TYPE_SPELL : pTable = &rLinguData.GetSpellTable(); break;
2039 case TYPE_GRAMMAR : pTable = &rLinguData.GetGrammarTable(); break;
2040 case TYPE_HYPH : pTable = &rLinguData.GetHyphTable(); break;
2041 case TYPE_THES : pTable = &rLinguData.GetThesTable(); break;
2043 if (pTable)
2045 aChange.realloc(nStart);
2046 (*pTable)[ nLang ] = aChange;
2049 nLocalIndex = nStart = 0;
2050 aChange.realloc(m_pModulesCLB->GetEntryCount());
2051 bChanged = false;
2053 else
2055 OUString* pChange = aChange.getArray();
2056 pChange[nStart] = pData->GetImplName();
2057 bChanged |= pData->GetIndex() != nLocalIndex ||
2058 pData->IsChecked() != m_pModulesCLB->IsChecked(i);
2059 if(m_pModulesCLB->IsChecked(i))
2060 nStart++;
2061 ++nLocalIndex;
2064 if(bChanged)
2066 aChange.realloc(nStart);
2067 rLinguData.GetThesTable()[ nLang ] = aChange;
2071 for(sal_uLong i = 0; i < m_pModulesCLB->GetEntryCount(); i++)
2072 delete (ModuleUserData_Impl*)m_pModulesCLB->GetEntry(i)->GetUserData();
2075 // display entries for new selected language
2077 m_pModulesCLB->Clear();
2078 if(LANGUAGE_DONTKNOW != eCurLanguage)
2080 sal_uLong n;
2081 ServiceInfo_Impl* pInfo;
2084 // spellchecker entries
2086 SvTreeListEntry* pEntry = CreateEntry( sSpell, CBCOL_SECOND );
2087 ModuleUserData_Impl* pUserData = new ModuleUserData_Impl(
2088 OUString(), true, false, TYPE_SPELL, 0 );
2089 pEntry->SetUserData( (void *)pUserData );
2090 pModel->Insert( pEntry );
2092 Sequence< OUString > aNames( rLinguData.GetSortedImplNames( eCurLanguage, TYPE_SPELL ) );
2093 const OUString *pName = aNames.getConstArray();
2094 sal_uLong nNames = (sal_uLong) aNames.getLength();
2095 sal_Int32 nLocalIndex = 0; // index relative to parent
2096 for (n = 0; n < nNames; ++n)
2098 OUString aImplName;
2099 bool bIsSuppLang = false;
2101 pInfo = rLinguData.GetInfoByImplName( pName[n] );
2102 if (pInfo)
2104 bIsSuppLang = pInfo->xSpell.is() &&
2105 pInfo->xSpell->hasLocale( aCurLocale );
2106 aImplName = pInfo->sSpellImplName;
2108 if (!aImplName.isEmpty() && bIsSuppLang)
2110 OUString aTxt( pInfo->sDisplayName );
2111 SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2113 LangImplNameTable &rTable = rLinguData.GetSpellTable();
2114 const bool bHasLang = rTable.count( eCurLanguage );
2115 if (!bHasLang)
2117 DBG_WARNING( "language entry missing" ); // only relevant if all languages found should be supported
2119 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2120 lcl_SetCheckButton( pNewEntry, bCheck );
2121 pUserData = new ModuleUserData_Impl( aImplName, false,
2122 bCheck, TYPE_SPELL, (sal_uInt8)nLocalIndex++ );
2123 pNewEntry->SetUserData( (void *)pUserData );
2124 pModel->Insert( pNewEntry );
2129 // grammar checker entries
2131 pEntry = CreateEntry( sGrammar, CBCOL_SECOND );
2132 pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_GRAMMAR, 0 );
2133 pEntry->SetUserData( (void *)pUserData );
2134 pModel->Insert( pEntry );
2136 aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_GRAMMAR );
2137 pName = aNames.getConstArray();
2138 nNames = (sal_uLong) aNames.getLength();
2139 nLocalIndex = 0;
2140 for (n = 0; n < nNames; ++n)
2142 OUString aImplName;
2143 bool bIsSuppLang = false;
2145 pInfo = rLinguData.GetInfoByImplName( pName[n] );
2146 if (pInfo)
2148 bIsSuppLang = pInfo->xGrammar.is() &&
2149 pInfo->xGrammar->hasLocale( aCurLocale );
2150 aImplName = pInfo->sGrammarImplName;
2152 if (!aImplName.isEmpty() && bIsSuppLang)
2154 OUString aTxt( pInfo->sDisplayName );
2155 SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2157 LangImplNameTable &rTable = rLinguData.GetGrammarTable();
2158 const bool bHasLang = rTable.count( eCurLanguage );
2159 if (!bHasLang)
2161 DBG_WARNING( "language entry missing" ); // only relevant if all languages found should be supported
2163 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2164 lcl_SetCheckButton( pNewEntry, bCheck );
2165 pUserData = new ModuleUserData_Impl( aImplName, false,
2166 bCheck, TYPE_GRAMMAR, (sal_uInt8)nLocalIndex++ );
2167 pNewEntry->SetUserData( (void *)pUserData );
2168 pModel->Insert( pNewEntry );
2173 // hyphenator entries
2175 pEntry = CreateEntry( sHyph, CBCOL_SECOND );
2176 pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_HYPH, 0 );
2177 pEntry->SetUserData( (void *)pUserData );
2178 pModel->Insert( pEntry );
2180 aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_HYPH );
2181 pName = aNames.getConstArray();
2182 nNames = (sal_uLong) aNames.getLength();
2183 nLocalIndex = 0;
2184 for (n = 0; n < nNames; ++n)
2186 OUString aImplName;
2187 bool bIsSuppLang = false;
2189 pInfo = rLinguData.GetInfoByImplName( pName[n] );
2190 if (pInfo)
2192 bIsSuppLang = pInfo->xHyph.is() &&
2193 pInfo->xHyph->hasLocale( aCurLocale );
2194 aImplName = pInfo->sHyphImplName;
2196 if (!aImplName.isEmpty() && bIsSuppLang)
2198 OUString aTxt( pInfo->sDisplayName );
2199 SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2201 LangImplNameTable &rTable = rLinguData.GetHyphTable();
2202 const bool bHasLang = rTable.count( eCurLanguage );
2203 if (!bHasLang)
2205 DBG_WARNING( "language entry missing" ); // only relevant if all languages found should be supported
2207 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2208 lcl_SetCheckButton( pNewEntry, bCheck );
2209 pUserData = new ModuleUserData_Impl( aImplName, false,
2210 bCheck, TYPE_HYPH, (sal_uInt8)nLocalIndex++ );
2211 pNewEntry->SetUserData( (void *)pUserData );
2212 pModel->Insert( pNewEntry );
2217 // thesaurus entries
2219 pEntry = CreateEntry( sThes, CBCOL_SECOND );
2220 pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_THES, 0 );
2221 pEntry->SetUserData( (void *)pUserData );
2222 pModel->Insert( pEntry );
2224 aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_THES );
2225 pName = aNames.getConstArray();
2226 nNames = (sal_uLong) aNames.getLength();
2227 nLocalIndex = 0;
2228 for (n = 0; n < nNames; ++n)
2230 OUString aImplName;
2231 bool bIsSuppLang = false;
2233 pInfo = rLinguData.GetInfoByImplName( pName[n] );
2234 if (pInfo)
2236 bIsSuppLang = pInfo->xThes.is() &&
2237 pInfo->xThes->hasLocale( aCurLocale );
2238 aImplName = pInfo->sThesImplName;
2240 if (!aImplName.isEmpty() && bIsSuppLang)
2242 OUString aTxt( pInfo->sDisplayName );
2243 SvTreeListEntry* pNewEntry = CreateEntry( aTxt, CBCOL_FIRST );
2245 LangImplNameTable &rTable = rLinguData.GetThesTable();
2246 const bool bHasLang = rTable.count( eCurLanguage );
2247 if (!bHasLang)
2249 DBG_WARNING( "language entry missing" ); // only relevant if all languages found should be supported
2251 const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0;
2252 lcl_SetCheckButton( pNewEntry, bCheck );
2253 pUserData = new ModuleUserData_Impl( aImplName, false,
2254 bCheck, TYPE_THES, (sal_uInt8)nLocalIndex++ );
2255 pNewEntry->SetUserData( (void *)pUserData );
2256 pModel->Insert( pNewEntry );
2260 aLastLocale = aCurLocale;
2261 return 0;
2264 IMPL_LINK( SvxEditModulesDlg, UpDownHdl_Impl, PushButton *, pBtn )
2266 bool bUp = m_pPrioUpPB == pBtn;
2267 sal_uLong nCurPos = m_pModulesCLB->GetSelectEntryPos();
2268 SvTreeListEntry* pEntry;
2269 if (nCurPos != TREELIST_ENTRY_NOTFOUND &&
2270 0 != (pEntry = m_pModulesCLB->GetEntry(nCurPos)))
2272 m_pModulesCLB->SetUpdateMode(false);
2273 SvTreeList *pModel = m_pModulesCLB->GetModel();
2275 ModuleUserData_Impl* pData = (ModuleUserData_Impl*)pEntry->GetUserData();
2276 OUString aStr(m_pModulesCLB->GetEntryText(pEntry));
2277 SvTreeListEntry* pToInsert = CreateEntry( aStr, CBCOL_FIRST );
2278 pToInsert->SetUserData( (void *)pData);
2279 bool bIsChecked = m_pModulesCLB->IsChecked(nCurPos);
2281 pModel->Remove(pEntry);
2283 sal_uLong nDestPos = bUp ? nCurPos - 1 : nCurPos + 1;
2284 pModel->Insert(pToInsert, nDestPos);
2285 m_pModulesCLB->CheckEntryPos(nDestPos, bIsChecked );
2286 m_pModulesCLB->SelectEntryPos(nDestPos );
2287 SelectHdl_Impl(m_pModulesCLB);
2288 m_pModulesCLB->SetUpdateMode(true);
2290 return 0;
2293 IMPL_LINK_NOARG(SvxEditModulesDlg, ClickHdl_Impl)
2295 // store language config
2296 LangSelectHdl_Impl(m_pLanguageLB);
2297 EndDialog( RET_OK );
2298 return 0;
2301 IMPL_LINK_NOARG(SvxEditModulesDlg, BackHdl_Impl)
2303 rLinguData = *pDefaultLinguData;
2304 LangSelectHdl_Impl(0);
2305 return 0;
2310 IMPL_LINK_NOARG(SvxEditModulesDlg, OpenURLHdl_Impl)
2312 OUString sURL( m_pMoreDictsLink->GetURL() );
2313 lcl_OpenURL( sURL );
2314 return 0;
2317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */