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_linguistic.hxx" 30 31 #include <com/sun/star/registry/XRegistryKey.hpp> 32 #include <com/sun/star/container/XContentEnumerationAccess.hpp> 33 #include <com/sun/star/container/XEnumeration.hpp> 34 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 35 #include <com/sun/star/linguistic2/XSupportedLocales.hpp> 36 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp> 37 #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp> 38 39 #include <tools/solar.h> 40 #include <unotools/lingucfg.hxx> 41 #include <unotools/processfactory.hxx> 42 #include <i18npool/lang.h> 43 #include <i18npool/mslangid.hxx> 44 #include <cppuhelper/factory.hxx> 45 #include <comphelper/extract.hxx> 46 #include <rtl/logfile.hxx> 47 48 #include <boost/checked_delete.hpp> 49 50 #include "lngsvcmgr.hxx" 51 #include "lngopt.hxx" 52 #include "linguistic/misc.hxx" 53 #include "spelldsp.hxx" 54 #include "hyphdsp.hxx" 55 #include "thesdsp.hxx" 56 #include "gciterator.hxx" 57 58 59 using namespace com::sun::star; 60 using namespace linguistic; 61 using ::rtl::OUString; 62 63 // forward declarations 64 uno::Sequence< OUString > static GetLangSvcList( const uno::Any &rVal ); 65 uno::Sequence< OUString > static GetLangSvc( const uno::Any &rVal ); 66 67 /////////////////////////////////////////////////////////////////////////// 68 69 static sal_Bool lcl_SeqHasString( const uno::Sequence< OUString > &rSeq, const OUString &rText ) 70 { 71 sal_Bool bRes = sal_False; 72 73 sal_Int32 nLen = rSeq.getLength(); 74 if (nLen == 0 || rText.getLength() == 0) 75 return bRes; 76 77 const OUString *pSeq = rSeq.getConstArray(); 78 for (sal_Int32 i = 0; i < nLen && !bRes; ++i) 79 { 80 if (rText == pSeq[i]) 81 bRes = sal_True; 82 } 83 return bRes; 84 } 85 86 /////////////////////////////////////////////////////////////////////////// 87 88 static uno::Sequence< lang::Locale > GetAvailLocales( 89 const uno::Sequence< OUString > &rSvcImplNames ) 90 { 91 uno::Sequence< lang::Locale > aRes; 92 93 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); 94 sal_Int32 nNames = rSvcImplNames.getLength(); 95 if (nNames && xFac.is()) 96 { 97 std::set< LanguageType > aLanguages; 98 99 //! since we're going to create one-instance services we have to 100 //! supply their arguments even if we would not need them here... 101 uno::Sequence< uno::Any > aArgs(2); 102 aArgs.getArray()[0] <<= GetLinguProperties(); 103 104 // check all services for the supported languages and new 105 // languages to the result 106 const OUString *pImplNames = rSvcImplNames.getConstArray(); 107 sal_Int32 i; 108 109 for (i = 0; i < nNames; ++i) 110 { 111 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc; 112 try 113 { 114 xSuppLoc = uno::Reference< linguistic2::XSupportedLocales >( 115 xFac->createInstanceWithArguments( pImplNames[i], aArgs ), uno::UNO_QUERY ); 116 } 117 catch (uno::Exception &) 118 { 119 DBG_ASSERT( 0, "createInstanceWithArguments failed" ); 120 } 121 122 if (xSuppLoc.is()) 123 { 124 uno::Sequence< lang::Locale > aLoc( xSuppLoc->getLocales() ); 125 sal_Int32 nLoc = aLoc.getLength(); 126 for (sal_Int32 k = 0; k < nLoc; ++k) 127 { 128 const lang::Locale *pLoc = aLoc.getConstArray(); 129 LanguageType nLang = LocaleToLanguage( pLoc[k] ); 130 131 // language not already added? 132 if (aLanguages.find( nLang ) == aLanguages.end()) 133 aLanguages.insert( nLang ); 134 } 135 } 136 else 137 { 138 DBG_ASSERT( 0, "interface not supported by service" ); 139 } 140 } 141 142 // build return sequence 143 sal_Int32 nLanguages = static_cast< sal_Int32 >(aLanguages.size()); 144 aRes.realloc( nLanguages ); 145 lang::Locale *pRes = aRes.getArray(); 146 std::set< LanguageType >::const_iterator aIt( aLanguages.begin() ); 147 for (i = 0; aIt != aLanguages.end(); ++aIt, ++i) 148 { 149 LanguageType nLang = *aIt; 150 pRes[i] = CreateLocale( nLang ); 151 } 152 } 153 154 return aRes; 155 } 156 157 /////////////////////////////////////////////////////////////////////////// 158 159 struct SvcInfo 160 { 161 const OUString aSvcImplName; 162 const uno::Sequence< sal_Int16 > aSuppLanguages; 163 164 SvcInfo( const OUString &rSvcImplName, 165 const uno::Sequence< sal_Int16 > &rSuppLanguages ) : 166 aSvcImplName (rSvcImplName), 167 aSuppLanguages (rSuppLanguages) 168 { 169 } 170 171 sal_Bool HasLanguage( sal_Int16 nLanguage ) const; 172 }; 173 174 175 sal_Bool SvcInfo::HasLanguage( sal_Int16 nLanguage ) const 176 { 177 sal_Int32 nCnt = aSuppLanguages.getLength(); 178 const sal_Int16 *pLang = aSuppLanguages.getConstArray(); 179 sal_Int32 i; 180 181 for ( i = 0; i < nCnt; ++i) 182 { 183 if (nLanguage == pLang[i]) 184 break; 185 } 186 return i < nCnt; 187 } 188 189 190 /////////////////////////////////////////////////////////////////////////// 191 192 193 void LngSvcMgr::SetAvailableCfgServiceLists( LinguDispatcher &rDispatcher, 194 const SvcInfoArray &rAvailSvcs ) 195 { 196 // get list of nodenames to look at for their service list 197 const char *pEntryName = 0; 198 sal_Bool bHasLangSvcList = sal_True; 199 switch (rDispatcher.GetDspType()) 200 { 201 case LinguDispatcher::DSP_SPELL : pEntryName = "ServiceManager/SpellCheckerList"; break; 202 case LinguDispatcher::DSP_GRAMMAR : pEntryName = "ServiceManager/GrammarCheckerList"; 203 bHasLangSvcList = sal_False; 204 break; 205 case LinguDispatcher::DSP_HYPH : pEntryName = "ServiceManager/HyphenatorList"; 206 bHasLangSvcList = sal_False; 207 break; 208 case LinguDispatcher::DSP_THES : pEntryName = "ServiceManager/ThesaurusList"; break; 209 default : 210 DBG_ASSERT( 0, "unexpected case" ); 211 } 212 String aNode( String::CreateFromAscii( pEntryName ) ); 213 uno::Sequence < OUString > aNodeNames( /*aCfg.*/GetNodeNames( aNode ) ); 214 215 216 sal_Int32 nLen = aNodeNames.getLength(); 217 const OUString *pNodeNames = aNodeNames.getConstArray(); 218 for (sal_Int32 i = 0; i < nLen; ++i) 219 { 220 uno::Sequence< OUString > aSvcImplNames; 221 222 uno::Sequence< OUString > aNames( 1 ); 223 OUString *pNames = aNames.getArray(); 224 225 OUString aPropName( aNode ); 226 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 227 aPropName += pNodeNames[i]; 228 pNames[0] = aPropName; 229 230 uno::Sequence< uno::Any > aValues = /*aCfg.*/GetProperties( aNames ); 231 if (aValues.getLength()) 232 { 233 // get list of configured service names for the 234 // current node (language) 235 const uno::Any &rValue = aValues.getConstArray()[0]; 236 if (bHasLangSvcList) 237 aSvcImplNames = GetLangSvcList( rValue ); 238 else 239 aSvcImplNames = GetLangSvc( rValue ); 240 241 sal_Int32 nSvcs = aSvcImplNames.getLength(); 242 if (nSvcs) 243 { 244 const OUString *pImplNames = aSvcImplNames.getConstArray(); 245 246 LanguageType nLang = MsLangId::convertIsoStringToLanguage( pNodeNames[i] ); 247 248 // build list of available services from those 249 sal_Int32 nCnt = 0; 250 uno::Sequence< OUString > aAvailSvcs( nSvcs ); 251 OUString *pAvailSvcs = aAvailSvcs.getArray(); 252 for (sal_Int32 k = 0; k < nSvcs; ++k) 253 { 254 // check for availability of the service 255 size_t nAvailSvcs = rAvailSvcs.size(); 256 for (size_t m = 0; m < nAvailSvcs; ++m) 257 { 258 const SvcInfo &rSvcInfo = *rAvailSvcs[m]; 259 if (rSvcInfo.aSvcImplName == pImplNames[k] && 260 rSvcInfo.HasLanguage( nLang )) 261 { 262 pAvailSvcs[ nCnt++ ] = rSvcInfo.aSvcImplName; 263 break; 264 } 265 } 266 } 267 268 if (nCnt) 269 { 270 aAvailSvcs.realloc( nCnt ); 271 rDispatcher.SetServiceList( CreateLocale( nLang ), aAvailSvcs ); 272 } 273 } 274 } 275 } 276 } 277 278 279 /////////////////////////////////////////////////////////////////////////// 280 281 282 class LngSvcMgrListenerHelper : 283 public cppu::WeakImplHelper2 284 < 285 linguistic2::XLinguServiceEventListener, 286 linguistic2::XDictionaryListEventListener 287 > 288 { 289 LngSvcMgr &rMyManager; 290 // Timer aLaunchTimer; 291 292 //cppu::OMultiTypeInterfaceContainerHelper aListeners; 293 ::cppu::OInterfaceContainerHelper aLngSvcMgrListeners; 294 ::cppu::OInterfaceContainerHelper aLngSvcEvtBroadcasters; 295 uno::Reference< linguistic2::XDictionaryList > xDicList; 296 uno::Reference< uno::XInterface > xMyEvtObj; 297 298 sal_Int16 nCombinedLngSvcEvt; 299 300 // disallow copy-constructor and assignment-operator for now 301 LngSvcMgrListenerHelper(const LngSvcMgrListenerHelper &); 302 LngSvcMgrListenerHelper & operator = (const LngSvcMgrListenerHelper &); 303 304 void LaunchEvent( sal_Int16 nLngSvcEvtFlags ); 305 306 // DECL_LINK( TimeOut, Timer* ); 307 long Timeout(); 308 309 public: 310 LngSvcMgrListenerHelper( LngSvcMgr &rLngSvcMgr, 311 const uno::Reference< uno::XInterface > &rxSource, 312 const uno::Reference< linguistic2::XDictionaryList > &rxDicList ); 313 314 // lang::XEventListener 315 virtual void SAL_CALL 316 disposing( const lang::EventObject& rSource ) 317 throw(uno::RuntimeException); 318 319 // linguistic2::XLinguServiceEventListener 320 virtual void SAL_CALL 321 processLinguServiceEvent( const linguistic2::LinguServiceEvent& aLngSvcEvent ) 322 throw(uno::RuntimeException); 323 324 // linguistic2::XDictionaryListEventListener 325 virtual void SAL_CALL 326 processDictionaryListEvent( 327 const linguistic2::DictionaryListEvent& rDicListEvent ) 328 throw(uno::RuntimeException); 329 330 inline sal_Bool AddLngSvcMgrListener( 331 const uno::Reference< lang::XEventListener >& rxListener ); 332 inline sal_Bool RemoveLngSvcMgrListener( 333 const uno::Reference< lang::XEventListener >& rxListener ); 334 void DisposeAndClear( const lang::EventObject &rEvtObj ); 335 sal_Bool AddLngSvcEvtBroadcaster( 336 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ); 337 sal_Bool RemoveLngSvcEvtBroadcaster( 338 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ); 339 340 void AddLngSvcEvt( sal_Int16 nLngSvcEvt ); 341 }; 342 343 344 LngSvcMgrListenerHelper::LngSvcMgrListenerHelper( 345 LngSvcMgr &rLngSvcMgr, 346 const uno::Reference< uno::XInterface > &rxSource, 347 const uno::Reference< linguistic2::XDictionaryList > &rxDicList ) : 348 rMyManager ( rLngSvcMgr ), 349 aLngSvcMgrListeners ( GetLinguMutex() ), 350 aLngSvcEvtBroadcasters ( GetLinguMutex() ), 351 xDicList ( rxDicList ), 352 xMyEvtObj ( rxSource ) 353 { 354 if (xDicList.is()) 355 { 356 xDicList->addDictionaryListEventListener( 357 (linguistic2::XDictionaryListEventListener *) this, sal_False ); 358 } 359 360 //! The timer is used to 'sum up' different events in order to reduce the 361 //! number of events forwarded. 362 //! (This may happen already if a property was changed that has several 363 //! listeners, and each of them is launching an event of it's own!) 364 //! Thus this behaviour is necessary to avoid unecessary actions of 365 //! this objects listeners! 366 // aLaunchTimer.SetTimeout( 2000 ); 367 // aLaunchTimer.SetTimeoutHdl( LINK( this, LngSvcMgrListenerHelper, TimeOut ) ); 368 nCombinedLngSvcEvt = 0; 369 } 370 371 372 void SAL_CALL LngSvcMgrListenerHelper::disposing( const lang::EventObject& rSource ) 373 throw(uno::RuntimeException) 374 { 375 osl::MutexGuard aGuard( GetLinguMutex() ); 376 377 uno::Reference< uno::XInterface > xRef( rSource.Source ); 378 if ( xRef.is() ) 379 { 380 aLngSvcMgrListeners .removeInterface( xRef ); 381 aLngSvcEvtBroadcasters.removeInterface( xRef ); 382 if (xDicList == xRef) 383 xDicList = 0; 384 } 385 } 386 387 388 //IMPL_LINK( LngSvcMgrListenerHelper, TimeOut, Timer*, pTimer ) 389 long LngSvcMgrListenerHelper::Timeout() 390 { 391 osl::MutexGuard aGuard( GetLinguMutex() ); 392 393 // if (&aLaunchTimer == pTimer) 394 { 395 // change event source to LinguServiceManager since the listeners 396 // probably do not know (and need not to know) about the specific 397 // SpellChecker's or Hyphenator's. 398 linguistic2::LinguServiceEvent aEvtObj( xMyEvtObj, nCombinedLngSvcEvt ); 399 nCombinedLngSvcEvt = 0; 400 401 if (rMyManager.pSpellDsp) 402 rMyManager.pSpellDsp->FlushSpellCache(); 403 404 // pass event on to linguistic2::XLinguServiceEventListener's 405 cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners ); 406 while (aIt.hasMoreElements()) 407 { 408 uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY ); 409 if (xRef.is()) 410 xRef->processLinguServiceEvent( aEvtObj ); 411 } 412 } 413 return 0; 414 } 415 416 417 void LngSvcMgrListenerHelper::AddLngSvcEvt( sal_Int16 nLngSvcEvt ) 418 { 419 nCombinedLngSvcEvt |= nLngSvcEvt; 420 // aLaunchTimer.Start(); 421 Timeout(); 422 } 423 424 425 void SAL_CALL 426 LngSvcMgrListenerHelper::processLinguServiceEvent( 427 const linguistic2::LinguServiceEvent& rLngSvcEvent ) 428 throw(uno::RuntimeException) 429 { 430 osl::MutexGuard aGuard( GetLinguMutex() ); 431 AddLngSvcEvt( rLngSvcEvent.nEvent ); 432 } 433 434 435 void SAL_CALL 436 LngSvcMgrListenerHelper::processDictionaryListEvent( 437 const linguistic2::DictionaryListEvent& rDicListEvent ) 438 throw(uno::RuntimeException) 439 { 440 osl::MutexGuard aGuard( GetLinguMutex() ); 441 442 sal_Int16 nDlEvt = rDicListEvent.nCondensedEvent; 443 if (0 == nDlEvt) 444 return; 445 446 // we do keep the original event source here though... 447 448 // pass event on to linguistic2::XDictionaryListEventListener's 449 cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners ); 450 while (aIt.hasMoreElements()) 451 { 452 uno::Reference< linguistic2::XDictionaryListEventListener > xRef( aIt.next(), uno::UNO_QUERY ); 453 if (xRef.is()) 454 xRef->processDictionaryListEvent( rDicListEvent ); 455 } 456 457 // 458 // "translate" DictionaryList event into linguistic2::LinguServiceEvent 459 // 460 sal_Int16 nLngSvcEvt = 0; 461 // 462 sal_Int16 nSpellCorrectFlags = 463 linguistic2::DictionaryListEventFlags::ADD_NEG_ENTRY | 464 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY | 465 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC | 466 linguistic2::DictionaryListEventFlags::DEACTIVATE_POS_DIC; 467 if (0 != (nDlEvt & nSpellCorrectFlags)) 468 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN; 469 // 470 sal_Int16 nSpellWrongFlags = 471 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY | 472 linguistic2::DictionaryListEventFlags::DEL_NEG_ENTRY | 473 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC | 474 linguistic2::DictionaryListEventFlags::DEACTIVATE_NEG_DIC; 475 if (0 != (nDlEvt & nSpellWrongFlags)) 476 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN; 477 // 478 sal_Int16 nHyphenateFlags = 479 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY | 480 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY | 481 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC | 482 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC; 483 if (0 != (nDlEvt & nHyphenateFlags)) 484 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN; 485 486 if (rMyManager.pSpellDsp) 487 rMyManager.pSpellDsp->FlushSpellCache(); 488 if (nLngSvcEvt) 489 LaunchEvent( nLngSvcEvt ); 490 } 491 492 493 void LngSvcMgrListenerHelper::LaunchEvent( sal_Int16 nLngSvcEvtFlags ) 494 { 495 linguistic2::LinguServiceEvent aEvt( xMyEvtObj, nLngSvcEvtFlags ); 496 497 // pass event on to linguistic2::XLinguServiceEventListener's 498 cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners ); 499 while (aIt.hasMoreElements()) 500 { 501 uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY ); 502 if (xRef.is()) 503 xRef->processLinguServiceEvent( aEvt ); 504 } 505 } 506 507 508 inline sal_Bool LngSvcMgrListenerHelper::AddLngSvcMgrListener( 509 const uno::Reference< lang::XEventListener >& rxListener ) 510 { 511 aLngSvcMgrListeners.addInterface( rxListener ); 512 return sal_True; 513 } 514 515 516 inline sal_Bool LngSvcMgrListenerHelper::RemoveLngSvcMgrListener( 517 const uno::Reference< lang::XEventListener >& rxListener ) 518 { 519 aLngSvcMgrListeners.removeInterface( rxListener ); 520 return sal_True; 521 } 522 523 524 void LngSvcMgrListenerHelper::DisposeAndClear( const lang::EventObject &rEvtObj ) 525 { 526 // call "disposing" for all listeners and clear list 527 aLngSvcMgrListeners .disposeAndClear( rEvtObj ); 528 529 // remove references to this object hold by the broadcasters 530 cppu::OInterfaceIteratorHelper aIt( aLngSvcEvtBroadcasters ); 531 while (aIt.hasMoreElements()) 532 { 533 uno::Reference< linguistic2::XLinguServiceEventBroadcaster > xRef( aIt.next(), uno::UNO_QUERY ); 534 if (xRef.is()) 535 RemoveLngSvcEvtBroadcaster( xRef ); 536 } 537 538 // remove refernce to this object hold by the dictionary-list 539 if (xDicList.is()) 540 { 541 xDicList->removeDictionaryListEventListener( 542 (linguistic2::XDictionaryListEventListener *) this ); 543 xDicList = 0; 544 } 545 } 546 547 548 sal_Bool LngSvcMgrListenerHelper::AddLngSvcEvtBroadcaster( 549 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) 550 { 551 sal_Bool bRes = sal_False; 552 if (rxBroadcaster.is()) 553 { 554 aLngSvcEvtBroadcasters.addInterface( rxBroadcaster ); 555 rxBroadcaster->addLinguServiceEventListener( 556 (linguistic2::XLinguServiceEventListener *) this ); 557 } 558 return bRes; 559 } 560 561 562 sal_Bool LngSvcMgrListenerHelper::RemoveLngSvcEvtBroadcaster( 563 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) 564 { 565 sal_Bool bRes = sal_False; 566 if (rxBroadcaster.is()) 567 { 568 aLngSvcEvtBroadcasters.removeInterface( rxBroadcaster ); 569 rxBroadcaster->removeLinguServiceEventListener( 570 (linguistic2::XLinguServiceEventListener *) this ); 571 } 572 return bRes; 573 } 574 575 576 /////////////////////////////////////////////////////////////////////////// 577 578 579 LngSvcMgr::LngSvcMgr() : 580 utl::ConfigItem( String::CreateFromAscii( "Office.Linguistic" ) ), 581 aEvtListeners ( GetLinguMutex() ) 582 { 583 bHasAvailSpellLocales = 584 bHasAvailGrammarLocales = 585 bHasAvailHyphLocales = 586 bHasAvailThesLocales = 587 bDisposing = sal_False; 588 589 pSpellDsp = 0; 590 pGrammarDsp = 0; 591 pHyphDsp = 0; 592 pThesDsp = 0; 593 594 pAvailSpellSvcs = 0; 595 pAvailGrammarSvcs = 0; 596 pAvailHyphSvcs = 0; 597 pAvailThesSvcs = 0; 598 pListenerHelper = 0; 599 600 // request notify events when properties (i.e. something in the subtree) changes 601 uno::Sequence< OUString > aNames(4); 602 OUString *pNames = aNames.getArray(); 603 pNames[0] = A2OU( "ServiceManager/SpellCheckerList" ); 604 pNames[1] = A2OU( "ServiceManager/GrammarCheckerList" ); 605 pNames[2] = A2OU( "ServiceManager/HyphenatorList" ); 606 pNames[3] = A2OU( "ServiceManager/ThesaurusList" ); 607 EnableNotification( aNames ); 608 } 609 610 void LngSvcMgr::clearSvcInfoArray(SvcInfoArray* pInfo) 611 { 612 if (pInfo) 613 { 614 std::for_each(pInfo->begin(), pInfo->end(), boost::checked_deleter<SvcInfo>()); 615 delete pInfo; 616 } 617 } 618 619 LngSvcMgr::~LngSvcMgr() 620 { 621 // memory for pSpellDsp, pHyphDsp, pThesDsp, pListenerHelper 622 // will be freed in the destructor of the respective Reference's 623 // xSpellDsp, xGrammarDsp, xHyphDsp, xThesDsp 624 625 clearSvcInfoArray(pAvailSpellSvcs); 626 clearSvcInfoArray(pAvailGrammarSvcs); 627 clearSvcInfoArray(pAvailHyphSvcs); 628 clearSvcInfoArray(pAvailThesSvcs); 629 } 630 631 632 void LngSvcMgr::Notify( const uno::Sequence< OUString > &rPropertyNames ) 633 { 634 const OUString aSpellCheckerList( A2OU("ServiceManager/SpellCheckerList") ); 635 const OUString aGrammarCheckerList( A2OU("ServiceManager/GrammarCheckerList") ); 636 const OUString aHyphenatorList( A2OU("ServiceManager/HyphenatorList") ); 637 const OUString aThesaurusList( A2OU("ServiceManager/ThesaurusList") ); 638 639 const uno::Sequence< OUString > aSpellCheckerListEntries( GetNodeNames( aSpellCheckerList ) ); 640 const uno::Sequence< OUString > aGrammarCheckerListEntries( GetNodeNames( aGrammarCheckerList ) ); 641 const uno::Sequence< OUString > aHyphenatorListEntries( GetNodeNames( aHyphenatorList ) ); 642 const uno::Sequence< OUString > aThesaurusListEntries( GetNodeNames( aThesaurusList ) ); 643 644 uno::Sequence< uno::Any > aValues; 645 uno::Sequence< OUString > aNames( 1 ); 646 OUString *pNames = aNames.getArray(); 647 648 sal_Int32 nLen = rPropertyNames.getLength(); 649 const OUString *pPropertyNames = rPropertyNames.getConstArray(); 650 for (sal_Int32 i = 0; i < nLen; ++i) 651 { 652 // property names look like 653 // "ServiceManager/ThesaurusList/de-CH" 654 655 const OUString &rName = pPropertyNames[i]; 656 sal_Int32 nKeyStart; 657 nKeyStart = rName.lastIndexOf( '/' ); 658 OUString aKeyText; 659 if (nKeyStart != -1) 660 aKeyText = rName.copy( nKeyStart + 1 ); 661 DBG_ASSERT( aKeyText.getLength() != 0, "unexpected key (lang::Locale) string" ); 662 if (0 == rName.compareTo( aSpellCheckerList, aSpellCheckerList.getLength() )) 663 { 664 // delete old cached data, needs to be acquired new on demand 665 clearSvcInfoArray(pAvailSpellSvcs); pAvailSpellSvcs = 0; 666 667 OUString aNode( aSpellCheckerList ); 668 if (lcl_SeqHasString( aSpellCheckerListEntries, aKeyText )) 669 { 670 OUString aPropName( aNode ); 671 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 672 aPropName += aKeyText; 673 pNames[0] = aPropName; 674 aValues = /*aCfg.*/GetProperties( aNames ); 675 uno::Sequence< OUString > aSvcImplNames; 676 if (aValues.getLength()) 677 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); 678 679 LanguageType nLang = LANGUAGE_NONE; 680 if (0 != aKeyText.getLength()) 681 nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); 682 683 GetSpellCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below 684 pSpellDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); 685 } 686 } 687 else if (0 == rName.compareTo( aGrammarCheckerList, aGrammarCheckerList.getLength() )) 688 { 689 // delete old cached data, needs to be acquired new on demand 690 clearSvcInfoArray(pAvailGrammarSvcs); pAvailGrammarSvcs = 0; 691 692 OUString aNode( aGrammarCheckerList ); 693 if (lcl_SeqHasString( aGrammarCheckerListEntries, aKeyText )) 694 { 695 OUString aPropName( aNode ); 696 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 697 aPropName += aKeyText; 698 pNames[0] = aPropName; 699 aValues = /*aCfg.*/GetProperties( aNames ); 700 uno::Sequence< OUString > aSvcImplNames; 701 if (aValues.getLength()) 702 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); 703 704 LanguageType nLang = LANGUAGE_NONE; 705 if (0 != aKeyText.getLength()) 706 nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); 707 708 if (SvtLinguConfig().HasGrammarChecker()) 709 { 710 GetGrammarCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below 711 pGrammarDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); 712 } 713 } 714 } 715 else if (0 == rName.compareTo( aHyphenatorList, aHyphenatorList.getLength() )) 716 { 717 // delete old cached data, needs to be acquired new on demand 718 clearSvcInfoArray(pAvailHyphSvcs); pAvailHyphSvcs = 0; 719 720 OUString aNode( aHyphenatorList ); 721 if (lcl_SeqHasString( aHyphenatorListEntries, aKeyText )) 722 { 723 OUString aPropName( aNode ); 724 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 725 aPropName += aKeyText; 726 pNames[0] = aPropName; 727 aValues = /*aCfg.*/GetProperties( aNames ); 728 uno::Sequence< OUString > aSvcImplNames; 729 if (aValues.getLength()) 730 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); 731 732 LanguageType nLang = LANGUAGE_NONE; 733 if (0 != aKeyText.getLength()) 734 nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); 735 736 GetHyphenatorDsp_Impl( sal_False ); // don't set service list, it will be done below 737 pHyphDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); 738 } 739 } 740 else if (0 == rName.compareTo( aThesaurusList, aThesaurusList.getLength() )) 741 { 742 // delete old cached data, needs to be acquired new on demand 743 clearSvcInfoArray(pAvailThesSvcs); pAvailThesSvcs = 0; 744 745 OUString aNode( aThesaurusList ); 746 if (lcl_SeqHasString( aThesaurusListEntries, aKeyText )) 747 { 748 OUString aPropName( aNode ); 749 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 750 aPropName += aKeyText; 751 pNames[0] = aPropName; 752 aValues = /*aCfg.*/GetProperties( aNames ); 753 uno::Sequence< OUString > aSvcImplNames; 754 if (aValues.getLength()) 755 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); 756 757 LanguageType nLang = LANGUAGE_NONE; 758 if (0 != aKeyText.getLength()) 759 nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); 760 761 GetThesaurusDsp_Impl( sal_False ); // don't set service list, it will be done below 762 pThesDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); 763 } 764 } 765 else 766 { 767 DBG_ASSERT( 0, "nofified for unexpected property" ); 768 } 769 } 770 } 771 772 773 void LngSvcMgr::Commit() 774 { 775 // everything necessary should have already been done by 'SaveCfgSvcs' 776 // called from within 'setConfiguredServices'. 777 // Also this class usually exits only when the Office i sbeing shutdown. 778 } 779 780 781 void LngSvcMgr::GetListenerHelper_Impl() 782 { 783 if (!pListenerHelper) 784 { 785 pListenerHelper = new LngSvcMgrListenerHelper( *this, 786 (XLinguServiceManager *) this, linguistic::GetDictionaryList() ); 787 xListenerHelper = (linguistic2::XLinguServiceEventListener *) pListenerHelper; 788 } 789 } 790 791 792 void LngSvcMgr::GetSpellCheckerDsp_Impl( sal_Bool bSetSvcList ) 793 { 794 if (!pSpellDsp) 795 { 796 pSpellDsp = new SpellCheckerDispatcher( *this ); 797 xSpellDsp = pSpellDsp; 798 if (bSetSvcList) 799 SetCfgServiceLists( *pSpellDsp ); 800 } 801 } 802 803 804 void LngSvcMgr::GetGrammarCheckerDsp_Impl( sal_Bool bSetSvcList ) 805 { 806 if (!pGrammarDsp && SvtLinguConfig().HasGrammarChecker()) 807 { 808 //! since the grammar checking iterator needs to be a one instance service 809 //! we need to create it the correct way! 810 uno::Reference< linguistic2::XProofreadingIterator > xGCI; 811 try 812 { 813 uno::Reference< lang::XMultiServiceFactory > xMgr( 814 utl::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); 815 xGCI = uno::Reference< linguistic2::XProofreadingIterator >( 816 xMgr->createInstance( A2OU( SN_GRAMMARCHECKINGITERATOR ) ), uno::UNO_QUERY_THROW ); 817 } 818 catch (uno::Exception &) 819 { 820 } 821 DBG_ASSERT( xGCI.is(), "instantiating grammar checking iterator failed" ); 822 823 if (xGCI.is()) 824 { 825 pGrammarDsp = dynamic_cast< GrammarCheckingIterator * >(xGCI.get()); 826 xGrammarDsp = xGCI; 827 DBG_ASSERT( pGrammarDsp, "failed to get implementation" ); 828 if (bSetSvcList) 829 SetCfgServiceLists( *pGrammarDsp ); 830 } 831 } 832 } 833 834 835 void LngSvcMgr::GetHyphenatorDsp_Impl( sal_Bool bSetSvcList ) 836 { 837 if (!pHyphDsp) 838 { 839 pHyphDsp = new HyphenatorDispatcher( *this ); 840 xHyphDsp = pHyphDsp; 841 if (bSetSvcList) 842 SetCfgServiceLists( *pHyphDsp ); 843 } 844 } 845 846 847 void LngSvcMgr::GetThesaurusDsp_Impl( sal_Bool bSetSvcList ) 848 { 849 if (!pThesDsp) 850 { 851 pThesDsp = new ThesaurusDispatcher; 852 xThesDsp = pThesDsp; 853 if (bSetSvcList) 854 SetCfgServiceLists( *pThesDsp ); 855 } 856 } 857 858 859 void LngSvcMgr::GetAvailableSpellSvcs_Impl() 860 { 861 if (!pAvailSpellSvcs) 862 { 863 pAvailSpellSvcs = new SvcInfoArray; 864 865 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); 866 if (xFac.is()) 867 { 868 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); 869 uno::Reference< container::XEnumeration > xEnum; 870 if (xEnumAccess.is()) 871 xEnum = xEnumAccess->createContentEnumeration( 872 A2OU( SN_SPELLCHECKER ) ); 873 874 if (xEnum.is()) 875 { 876 while (xEnum->hasMoreElements()) 877 { 878 uno::Any aCurrent = xEnum->nextElement(); 879 uno::Reference< lang::XSingleComponentFactory > xCompFactory; 880 uno::Reference< lang::XSingleServiceFactory > xFactory; 881 882 uno::Reference< linguistic2::XSpellChecker > xSvc; 883 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) 884 { 885 try 886 { 887 uno::Reference < uno::XComponentContext > xContext; 888 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); 889 890 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; 891 xSvc = uno::Reference< linguistic2::XSpellChecker >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); 892 } 893 catch (uno::Exception &rEx) 894 { 895 (void) rEx; 896 DBG_ASSERT( 0, "createInstance failed" ); 897 } 898 } 899 900 if (xSvc.is()) 901 { 902 OUString aImplName; 903 uno::Sequence< sal_Int16 > aLanguages; 904 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); 905 if (xInfo.is()) 906 aImplName = xInfo->getImplementationName(); 907 DBG_ASSERT( aImplName.getLength(), 908 "empty implementation name" ); 909 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); 910 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); 911 if (xSuppLoc.is()) { 912 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); 913 aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); 914 } 915 916 pAvailSpellSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); 917 } 918 } 919 } 920 } 921 } 922 } 923 924 925 void LngSvcMgr::GetAvailableGrammarSvcs_Impl() 926 { 927 if (!pAvailGrammarSvcs) 928 { 929 pAvailGrammarSvcs = new SvcInfoArray; 930 931 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); 932 if (xFac.is()) 933 { 934 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); 935 uno::Reference< container::XEnumeration > xEnum; 936 if (xEnumAccess.is()) 937 xEnum = xEnumAccess->createContentEnumeration( 938 A2OU( SN_GRAMMARCHECKER ) ); 939 940 if (xEnum.is()) 941 { 942 while (xEnum->hasMoreElements()) 943 { 944 uno::Any aCurrent = xEnum->nextElement(); 945 uno::Reference< lang::XSingleComponentFactory > xCompFactory; 946 uno::Reference< lang::XSingleServiceFactory > xFactory; 947 948 uno::Reference< linguistic2::XProofreader > xSvc; 949 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) 950 { 951 try 952 { 953 uno::Reference < uno::XComponentContext > xContext; 954 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); 955 956 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; 957 xSvc = uno::Reference< linguistic2::XProofreader >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); 958 } 959 catch (uno::Exception &rEx) 960 { 961 (void) rEx; 962 DBG_ASSERT( 0, "createInstance failed" ); 963 } 964 } 965 966 if (xSvc.is()) 967 { 968 OUString aImplName; 969 uno::Sequence< sal_Int16 > aLanguages; 970 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); 971 if (xInfo.is()) 972 aImplName = xInfo->getImplementationName(); 973 DBG_ASSERT( aImplName.getLength(), 974 "empty implementation name" ); 975 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); 976 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); 977 if (xSuppLoc.is()) { 978 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); 979 aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); 980 } 981 982 pAvailGrammarSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); 983 } 984 } 985 } 986 } 987 } 988 } 989 990 991 void LngSvcMgr::GetAvailableHyphSvcs_Impl() 992 { 993 if (!pAvailHyphSvcs) 994 { 995 pAvailHyphSvcs = new SvcInfoArray; 996 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); 997 if (xFac.is()) 998 { 999 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); 1000 uno::Reference< container::XEnumeration > xEnum; 1001 if (xEnumAccess.is()) 1002 xEnum = xEnumAccess->createContentEnumeration( A2OU( SN_HYPHENATOR ) ); 1003 1004 if (xEnum.is()) 1005 { 1006 while (xEnum->hasMoreElements()) 1007 { 1008 uno::Any aCurrent = xEnum->nextElement(); 1009 uno::Reference< lang::XSingleComponentFactory > xCompFactory; 1010 uno::Reference< lang::XSingleServiceFactory > xFactory; 1011 1012 uno::Reference< linguistic2::XHyphenator > xSvc; 1013 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) 1014 { 1015 try 1016 { 1017 uno::Reference < uno::XComponentContext > xContext; 1018 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); 1019 1020 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; 1021 xSvc = uno::Reference< linguistic2::XHyphenator >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); 1022 1023 } 1024 catch (uno::Exception &rEx) 1025 { 1026 (void) rEx; 1027 DBG_ASSERT( 0, "createInstance failed" ); 1028 } 1029 } 1030 1031 if (xSvc.is()) 1032 { 1033 OUString aImplName; 1034 uno::Sequence< sal_Int16 > aLanguages; 1035 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); 1036 if (xInfo.is()) 1037 aImplName = xInfo->getImplementationName(); 1038 DBG_ASSERT( aImplName.getLength(), 1039 "empty implementation name" ); 1040 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); 1041 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); 1042 if (xSuppLoc.is()) { 1043 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); 1044 aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); 1045 } 1046 1047 pAvailHyphSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); 1048 } 1049 } 1050 } 1051 } 1052 } 1053 } 1054 1055 1056 void LngSvcMgr::GetAvailableThesSvcs_Impl() 1057 { 1058 if (!pAvailThesSvcs) 1059 { 1060 pAvailThesSvcs = new SvcInfoArray; 1061 1062 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); 1063 if (xFac.is()) 1064 { 1065 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); 1066 uno::Reference< container::XEnumeration > xEnum; 1067 if (xEnumAccess.is()) 1068 xEnum = xEnumAccess->createContentEnumeration( 1069 A2OU( SN_THESAURUS ) ); 1070 1071 if (xEnum.is()) 1072 { 1073 while (xEnum->hasMoreElements()) 1074 { 1075 uno::Any aCurrent = xEnum->nextElement(); 1076 1077 uno::Reference< lang::XSingleComponentFactory > xCompFactory; 1078 uno::Reference< lang::XSingleServiceFactory > xFactory; 1079 1080 uno::Reference< linguistic2::XThesaurus > xSvc; 1081 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) 1082 { 1083 try 1084 { 1085 uno::Reference < uno::XComponentContext > xContext; 1086 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); 1087 1088 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; 1089 xSvc = uno::Reference< linguistic2::XThesaurus >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); 1090 } 1091 catch (uno::Exception &rEx) 1092 { 1093 (void) rEx; 1094 DBG_ASSERT( 0, "createInstance failed" ); 1095 } 1096 } 1097 1098 if (xSvc.is()) 1099 { 1100 OUString aImplName; 1101 uno::Sequence< sal_Int16 > aLanguages; 1102 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); 1103 if (xInfo.is()) 1104 aImplName = xInfo->getImplementationName(); 1105 DBG_ASSERT( aImplName.getLength(), 1106 "empty implementation name" ); 1107 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); 1108 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); 1109 if (xSuppLoc.is()) { 1110 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); 1111 aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); 1112 } 1113 1114 pAvailThesSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); 1115 } 1116 } 1117 } 1118 } 1119 } 1120 } 1121 1122 1123 void LngSvcMgr::SetCfgServiceLists( SpellCheckerDispatcher &rSpellDsp ) 1124 { 1125 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Spell" ); 1126 1127 String aNode( String::CreateFromAscii( "ServiceManager/SpellCheckerList" ) ); 1128 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); 1129 OUString *pNames = aNames.getArray(); 1130 sal_Int32 nLen = aNames.getLength(); 1131 1132 // append path prefix need for 'GetProperties' call below 1133 String aPrefix( aNode ); 1134 aPrefix.Append( (sal_Unicode) '/' ); 1135 for (int i = 0; i < nLen; ++i) 1136 { 1137 OUString aTmp( aPrefix ); 1138 aTmp += pNames[i]; 1139 pNames[i] = aTmp; 1140 } 1141 1142 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); 1143 if (nLen && nLen == aValues.getLength()) 1144 { 1145 const uno::Any *pValues = aValues.getConstArray(); 1146 for (sal_Int32 i = 0; i < nLen; ++i) 1147 { 1148 uno::Sequence< OUString > aSvcImplNames; 1149 if (pValues[i] >>= aSvcImplNames) 1150 { 1151 #if OSL_DEBUG_LEVEL > 1 1152 // sal_Int32 nSvcs = aSvcImplNames.getLength(); 1153 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); 1154 #endif 1155 String aLocaleStr( pNames[i] ); 1156 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); 1157 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); 1158 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); 1159 rSpellDsp.SetServiceList( aLocale, aSvcImplNames ); 1160 } 1161 } 1162 } 1163 } 1164 1165 1166 void LngSvcMgr::SetCfgServiceLists( GrammarCheckingIterator &rGrammarDsp ) 1167 { 1168 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Grammar" ); 1169 1170 String aNode( String::CreateFromAscii( "ServiceManager/GrammarCheckerList" ) ); 1171 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); 1172 OUString *pNames = aNames.getArray(); 1173 sal_Int32 nLen = aNames.getLength(); 1174 1175 // append path prefix need for 'GetProperties' call below 1176 String aPrefix( aNode ); 1177 aPrefix.Append( (sal_Unicode) '/' ); 1178 for (int i = 0; i < nLen; ++i) 1179 { 1180 OUString aTmp( aPrefix ); 1181 aTmp += pNames[i]; 1182 pNames[i] = aTmp; 1183 } 1184 1185 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); 1186 if (nLen && nLen == aValues.getLength()) 1187 { 1188 const uno::Any *pValues = aValues.getConstArray(); 1189 for (sal_Int32 i = 0; i < nLen; ++i) 1190 { 1191 uno::Sequence< OUString > aSvcImplNames; 1192 if (pValues[i] >>= aSvcImplNames) 1193 { 1194 // there should only be one grammar checker in use per language... 1195 if (aSvcImplNames.getLength() > 1) 1196 aSvcImplNames.realloc(1); 1197 1198 #if OSL_DEBUG_LEVEL > 1 1199 // sal_Int32 nSvcs = aSvcImplNames.getLength(); 1200 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); 1201 #endif 1202 String aLocaleStr( pNames[i] ); 1203 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); 1204 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); 1205 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); 1206 rGrammarDsp.SetServiceList( aLocale, aSvcImplNames ); 1207 } 1208 } 1209 } 1210 } 1211 1212 1213 void LngSvcMgr::SetCfgServiceLists( HyphenatorDispatcher &rHyphDsp ) 1214 { 1215 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Hyph" ); 1216 1217 String aNode( String::CreateFromAscii( "ServiceManager/HyphenatorList" ) ); 1218 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); 1219 OUString *pNames = aNames.getArray(); 1220 sal_Int32 nLen = aNames.getLength(); 1221 1222 // append path prefix need for 'GetProperties' call below 1223 String aPrefix( aNode ); 1224 aPrefix.Append( (sal_Unicode) '/' ); 1225 for (int i = 0; i < nLen; ++i) 1226 { 1227 OUString aTmp( aPrefix ); 1228 aTmp += pNames[i]; 1229 pNames[i] = aTmp; 1230 } 1231 1232 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); 1233 if (nLen && nLen == aValues.getLength()) 1234 { 1235 const uno::Any *pValues = aValues.getConstArray(); 1236 for (sal_Int32 i = 0; i < nLen; ++i) 1237 { 1238 uno::Sequence< OUString > aSvcImplNames; 1239 if (pValues[i] >>= aSvcImplNames) 1240 { 1241 // there should only be one hyphenator in use per language... 1242 if (aSvcImplNames.getLength() > 1) 1243 aSvcImplNames.realloc(1); 1244 1245 #if OSL_DEBUG_LEVEL > 1 1246 // sal_Int32 nSvcs = aSvcImplNames.getLength(); 1247 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); 1248 #endif 1249 String aLocaleStr( pNames[i] ); 1250 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); 1251 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); 1252 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); 1253 rHyphDsp.SetServiceList( aLocale, aSvcImplNames ); 1254 } 1255 } 1256 } 1257 } 1258 1259 1260 void LngSvcMgr::SetCfgServiceLists( ThesaurusDispatcher &rThesDsp ) 1261 { 1262 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Thes" ); 1263 1264 String aNode( String::CreateFromAscii( "ServiceManager/ThesaurusList" ) ); 1265 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); 1266 OUString *pNames = aNames.getArray(); 1267 sal_Int32 nLen = aNames.getLength(); 1268 1269 // append path prefix need for 'GetProperties' call below 1270 String aPrefix( aNode ); 1271 aPrefix.Append( (sal_Unicode) '/' ); 1272 for (int i = 0; i < nLen; ++i) 1273 { 1274 OUString aTmp( aPrefix ); 1275 aTmp += pNames[i]; 1276 pNames[i] = aTmp; 1277 } 1278 1279 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); 1280 if (nLen && nLen == aValues.getLength()) 1281 { 1282 const uno::Any *pValues = aValues.getConstArray(); 1283 for (sal_Int32 i = 0; i < nLen; ++i) 1284 { 1285 uno::Sequence< OUString > aSvcImplNames; 1286 if (pValues[i] >>= aSvcImplNames) 1287 { 1288 #if OSL_DEBUG_LEVEL > 1 1289 // sal_Int32 nSvcs = aSvcImplNames.getLength(); 1290 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); 1291 #endif 1292 String aLocaleStr( pNames[i] ); 1293 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); 1294 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); 1295 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); 1296 rThesDsp.SetServiceList( aLocale, aSvcImplNames ); 1297 } 1298 } 1299 } 1300 } 1301 1302 1303 uno::Reference< linguistic2::XSpellChecker > SAL_CALL 1304 LngSvcMgr::getSpellChecker() 1305 throw(uno::RuntimeException) 1306 { 1307 osl::MutexGuard aGuard( GetLinguMutex() ); 1308 #if OSL_DEBUG_LEVEL > 1 1309 getAvailableLocales( A2OU( SN_SPELLCHECKER )); 1310 #endif 1311 1312 uno::Reference< linguistic2::XSpellChecker > xRes; 1313 if (!bDisposing) 1314 { 1315 if (!xSpellDsp.is()) 1316 GetSpellCheckerDsp_Impl(); 1317 xRes = xSpellDsp; 1318 } 1319 return xRes; 1320 } 1321 1322 1323 uno::Reference< linguistic2::XHyphenator > SAL_CALL 1324 LngSvcMgr::getHyphenator() 1325 throw(uno::RuntimeException) 1326 { 1327 osl::MutexGuard aGuard( GetLinguMutex() ); 1328 #if OSL_DEBUG_LEVEL > 1 1329 getAvailableLocales( A2OU( SN_HYPHENATOR )); 1330 #endif 1331 1332 uno::Reference< linguistic2::XHyphenator > xRes; 1333 if (!bDisposing) 1334 { 1335 if (!xHyphDsp.is()) 1336 GetHyphenatorDsp_Impl(); 1337 xRes = xHyphDsp; 1338 } 1339 return xRes; 1340 } 1341 1342 1343 uno::Reference< linguistic2::XThesaurus > SAL_CALL 1344 LngSvcMgr::getThesaurus() 1345 throw(uno::RuntimeException) 1346 { 1347 osl::MutexGuard aGuard( GetLinguMutex() ); 1348 #if OSL_DEBUG_LEVEL > 1 1349 getAvailableLocales( A2OU( SN_THESAURUS )); 1350 #endif 1351 1352 uno::Reference< linguistic2::XThesaurus > xRes; 1353 if (!bDisposing) 1354 { 1355 if (!xThesDsp.is()) 1356 GetThesaurusDsp_Impl(); 1357 xRes = xThesDsp; 1358 } 1359 return xRes; 1360 } 1361 1362 1363 sal_Bool SAL_CALL 1364 LngSvcMgr::addLinguServiceManagerListener( 1365 const uno::Reference< lang::XEventListener >& xListener ) 1366 throw(uno::RuntimeException) 1367 { 1368 osl::MutexGuard aGuard( GetLinguMutex() ); 1369 1370 sal_Bool bRes = sal_False; 1371 if (!bDisposing && xListener.is()) 1372 { 1373 if (!pListenerHelper) 1374 GetListenerHelper_Impl(); 1375 bRes = pListenerHelper->AddLngSvcMgrListener( xListener ); 1376 } 1377 return bRes; 1378 } 1379 1380 1381 sal_Bool SAL_CALL 1382 LngSvcMgr::removeLinguServiceManagerListener( 1383 const uno::Reference< lang::XEventListener >& xListener ) 1384 throw(uno::RuntimeException) 1385 { 1386 osl::MutexGuard aGuard( GetLinguMutex() ); 1387 1388 sal_Bool bRes = sal_False; 1389 if (!bDisposing && xListener.is()) 1390 { 1391 DBG_ASSERT( pListenerHelper, "listener removed without being added" ); 1392 if (!pListenerHelper) 1393 GetListenerHelper_Impl(); 1394 bRes = pListenerHelper->RemoveLngSvcMgrListener( xListener ); 1395 } 1396 return bRes; 1397 } 1398 1399 1400 uno::Sequence< OUString > SAL_CALL 1401 LngSvcMgr::getAvailableServices( 1402 const OUString& rServiceName, 1403 const lang::Locale& rLocale ) 1404 throw(uno::RuntimeException) 1405 { 1406 osl::MutexGuard aGuard( GetLinguMutex() ); 1407 1408 uno::Sequence< OUString > aRes; 1409 const SvcInfoArray *pInfoArray = 0; 1410 1411 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) 1412 { 1413 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries 1414 // already found without the need to restart the office 1415 clearSvcInfoArray(pAvailSpellSvcs); pAvailSpellSvcs = 0; 1416 GetAvailableSpellSvcs_Impl(); 1417 pInfoArray = pAvailSpellSvcs; 1418 } 1419 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) 1420 { 1421 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries 1422 // already found without the need to restart the office 1423 clearSvcInfoArray(pAvailGrammarSvcs); pAvailGrammarSvcs = 0; 1424 GetAvailableGrammarSvcs_Impl(); 1425 pInfoArray = pAvailGrammarSvcs; 1426 } 1427 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) 1428 { 1429 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries 1430 // already found without the need to restart the office 1431 clearSvcInfoArray(pAvailHyphSvcs); pAvailHyphSvcs = 0; 1432 GetAvailableHyphSvcs_Impl(); 1433 pInfoArray = pAvailHyphSvcs; 1434 } 1435 else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) 1436 { 1437 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries 1438 // already found without the need to restart the office 1439 clearSvcInfoArray(pAvailThesSvcs); pAvailThesSvcs = 0; 1440 GetAvailableThesSvcs_Impl(); 1441 pInfoArray = pAvailThesSvcs; 1442 } 1443 1444 if (pInfoArray) 1445 { 1446 // resize to max number of entries 1447 size_t nMaxCnt = pInfoArray->size(); 1448 aRes.realloc( nMaxCnt ); 1449 OUString *pImplName = aRes.getArray(); 1450 1451 sal_uInt16 nCnt = 0; 1452 LanguageType nLanguage = LocaleToLanguage( rLocale ); 1453 for (size_t i = 0; i < nMaxCnt; ++i) 1454 { 1455 const SvcInfo *pInfo = (*pInfoArray)[i]; 1456 if (LANGUAGE_NONE == nLanguage 1457 || (pInfo && pInfo->HasLanguage( nLanguage ))) 1458 { 1459 pImplName[ nCnt++ ] = pInfo->aSvcImplName; 1460 } 1461 } 1462 1463 // resize to actual number of entries 1464 if (nCnt != nMaxCnt) 1465 aRes.realloc( nCnt ); 1466 } 1467 1468 return aRes; 1469 } 1470 1471 1472 uno::Sequence< lang::Locale > SAL_CALL 1473 LngSvcMgr::getAvailableLocales( 1474 const OUString& rServiceName ) 1475 throw(uno::RuntimeException) 1476 { 1477 osl::MutexGuard aGuard( GetLinguMutex() ); 1478 1479 uno::Sequence< lang::Locale > aRes; 1480 1481 uno::Sequence< lang::Locale > *pAvailLocales = NULL; 1482 sal_Bool *pHasAvailLocales = NULL; 1483 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) 1484 { 1485 pAvailLocales = &aAvailSpellLocales; 1486 pHasAvailLocales = &bHasAvailSpellLocales; 1487 } 1488 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) 1489 { 1490 pAvailLocales = &aAvailGrammarLocales; 1491 pHasAvailLocales = &bHasAvailGrammarLocales; 1492 } 1493 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) 1494 { 1495 pAvailLocales = &aAvailHyphLocales; 1496 pHasAvailLocales = &bHasAvailHyphLocales; 1497 } 1498 else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) 1499 { 1500 pAvailLocales = &aAvailThesLocales; 1501 pHasAvailLocales = &bHasAvailThesLocales; 1502 } 1503 1504 // about pHasAvailLocales: nowadays (with OOo lingu in SO) we want to know immediately about 1505 // new downloaded dictionaries and have them ready right away if the Tools/Options... 1506 // is used to activate them. Thus we can not rely anymore on buffered data. 1507 if (pAvailLocales /*&& pHasAvailLocales */) 1508 { 1509 // if (!*pHasAvailLocales) 1510 // { 1511 *pAvailLocales = GetAvailLocales( 1512 getAvailableServices( rServiceName, lang::Locale() ) ); 1513 // *pHasAvailLocales = sal_True; 1514 // } 1515 aRes = *pAvailLocales; 1516 } 1517 1518 return aRes; 1519 } 1520 1521 static sal_Bool IsEqSvcList( const uno::Sequence< OUString > &rList1, 1522 const uno::Sequence< OUString > &rList2 ) 1523 { 1524 // returns sal_True iff both sequences are equal 1525 1526 sal_Bool bRes = sal_False; 1527 sal_Int32 nLen = rList1.getLength(); 1528 if (rList2.getLength() == nLen) 1529 { 1530 const OUString *pStr1 = rList1.getConstArray(); 1531 const OUString *pStr2 = rList2.getConstArray(); 1532 bRes = sal_True; 1533 for (sal_Int32 i = 0; i < nLen && bRes; ++i) 1534 { 1535 if (*pStr1++ != *pStr2++) 1536 bRes = sal_False; 1537 } 1538 } 1539 return bRes; 1540 } 1541 1542 1543 void SAL_CALL 1544 LngSvcMgr::setConfiguredServices( 1545 const OUString& rServiceName, 1546 const lang::Locale& rLocale, 1547 const uno::Sequence< OUString >& rServiceImplNames ) 1548 throw(uno::RuntimeException) 1549 { 1550 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::setConfiguredServices" ); 1551 1552 osl::MutexGuard aGuard( GetLinguMutex() ); 1553 1554 #if OSL_DEBUG_LEVEL > 1 1555 // const OUString *pImplNames = rServiceImplNames.getConstArray(); 1556 #endif 1557 1558 LanguageType nLanguage = LocaleToLanguage( rLocale ); 1559 if (LANGUAGE_NONE != nLanguage) 1560 { 1561 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) 1562 { 1563 if (!xSpellDsp.is()) 1564 GetSpellCheckerDsp_Impl(); 1565 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1566 pSpellDsp->GetServiceList( rLocale ) ); 1567 if (bChanged) 1568 { 1569 pSpellDsp->SetServiceList( rLocale, rServiceImplNames ); 1570 SaveCfgSvcs( A2OU( SN_SPELLCHECKER ) ); 1571 1572 if (pListenerHelper && bChanged) 1573 pListenerHelper->AddLngSvcEvt( 1574 linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN | 1575 linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN ); 1576 } 1577 } 1578 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) 1579 { 1580 if (!xGrammarDsp.is()) 1581 GetGrammarCheckerDsp_Impl(); 1582 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1583 pGrammarDsp->GetServiceList( rLocale ) ); 1584 if (bChanged) 1585 { 1586 pGrammarDsp->SetServiceList( rLocale, rServiceImplNames ); 1587 SaveCfgSvcs( A2OU( SN_GRAMMARCHECKER ) ); 1588 1589 if (pListenerHelper && bChanged) 1590 pListenerHelper->AddLngSvcEvt( 1591 linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN ); 1592 } 1593 } 1594 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) 1595 { 1596 if (!xHyphDsp.is()) 1597 GetHyphenatorDsp_Impl(); 1598 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1599 pHyphDsp->GetServiceList( rLocale ) ); 1600 if (bChanged) 1601 { 1602 pHyphDsp->SetServiceList( rLocale, rServiceImplNames ); 1603 SaveCfgSvcs( A2OU( SN_HYPHENATOR ) ); 1604 1605 if (pListenerHelper && bChanged) 1606 pListenerHelper->AddLngSvcEvt( 1607 linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN ); 1608 } 1609 } 1610 else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) 1611 { 1612 if (!xThesDsp.is()) 1613 GetThesaurusDsp_Impl(); 1614 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1615 pThesDsp->GetServiceList( rLocale ) ); 1616 if (bChanged) 1617 { 1618 pThesDsp->SetServiceList( rLocale, rServiceImplNames ); 1619 SaveCfgSvcs( A2OU( SN_THESAURUS ) ); 1620 } 1621 } 1622 } 1623 } 1624 1625 1626 sal_Bool LngSvcMgr::SaveCfgSvcs( const String &rServiceName ) 1627 { 1628 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs" ); 1629 1630 sal_Bool bRes = sal_False; 1631 1632 LinguDispatcher *pDsp = 0; 1633 uno::Sequence< lang::Locale > aLocales; 1634 1635 if (0 == rServiceName.CompareToAscii( SN_SPELLCHECKER )) 1636 { 1637 if (!pSpellDsp) 1638 GetSpellCheckerDsp_Impl(); 1639 pDsp = pSpellDsp; 1640 aLocales = getAvailableLocales( A2OU( SN_SPELLCHECKER ) ); 1641 } 1642 else if (0 == rServiceName.CompareToAscii( SN_GRAMMARCHECKER )) 1643 { 1644 if (!pGrammarDsp) 1645 GetGrammarCheckerDsp_Impl(); 1646 pDsp = pGrammarDsp; 1647 aLocales = getAvailableLocales( A2OU( SN_GRAMMARCHECKER ) ); 1648 } 1649 else if (0 == rServiceName.CompareToAscii( SN_HYPHENATOR )) 1650 { 1651 if (!pHyphDsp) 1652 GetHyphenatorDsp_Impl(); 1653 pDsp = pHyphDsp; 1654 aLocales = getAvailableLocales( A2OU( SN_HYPHENATOR ) ); 1655 } 1656 else if (0 == rServiceName.CompareToAscii( SN_THESAURUS )) 1657 { 1658 if (!pThesDsp) 1659 GetThesaurusDsp_Impl(); 1660 pDsp = pThesDsp; 1661 aLocales = getAvailableLocales( A2OU( SN_THESAURUS ) ); 1662 } 1663 1664 if (pDsp && aLocales.getLength()) 1665 { 1666 sal_Int32 nLen = aLocales.getLength(); 1667 const lang::Locale *pLocale = aLocales.getConstArray(); 1668 1669 uno::Sequence< beans::PropertyValue > aValues( nLen ); 1670 beans::PropertyValue *pValues = aValues.getArray(); 1671 beans::PropertyValue *pValue = pValues; 1672 1673 // get node name to be used 1674 const char *pNodeName = NULL; 1675 if (pDsp == pSpellDsp) 1676 pNodeName = "ServiceManager/SpellCheckerList"; 1677 else if (pDsp == pGrammarDsp) 1678 pNodeName = "ServiceManager/GrammarCheckerList"; 1679 else if (pDsp == pHyphDsp) 1680 pNodeName = "ServiceManager/HyphenatorList"; 1681 else if (pDsp == pThesDsp) 1682 pNodeName = "ServiceManager/ThesaurusList"; 1683 else 1684 { 1685 DBG_ASSERT( 0, "node name missing" ); 1686 } 1687 OUString aNodeName( A2OU(pNodeName) ); 1688 1689 for (sal_Int32 i = 0; i < nLen; ++i) 1690 { 1691 uno::Sequence< OUString > aSvcImplNames; 1692 aSvcImplNames = pDsp->GetServiceList( pLocale[i] ); 1693 1694 #if OSL_DEBUG_LEVEL > 1 1695 sal_Int32 nSvcs = aSvcImplNames.getLength(); 1696 const OUString *pSvcImplName = aSvcImplNames.getConstArray(); 1697 for (sal_Int32 j = 0; j < nSvcs; ++j) 1698 { 1699 OUString aImplName( pSvcImplName[j] ); 1700 } 1701 #endif 1702 // build value to be written back to configuration 1703 uno::Any aCfgAny; 1704 if ((pDsp == pHyphDsp || pDsp == pGrammarDsp) && aSvcImplNames.getLength() > 1) 1705 aSvcImplNames.realloc(1); // there should be only one entry for hyphenators or grammar checkers (because they are not chained) 1706 aCfgAny <<= aSvcImplNames; 1707 DBG_ASSERT( aCfgAny.hasValue(), "missing value for 'Any' type" ); 1708 1709 OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString( 1710 LocaleToLanguage( pLocale[i] ) ) ); 1711 pValue->Value = aCfgAny; 1712 pValue->Name = aNodeName; 1713 pValue->Name += OUString::valueOf( (sal_Unicode) '/' ); 1714 pValue->Name += aCfgLocaleStr; 1715 pValue++; 1716 } 1717 { 1718 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs - ReplaceSetProperties" ); 1719 // change, add new or replace existing entries. 1720 bRes |= /*aCfg.*/ReplaceSetProperties( aNodeName, aValues ); 1721 } 1722 } 1723 1724 return bRes; 1725 } 1726 1727 1728 static uno::Sequence< OUString > GetLangSvcList( const uno::Any &rVal ) 1729 { 1730 uno::Sequence< OUString > aRes; 1731 1732 if (rVal.hasValue()) 1733 { 1734 rVal >>= aRes; 1735 #if OSL_DEBUG_LEVEL > 1 1736 sal_Int32 nSvcs = aRes.getLength(); 1737 if (nSvcs) 1738 { 1739 const OUString *pSvcName = aRes.getConstArray(); 1740 for (sal_Int32 j = 0; j < nSvcs; ++j) 1741 { 1742 OUString aImplName( pSvcName[j] ); 1743 DBG_ASSERT( aImplName.getLength(), "service impl-name missing" ); 1744 } 1745 } 1746 #endif 1747 } 1748 1749 return aRes; 1750 } 1751 1752 1753 static uno::Sequence< OUString > GetLangSvc( const uno::Any &rVal ) 1754 { 1755 uno::Sequence< OUString > aRes; 1756 if (!rVal.hasValue()) 1757 return aRes; 1758 1759 // allowing for a sequence here as well (even though it should only 1760 // be a string) makes coding easier in other places since one needs 1761 // not make a special case for writing a string only and not a 1762 // sequence of strings. 1763 if (rVal >>= aRes) 1764 { 1765 // but only the first string should be used. 1766 if (aRes.getLength() > 1) 1767 aRes.realloc(1); 1768 } 1769 else 1770 { 1771 OUString aImplName; 1772 if ((rVal >>= aImplName) && aImplName.getLength() != 0) 1773 { 1774 aRes.realloc(1); 1775 aRes.getArray()[0] = aImplName; 1776 } 1777 else 1778 { 1779 DBG_ASSERT( 0, "GetLangSvc: unexpected type encountered" ); 1780 } 1781 } 1782 1783 return aRes; 1784 } 1785 1786 1787 /////////////////////////////////////////////////////////////////////////// 1788 1789 uno::Sequence< OUString > SAL_CALL 1790 LngSvcMgr::getConfiguredServices( 1791 const OUString& rServiceName, 1792 const lang::Locale& rLocale ) 1793 throw(uno::RuntimeException) 1794 { 1795 osl::MutexGuard aGuard( GetLinguMutex() ); 1796 1797 uno::Sequence< OUString > aSvcImplNames; 1798 1799 LanguageType nLanguage = LocaleToLanguage( rLocale ); 1800 OUString aCfgLocale( MsLangId::convertLanguageToIsoString( nLanguage ) ); 1801 1802 uno::Sequence< uno::Any > aValues; 1803 uno::Sequence< OUString > aNames( 1 ); 1804 OUString *pNames = aNames.getArray(); 1805 if ( 0 == rServiceName.compareToAscii( SN_SPELLCHECKER ) ) 1806 { 1807 OUString aNode( OUString::createFromAscii( "ServiceManager/SpellCheckerList" )); 1808 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1809 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1810 { 1811 OUString aPropName( aNode ); 1812 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1813 aPropName += aCfgLocale; 1814 pNames[0] = aPropName; 1815 aValues = /*aCfg.*/GetProperties( aNames ); 1816 if (aValues.getLength()) 1817 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); 1818 } 1819 } 1820 else if ( 0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ) ) 1821 { 1822 OUString aNode( OUString::createFromAscii( "ServiceManager/GrammarCheckerList" )); 1823 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1824 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1825 { 1826 OUString aPropName( aNode ); 1827 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1828 aPropName += aCfgLocale; 1829 pNames[0] = aPropName; 1830 aValues = /*aCfg.*/GetProperties( aNames ); 1831 if (aValues.getLength()) 1832 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); 1833 } 1834 } 1835 else if ( 0 == rServiceName.compareToAscii( SN_HYPHENATOR ) ) 1836 { 1837 OUString aNode( OUString::createFromAscii( "ServiceManager/HyphenatorList" )); 1838 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1839 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1840 { 1841 OUString aPropName( aNode ); 1842 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1843 aPropName += aCfgLocale; 1844 pNames[0] = aPropName; 1845 aValues = /*aCfg.*/GetProperties( aNames ); 1846 if (aValues.getLength()) 1847 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); 1848 } 1849 } 1850 else if ( 0 == rServiceName.compareToAscii( SN_THESAURUS ) ) 1851 { 1852 OUString aNode( OUString::createFromAscii( "ServiceManager/ThesaurusList" )); 1853 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1854 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1855 { 1856 OUString aPropName( aNode ); 1857 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1858 aPropName += aCfgLocale; 1859 pNames[0] = aPropName; 1860 aValues = /*aCfg.*/GetProperties( aNames ); 1861 if (aValues.getLength()) 1862 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); 1863 } 1864 } 1865 1866 #if OSL_DEBUG_LEVEL > 1 1867 const OUString *pImplNames = aSvcImplNames.getConstArray(); 1868 (void) pImplNames; 1869 #endif 1870 return aSvcImplNames; 1871 } 1872 1873 1874 void SAL_CALL 1875 LngSvcMgr::dispose() 1876 throw(uno::RuntimeException) 1877 { 1878 osl::MutexGuard aGuard( GetLinguMutex() ); 1879 1880 if (!bDisposing) 1881 { 1882 bDisposing = sal_True; 1883 1884 // require listeners to release this object 1885 lang::EventObject aEvtObj( (XLinguServiceManager *) this ); 1886 aEvtListeners.disposeAndClear( aEvtObj ); 1887 1888 if (pListenerHelper) 1889 pListenerHelper->DisposeAndClear( aEvtObj ); 1890 } 1891 } 1892 1893 1894 void SAL_CALL 1895 LngSvcMgr::addEventListener( 1896 const uno::Reference< lang::XEventListener >& xListener ) 1897 throw(uno::RuntimeException) 1898 { 1899 osl::MutexGuard aGuard( GetLinguMutex() ); 1900 1901 if (!bDisposing && xListener.is()) 1902 { 1903 aEvtListeners.addInterface( xListener ); 1904 } 1905 } 1906 1907 1908 void SAL_CALL 1909 LngSvcMgr::removeEventListener( 1910 const uno::Reference< lang::XEventListener >& xListener ) 1911 throw(uno::RuntimeException) 1912 { 1913 osl::MutexGuard aGuard( GetLinguMutex() ); 1914 1915 if (xListener.is()) 1916 { 1917 aEvtListeners.removeInterface( xListener ); 1918 } 1919 } 1920 1921 1922 sal_Bool LngSvcMgr::AddLngSvcEvtBroadcaster( 1923 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) 1924 { 1925 sal_Bool bRes = sal_False; 1926 if (rxBroadcaster.is()) 1927 { 1928 if (!pListenerHelper) 1929 GetListenerHelper_Impl(); 1930 bRes = pListenerHelper->AddLngSvcEvtBroadcaster( rxBroadcaster ); 1931 } 1932 return bRes; 1933 } 1934 1935 1936 sal_Bool LngSvcMgr::RemoveLngSvcEvtBroadcaster( 1937 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) 1938 { 1939 sal_Bool bRes = sal_False; 1940 if (rxBroadcaster.is()) 1941 { 1942 DBG_ASSERT( pListenerHelper, "pListenerHelper non existent" ); 1943 if (!pListenerHelper) 1944 GetListenerHelper_Impl(); 1945 bRes = pListenerHelper->RemoveLngSvcEvtBroadcaster( rxBroadcaster ); 1946 } 1947 return bRes; 1948 } 1949 1950 1951 OUString SAL_CALL 1952 LngSvcMgr::getImplementationName() 1953 throw(uno::RuntimeException) 1954 { 1955 osl::MutexGuard aGuard( GetLinguMutex() ); 1956 return getImplementationName_Static(); 1957 } 1958 1959 1960 sal_Bool SAL_CALL 1961 LngSvcMgr::supportsService( const OUString& ServiceName ) 1962 throw(uno::RuntimeException) 1963 { 1964 osl::MutexGuard aGuard( GetLinguMutex() ); 1965 1966 uno::Sequence< OUString > aSNL = getSupportedServiceNames(); 1967 const OUString * pArray = aSNL.getConstArray(); 1968 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 1969 if( pArray[i] == ServiceName ) 1970 return sal_True; 1971 return sal_False; 1972 } 1973 1974 1975 uno::Sequence< OUString > SAL_CALL 1976 LngSvcMgr::getSupportedServiceNames() 1977 throw(uno::RuntimeException) 1978 { 1979 osl::MutexGuard aGuard( GetLinguMutex() ); 1980 return getSupportedServiceNames_Static(); 1981 } 1982 1983 1984 uno::Sequence< OUString > LngSvcMgr::getSupportedServiceNames_Static() 1985 throw() 1986 { 1987 osl::MutexGuard aGuard( GetLinguMutex() ); 1988 1989 uno::Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich 1990 aSNS.getArray()[0] = A2OU( SN_LINGU_SERVCICE_MANAGER ); 1991 return aSNS; 1992 } 1993 1994 1995 uno::Reference< uno::XInterface > SAL_CALL LngSvcMgr_CreateInstance( 1996 const uno::Reference< lang::XMultiServiceFactory > & /*rSMgr*/ ) 1997 throw(uno::Exception) 1998 { 1999 uno::Reference< uno::XInterface > xService = (cppu::OWeakObject*) new LngSvcMgr; 2000 return xService; 2001 } 2002 2003 void * SAL_CALL LngSvcMgr_getFactory( 2004 const sal_Char * pImplName, 2005 lang::XMultiServiceFactory * pServiceManager, 2006 void * /*pRegistryKey*/ ) 2007 { 2008 2009 void * pRet = 0; 2010 if ( !LngSvcMgr::getImplementationName_Static().compareToAscii( pImplName ) ) 2011 { 2012 uno::Reference< lang::XSingleServiceFactory > xFactory = 2013 cppu::createOneInstanceFactory( 2014 pServiceManager, 2015 LngSvcMgr::getImplementationName_Static(), 2016 LngSvcMgr_CreateInstance, 2017 LngSvcMgr::getSupportedServiceNames_Static()); 2018 // acquire, because we return an interface pointer instead of a reference 2019 xFactory->acquire(); 2020 pRet = xFactory.get(); 2021 } 2022 return pRet; 2023 } 2024 2025 2026 /////////////////////////////////////////////////////////////////////////// 2027 2028