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