Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / dialog / langbox.cxx
blob92f5cb6b0b8dcff6aee7e0582685f2c91b267346
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;
43 // If these ever dispersed we'd need a solution.
44 BOOST_STATIC_ASSERT((LISTBOX_APPEND == COMBOBOX_APPEND) && (LISTBOX_ENTRY_NOTFOUND == COMBOBOX_ENTRY_NOTFOUND));
47 OUString GetDicInfoStr( const OUString& rName, const sal_uInt16 nLang, bool bNeg )
49 INetURLObject aURLObj;
50 aURLObj.SetSmartProtocol( INET_PROT_FILE );
51 aURLObj.SetSmartURL( rName, INetURLObject::ENCODE_ALL );
52 OUString aTmp( aURLObj.GetBase() );
53 aTmp += " ";
55 if ( bNeg )
57 aTmp += " (-) ";
60 if ( LANGUAGE_NONE == nLang )
61 aTmp += SVX_RESSTR(RID_SVXSTR_LANGUAGE_ALL);
62 else
64 aTmp += "[";
65 aTmp += SvtLanguageTable::GetLanguageString( (LanguageType)nLang );
66 aTmp += "]";
69 return aTmp;
73 // misc local helper functions
76 static Sequence< sal_Int16 > lcl_LocaleSeqToLangSeq( Sequence< Locale > &rSeq )
78 const Locale *pLocale = rSeq.getConstArray();
79 sal_Int32 nCount = rSeq.getLength();
81 Sequence< sal_Int16 > aLangs( nCount );
82 sal_Int16 *pLang = aLangs.getArray();
83 for (sal_Int32 i = 0; i < nCount; ++i)
85 pLang[i] = LanguageTag::convertToLanguageType( pLocale[i] );
89 return aLangs;
93 static bool lcl_SeqHasLang( const Sequence< sal_Int16 > & rLangSeq, sal_Int16 nLang )
95 sal_Int32 i = -1;
96 sal_Int32 nLen = rLangSeq.getLength();
97 if (nLen)
99 const sal_Int16 *pLang = rLangSeq.getConstArray();
100 for (i = 0; i < nLen; ++i)
102 if (nLang == pLang[i])
103 break;
106 return i >= 0 && i < nLen;
110 extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeSvxLanguageBox(Window *pParent, VclBuilder::stringmap &rMap)
112 WinBits nBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
113 bool bDropdown = VclBuilder::extractDropdown(rMap);
114 if (bDropdown)
115 nBits |= WB_DROPDOWN;
116 else
117 nBits |= WB_BORDER;
118 SvxLanguageBox *pLanguageBox = new SvxLanguageBox(pParent, nBits);
119 pLanguageBox->EnableAutoSize(true);
120 return pLanguageBox;
123 extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeSvxLanguageComboBox(Window *pParent, VclBuilder::stringmap &rMap)
125 WinBits nBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
126 bool bDropdown = VclBuilder::extractDropdown(rMap);
127 if (bDropdown)
128 nBits |= WB_DROPDOWN;
129 else
130 nBits |= WB_BORDER;
131 SvxLanguageComboBox *pLanguageBox = new SvxLanguageComboBox(pParent, nBits);
132 pLanguageBox->EnableAutoSize(true);
133 return pLanguageBox;
137 SvxLanguageBoxBase::SvxLanguageBoxBase( bool bCheck )
138 : m_pSpellUsedLang( NULL )
139 , m_bWithCheckmark( bCheck )
143 void SvxLanguageBoxBase::ImplLanguageBoxBaseInit()
145 m_aNotCheckedImage = Image( SVX_RES( RID_SVXIMG_NOTCHECKED ) );
146 m_aCheckedImage = Image( SVX_RES( RID_SVXIMG_CHECKED ) );
147 m_aAllString = SVX_RESSTR( RID_SVXSTR_LANGUAGE_ALL );
148 m_nLangList = LANG_LIST_EMPTY;
149 m_bHasLangNone = false;
150 m_bLangNoneIsLangAll = false;
152 if ( m_bWithCheckmark )
154 sal_uInt32 nCount = SvtLanguageTable::GetLanguageEntryCount();
155 for ( sal_uInt32 i = 0; i < nCount; i++ )
157 LanguageType nLangType = SvtLanguageTable::GetLanguageTypeAtIndex( i );
159 bool bInsert = true;
160 if ((LANGUAGE_DONTKNOW == nLangType) ||
161 (LANGUAGE_SYSTEM == nLangType))
163 bInsert = false;
166 if ( bInsert )
167 InsertLanguage( nLangType );
169 m_nLangList = LANG_LIST_ALL;
174 SvxLanguageBoxBase::~SvxLanguageBoxBase()
176 delete m_pSpellUsedLang;
180 void SvxLanguageBoxBase::SetLanguageList( sal_Int16 nLangList,
181 bool bHasLangNone, bool bLangNoneIsLangAll, bool bCheckSpellAvail )
183 ImplClear();
185 m_nLangList = nLangList;
186 m_bHasLangNone = bHasLangNone;
187 m_bLangNoneIsLangAll = bLangNoneIsLangAll;
188 m_bWithCheckmark = bCheckSpellAvail;
190 if ( LANG_LIST_EMPTY != nLangList )
192 Sequence< sal_Int16 > aSpellAvailLang;
193 Sequence< sal_Int16 > aHyphAvailLang;
194 Sequence< sal_Int16 > aThesAvailLang;
195 Sequence< sal_Int16 > aSpellUsedLang;
196 Sequence< sal_Int16 > aHyphUsedLang;
197 Sequence< sal_Int16 > aThesUsedLang;
198 Reference< XAvailableLocales > xAvail( LinguMgr::GetLngSvcMgr(), UNO_QUERY );
199 if (xAvail.is())
201 Sequence< Locale > aTmp;
203 if (LANG_LIST_SPELL_AVAIL & nLangList)
205 aTmp = xAvail->getAvailableLocales( SN_SPELLCHECKER );
206 aSpellAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
208 if (LANG_LIST_HYPH_AVAIL & nLangList)
210 aTmp = xAvail->getAvailableLocales( SN_HYPHENATOR );
211 aHyphAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
213 if (LANG_LIST_THES_AVAIL & nLangList)
215 aTmp = xAvail->getAvailableLocales( SN_THESAURUS );
216 aThesAvailLang = lcl_LocaleSeqToLangSeq( aTmp );
219 if (LANG_LIST_SPELL_USED & nLangList)
221 Reference< XSpellChecker1 > xTmp1( SvxGetSpellChecker(), UNO_QUERY );
222 if (xTmp1.is())
223 aSpellUsedLang = xTmp1->getLanguages();
225 if (LANG_LIST_HYPH_USED & nLangList)
227 Reference< XHyphenator > xTmp( SvxGetHyphenator() );
228 if (xTmp.is()) {
229 Sequence < Locale > aLocaleSequence( xTmp->getLocales() );
230 aHyphUsedLang = lcl_LocaleSeqToLangSeq( aLocaleSequence );
233 if (LANG_LIST_THES_USED & nLangList)
235 Reference< XThesaurus > xTmp( SvxGetThesaurus() );
236 if (xTmp.is()) {
237 Sequence < Locale > aLocaleSequence( xTmp->getLocales() );
238 aThesUsedLang = lcl_LocaleSeqToLangSeq( aLocaleSequence );
242 ::com::sun::star::uno::Sequence< sal_uInt16 > xKnown;
243 const sal_uInt16* pKnown;
244 sal_uInt32 nCount;
245 if ( nLangList & LANG_LIST_ONLY_KNOWN )
247 xKnown = LocaleDataWrapper::getInstalledLanguageTypes();
248 pKnown = xKnown.getConstArray();
249 nCount = xKnown.getLength();
251 else
253 nCount = SvtLanguageTable::GetLanguageEntryCount();
254 pKnown = NULL;
256 for ( sal_uInt32 i = 0; i < nCount; i++ )
258 LanguageType nLangType;
259 if ( nLangList & LANG_LIST_ONLY_KNOWN )
260 nLangType = pKnown[i];
261 else
262 nLangType = SvtLanguageTable::GetLanguageTypeAtIndex( i );
263 if ( nLangType != LANGUAGE_DONTKNOW &&
264 nLangType != LANGUAGE_SYSTEM &&
265 nLangType != LANGUAGE_NONE &&
266 (MsLangId::getSubLanguage( nLangType) != 0 ||
267 (nLangList & LANG_LIST_ALSO_PRIMARY_ONLY)) &&
268 ((nLangList & LANG_LIST_ALL) != 0 ||
269 ((nLangList & LANG_LIST_WESTERN) != 0 &&
270 (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
271 SCRIPTTYPE_LATIN)) ||
272 ((nLangList & LANG_LIST_CTL) != 0 &&
273 (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
274 SCRIPTTYPE_COMPLEX)) ||
275 ((nLangList & LANG_LIST_CJK) != 0 &&
276 (SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType) ==
277 SCRIPTTYPE_ASIAN)) ||
278 ((nLangList & LANG_LIST_FBD_CHARS) != 0 &&
279 MsLangId::hasForbiddenCharacters(nLangType)) ||
280 ((nLangList & LANG_LIST_SPELL_AVAIL) != 0 &&
281 lcl_SeqHasLang(aSpellAvailLang, nLangType)) ||
282 ((nLangList & LANG_LIST_HYPH_AVAIL) != 0 &&
283 lcl_SeqHasLang(aHyphAvailLang, nLangType)) ||
284 ((nLangList & LANG_LIST_THES_AVAIL) != 0 &&
285 lcl_SeqHasLang(aThesAvailLang, nLangType)) ||
286 ((nLangList & LANG_LIST_SPELL_USED) != 0 &&
287 lcl_SeqHasLang(aSpellUsedLang, nLangType)) ||
288 ((nLangList & LANG_LIST_HYPH_USED) != 0 &&
289 lcl_SeqHasLang(aHyphUsedLang, nLangType)) ||
290 ((nLangList & LANG_LIST_THES_USED) != 0 &&
291 lcl_SeqHasLang(aThesUsedLang, nLangType))) )
292 InsertLanguage( nLangType );
295 if (bHasLangNone)
296 InsertLanguage( LANGUAGE_NONE );
301 sal_Int32 SvxLanguageBoxBase::InsertLanguage( const LanguageType nLangType, sal_Int32 nPos )
303 return ImplInsertLanguage( nLangType, nPos, ::com::sun::star::i18n::ScriptType::WEAK );
307 sal_Int32 SvxLanguageBoxBase::ImplInsertLanguage( const LanguageType nLangType, sal_Int32 nPos, sal_Int16 nType )
309 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( nLangType);
310 // For obsolete and to be replaced languages check whether an entry of the
311 // replacement already exists and if so don't add an entry with identical
312 // string as would be returned by SvtLanguageTable::GetString().
313 if (nLang != nLangType)
315 sal_Int32 nAt = ImplTypeToPos( nLang );
316 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
317 return nAt;
320 OUString aStrEntry = SvtLanguageTable::GetLanguageString( nLang );
321 if (LANGUAGE_NONE == nLang && m_bHasLangNone && m_bLangNoneIsLangAll)
322 aStrEntry = m_aAllString;
324 LanguageType nRealLang = nLang;
325 if (nRealLang == LANGUAGE_SYSTEM)
327 nRealLang = MsLangId::resolveSystemLanguageByScriptType(nRealLang, nType);
328 aStrEntry += " - ";
329 aStrEntry += SvtLanguageTable::GetLanguageString( nRealLang );
330 } else if (nRealLang == LANGUAGE_USER_SYSTEM_CONFIG) {
331 nRealLang = MsLangId::getSystemLanguage();
332 aStrEntry += " - ";
333 aStrEntry += SvtLanguageTable::GetLanguageString( nRealLang );
336 aStrEntry = ApplyLreOrRleEmbedding( aStrEntry );
338 sal_Int32 nAt = 0;
339 if ( m_bWithCheckmark )
341 bool bFound = false;
343 if (!m_pSpellUsedLang)
345 Reference< XSpellChecker1 > xSpell( SvxGetSpellChecker(), UNO_QUERY );
346 if ( xSpell.is() )
347 m_pSpellUsedLang = new Sequence< sal_Int16 >( xSpell->getLanguages() );
349 bFound = m_pSpellUsedLang ?
350 lcl_SeqHasLang( *m_pSpellUsedLang, nRealLang ) : false;
352 nAt = ImplInsertImgEntry( aStrEntry, nPos, bFound );
354 else
355 nAt = ImplInsertEntry( aStrEntry, nPos );
357 ImplSetEntryData( nAt, (void*)(sal_uIntPtr)nLangType );
358 return nAt;
362 sal_Int32 SvxLanguageBoxBase::InsertDefaultLanguage( sal_Int16 nType, sal_Int32 nPos )
364 return ImplInsertLanguage( LANGUAGE_SYSTEM, nPos, nType );
368 sal_Int32 SvxLanguageBoxBase::InsertSystemLanguage( sal_Int32 nPos )
370 return ImplInsertLanguage( LANGUAGE_USER_SYSTEM_CONFIG, nPos, ::com::sun::star::i18n::ScriptType::WEAK );
374 sal_Int32 SvxLanguageBoxBase::InsertLanguage( const LanguageType nLangType,
375 bool bCheckEntry, sal_Int32 nPos )
377 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( nLangType);
378 // For obsolete and to be replaced languages check whether an entry of the
379 // replacement already exists and if so don't add an entry with identical
380 // string as would be returned by SvtLanguageTable::GetString().
381 if (nLang != nLangType)
383 sal_Int32 nAt = ImplTypeToPos( nLang );
384 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
385 return nAt;
388 OUString aStrEntry = SvtLanguageTable::GetLanguageString( nLang );
389 if (LANGUAGE_NONE == nLang && m_bHasLangNone && m_bLangNoneIsLangAll)
390 aStrEntry = m_aAllString;
392 sal_Int32 nAt = ImplInsertImgEntry( aStrEntry, nPos, bCheckEntry );
393 ImplSetEntryData( nAt, (void*)(sal_uIntPtr)nLang );
395 return nAt;
399 void SvxLanguageBoxBase::RemoveLanguage( const LanguageType eLangType )
401 sal_Int32 nAt = ImplTypeToPos( eLangType );
403 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
404 ImplRemoveEntryAt( nAt );
408 LanguageType SvxLanguageBoxBase::GetSelectLanguage() const
410 sal_Int32 nPos = ImplGetSelectEntryPos();
412 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
413 return LanguageType( (sal_uIntPtr)ImplGetEntryData(nPos) );
414 else
415 return LanguageType( LANGUAGE_DONTKNOW );
419 void SvxLanguageBoxBase::SelectLanguage( const LanguageType eLangType, bool bSelect )
421 // If the core uses a LangID of an imported MS document and wants to select
422 // a language that is replaced, we need to select the replacement instead.
423 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( eLangType);
425 sal_Int32 nAt = ImplTypeToPos( nLang );
427 if ( nAt == LISTBOX_ENTRY_NOTFOUND )
428 nAt = InsertLanguage( nLang ); // on-the-fly-ID
430 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
431 ImplSelectEntryPos( nAt, bSelect );
435 bool SvxLanguageBoxBase::IsLanguageSelected( const LanguageType eLangType ) const
437 // Same here, work on the replacement if applicable.
438 LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( eLangType);
440 sal_Int32 nAt = ImplTypeToPos( nLang );
442 if ( nAt != LISTBOX_ENTRY_NOTFOUND )
443 return ImplIsEntryPosSelected( nAt );
444 else
445 return false;
449 sal_Int32 SvxLanguageBoxBase::ImplTypeToPos( LanguageType eType ) const
451 return ImplGetEntryPos( (void*)(sal_uIntPtr)eType);
455 void SvxLanguageBoxBase::SetNoSelectionLBB()
457 ImplSetNoSelection();
460 void SvxLanguageBoxBase::HideLBB()
462 ImplHide();
465 void SvxLanguageBoxBase::DisableLBB()
467 ImplDisable();
470 void SvxLanguageBoxBase::SaveValueLBB()
472 ImplSaveValue();
475 sal_Int32 SvxLanguageBoxBase::GetSelectEntryPosLBB( sal_Int32 nSelIndex ) const
477 return ImplGetSelectEntryPos( nSelIndex);
480 void* SvxLanguageBoxBase::GetEntryDataLBB( sal_Int32 nPos ) const
482 return ImplGetEntryData( nPos);
485 sal_Int32 SvxLanguageBoxBase::GetSavedValueLBB() const
487 return ImplGetSavedValue();
491 SvxLanguageBox::SvxLanguageBox( Window* pParent, WinBits nBits, bool bCheck )
492 : ListBox( pParent, nBits )
493 , SvxLanguageBoxBase( bCheck )
495 // display entries sorted
496 SetStyle( GetStyle() | WB_SORT );
498 ImplLanguageBoxBaseInit();
501 SvxLanguageBox::~SvxLanguageBox()
506 SvxLanguageComboBox::SvxLanguageComboBox( Window* pParent, WinBits nBits, bool bCheck )
507 : ComboBox( pParent, nBits )
508 , SvxLanguageBoxBase( bCheck )
509 , mnSavedValuePos( COMBOBOX_ENTRY_NOTFOUND )
511 // display entries sorted
512 SetStyle( GetStyle() | WB_SORT );
514 EnableMultiSelection( false );
516 ImplLanguageBoxBaseInit();
519 SvxLanguageComboBox::~SvxLanguageComboBox()
524 sal_Int32 SvxLanguageBox::ImplInsertImgEntry( const OUString& rEntry, sal_Int32 nPos, bool bChecked )
526 return InsertEntry( rEntry, (bChecked ? m_aCheckedImage : m_aNotCheckedImage), nPos );
529 sal_Int32 SvxLanguageComboBox::ImplInsertImgEntry( const OUString& rEntry, sal_Int32 nPos, bool bChecked )
531 return InsertEntryWithImage( rEntry, (bChecked ? m_aCheckedImage : m_aNotCheckedImage), nPos );
535 void SvxLanguageBox::ImplRemoveEntryAt( sal_Int32 nPos )
537 RemoveEntry( nPos);
540 void SvxLanguageComboBox::ImplRemoveEntryAt( sal_Int32 nPos )
542 RemoveEntryAt( nPos);
546 void SvxLanguageBox::ImplClear()
548 Clear();
551 void SvxLanguageComboBox::ImplClear()
553 Clear();
557 sal_Int32 SvxLanguageBox::ImplInsertEntry( const OUString& rEntry, sal_Int32 nPos )
559 return InsertEntry( rEntry, nPos);
562 sal_Int32 SvxLanguageComboBox::ImplInsertEntry( const OUString& rEntry, sal_Int32 nPos )
564 return InsertEntry( rEntry, nPos);
568 void SvxLanguageBox::ImplSetEntryData( sal_Int32 nPos, void* pData )
570 SetEntryData( nPos, pData);
573 void SvxLanguageComboBox::ImplSetEntryData( sal_Int32 nPos, void* pData )
575 SetEntryData( nPos, pData);
579 sal_Int32 SvxLanguageBox::ImplGetSelectEntryPos( sal_Int32 nSelIndex ) const
581 return GetSelectEntryPos( nSelIndex);
584 sal_Int32 SvxLanguageComboBox::ImplGetSelectEntryPos( sal_Int32 nSelIndex ) const
586 return GetSelectEntryPos( nSelIndex);
590 void* SvxLanguageBox::ImplGetEntryData( sal_Int32 nPos ) const
592 return GetEntryData( nPos);
595 void* SvxLanguageComboBox::ImplGetEntryData( sal_Int32 nPos ) const
597 return GetEntryData( nPos);
601 void SvxLanguageBox::ImplSelectEntryPos( sal_Int32 nPos, bool bSelect )
603 SelectEntryPos( nPos, bSelect);
606 void SvxLanguageComboBox::ImplSelectEntryPos( sal_Int32 nPos, bool bSelect )
608 SelectEntryPos( nPos, bSelect);
612 bool SvxLanguageBox::ImplIsEntryPosSelected( sal_Int32 nPos ) const
614 return IsEntryPosSelected( nPos);
617 bool SvxLanguageComboBox::ImplIsEntryPosSelected( sal_Int32 nPos ) const
619 return IsEntryPosSelected( nPos);
623 sal_Int32 SvxLanguageBox::ImplGetEntryPos( const void* pData ) const
625 return GetEntryPos( pData);
628 sal_Int32 SvxLanguageComboBox::ImplGetEntryPos( const void* pData ) const
630 return GetEntryPos( pData);
634 sal_Int32 SvxLanguageBox::ImplGetEntryCount() const
636 return GetEntryCount();
639 sal_Int32 SvxLanguageComboBox::ImplGetEntryCount() const
641 return GetEntryCount();
645 void SvxLanguageBox::ImplSetNoSelection()
647 SetNoSelection();
650 void SvxLanguageComboBox::ImplSetNoSelection()
652 SetNoSelection();
656 void SvxLanguageBox::ImplHide()
658 Hide();
661 void SvxLanguageComboBox::ImplHide()
663 Hide();
667 void SvxLanguageBox::ImplDisable()
669 Disable();
672 void SvxLanguageComboBox::ImplDisable()
674 Disable();
678 void SvxLanguageBox::ImplSaveValue()
680 SaveValue();
683 void SvxLanguageComboBox::ImplSaveValue()
685 // Emulate the ListBox behavior.
686 mnSavedValuePos = GetSelectEntryPos();
690 sal_Int32 SvxLanguageBox::ImplGetSavedValue() const
692 return GetSavedValue();
695 sal_Int32 SvxLanguageComboBox::ImplGetSavedValue() const
697 return mnSavedValuePos;
701 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */