1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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() );
60 if ( LANGUAGE_NONE
== nLang
)
61 aTmp
+= SVX_RESSTR(RID_SVXSTR_LANGUAGE_ALL
);
65 aTmp
+= SvtLanguageTable::GetLanguageString( (LanguageType
)nLang
);
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
] );
93 static bool lcl_SeqHasLang( const Sequence
< sal_Int16
> & rLangSeq
, sal_Int16 nLang
)
96 sal_Int32 nLen
= rLangSeq
.getLength();
99 const sal_Int16
*pLang
= rLangSeq
.getConstArray();
100 for (i
= 0; i
< nLen
; ++i
)
102 if (nLang
== pLang
[i
])
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
);
115 nBits
|= WB_DROPDOWN
;
118 SvxLanguageBox
*pLanguageBox
= new SvxLanguageBox(pParent
, nBits
);
119 pLanguageBox
->EnableAutoSize(true);
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
);
128 nBits
|= WB_DROPDOWN
;
131 SvxLanguageComboBox
*pLanguageBox
= new SvxLanguageComboBox(pParent
, nBits
);
132 pLanguageBox
->EnableAutoSize(true);
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
);
160 if ((LANGUAGE_DONTKNOW
== nLangType
) ||
161 (LANGUAGE_SYSTEM
== nLangType
))
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
)
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
);
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
);
223 aSpellUsedLang
= xTmp1
->getLanguages();
225 if (LANG_LIST_HYPH_USED
& nLangList
)
227 Reference
< XHyphenator
> xTmp( SvxGetHyphenator() );
229 Sequence
< Locale
> aLocaleSequence( xTmp
->getLocales() );
230 aHyphUsedLang
= lcl_LocaleSeqToLangSeq( aLocaleSequence
);
233 if (LANG_LIST_THES_USED
& nLangList
)
235 Reference
< XThesaurus
> xTmp( SvxGetThesaurus() );
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
;
245 if ( nLangList
& LANG_LIST_ONLY_KNOWN
)
247 xKnown
= LocaleDataWrapper::getInstalledLanguageTypes();
248 pKnown
= xKnown
.getConstArray();
249 nCount
= xKnown
.getLength();
253 nCount
= SvtLanguageTable::GetLanguageEntryCount();
256 for ( sal_uInt32 i
= 0; i
< nCount
; i
++ )
258 LanguageType nLangType
;
259 if ( nLangList
& LANG_LIST_ONLY_KNOWN
)
260 nLangType
= pKnown
[i
];
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
);
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
)
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
);
329 aStrEntry
+= SvtLanguageTable::GetLanguageString( nRealLang
);
330 } else if (nRealLang
== LANGUAGE_USER_SYSTEM_CONFIG
) {
331 nRealLang
= MsLangId::getSystemLanguage();
333 aStrEntry
+= SvtLanguageTable::GetLanguageString( nRealLang
);
336 aStrEntry
= ApplyLreOrRleEmbedding( aStrEntry
);
339 if ( m_bWithCheckmark
)
343 if (!m_pSpellUsedLang
)
345 Reference
< XSpellChecker1
> xSpell( SvxGetSpellChecker(), UNO_QUERY
);
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
);
355 nAt
= ImplInsertEntry( aStrEntry
, nPos
);
357 ImplSetEntryData( nAt
, (void*)(sal_uIntPtr
)nLangType
);
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
)
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
);
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
) );
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
);
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()
465 void SvxLanguageBoxBase::DisableLBB()
470 void SvxLanguageBoxBase::SaveValueLBB()
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
)
540 void SvxLanguageComboBox::ImplRemoveEntryAt( sal_Int32 nPos
)
542 RemoveEntryAt( nPos
);
546 void SvxLanguageBox::ImplClear()
551 void SvxLanguageComboBox::ImplClear()
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()
650 void SvxLanguageComboBox::ImplSetNoSelection()
656 void SvxLanguageBox::ImplHide()
661 void SvxLanguageComboBox::ImplHide()
667 void SvxLanguageBox::ImplDisable()
672 void SvxLanguageComboBox::ImplDisable()
678 void SvxLanguageBox::ImplSaveValue()
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: */