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