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