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 clear cache as it makes start with some extentions so slow it looks 1418 // like a freeze (a restart is needed anyway after grammar checker installation), 1419 // see https://issues.apache.org/ooo/show_bug.cgi?id=116409 1420 //clearSvcInfoArray(pAvailGrammarSvcs); pAvailGrammarSvcs = 0; 1421 GetAvailableGrammarSvcs_Impl(); 1422 pInfoArray = pAvailGrammarSvcs; 1423 } 1424 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) 1425 { 1426 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries 1427 // already found without the need to restart the office 1428 clearSvcInfoArray(pAvailHyphSvcs); pAvailHyphSvcs = 0; 1429 GetAvailableHyphSvcs_Impl(); 1430 pInfoArray = pAvailHyphSvcs; 1431 } 1432 else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) 1433 { 1434 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries 1435 // already found without the need to restart the office 1436 clearSvcInfoArray(pAvailThesSvcs); pAvailThesSvcs = 0; 1437 GetAvailableThesSvcs_Impl(); 1438 pInfoArray = pAvailThesSvcs; 1439 } 1440 1441 if (pInfoArray) 1442 { 1443 // resize to max number of entries 1444 size_t nMaxCnt = pInfoArray->size(); 1445 aRes.realloc( nMaxCnt ); 1446 OUString *pImplName = aRes.getArray(); 1447 1448 sal_uInt16 nCnt = 0; 1449 LanguageType nLanguage = LocaleToLanguage( rLocale ); 1450 for (size_t i = 0; i < nMaxCnt; ++i) 1451 { 1452 const SvcInfo *pInfo = (*pInfoArray)[i]; 1453 if (LANGUAGE_NONE == nLanguage 1454 || (pInfo && pInfo->HasLanguage( nLanguage ))) 1455 { 1456 pImplName[ nCnt++ ] = pInfo->aSvcImplName; 1457 } 1458 } 1459 1460 // resize to actual number of entries 1461 if (nCnt != nMaxCnt) 1462 aRes.realloc( nCnt ); 1463 } 1464 1465 return aRes; 1466 } 1467 1468 1469 uno::Sequence< lang::Locale > SAL_CALL 1470 LngSvcMgr::getAvailableLocales( 1471 const OUString& rServiceName ) 1472 throw(uno::RuntimeException) 1473 { 1474 osl::MutexGuard aGuard( GetLinguMutex() ); 1475 1476 uno::Sequence< lang::Locale > aRes; 1477 1478 uno::Sequence< lang::Locale > *pAvailLocales = NULL; 1479 sal_Bool *pHasAvailLocales = NULL; 1480 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) 1481 { 1482 pAvailLocales = &aAvailSpellLocales; 1483 pHasAvailLocales = &bHasAvailSpellLocales; 1484 } 1485 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) 1486 { 1487 pAvailLocales = &aAvailGrammarLocales; 1488 pHasAvailLocales = &bHasAvailGrammarLocales; 1489 } 1490 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) 1491 { 1492 pAvailLocales = &aAvailHyphLocales; 1493 pHasAvailLocales = &bHasAvailHyphLocales; 1494 } 1495 else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) 1496 { 1497 pAvailLocales = &aAvailThesLocales; 1498 pHasAvailLocales = &bHasAvailThesLocales; 1499 } 1500 1501 // about pHasAvailLocales: nowadays (with OOo lingu in SO) we want to know immediately about 1502 // new downloaded dictionaries and have them ready right away if the Tools/Options... 1503 // is used to activate them. Thus we can not rely anymore on buffered data. 1504 if (pAvailLocales /*&& pHasAvailLocales */) 1505 { 1506 // if (!*pHasAvailLocales) 1507 // { 1508 *pAvailLocales = GetAvailLocales( 1509 getAvailableServices( rServiceName, lang::Locale() ) ); 1510 // *pHasAvailLocales = sal_True; 1511 // } 1512 aRes = *pAvailLocales; 1513 } 1514 1515 return aRes; 1516 } 1517 1518 static sal_Bool IsEqSvcList( const uno::Sequence< OUString > &rList1, 1519 const uno::Sequence< OUString > &rList2 ) 1520 { 1521 // returns sal_True iff both sequences are equal 1522 1523 sal_Bool bRes = sal_False; 1524 sal_Int32 nLen = rList1.getLength(); 1525 if (rList2.getLength() == nLen) 1526 { 1527 const OUString *pStr1 = rList1.getConstArray(); 1528 const OUString *pStr2 = rList2.getConstArray(); 1529 bRes = sal_True; 1530 for (sal_Int32 i = 0; i < nLen && bRes; ++i) 1531 { 1532 if (*pStr1++ != *pStr2++) 1533 bRes = sal_False; 1534 } 1535 } 1536 return bRes; 1537 } 1538 1539 1540 void SAL_CALL 1541 LngSvcMgr::setConfiguredServices( 1542 const OUString& rServiceName, 1543 const lang::Locale& rLocale, 1544 const uno::Sequence< OUString >& rServiceImplNames ) 1545 throw(uno::RuntimeException) 1546 { 1547 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::setConfiguredServices" ); 1548 1549 osl::MutexGuard aGuard( GetLinguMutex() ); 1550 1551 #if OSL_DEBUG_LEVEL > 1 1552 // const OUString *pImplNames = rServiceImplNames.getConstArray(); 1553 #endif 1554 1555 LanguageType nLanguage = LocaleToLanguage( rLocale ); 1556 if (LANGUAGE_NONE != nLanguage) 1557 { 1558 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) 1559 { 1560 if (!xSpellDsp.is()) 1561 GetSpellCheckerDsp_Impl(); 1562 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1563 pSpellDsp->GetServiceList( rLocale ) ); 1564 if (bChanged) 1565 { 1566 pSpellDsp->SetServiceList( rLocale, rServiceImplNames ); 1567 SaveCfgSvcs( A2OU( SN_SPELLCHECKER ) ); 1568 1569 if (pListenerHelper && bChanged) 1570 pListenerHelper->AddLngSvcEvt( 1571 linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN | 1572 linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN ); 1573 } 1574 } 1575 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) 1576 { 1577 if (!xGrammarDsp.is()) 1578 GetGrammarCheckerDsp_Impl(); 1579 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1580 pGrammarDsp->GetServiceList( rLocale ) ); 1581 if (bChanged) 1582 { 1583 pGrammarDsp->SetServiceList( rLocale, rServiceImplNames ); 1584 SaveCfgSvcs( A2OU( SN_GRAMMARCHECKER ) ); 1585 1586 if (pListenerHelper && bChanged) 1587 pListenerHelper->AddLngSvcEvt( 1588 linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN ); 1589 } 1590 } 1591 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) 1592 { 1593 if (!xHyphDsp.is()) 1594 GetHyphenatorDsp_Impl(); 1595 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1596 pHyphDsp->GetServiceList( rLocale ) ); 1597 if (bChanged) 1598 { 1599 pHyphDsp->SetServiceList( rLocale, rServiceImplNames ); 1600 SaveCfgSvcs( A2OU( SN_HYPHENATOR ) ); 1601 1602 if (pListenerHelper && bChanged) 1603 pListenerHelper->AddLngSvcEvt( 1604 linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN ); 1605 } 1606 } 1607 else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) 1608 { 1609 if (!xThesDsp.is()) 1610 GetThesaurusDsp_Impl(); 1611 sal_Bool bChanged = !IsEqSvcList( rServiceImplNames, 1612 pThesDsp->GetServiceList( rLocale ) ); 1613 if (bChanged) 1614 { 1615 pThesDsp->SetServiceList( rLocale, rServiceImplNames ); 1616 SaveCfgSvcs( A2OU( SN_THESAURUS ) ); 1617 } 1618 } 1619 } 1620 } 1621 1622 1623 sal_Bool LngSvcMgr::SaveCfgSvcs( const String &rServiceName ) 1624 { 1625 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs" ); 1626 1627 sal_Bool bRes = sal_False; 1628 1629 LinguDispatcher *pDsp = 0; 1630 uno::Sequence< lang::Locale > aLocales; 1631 1632 if (0 == rServiceName.CompareToAscii( SN_SPELLCHECKER )) 1633 { 1634 if (!pSpellDsp) 1635 GetSpellCheckerDsp_Impl(); 1636 pDsp = pSpellDsp; 1637 aLocales = getAvailableLocales( A2OU( SN_SPELLCHECKER ) ); 1638 } 1639 else if (0 == rServiceName.CompareToAscii( SN_GRAMMARCHECKER )) 1640 { 1641 if (!pGrammarDsp) 1642 GetGrammarCheckerDsp_Impl(); 1643 pDsp = pGrammarDsp; 1644 aLocales = getAvailableLocales( A2OU( SN_GRAMMARCHECKER ) ); 1645 } 1646 else if (0 == rServiceName.CompareToAscii( SN_HYPHENATOR )) 1647 { 1648 if (!pHyphDsp) 1649 GetHyphenatorDsp_Impl(); 1650 pDsp = pHyphDsp; 1651 aLocales = getAvailableLocales( A2OU( SN_HYPHENATOR ) ); 1652 } 1653 else if (0 == rServiceName.CompareToAscii( SN_THESAURUS )) 1654 { 1655 if (!pThesDsp) 1656 GetThesaurusDsp_Impl(); 1657 pDsp = pThesDsp; 1658 aLocales = getAvailableLocales( A2OU( SN_THESAURUS ) ); 1659 } 1660 1661 if (pDsp && aLocales.getLength()) 1662 { 1663 sal_Int32 nLen = aLocales.getLength(); 1664 const lang::Locale *pLocale = aLocales.getConstArray(); 1665 1666 uno::Sequence< beans::PropertyValue > aValues( nLen ); 1667 beans::PropertyValue *pValues = aValues.getArray(); 1668 beans::PropertyValue *pValue = pValues; 1669 1670 // get node name to be used 1671 const char *pNodeName = NULL; 1672 if (pDsp == pSpellDsp) 1673 pNodeName = "ServiceManager/SpellCheckerList"; 1674 else if (pDsp == pGrammarDsp) 1675 pNodeName = "ServiceManager/GrammarCheckerList"; 1676 else if (pDsp == pHyphDsp) 1677 pNodeName = "ServiceManager/HyphenatorList"; 1678 else if (pDsp == pThesDsp) 1679 pNodeName = "ServiceManager/ThesaurusList"; 1680 else 1681 { 1682 DBG_ASSERT( 0, "node name missing" ); 1683 } 1684 OUString aNodeName( A2OU(pNodeName) ); 1685 1686 for (sal_Int32 i = 0; i < nLen; ++i) 1687 { 1688 uno::Sequence< OUString > aSvcImplNames; 1689 aSvcImplNames = pDsp->GetServiceList( pLocale[i] ); 1690 1691 #if OSL_DEBUG_LEVEL > 1 1692 sal_Int32 nSvcs = aSvcImplNames.getLength(); 1693 const OUString *pSvcImplName = aSvcImplNames.getConstArray(); 1694 for (sal_Int32 j = 0; j < nSvcs; ++j) 1695 { 1696 OUString aImplName( pSvcImplName[j] ); 1697 } 1698 #endif 1699 // build value to be written back to configuration 1700 uno::Any aCfgAny; 1701 if ((pDsp == pHyphDsp || pDsp == pGrammarDsp) && aSvcImplNames.getLength() > 1) 1702 aSvcImplNames.realloc(1); // there should be only one entry for hyphenators or grammar checkers (because they are not chained) 1703 aCfgAny <<= aSvcImplNames; 1704 DBG_ASSERT( aCfgAny.hasValue(), "missing value for 'Any' type" ); 1705 1706 OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString( 1707 LocaleToLanguage( pLocale[i] ) ) ); 1708 pValue->Value = aCfgAny; 1709 pValue->Name = aNodeName; 1710 pValue->Name += OUString::valueOf( (sal_Unicode) '/' ); 1711 pValue->Name += aCfgLocaleStr; 1712 pValue++; 1713 } 1714 { 1715 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs - ReplaceSetProperties" ); 1716 // change, add new or replace existing entries. 1717 bRes |= /*aCfg.*/ReplaceSetProperties( aNodeName, aValues ); 1718 } 1719 } 1720 1721 return bRes; 1722 } 1723 1724 1725 static uno::Sequence< OUString > GetLangSvcList( const uno::Any &rVal ) 1726 { 1727 uno::Sequence< OUString > aRes; 1728 1729 if (rVal.hasValue()) 1730 { 1731 rVal >>= aRes; 1732 #if OSL_DEBUG_LEVEL > 1 1733 sal_Int32 nSvcs = aRes.getLength(); 1734 if (nSvcs) 1735 { 1736 const OUString *pSvcName = aRes.getConstArray(); 1737 for (sal_Int32 j = 0; j < nSvcs; ++j) 1738 { 1739 OUString aImplName( pSvcName[j] ); 1740 DBG_ASSERT( aImplName.getLength(), "service impl-name missing" ); 1741 } 1742 } 1743 #endif 1744 } 1745 1746 return aRes; 1747 } 1748 1749 1750 static uno::Sequence< OUString > GetLangSvc( const uno::Any &rVal ) 1751 { 1752 uno::Sequence< OUString > aRes; 1753 if (!rVal.hasValue()) 1754 return aRes; 1755 1756 // allowing for a sequence here as well (even though it should only 1757 // be a string) makes coding easier in other places since one needs 1758 // not make a special case for writing a string only and not a 1759 // sequence of strings. 1760 if (rVal >>= aRes) 1761 { 1762 // but only the first string should be used. 1763 if (aRes.getLength() > 1) 1764 aRes.realloc(1); 1765 } 1766 else 1767 { 1768 OUString aImplName; 1769 if ((rVal >>= aImplName) && aImplName.getLength() != 0) 1770 { 1771 aRes.realloc(1); 1772 aRes.getArray()[0] = aImplName; 1773 } 1774 else 1775 { 1776 DBG_ASSERT( 0, "GetLangSvc: unexpected type encountered" ); 1777 } 1778 } 1779 1780 return aRes; 1781 } 1782 1783 1784 /////////////////////////////////////////////////////////////////////////// 1785 1786 uno::Sequence< OUString > SAL_CALL 1787 LngSvcMgr::getConfiguredServices( 1788 const OUString& rServiceName, 1789 const lang::Locale& rLocale ) 1790 throw(uno::RuntimeException) 1791 { 1792 osl::MutexGuard aGuard( GetLinguMutex() ); 1793 1794 uno::Sequence< OUString > aSvcImplNames; 1795 1796 LanguageType nLanguage = LocaleToLanguage( rLocale ); 1797 OUString aCfgLocale( MsLangId::convertLanguageToIsoString( nLanguage ) ); 1798 1799 uno::Sequence< uno::Any > aValues; 1800 uno::Sequence< OUString > aNames( 1 ); 1801 OUString *pNames = aNames.getArray(); 1802 if ( 0 == rServiceName.compareToAscii( SN_SPELLCHECKER ) ) 1803 { 1804 OUString aNode( OUString::createFromAscii( "ServiceManager/SpellCheckerList" )); 1805 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1806 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1807 { 1808 OUString aPropName( aNode ); 1809 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1810 aPropName += aCfgLocale; 1811 pNames[0] = aPropName; 1812 aValues = /*aCfg.*/GetProperties( aNames ); 1813 if (aValues.getLength()) 1814 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); 1815 } 1816 } 1817 else if ( 0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ) ) 1818 { 1819 OUString aNode( OUString::createFromAscii( "ServiceManager/GrammarCheckerList" )); 1820 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1821 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1822 { 1823 OUString aPropName( aNode ); 1824 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1825 aPropName += aCfgLocale; 1826 pNames[0] = aPropName; 1827 aValues = /*aCfg.*/GetProperties( aNames ); 1828 if (aValues.getLength()) 1829 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); 1830 } 1831 } 1832 else if ( 0 == rServiceName.compareToAscii( SN_HYPHENATOR ) ) 1833 { 1834 OUString aNode( OUString::createFromAscii( "ServiceManager/HyphenatorList" )); 1835 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1836 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1837 { 1838 OUString aPropName( aNode ); 1839 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1840 aPropName += aCfgLocale; 1841 pNames[0] = aPropName; 1842 aValues = /*aCfg.*/GetProperties( aNames ); 1843 if (aValues.getLength()) 1844 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); 1845 } 1846 } 1847 else if ( 0 == rServiceName.compareToAscii( SN_THESAURUS ) ) 1848 { 1849 OUString aNode( OUString::createFromAscii( "ServiceManager/ThesaurusList" )); 1850 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); 1851 if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) 1852 { 1853 OUString aPropName( aNode ); 1854 aPropName += OUString::valueOf( (sal_Unicode) '/' ); 1855 aPropName += aCfgLocale; 1856 pNames[0] = aPropName; 1857 aValues = /*aCfg.*/GetProperties( aNames ); 1858 if (aValues.getLength()) 1859 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); 1860 } 1861 } 1862 1863 #if OSL_DEBUG_LEVEL > 1 1864 const OUString *pImplNames = aSvcImplNames.getConstArray(); 1865 (void) pImplNames; 1866 #endif 1867 return aSvcImplNames; 1868 } 1869 1870 1871 void SAL_CALL 1872 LngSvcMgr::dispose() 1873 throw(uno::RuntimeException) 1874 { 1875 osl::MutexGuard aGuard( GetLinguMutex() ); 1876 1877 if (!bDisposing) 1878 { 1879 bDisposing = sal_True; 1880 1881 // require listeners to release this object 1882 lang::EventObject aEvtObj( (XLinguServiceManager *) this ); 1883 aEvtListeners.disposeAndClear( aEvtObj ); 1884 1885 if (pListenerHelper) 1886 pListenerHelper->DisposeAndClear( aEvtObj ); 1887 } 1888 } 1889 1890 1891 void SAL_CALL 1892 LngSvcMgr::addEventListener( 1893 const uno::Reference< lang::XEventListener >& xListener ) 1894 throw(uno::RuntimeException) 1895 { 1896 osl::MutexGuard aGuard( GetLinguMutex() ); 1897 1898 if (!bDisposing && xListener.is()) 1899 { 1900 aEvtListeners.addInterface( xListener ); 1901 } 1902 } 1903 1904 1905 void SAL_CALL 1906 LngSvcMgr::removeEventListener( 1907 const uno::Reference< lang::XEventListener >& xListener ) 1908 throw(uno::RuntimeException) 1909 { 1910 osl::MutexGuard aGuard( GetLinguMutex() ); 1911 1912 if (xListener.is()) 1913 { 1914 aEvtListeners.removeInterface( xListener ); 1915 } 1916 } 1917 1918 1919 sal_Bool LngSvcMgr::AddLngSvcEvtBroadcaster( 1920 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) 1921 { 1922 sal_Bool bRes = sal_False; 1923 if (rxBroadcaster.is()) 1924 { 1925 if (!pListenerHelper) 1926 GetListenerHelper_Impl(); 1927 bRes = pListenerHelper->AddLngSvcEvtBroadcaster( rxBroadcaster ); 1928 } 1929 return bRes; 1930 } 1931 1932 1933 sal_Bool LngSvcMgr::RemoveLngSvcEvtBroadcaster( 1934 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) 1935 { 1936 sal_Bool bRes = sal_False; 1937 if (rxBroadcaster.is()) 1938 { 1939 DBG_ASSERT( pListenerHelper, "pListenerHelper non existent" ); 1940 if (!pListenerHelper) 1941 GetListenerHelper_Impl(); 1942 bRes = pListenerHelper->RemoveLngSvcEvtBroadcaster( rxBroadcaster ); 1943 } 1944 return bRes; 1945 } 1946 1947 1948 OUString SAL_CALL 1949 LngSvcMgr::getImplementationName() 1950 throw(uno::RuntimeException) 1951 { 1952 osl::MutexGuard aGuard( GetLinguMutex() ); 1953 return getImplementationName_Static(); 1954 } 1955 1956 1957 sal_Bool SAL_CALL 1958 LngSvcMgr::supportsService( const OUString& ServiceName ) 1959 throw(uno::RuntimeException) 1960 { 1961 osl::MutexGuard aGuard( GetLinguMutex() ); 1962 1963 uno::Sequence< OUString > aSNL = getSupportedServiceNames(); 1964 const OUString * pArray = aSNL.getConstArray(); 1965 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 1966 if( pArray[i] == ServiceName ) 1967 return sal_True; 1968 return sal_False; 1969 } 1970 1971 1972 uno::Sequence< OUString > SAL_CALL 1973 LngSvcMgr::getSupportedServiceNames() 1974 throw(uno::RuntimeException) 1975 { 1976 osl::MutexGuard aGuard( GetLinguMutex() ); 1977 return getSupportedServiceNames_Static(); 1978 } 1979 1980 1981 uno::Sequence< OUString > LngSvcMgr::getSupportedServiceNames_Static() 1982 throw() 1983 { 1984 osl::MutexGuard aGuard( GetLinguMutex() ); 1985 1986 uno::Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich 1987 aSNS.getArray()[0] = A2OU( SN_LINGU_SERVCICE_MANAGER ); 1988 return aSNS; 1989 } 1990 1991 1992 uno::Reference< uno::XInterface > SAL_CALL LngSvcMgr_CreateInstance( 1993 const uno::Reference< lang::XMultiServiceFactory > & /*rSMgr*/ ) 1994 throw(uno::Exception) 1995 { 1996 uno::Reference< uno::XInterface > xService = (cppu::OWeakObject*) new LngSvcMgr; 1997 return xService; 1998 } 1999 2000 void * SAL_CALL LngSvcMgr_getFactory( 2001 const sal_Char * pImplName, 2002 lang::XMultiServiceFactory * pServiceManager, 2003 void * /*pRegistryKey*/ ) 2004 { 2005 2006 void * pRet = 0; 2007 if ( !LngSvcMgr::getImplementationName_Static().compareToAscii( pImplName ) ) 2008 { 2009 uno::Reference< lang::XSingleServiceFactory > xFactory = 2010 cppu::createOneInstanceFactory( 2011 pServiceManager, 2012 LngSvcMgr::getImplementationName_Static(), 2013 LngSvcMgr_CreateInstance, 2014 LngSvcMgr::getSupportedServiceNames_Static()); 2015 // acquire, because we return an interface pointer instead of a reference 2016 xFactory->acquire(); 2017 pRet = xFactory.get(); 2018 } 2019 return pRet; 2020 } 2021 2022 2023 /////////////////////////////////////////////////////////////////////////// 2024 2025