update credits
[LibreOffice.git] / svx / source / dialog / langbox.cxx
blob7291b1728cbdf3a849ee18b4612052632e787620
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 <com/sun/star/linguistic2/XAvailableLocales.hpp>
21 #include <com/sun/star/i18n/ScriptType.hpp>
22 #include <linguistic/misc.hxx>
23 #include <rtl/ustring.hxx>
24 #include <unotools/localedatawrapper.hxx>
25 #include <tools/urlobj.hxx>
26 #include <svtools/langtab.hxx>
27 #include <tools/shl.hxx>
28 #include <i18nlangtag/mslangid.hxx>
29 #include <i18nlangtag/lang.h>
30 #include <editeng/scripttypeitem.hxx>
31 #include <editeng/unolingu.hxx>
32 #include <svx/langbox.hxx>
33 #include <svx/dialmgr.hxx>
34 #include <svx/dialogs.hrc>
35 #include <vcl/builder.hxx>
37 using namespace ::com::sun::star::util;
38 using namespace ::com::sun::star::lang;
39 using namespace ::com::sun::star::linguistic2;
40 using namespace ::com::sun::star::uno;
42 // -----------------------------------------------------------------------
44 String GetDicInfoStr( const String& rName, const sal_uInt16 nLang, bool bNeg )
46 INetURLObject aURLObj;
47 aURLObj.SetSmartProtocol( INET_PROT_FILE );
48 aURLObj.SetSmartURL( rName, INetURLObject::ENCODE_ALL );
49 String aTmp( aURLObj.GetBase() );
50 aTmp += sal_Unicode( ' ' );
52 if ( bNeg )
54 sal_Char const sTmp[] = " (-) ";
55 aTmp.AppendAscii( sTmp );
58 if ( LANGUAGE_NONE == nLang )
59 aTmp += SVX_RESSTR(RID_SVXSTR_LANGUAGE_ALL);
60 else
62 aTmp += sal_Unicode( '[' );
63 aTmp += SvtLanguageTable::GetLanguageString( (LanguageType)nLang );
64 aTmp += sal_Unicode( ']' );
67 return aTmp;
70 //========================================================================
71 // misc local helper functions
72 //========================================================================
74 static Sequence< sal_Int16 > lcl_LocaleSeqToLangSeq( Sequence< Locale > &rSeq )
76 const Locale *pLocale = rSeq.getConstArray();
77 sal_Int32 nCount = rSeq.getLength();
79 Sequence< sal_Int16 > aLangs( nCount );
80 sal_Int16 *pLang = aLangs.getArray();
81 for (sal_Int32 i = 0; i < nCount; ++i)
83 pLang[i] = LanguageTag( pLocale[i] ).getLanguageType();
87 return aLangs;
91 static bool lcl_SeqHasLang( const Sequence< sal_Int16 > & rLangSeq, sal_Int16 nLang )
93 sal_Int32 i = -1;
94 sal_Int32 nLen = rLangSeq.getLength();
95 if (nLen)
97 const sal_Int16 *pLang = rLangSeq.getConstArray();
98 for (i = 0; i < nLen; ++i)
100 if (nLang == pLang[i])
101 break;
104 return i >= 0 && i < nLen;
107 //========================================================================
108 // class SvxLanguageBox
109 //========================================================================
111 sal_uInt16 TypeToPos_Impl( LanguageType eType, const ListBox& rLb )
113 sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND;
114 sal_uInt16 nCount = rLb.GetEntryCount();
116 for ( sal_uInt16 i=0; nPos == LISTBOX_ENTRY_NOTFOUND && i<nCount; i++ )
117 if ( eType == LanguageType((sal_uIntPtr)rLb.GetEntryData(i)) )
118 nPos = i;
120 return nPos;
123 //------------------------------------------------------------------------
124 SvxLanguageBox::SvxLanguageBox( Window* pParent, const ResId& rResId, sal_Bool bCheck ) :
125 ListBox( pParent, rResId ),
126 m_pSpellUsedLang( NULL ),
127 m_bWithCheckmark( bCheck )
129 Init();
132 SvxLanguageBox::SvxLanguageBox( Window* pParent, WinBits nBits, sal_Bool bCheck )
133 : ListBox( pParent, nBits )
134 , m_pSpellUsedLang( NULL )
135 , m_bWithCheckmark( bCheck )
137 Init();
140 extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeSvxLanguageBox(Window *pParent, VclBuilder::stringmap &)
142 SvxLanguageBox *pListBox = new SvxLanguageBox(pParent, WB_LEFT|WB_DROPDOWN|WB_VCENTER|WB_3DLOOK|WB_TABSTOP);
143 pListBox->EnableAutoSize(true);
144 return pListBox;
147 //------------------------------------------------------------------------
148 void SvxLanguageBox::Init()
150 m_pLangTable = new SvtLanguageTable;
151 m_aNotCheckedImage = Image( SVX_RES( RID_SVXIMG_NOTCHECKED ) );
152 m_aCheckedImage = Image( SVX_RES( RID_SVXIMG_CHECKED ) );
153 m_aAllString = String( SVX_RESSTR( RID_SVXSTR_LANGUAGE_ALL ) );
154 m_nLangList = LANG_LIST_EMPTY;
155 m_bHasLangNone = sal_False;
156 m_bLangNoneIsLangAll = sal_False;
158 // display entries sorted
159 SetStyle( GetStyle() | WB_SORT );
161 if ( m_bWithCheckmark )
163 SvtLanguageTable aLangTable;
164 sal_uInt32 nCount = aLangTable.GetEntryCount();
165 for ( sal_uInt32 i = 0; i < nCount; i++ )
167 LanguageType nLangType = aLangTable.GetTypeAtIndex( i );
169 bool bInsert = true;
170 if ((LANGUAGE_DONTKNOW == nLangType) ||
171 (LANGUAGE_SYSTEM == nLangType))
173 bInsert = false;
176 if ( bInsert )
177 InsertLanguage( nLangType );
179 m_nLangList = LANG_LIST_ALL;
182 //------------------------------------------------------------------------
184 SvxLanguageBox::~SvxLanguageBox()
186 delete m_pSpellUsedLang;
187 delete m_pLangTable;
190 //------------------------------------------------------------------------
192 sal_uInt16 SvxLanguageBox::ImplInsertImgEntry( const String& rEntry, sal_uInt16 nPos, bool bChecked )
194 sal_uInt16 nRet = 0;
195 if( !bChecked )
196 nRet = InsertEntry( rEntry, m_aNotCheckedImage, nPos );
197 else
198 nRet = InsertEntry( rEntry, m_aCheckedImage, nPos );
199 return nRet;
202 //------------------------------------------------------------------------
204 void SvxLanguageBox::SetLanguageList( sal_Int16 nLangList,
205 sal_Bool bHasLangNone, sal_Bool bLangNoneIsLangAll, sal_Bool bCheckSpellAvail )
207 Clear();
209 m_nLangList = nLangList;
210 m_bHasLangNone = bHasLangNone;
211 m_bLangNoneIsLangAll = bLangNoneIsLangAll;
212 m_bWithCheckmark = bCheckSpellAvail;
214 if ( LANG_LIST_EMPTY != nLangList )
216 Sequence< sal_Int16 > aSpellAvailLang;
217 Sequence< sal_Int16 > aHyphAvailLang;
218 Sequence< sal_Int16 > aThesAvailLang;
219 Sequence< sal_Int16 > aSpellUsedLang;
220 Sequence< sal_Int16 > aHyphUsedLang;
221 Sequence< sal_Int16 > aThesUsedLang;
222 Reference< XAvailableLocales > xAvail( LinguMgr::GetLngSvcMgr(), UNO_QUERY );
223 if (xAvail.is())
225 Sequence< Locale > aTmp;
227 if (LANG_LIST_SPELL_AVAIL & nLangList)
229 aTmp = xAvail->getAvailableLocales( SN_SPELLCHECKER );
230 aSpellAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
232 if (LANG_LIST_HYPH_AVAIL & nLangList)
234 aTmp = xAvail->getAvailableLocales( SN_HYPHENATOR );
235 aHyphAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
237 if (LANG_LIST_THES_AVAIL & nLangList)
239 aTmp = xAvail->getAvailableLocales( SN_THESAURUS );
240 aThesAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
243 if (LANG_LIST_SPELL_USED & nLangList)
245 Reference< XSpellChecker1 > xTmp1( SvxGetSpellChecker(), UNO_QUERY );
246 if (xTmp1.is())
247 aSpellUsedLang = xTmp1->getLanguages();
249 if (LANG_LIST_HYPH_USED & nLangList)
251 Reference< XHyphenator > xTmp( SvxGetHyphenator() );
252 if (xTmp.is()) {
253 Sequence < Locale > aLocaleSequence( xTmp->getLocales() );
254 aHyphUsedLang = lcl_LocaleSeqToLangSeq( aLocaleSequence );
257 if (LANG_LIST_THES_USED & nLangList)
259 Reference< XThesaurus > xTmp( SvxGetThesaurus() );
260 if (xTmp.is()) {
261 Sequence < Locale > aLocaleSequence( xTmp->getLocales() );
262 aThesUsedLang = lcl_LocaleSeqToLangSeq( aLocaleSequence );
266 SvtLanguageTable aLangTable;
267 ::com::sun::star::uno::Sequence< sal_uInt16 > xKnown;
268 const sal_uInt16* pKnown;
269 sal_uInt32 nCount;
270 if ( nLangList & LANG_LIST_ONLY_KNOWN )
272 xKnown = LocaleDataWrapper::getInstalledLanguageTypes();
273 pKnown = xKnown.getConstArray();
274 nCount = xKnown.getLength();
276 else
278 nCount = aLangTable.GetEntryCount();
279 pKnown = NULL;
281 for ( sal_uInt32 i = 0; i < nCount; i++ )
283 LanguageType nLangType;
284 if ( nLangList & LANG_LIST_ONLY_KNOWN )
285 nLangType = pKnown[i];
286 else
287 nLangType = aLangTable.GetTypeAtIndex( i );
288 if ( nLangType != LANGUAGE_DONTKNOW &&
289 nLangType != LANGUAGE_SYSTEM &&
290 nLangType != LANGUAGE_NONE &&
291 (MsLangId::getSubLanguage( nLangType) != 0 ||
292 (nLangList & LANG_LIST_ALSO_PRIMARY_ONLY)) &&
293 ((nLangList & LANG_LIST_ALL) != 0 ||
294 ((nLangList & LANG_LIST_WESTERN) != 0 &&
295 (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
296 SCRIPTTYPE_LATIN)) ||
297 ((nLangList & LANG_LIST_CTL) != 0 &&
298 (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
299 SCRIPTTYPE_COMPLEX)) ||
300 ((nLangList & LANG_LIST_CJK) != 0 &&
301 (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
302 SCRIPTTYPE_ASIAN)) ||
303 ((nLangList & LANG_LIST_FBD_CHARS) != 0 &&
304 MsLangId::hasForbiddenCharacters(nLangType)) ||
305 ((nLangList & LANG_LIST_SPELL_AVAIL) != 0 &&
306 lcl_SeqHasLang(aSpellAvailLang, nLangType)) ||
307 ((nLangList & LANG_LIST_HYPH_AVAIL) != 0 &&
308 lcl_SeqHasLang(aHyphAvailLang, nLangType)) ||
309 ((nLangList & LANG_LIST_THES_AVAIL) != 0 &&
310 lcl_SeqHasLang(aThesAvailLang, nLangType)) ||
311 ((nLangList & LANG_LIST_SPELL_USED) != 0 &&
312 lcl_SeqHasLang(aSpellUsedLang, nLangType)) ||
313 ((nLangList & LANG_LIST_HYPH_USED) != 0 &&
314 lcl_SeqHasLang(aHyphUsedLang, nLangType)) ||
315 ((nLangList & LANG_LIST_THES_USED) != 0 &&
316 lcl_SeqHasLang(aThesUsedLang, nLangType))) )
317 InsertLanguage( nLangType );
320 if (bHasLangNone)
321 InsertLanguage( LANGUAGE_NONE );
325 //------------------------------------------------------------------------
327 sal_uInt16 SvxLanguageBox::InsertLanguage( const LanguageType nLangType, sal_uInt16 nPos )
329 return ImplInsertLanguage( nLangType, nPos, ::com::sun::star::i18n::ScriptType::WEAK );
332 //------------------------------------------------------------------------
334 sal_uInt16 SvxLanguageBox::ImplInsertLanguage( const LanguageType nLangType, sal_uInt16 nPos, sal_Int16 nType )
336 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( nLangType);
337 // For obsolete and to be replaced languages check whether an entry of the
338 // replacement already exists and if so don't add an entry with identical
339 // string as would be returned by SvtLanguageTable::GetString().
340 if (nLang != nLangType)
342 sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
343 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
344 return nAt;
347 String aStrEntry = m_pLangTable->GetString( nLang );
348 if (LANGUAGE_NONE == nLang && m_bHasLangNone && m_bLangNoneIsLangAll)
349 aStrEntry = m_aAllString;
351 LanguageType nRealLang = nLang;
352 if (nRealLang == LANGUAGE_SYSTEM)
354 nRealLang = MsLangId::resolveSystemLanguageByScriptType(nRealLang, nType);
355 aStrEntry.AppendAscii(" - ");
356 aStrEntry.Append(m_pLangTable->GetString( nRealLang ));
357 } else if (nRealLang == LANGUAGE_USER_SYSTEM_CONFIG) {
358 nRealLang = MsLangId::getSystemLanguage();
359 aStrEntry.AppendAscii(" - ");
360 aStrEntry.Append(m_pLangTable->GetString( nRealLang ));
363 aStrEntry = ApplyLreOrRleEmbedding( aStrEntry );
365 sal_uInt16 nAt = 0;
366 if ( m_bWithCheckmark )
368 bool bFound = false;
370 if (!m_pSpellUsedLang)
372 Reference< XSpellChecker1 > xSpell( SvxGetSpellChecker(), UNO_QUERY );
373 if ( xSpell.is() )
374 m_pSpellUsedLang = new Sequence< sal_Int16 >( xSpell->getLanguages() );
376 bFound = m_pSpellUsedLang ?
377 lcl_SeqHasLang( *m_pSpellUsedLang, nRealLang ) : false;
379 nAt = ImplInsertImgEntry( aStrEntry, nPos, bFound );
381 else
382 nAt = InsertEntry( aStrEntry, nPos );
384 SetEntryData( nAt, (void*)(sal_uIntPtr)nLangType );
385 return nAt;
388 //------------------------------------------------------------------------
390 sal_uInt16 SvxLanguageBox::InsertDefaultLanguage( sal_Int16 nType, sal_uInt16 nPos )
392 return ImplInsertLanguage( LANGUAGE_SYSTEM, nPos, nType );
395 //------------------------------------------------------------------------
397 sal_uInt16 SvxLanguageBox::InsertSystemLanguage( sal_uInt16 nPos )
399 return ImplInsertLanguage( LANGUAGE_USER_SYSTEM_CONFIG, nPos, ::com::sun::star::i18n::ScriptType::WEAK );
402 //------------------------------------------------------------------------
404 sal_uInt16 SvxLanguageBox::InsertLanguage( const LanguageType nLangType,
405 sal_Bool bCheckEntry, sal_uInt16 nPos )
407 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( nLangType);
408 // For obsolete and to be replaced languages check whether an entry of the
409 // replacement already exists and if so don't add an entry with identical
410 // string as would be returned by SvtLanguageTable::GetString().
411 if (nLang != nLangType)
413 sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
414 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
415 return nAt;
418 String aStrEntry = m_pLangTable->GetString( nLang );
419 if (LANGUAGE_NONE == nLang && m_bHasLangNone && m_bLangNoneIsLangAll)
420 aStrEntry = m_aAllString;
422 sal_uInt16 nAt = ImplInsertImgEntry( aStrEntry, nPos, bCheckEntry );
423 SetEntryData( nAt, (void*)(sal_uIntPtr)nLang );
425 return nAt;
428 //------------------------------------------------------------------------
430 void SvxLanguageBox::RemoveLanguage( const LanguageType eLangType )
432 sal_uInt16 nAt = TypeToPos_Impl( eLangType, *this );
434 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
435 RemoveEntry( nAt );
438 //------------------------------------------------------------------------
440 LanguageType SvxLanguageBox::GetSelectLanguage() const
442 sal_uInt16 nPos = GetSelectEntryPos();
444 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
445 return LanguageType( (sal_uIntPtr)GetEntryData(nPos) );
446 else
447 return LanguageType( LANGUAGE_DONTKNOW );
450 //------------------------------------------------------------------------
452 void SvxLanguageBox::SelectLanguage( const LanguageType eLangType, sal_Bool bSelect )
454 // If the core uses a LangID of an imported MS document and wants to select
455 // a language that is replaced, we need to select the replacement instead.
456 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( eLangType);
458 sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
460 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
461 SelectEntryPos( nAt, bSelect );
464 //------------------------------------------------------------------------
466 sal_Bool SvxLanguageBox::IsLanguageSelected( const LanguageType eLangType ) const
468 // Same here, work on the replacement if applicable.
469 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( eLangType);
471 sal_uInt16 nAt = TypeToPos_Impl( nLang, *this );
473 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
474 return IsEntryPosSelected( nAt );
475 else
476 return sal_False;
479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */