xref: /aoo41x/main/svx/source/dialog/langbox.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 // include ---------------------------------------------------------------
32 
33 #include <com/sun/star/linguistic2/XLinguServiceManager.hdl>
34 #include <com/sun/star/linguistic2/XAvailableLocales.hpp>
35 #include <com/sun/star/i18n/ScriptType.hpp>
36 #include <linguistic/misc.hxx>
37 #include <rtl/ustring.hxx>
38 #include <unotools/localedatawrapper.hxx>
39 #include <tools/urlobj.hxx>
40 #include <svtools/langtab.hxx>
41 #include <tools/shl.hxx>
42 #include <i18npool/mslangid.hxx>
43 #include <i18npool/lang.h>
44 #include <editeng/scripttypeitem.hxx>
45 #include <editeng/unolingu.hxx>
46 #include <svx/langbox.hxx>
47 #include <svx/dialmgr.hxx>
48 #include <svx/dialogs.hrc>
49 
50 using namespace ::com::sun::star::util;
51 using namespace ::com::sun::star::lang;
52 using namespace ::com::sun::star::linguistic2;
53 using namespace ::com::sun::star::uno;
54 
55 // -----------------------------------------------------------------------
56 
57 String GetDicInfoStr( const String& rName, const sal_uInt16 nLang, sal_Bool bNeg )
58 {
59 	INetURLObject aURLObj;
60 	aURLObj.SetSmartProtocol( INET_PROT_FILE );
61 	aURLObj.SetSmartURL( rName, INetURLObject::ENCODE_ALL );
62 	String aTmp( aURLObj.GetBase() );
63 	aTmp += sal_Unicode( ' ' );
64 
65 	if ( bNeg )
66 	{
67 		sal_Char const sTmp[] = " (-) ";
68 		aTmp.AppendAscii( sTmp );
69 	}
70 
71 	if ( LANGUAGE_NONE == nLang )
72 		aTmp += String( ResId( RID_SVXSTR_LANGUAGE_ALL, DIALOG_MGR() ) );
73 	else
74 	{
75 		aTmp += sal_Unicode( '[' );
76 		aTmp += SvtLanguageTable::GetLanguageString( (LanguageType)nLang );
77 		aTmp += sal_Unicode( ']' );
78 	}
79 
80 	return aTmp;
81 }
82 
83 //========================================================================
84 //	misc local helper functions
85 //========================================================================
86 
87 static Sequence< sal_Int16 > lcl_LocaleSeqToLangSeq( Sequence< Locale > &rSeq )
88 {
89 	const Locale *pLocale = rSeq.getConstArray();
90 	sal_Int32 nCount = rSeq.getLength();
91 
92 	Sequence< sal_Int16 >	aLangs( nCount );
93 	sal_Int16 *pLang = aLangs.getArray();
94 	for (sal_Int32 i = 0;  i < nCount;  ++i)
95 	{
96 		pLang[i] = SvxLocaleToLanguage( pLocale[i] );
97 
98 	}
99 
100 	return aLangs;
101 }
102 
103 
104 static sal_Bool lcl_SeqHasLang( const Sequence< sal_Int16 > & rLangSeq, sal_Int16 nLang )
105 {
106 	sal_Int32 i = -1;
107 	sal_Int32 nLen = rLangSeq.getLength();
108 	if (nLen)
109 	{
110 		const sal_Int16 *pLang = rLangSeq.getConstArray();
111 		for (i = 0;  i < nLen;  ++i)
112 		{
113 			if (nLang == pLang[i])
114 				break;
115 		}
116 	}
117 	return i >= 0  &&  i < nLen;
118 }
119 
120 //========================================================================
121 //	class SvxLanguageBox
122 //========================================================================
123 
124 sal_uInt16 TypeToPos_Impl( LanguageType eType, const ListBox& rLb )
125 {
126 	sal_uInt16	nPos   = LISTBOX_ENTRY_NOTFOUND;
127 	sal_uInt16	nCount = rLb.GetEntryCount();
128 
129 	for ( sal_uInt16 i=0; nPos == LISTBOX_ENTRY_NOTFOUND && i<nCount; i++ )
130 		if ( eType == LanguageType((sal_uIntPtr)rLb.GetEntryData(i)) )
131 			nPos = i;
132 
133 	return nPos;
134 }
135 
136 //-----------------------------------------------------------------------
137 SvxLanguageBox::SvxLanguageBox( Window* pParent, WinBits nWinStyle, sal_Bool bCheck ) :
138     ListBox( pParent, nWinStyle ),
139     m_pSpellUsedLang( NULL ),
140     m_bWithCheckmark( bCheck )
141 {
142     Init();
143 }
144 //------------------------------------------------------------------------
145 SvxLanguageBox::SvxLanguageBox( Window* pParent, const ResId& rResId, sal_Bool bCheck ) :
146 	ListBox( pParent, rResId ),
147     m_pSpellUsedLang( NULL ),
148 	m_bWithCheckmark( bCheck )
149 {
150     Init();
151 }
152 //------------------------------------------------------------------------
153 void SvxLanguageBox::Init()
154 {
155     m_pLangTable = new SvtLanguageTable;
156 	m_aNotCheckedImage = Image( SVX_RES( RID_SVXIMG_NOTCHECKED ) );
157     m_aCheckedImage = Image( SVX_RES( RID_SVXIMG_CHECKED ) );
158     m_aCheckedImageHC = Image( SVX_RES( RID_SVXIMG_CHECKED_H ) );
159 	m_aAllString			= String( SVX_RESSTR( RID_SVXSTR_LANGUAGE_ALL ) );
160 	m_nLangList				= LANG_LIST_EMPTY;
161 	m_bHasLangNone			= sal_False;
162 	m_bLangNoneIsLangAll	= sal_False;
163 
164 	// display entries sorted
165 	SetStyle( GetStyle() | WB_SORT );
166 
167 	if ( m_bWithCheckmark )
168 	{
169         SvtLanguageTable aLangTable;
170 		sal_uInt32 nCount = aLangTable.GetEntryCount();
171 		for ( sal_uInt32 i = 0; i < nCount; i++ )
172 		{
173 			LanguageType nLangType = aLangTable.GetTypeAtIndex( i );
174 
175 			sal_Bool bInsert = sal_True;
176 			if ((LANGUAGE_DONTKNOW == nLangType)  ||
177 				(LANGUAGE_SYSTEM   == nLangType)  ||
178 				(LANGUAGE_USER1 <= nLangType  &&  nLangType <= LANGUAGE_USER9))
179 			{
180 				bInsert = sal_False;
181 			}
182 
183 			if ( bInsert )
184 				InsertLanguage( nLangType );
185 		}
186 		m_nLangList	= LANG_LIST_ALL;
187 	}
188 }
189 //------------------------------------------------------------------------
190 
191 SvxLanguageBox::~SvxLanguageBox()
192 {
193     delete m_pSpellUsedLang;
194 	delete m_pLangTable;
195 }
196 
197 //------------------------------------------------------------------------
198 
199 sal_uInt16 SvxLanguageBox::ImplInsertImgEntry( const String& rEntry, sal_uInt16 nPos, bool bChecked )
200 {
201     sal_uInt16 nRet = 0;
202     if( !bChecked )
203         nRet = InsertEntry( rEntry, m_aNotCheckedImage, nPos );
204     else if( GetSettings().GetStyleSettings().GetHighContrastMode() )
205         nRet = InsertEntry( rEntry, m_aCheckedImageHC, nPos );
206     else
207         nRet = InsertEntry( rEntry, m_aCheckedImage, nPos );
208     return nRet;
209 }
210 
211 //------------------------------------------------------------------------
212 
213 void SvxLanguageBox::SetLanguageList( sal_Int16 nLangList,
214 		sal_Bool bHasLangNone, sal_Bool bLangNoneIsLangAll, sal_Bool bCheckSpellAvail )
215 {
216 	Clear();
217 
218 	m_nLangList				= nLangList;
219 	m_bHasLangNone			= bHasLangNone;
220 	m_bLangNoneIsLangAll	= bLangNoneIsLangAll;
221 	m_bWithCheckmark		= bCheckSpellAvail;
222 
223 	if ( LANG_LIST_EMPTY != nLangList )
224 	{
225 		Sequence< sal_Int16 > aSpellAvailLang;
226 		Sequence< sal_Int16 > aHyphAvailLang;
227 		Sequence< sal_Int16 > aThesAvailLang;
228         Sequence< sal_Int16 > aSpellUsedLang;
229         Sequence< sal_Int16 > aHyphUsedLang;
230         Sequence< sal_Int16 > aThesUsedLang;
231 		Reference< XAvailableLocales > xAvail( LinguMgr::GetLngSvcMgr(), UNO_QUERY );
232 		if (xAvail.is())
233 		{
234 			Sequence< Locale > aTmp;
235 
236 			if (LANG_LIST_SPELL_AVAIL & nLangList)
237 			{
238 				aTmp = xAvail->getAvailableLocales( A2OU( SN_SPELLCHECKER ) );
239 				aSpellAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
240 			}
241 			if (LANG_LIST_HYPH_AVAIL  & nLangList)
242 			{
243 				aTmp = xAvail->getAvailableLocales( A2OU( SN_HYPHENATOR ) );
244 				aHyphAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
245 			}
246 			if (LANG_LIST_THES_AVAIL  & nLangList)
247 			{
248 				aTmp = xAvail->getAvailableLocales( A2OU( SN_THESAURUS ) );
249 				aThesAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
250 			}
251 		}
252         if (LANG_LIST_SPELL_USED & nLangList)
253         {
254             Reference< XSpellChecker1 > xTmp1( SvxGetSpellChecker(), UNO_QUERY );
255             if (xTmp1.is())
256                 aSpellUsedLang = xTmp1->getLanguages();
257         }
258         if (LANG_LIST_HYPH_USED  & nLangList)
259         {
260             Reference< XHyphenator > xTmp( SvxGetHyphenator() );
261             if (xTmp.is()) {
262                 Sequence < Locale > aLocaleSequence( xTmp->getLocales() );
263                 aHyphUsedLang = lcl_LocaleSeqToLangSeq( aLocaleSequence );
264             }
265         }
266         if (LANG_LIST_THES_USED  & nLangList)
267         {
268             Reference< XThesaurus > xTmp( SvxGetThesaurus() );
269             if (xTmp.is()) {
270                 Sequence < Locale > aLocaleSequence( xTmp->getLocales() );
271                 aThesUsedLang = lcl_LocaleSeqToLangSeq( aLocaleSequence );
272             }
273         }
274 
275         SvtLanguageTable aLangTable;
276         ::com::sun::star::uno::Sequence< sal_uInt16 > xKnown;
277         const sal_uInt16* pKnown;
278         sal_uInt32 nCount;
279         if ( nLangList & LANG_LIST_ONLY_KNOWN )
280         {
281             xKnown = LocaleDataWrapper::getInstalledLanguageTypes();
282             pKnown = xKnown.getConstArray();
283             nCount = xKnown.getLength();
284         }
285         else
286         {
287             nCount = aLangTable.GetEntryCount();
288             pKnown = NULL;
289         }
290 		for ( sal_uInt32 i = 0; i < nCount; i++ )
291 		{
292             LanguageType nLangType;
293             if ( nLangList & LANG_LIST_ONLY_KNOWN )
294                 nLangType = pKnown[i];
295             else
296                 nLangType = aLangTable.GetTypeAtIndex( i );
297 			if ( nLangType != LANGUAGE_DONTKNOW &&
298 				 nLangType != LANGUAGE_SYSTEM &&
299 			     nLangType != LANGUAGE_NONE &&
300                  (nLangType < LANGUAGE_USER1 || nLangType > LANGUAGE_USER9) &&
301                  (MsLangId::getSubLanguage( nLangType) != 0 ||
302                   (nLangList & LANG_LIST_ALSO_PRIMARY_ONLY)) &&
303                  ((nLangList & LANG_LIST_ALL) != 0 ||
304                   ((nLangList & LANG_LIST_WESTERN) != 0 &&
305                    (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
306                     SCRIPTTYPE_LATIN)) ||
307                   ((nLangList & LANG_LIST_CTL) != 0 &&
308                    (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
309                     SCRIPTTYPE_COMPLEX)) ||
310                   ((nLangList & LANG_LIST_CJK) != 0 &&
311                    (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
312                     SCRIPTTYPE_ASIAN)) ||
313                   ((nLangList & LANG_LIST_FBD_CHARS) != 0 &&
314                    MsLangId::hasForbiddenCharacters(nLangType)) ||
315                   ((nLangList & LANG_LIST_SPELL_AVAIL) != 0 &&
316                    lcl_SeqHasLang(aSpellAvailLang, nLangType)) ||
317                   ((nLangList & LANG_LIST_HYPH_AVAIL) != 0 &&
318                    lcl_SeqHasLang(aHyphAvailLang, nLangType)) ||
319                   ((nLangList & LANG_LIST_THES_AVAIL) != 0 &&
320                    lcl_SeqHasLang(aThesAvailLang, nLangType)) ||
321                   ((nLangList & LANG_LIST_SPELL_USED) != 0 &&
322                    lcl_SeqHasLang(aSpellUsedLang, nLangType)) ||
323                   ((nLangList & LANG_LIST_HYPH_USED) != 0 &&
324                    lcl_SeqHasLang(aHyphUsedLang, nLangType)) ||
325                   ((nLangList & LANG_LIST_THES_USED) != 0 &&
326                    lcl_SeqHasLang(aThesUsedLang, nLangType))) )
327 				InsertLanguage( nLangType );
328 		}
329 
330 		if (bHasLangNone)
331 			InsertLanguage( LANGUAGE_NONE );
332 	}
333 }
334 
335 //------------------------------------------------------------------------
336 
337 sal_uInt16 SvxLanguageBox::InsertLanguage( const LanguageType nLangType, sal_uInt16 nPos )
338 {
339     return ImplInsertLanguage( nLangType, nPos, ::com::sun::star::i18n::ScriptType::WEAK );
340 }
341 
342 //------------------------------------------------------------------------
343 
344 sal_uInt16 SvxLanguageBox::ImplInsertLanguage( const LanguageType nLangType, sal_uInt16 nPos, sal_Int16 nType )
345 {
346     LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( nLangType);
347     // For obsolete and to be replaced languages check whether an entry of the
348     // replacement already exists and if so don't add an entry with identical
349     // string as would be returned by SvtLanguageTable::GetString().
350     if (nLang != nLangType)
351     {
352         sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
353         if ( nAt != LISTBOX_ENTRY_NOTFOUND )
354             return nAt;
355     }
356 
357     String aStrEntry = m_pLangTable->GetString( nLang );
358     if (LANGUAGE_NONE == nLang && m_bHasLangNone && m_bLangNoneIsLangAll)
359         aStrEntry = m_aAllString;
360 
361     LanguageType nRealLang = nLang;
362     if (nRealLang == LANGUAGE_SYSTEM)
363     {
364         nRealLang = MsLangId::resolveSystemLanguageByScriptType(nRealLang, nType);
365         aStrEntry.AppendAscii(" - ");
366         aStrEntry.Append(m_pLangTable->GetString( nRealLang ));
367     }
368 
369     aStrEntry = ApplyLreOrRleEmbedding( aStrEntry );
370 
371     sal_uInt16 nAt = 0;
372     if ( m_bWithCheckmark )
373     {
374         sal_Bool bFound = sal_False;
375 
376         if (!m_pSpellUsedLang)
377         {
378             Reference< XSpellChecker1 > xSpell( SvxGetSpellChecker(), UNO_QUERY );
379             if ( xSpell.is() )
380                 m_pSpellUsedLang = new Sequence< sal_Int16 >( xSpell->getLanguages() );
381         }
382         bFound = m_pSpellUsedLang ?
383             lcl_SeqHasLang( *m_pSpellUsedLang, nRealLang ) : sal_False;
384 
385         nAt = ImplInsertImgEntry( aStrEntry, nPos, bFound );
386     }
387     else
388         nAt = InsertEntry( aStrEntry, nPos );
389 
390     SetEntryData( nAt, (void*)(sal_uIntPtr)nLangType );
391     return nAt;
392 }
393 
394 //------------------------------------------------------------------------
395 
396 sal_uInt16 SvxLanguageBox::InsertDefaultLanguage( sal_Int16 nType, sal_uInt16 nPos )
397 {
398     return ImplInsertLanguage( LANGUAGE_SYSTEM, nPos, nType );
399 }
400 
401 //------------------------------------------------------------------------
402 
403 sal_uInt16 SvxLanguageBox::InsertLanguage( const LanguageType nLangType,
404         sal_Bool bCheckEntry, sal_uInt16 nPos )
405 {
406     LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( nLangType);
407     // For obsolete and to be replaced languages check whether an entry of the
408     // replacement already exists and if so don't add an entry with identical
409     // string as would be returned by SvtLanguageTable::GetString().
410     if (nLang != nLangType)
411     {
412         sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
413         if ( nAt != LISTBOX_ENTRY_NOTFOUND )
414             return nAt;
415     }
416 
417 	String aStrEntry = m_pLangTable->GetString( nLang );
418 	if (LANGUAGE_NONE == nLang && m_bHasLangNone && m_bLangNoneIsLangAll)
419 		aStrEntry = m_aAllString;
420 
421     sal_uInt16 nAt = ImplInsertImgEntry( aStrEntry, nPos, bCheckEntry );
422 	SetEntryData( nAt, (void*)(sal_uIntPtr)nLang );
423 
424     return nAt;
425 }
426 
427 //------------------------------------------------------------------------
428 
429 void SvxLanguageBox::RemoveLanguage( const LanguageType eLangType )
430 {
431 	sal_uInt16 nAt = TypeToPos_Impl( eLangType, *this );
432 
433 	if ( nAt != LISTBOX_ENTRY_NOTFOUND )
434 		RemoveEntry( nAt );
435 }
436 
437 //------------------------------------------------------------------------
438 
439 LanguageType SvxLanguageBox::GetSelectLanguage() const
440 {
441 	sal_uInt16 		 nPos	= GetSelectEntryPos();
442 
443 	if ( nPos != LISTBOX_ENTRY_NOTFOUND )
444 		return LanguageType( (sal_uIntPtr)GetEntryData(nPos) );
445 	else
446 		return LanguageType( LANGUAGE_DONTKNOW );
447 }
448 
449 //------------------------------------------------------------------------
450 
451 void SvxLanguageBox::SelectLanguage( const LanguageType eLangType, sal_Bool bSelect )
452 {
453     // If the core uses a LangID of an imported MS document and wants to select
454     // a language that is replaced, we need to select the replacement instead.
455     LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( eLangType);
456 
457 	sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
458 
459 	if ( nAt != LISTBOX_ENTRY_NOTFOUND )
460 		SelectEntryPos( nAt, bSelect );
461 }
462 
463 //------------------------------------------------------------------------
464 
465 sal_Bool SvxLanguageBox::IsLanguageSelected( const LanguageType eLangType ) const
466 {
467     // Same here, work on the replacement if applicable.
468     LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( eLangType);
469 
470 	sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
471 
472 	if ( nAt != LISTBOX_ENTRY_NOTFOUND )
473 		return IsEntryPosSelected( nAt );
474 	else
475 		return sal_False;
476 }
477 
478 #if ENABLE_LAYOUT
479 
480 namespace layout
481 {
482 
483 SvxLanguageBox::~SvxLanguageBox ()
484 {
485 }
486 
487 SvxLanguageBox::SvxLanguageBox( Context* pParent, const char* pFile, sal_Bool bCheck )
488 : ListBox ( pParent, pFile, bCheck )
489 {
490 }
491 
492 void SvxLanguageBox::SetLanguageList( sal_Int16/*list*/, bool/*hasLangNone*/, bool /*langNoneIsLangAll*/, bool /*checkSpellAvail*/)
493 {
494 }
495 
496 sal_uInt16 SvxLanguageBox::InsertLanguage( const LanguageType/*type*/, sal_uInt16/*pos*/)
497 {
498     return 0;
499 }
500 sal_uInt16 SvxLanguageBox::InsertLanguage( const LanguageType/*type*/, bool/*checkEntry*/, sal_uInt16 /*pos*/)
501 {
502     return 0;
503 }
504 void SvxLanguageBox::RemoveLanguage( const LanguageType/*type*/)
505 {
506 }
507 void SvxLanguageBox::SelectLanguage( const LanguageType/*type*/, bool/*select*/)
508 {
509 }
510 LanguageType SvxLanguageBox::GetSelectLanguage() const
511 {
512     return 0;
513 }
514 bool SvxLanguageBox::IsLanguageSelected( const LanguageType/*type*/) const
515 {
516     return true;
517 }
518 
519 /*IMPL_IMPL (SvxLanguageBox, ListBox);
520 IMPL_CONSTRUCTORS ( SvxLanguageBox, ListBox, "svxlanguagebox" );
521 IMPL_GET_IMPL( SvxLanguageBox );
522 IMPL_GET_WINDOW (SvxLanguageBox);*/
523 };
524 
525 #endif
526 
527