Update ooo320-m1
[ooovba.git] / linguistic / source / lngsvcmgr.cxx
blob2a70e9eeb1a5582c9e250866d67ffa65347bbc15
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: lngsvcmgr.cxx,v $
10 * $Revision: 1.32 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_linguistic.hxx"
34 #include <com/sun/star/registry/XRegistryKey.hpp>
35 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
36 #include <com/sun/star/container/XEnumeration.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/linguistic2/XSupportedLocales.hpp>
39 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
40 #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
42 #include <tools/solar.h>
43 #include <svtools/lingucfg.hxx>
44 #include <unotools/processfactory.hxx>
45 #include <i18npool/lang.h>
46 #include <i18npool/mslangid.hxx>
47 #include <cppuhelper/factory.hxx>
48 #include <cppuhelper/extract.hxx>
49 #include <rtl/logfile.hxx>
51 #include "lngsvcmgr.hxx"
52 #include "lngopt.hxx"
53 #include "misc.hxx"
54 #include "spelldsp.hxx"
55 #include "hyphdsp.hxx"
56 #include "thesdsp.hxx"
57 #include "gciterator.hxx"
60 using namespace com::sun::star;
61 using namespace linguistic;
62 using ::rtl::OUString;
64 // forward declarations
65 uno::Sequence< OUString > static GetLangSvcList( const uno::Any &rVal );
66 uno::Sequence< OUString > static GetLangSvc( const uno::Any &rVal );
68 ///////////////////////////////////////////////////////////////////////////
70 static BOOL lcl_SeqHasString( const uno::Sequence< OUString > &rSeq, const OUString &rText )
72 BOOL bRes = FALSE;
74 INT32 nLen = rSeq.getLength();
75 if (nLen == 0 || rText.getLength() == 0)
76 return bRes;
78 const OUString *pSeq = rSeq.getConstArray();
79 for (INT32 i = 0; i < nLen && !bRes; ++i)
81 if (rText == pSeq[i])
82 bRes = TRUE;
84 return bRes;
87 ///////////////////////////////////////////////////////////////////////////
89 static uno::Sequence< lang::Locale > GetAvailLocales(
90 const uno::Sequence< OUString > &rSvcImplNames )
92 uno::Sequence< lang::Locale > aRes;
94 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() );
95 INT32 nNames = rSvcImplNames.getLength();
96 if (nNames && xFac.is())
98 std::set< LanguageType > aLanguages;
100 //! since we're going to create one-instance services we have to
101 //! supply their arguments even if we would not need them here...
102 uno::Sequence< uno::Any > aArgs(2);
103 aArgs.getArray()[0] <<= GetLinguProperties();
105 // check all services for the supported languages and new
106 // languages to the result
107 const OUString *pImplNames = rSvcImplNames.getConstArray();
108 INT32 i;
110 for (i = 0; i < nNames; ++i)
112 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc;
115 xSuppLoc = uno::Reference< linguistic2::XSupportedLocales >(
116 xFac->createInstanceWithArguments( pImplNames[i], aArgs ), uno::UNO_QUERY );
118 catch (uno::Exception &)
120 DBG_ASSERT( 0, "createInstanceWithArguments failed" );
123 if (xSuppLoc.is())
125 uno::Sequence< lang::Locale > aLoc( xSuppLoc->getLocales() );
126 INT32 nLoc = aLoc.getLength();
127 for (INT32 k = 0; k < nLoc; ++k)
129 const lang::Locale *pLoc = aLoc.getConstArray();
130 LanguageType nLang = LocaleToLanguage( pLoc[k] );
132 // language not already added?
133 if (aLanguages.find( nLang ) == aLanguages.end())
134 aLanguages.insert( nLang );
137 else
139 DBG_ASSERT( 0, "interface not supported by service" );
143 // build return sequence
144 INT32 nLanguages = static_cast< INT32 >(aLanguages.size());
145 aRes.realloc( nLanguages );
146 lang::Locale *pRes = aRes.getArray();
147 std::set< LanguageType >::const_iterator aIt( aLanguages.begin() );
148 for (i = 0; aIt != aLanguages.end(); ++aIt, ++i)
150 LanguageType nLang = *aIt;
151 pRes[i] = CreateLocale( nLang );
155 return aRes;
158 ///////////////////////////////////////////////////////////////////////////
160 struct SvcInfo
162 const OUString aSvcImplName;
163 const uno::Sequence< INT16 > aSuppLanguages;
165 SvcInfo( const OUString &rSvcImplName,
166 const uno::Sequence< INT16 > &rSuppLanguages ) :
167 aSvcImplName (rSvcImplName),
168 aSuppLanguages (rSuppLanguages)
172 BOOL HasLanguage( INT16 nLanguage ) const;
176 BOOL SvcInfo::HasLanguage( INT16 nLanguage ) const
178 INT32 nCnt = aSuppLanguages.getLength();
179 const INT16 *pLang = aSuppLanguages.getConstArray();
180 INT32 i;
182 for ( i = 0; i < nCnt; ++i)
184 if (nLanguage == pLang[i])
185 break;
187 return i < nCnt;
191 ///////////////////////////////////////////////////////////////////////////
194 void LngSvcMgr::SetAvailableCfgServiceLists( LinguDispatcher &rDispatcher,
195 const SvcInfoArray &rAvailSvcs )
197 // get list of nodenames to look at for their service list
198 const char *pEntryName = 0;
199 BOOL bHasLangSvcList = TRUE;
200 switch (rDispatcher.GetDspType())
202 case LinguDispatcher::DSP_SPELL : pEntryName = "ServiceManager/SpellCheckerList"; break;
203 case LinguDispatcher::DSP_GRAMMAR : pEntryName = "ServiceManager/GrammarCheckerList";
204 bHasLangSvcList = FALSE;
205 break;
206 case LinguDispatcher::DSP_HYPH : pEntryName = "ServiceManager/HyphenatorList";
207 bHasLangSvcList = FALSE;
208 break;
209 case LinguDispatcher::DSP_THES : pEntryName = "ServiceManager/ThesaurusList"; break;
210 default :
211 DBG_ASSERT( 0, "unexpected case" );
213 String aNode( String::CreateFromAscii( pEntryName ) );
214 uno::Sequence < OUString > aNodeNames( /*aCfg.*/GetNodeNames( aNode ) );
217 INT32 nLen = aNodeNames.getLength();
218 const OUString *pNodeNames = aNodeNames.getConstArray();
219 for (INT32 i = 0; i < nLen; ++i)
221 uno::Sequence< OUString > aSvcImplNames;
223 uno::Sequence< OUString > aNames( 1 );
224 OUString *pNames = aNames.getArray();
226 OUString aPropName( aNode );
227 aPropName += OUString::valueOf( (sal_Unicode) '/' );
228 aPropName += pNodeNames[i];
229 pNames[0] = aPropName;
231 uno::Sequence< uno::Any > aValues = /*aCfg.*/GetProperties( aNames );
232 if (aValues.getLength())
234 // get list of configured service names for the
235 // current node (language)
236 const uno::Any &rValue = aValues.getConstArray()[0];
237 if (bHasLangSvcList)
238 aSvcImplNames = GetLangSvcList( rValue );
239 else
240 aSvcImplNames = GetLangSvc( rValue );
242 INT32 nSvcs = aSvcImplNames.getLength();
243 if (nSvcs)
245 const OUString *pImplNames = aSvcImplNames.getConstArray();
247 LanguageType nLang = MsLangId::convertIsoStringToLanguage( pNodeNames[i] );
249 // build list of available services from those
250 INT32 nCnt = 0;
251 uno::Sequence< OUString > aAvailSvcs( nSvcs );
252 OUString *pAvailSvcs = aAvailSvcs.getArray();
253 for (INT32 k = 0; k < nSvcs; ++k)
255 // check for availability of the service
256 size_t nAvailSvcs = rAvailSvcs.size();
257 for (size_t m = 0; m < nAvailSvcs; ++m)
259 const SvcInfo &rSvcInfo = *rAvailSvcs[m];
260 if (rSvcInfo.aSvcImplName == pImplNames[k] &&
261 rSvcInfo.HasLanguage( nLang ))
263 pAvailSvcs[ nCnt++ ] = rSvcInfo.aSvcImplName;
264 break;
269 if (nCnt)
271 aAvailSvcs.realloc( nCnt );
272 rDispatcher.SetServiceList( CreateLocale( nLang ), aAvailSvcs );
280 ///////////////////////////////////////////////////////////////////////////
283 class LngSvcMgrListenerHelper :
284 public cppu::WeakImplHelper2
286 linguistic2::XLinguServiceEventListener,
287 linguistic2::XDictionaryListEventListener
290 LngSvcMgr &rMyManager;
291 Timer aLaunchTimer;
293 //cppu::OMultiTypeInterfaceContainerHelper aListeners;
294 ::cppu::OInterfaceContainerHelper aLngSvcMgrListeners;
295 ::cppu::OInterfaceContainerHelper aLngSvcEvtBroadcasters;
296 uno::Reference< linguistic2::XDictionaryList > xDicList;
297 uno::Reference< uno::XInterface > xMyEvtObj;
299 INT16 nCombinedLngSvcEvt;
301 // disallow copy-constructor and assignment-operator for now
302 LngSvcMgrListenerHelper(const LngSvcMgrListenerHelper &);
303 LngSvcMgrListenerHelper & operator = (const LngSvcMgrListenerHelper &);
305 void LaunchEvent( INT16 nLngSvcEvtFlags );
307 DECL_LINK( TimeOut, Timer* );
309 public:
310 LngSvcMgrListenerHelper( LngSvcMgr &rLngSvcMgr,
311 const uno::Reference< uno::XInterface > &rxSource,
312 const uno::Reference< linguistic2::XDictionaryList > &rxDicList );
314 // lang::XEventListener
315 virtual void SAL_CALL
316 disposing( const lang::EventObject& rSource )
317 throw(uno::RuntimeException);
319 // linguistic2::XLinguServiceEventListener
320 virtual void SAL_CALL
321 processLinguServiceEvent( const linguistic2::LinguServiceEvent& aLngSvcEvent )
322 throw(uno::RuntimeException);
324 // linguistic2::XDictionaryListEventListener
325 virtual void SAL_CALL
326 processDictionaryListEvent(
327 const linguistic2::DictionaryListEvent& rDicListEvent )
328 throw(uno::RuntimeException);
330 inline BOOL AddLngSvcMgrListener(
331 const uno::Reference< lang::XEventListener >& rxListener );
332 inline BOOL RemoveLngSvcMgrListener(
333 const uno::Reference< lang::XEventListener >& rxListener );
334 void DisposeAndClear( const lang::EventObject &rEvtObj );
335 BOOL AddLngSvcEvtBroadcaster(
336 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster );
337 BOOL RemoveLngSvcEvtBroadcaster(
338 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster );
340 void AddLngSvcEvt( INT16 nLngSvcEvt );
344 LngSvcMgrListenerHelper::LngSvcMgrListenerHelper(
345 LngSvcMgr &rLngSvcMgr,
346 const uno::Reference< uno::XInterface > &rxSource,
347 const uno::Reference< linguistic2::XDictionaryList > &rxDicList ) :
348 rMyManager ( rLngSvcMgr ),
349 aLngSvcMgrListeners ( GetLinguMutex() ),
350 aLngSvcEvtBroadcasters ( GetLinguMutex() ),
351 xDicList ( rxDicList ),
352 xMyEvtObj ( rxSource )
354 if (xDicList.is())
356 xDicList->addDictionaryListEventListener(
357 (linguistic2::XDictionaryListEventListener *) this, FALSE );
360 //! The timer is used to 'sum up' different events in order to reduce the
361 //! number of events forwarded.
362 //! (This may happen already if a property was changed that has several
363 //! listeners, and each of them is launching an event of it's own!)
364 //! Thus this behaviour is necessary to avoid unecessary actions of
365 //! this objects listeners!
366 aLaunchTimer.SetTimeout( 2000 );
367 aLaunchTimer.SetTimeoutHdl( LINK( this, LngSvcMgrListenerHelper, TimeOut ) );
368 nCombinedLngSvcEvt = 0;
372 void SAL_CALL LngSvcMgrListenerHelper::disposing( const lang::EventObject& rSource )
373 throw(uno::RuntimeException)
375 osl::MutexGuard aGuard( GetLinguMutex() );
377 uno::Reference< uno::XInterface > xRef( rSource.Source );
378 if ( xRef.is() )
380 aLngSvcMgrListeners .removeInterface( xRef );
381 aLngSvcEvtBroadcasters.removeInterface( xRef );
382 if (xDicList == xRef)
383 xDicList = 0;
388 IMPL_LINK( LngSvcMgrListenerHelper, TimeOut, Timer*, pTimer )
390 osl::MutexGuard aGuard( GetLinguMutex() );
392 if (&aLaunchTimer == pTimer)
394 // change event source to LinguServiceManager since the listeners
395 // probably do not know (and need not to know) about the specific
396 // SpellChecker's or Hyphenator's.
397 linguistic2::LinguServiceEvent aEvtObj( xMyEvtObj, nCombinedLngSvcEvt );
398 nCombinedLngSvcEvt = 0;
400 if (rMyManager.pSpellDsp)
401 rMyManager.pSpellDsp->FlushSpellCache();
403 // pass event on to linguistic2::XLinguServiceEventListener's
404 cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners );
405 while (aIt.hasMoreElements())
407 uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY );
408 if (xRef.is())
409 xRef->processLinguServiceEvent( aEvtObj );
412 return 0;
416 void LngSvcMgrListenerHelper::AddLngSvcEvt( INT16 nLngSvcEvt )
418 nCombinedLngSvcEvt |= nLngSvcEvt;
419 aLaunchTimer.Start();
423 void SAL_CALL
424 LngSvcMgrListenerHelper::processLinguServiceEvent(
425 const linguistic2::LinguServiceEvent& rLngSvcEvent )
426 throw(uno::RuntimeException)
428 osl::MutexGuard aGuard( GetLinguMutex() );
429 AddLngSvcEvt( rLngSvcEvent.nEvent );
433 void SAL_CALL
434 LngSvcMgrListenerHelper::processDictionaryListEvent(
435 const linguistic2::DictionaryListEvent& rDicListEvent )
436 throw(uno::RuntimeException)
438 osl::MutexGuard aGuard( GetLinguMutex() );
440 INT16 nDlEvt = rDicListEvent.nCondensedEvent;
441 if (0 == nDlEvt)
442 return;
444 // we do keep the original event source here though...
446 // pass event on to linguistic2::XDictionaryListEventListener's
447 cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners );
448 while (aIt.hasMoreElements())
450 uno::Reference< linguistic2::XDictionaryListEventListener > xRef( aIt.next(), uno::UNO_QUERY );
451 if (xRef.is())
452 xRef->processDictionaryListEvent( rDicListEvent );
456 // "translate" DictionaryList event into linguistic2::LinguServiceEvent
458 INT16 nLngSvcEvt = 0;
460 INT16 nSpellCorrectFlags =
461 linguistic2::DictionaryListEventFlags::ADD_NEG_ENTRY |
462 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY |
463 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC |
464 linguistic2::DictionaryListEventFlags::DEACTIVATE_POS_DIC;
465 if (0 != (nDlEvt & nSpellCorrectFlags))
466 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN;
468 INT16 nSpellWrongFlags =
469 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY |
470 linguistic2::DictionaryListEventFlags::DEL_NEG_ENTRY |
471 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC |
472 linguistic2::DictionaryListEventFlags::DEACTIVATE_NEG_DIC;
473 if (0 != (nDlEvt & nSpellWrongFlags))
474 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN;
476 INT16 nHyphenateFlags =
477 linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY |
478 linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY |
479 linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC |
480 linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC;
481 if (0 != (nDlEvt & nHyphenateFlags))
482 nLngSvcEvt |= linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN;
484 if (rMyManager.pSpellDsp)
485 rMyManager.pSpellDsp->FlushSpellCache();
486 if (nLngSvcEvt)
487 LaunchEvent( nLngSvcEvt );
491 void LngSvcMgrListenerHelper::LaunchEvent( INT16 nLngSvcEvtFlags )
493 linguistic2::LinguServiceEvent aEvt( xMyEvtObj, nLngSvcEvtFlags );
495 // pass event on to linguistic2::XLinguServiceEventListener's
496 cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners );
497 while (aIt.hasMoreElements())
499 uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY );
500 if (xRef.is())
501 xRef->processLinguServiceEvent( aEvt );
506 inline BOOL LngSvcMgrListenerHelper::AddLngSvcMgrListener(
507 const uno::Reference< lang::XEventListener >& rxListener )
509 aLngSvcMgrListeners.addInterface( rxListener );
510 return TRUE;
514 inline BOOL LngSvcMgrListenerHelper::RemoveLngSvcMgrListener(
515 const uno::Reference< lang::XEventListener >& rxListener )
517 aLngSvcMgrListeners.removeInterface( rxListener );
518 return TRUE;
522 void LngSvcMgrListenerHelper::DisposeAndClear( const lang::EventObject &rEvtObj )
524 // call "disposing" for all listeners and clear list
525 aLngSvcMgrListeners .disposeAndClear( rEvtObj );
527 // remove references to this object hold by the broadcasters
528 cppu::OInterfaceIteratorHelper aIt( aLngSvcEvtBroadcasters );
529 while (aIt.hasMoreElements())
531 uno::Reference< linguistic2::XLinguServiceEventBroadcaster > xRef( aIt.next(), uno::UNO_QUERY );
532 if (xRef.is())
533 RemoveLngSvcEvtBroadcaster( xRef );
536 // remove refernce to this object hold by the dictionary-list
537 if (xDicList.is())
539 xDicList->removeDictionaryListEventListener(
540 (linguistic2::XDictionaryListEventListener *) this );
541 xDicList = 0;
546 BOOL LngSvcMgrListenerHelper::AddLngSvcEvtBroadcaster(
547 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
549 BOOL bRes = FALSE;
550 if (rxBroadcaster.is())
552 aLngSvcEvtBroadcasters.addInterface( rxBroadcaster );
553 rxBroadcaster->addLinguServiceEventListener(
554 (linguistic2::XLinguServiceEventListener *) this );
556 return bRes;
560 BOOL LngSvcMgrListenerHelper::RemoveLngSvcEvtBroadcaster(
561 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
563 BOOL bRes = FALSE;
564 if (rxBroadcaster.is())
566 aLngSvcEvtBroadcasters.removeInterface( rxBroadcaster );
567 rxBroadcaster->removeLinguServiceEventListener(
568 (linguistic2::XLinguServiceEventListener *) this );
570 return bRes;
574 ///////////////////////////////////////////////////////////////////////////
577 LngSvcMgr::LngSvcMgr() :
578 utl::ConfigItem( String::CreateFromAscii( "Office.Linguistic" ) ),
579 aEvtListeners ( GetLinguMutex() )
581 bHasAvailSpellLocales =
582 bHasAvailGrammarLocales =
583 bHasAvailHyphLocales =
584 bHasAvailThesLocales =
585 bDisposing = FALSE;
587 pSpellDsp = 0;
588 pGrammarDsp = 0;
589 pHyphDsp = 0;
590 pThesDsp = 0;
592 pAvailSpellSvcs = 0;
593 pAvailGrammarSvcs = 0;
594 pAvailHyphSvcs = 0;
595 pAvailThesSvcs = 0;
596 pListenerHelper = 0;
598 // request notify events when properties (i.e. something in the subtree) changes
599 uno::Sequence< OUString > aNames(4);
600 OUString *pNames = aNames.getArray();
601 pNames[0] = A2OU( "ServiceManager/SpellCheckerList" );
602 pNames[1] = A2OU( "ServiceManager/GrammarCheckerList" );
603 pNames[2] = A2OU( "ServiceManager/HyphenatorList" );
604 pNames[3] = A2OU( "ServiceManager/ThesaurusList" );
605 EnableNotification( aNames );
609 LngSvcMgr::~LngSvcMgr()
611 // memory for pSpellDsp, pHyphDsp, pThesDsp, pListenerHelper
612 // will be freed in the destructor of the respective Reference's
613 // xSpellDsp, xGrammarDsp, xHyphDsp, xThesDsp
615 delete pAvailSpellSvcs;
616 delete pAvailGrammarSvcs;
617 delete pAvailHyphSvcs;
618 delete pAvailThesSvcs;
622 void LngSvcMgr::Notify( const uno::Sequence< OUString > &rPropertyNames )
624 const OUString aSpellCheckerList( A2OU("ServiceManager/SpellCheckerList") );
625 const OUString aGrammarCheckerList( A2OU("ServiceManager/GrammarCheckerList") );
626 const OUString aHyphenatorList( A2OU("ServiceManager/HyphenatorList") );
627 const OUString aThesaurusList( A2OU("ServiceManager/ThesaurusList") );
629 const uno::Sequence< OUString > aSpellCheckerListEntries( GetNodeNames( aSpellCheckerList ) );
630 const uno::Sequence< OUString > aGrammarCheckerListEntries( GetNodeNames( aGrammarCheckerList ) );
631 const uno::Sequence< OUString > aHyphenatorListEntries( GetNodeNames( aHyphenatorList ) );
632 const uno::Sequence< OUString > aThesaurusListEntries( GetNodeNames( aThesaurusList ) );
634 uno::Sequence< uno::Any > aValues;
635 uno::Sequence< OUString > aNames( 1 );
636 OUString *pNames = aNames.getArray();
638 sal_Int32 nLen = rPropertyNames.getLength();
639 const OUString *pPropertyNames = rPropertyNames.getConstArray();
640 for (sal_Int32 i = 0; i < nLen; ++i)
642 // property names look like
643 // "ServiceManager/ThesaurusList/cfg:any['de-CH']"
645 const OUString &rName = pPropertyNames[i];
646 sal_Int32 nKeyStart, nKeyEnd;
647 nKeyStart = rName.indexOf( A2OU("['"), 0 );
648 nKeyEnd = rName.indexOf( A2OU("']"), nKeyStart + 2);
649 OUString aKeyText;
650 if (nKeyStart != -1 && nKeyEnd != -1)
651 aKeyText = rName.copy( nKeyStart + 2, nKeyEnd - nKeyStart - 2);
652 DBG_ASSERT( aKeyText.getLength() != 0, "unexpected key (lang::Locale) string" );
653 if (0 == rName.compareTo( aSpellCheckerList, aSpellCheckerList.getLength() ))
655 // delete old cached data, needs to be acquired new on demand
656 delete pAvailSpellSvcs; pAvailSpellSvcs = 0;
658 OUString aNode( aSpellCheckerList );
659 if (lcl_SeqHasString( aSpellCheckerListEntries, aKeyText ))
661 OUString aPropName( aNode );
662 aPropName += OUString::valueOf( (sal_Unicode) '/' );
663 aPropName += aKeyText;
664 pNames[0] = aPropName;
665 aValues = /*aCfg.*/GetProperties( aNames );
666 uno::Sequence< OUString > aSvcImplNames;
667 if (aValues.getLength())
668 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
670 LanguageType nLang = LANGUAGE_NONE;
671 if (0 != aKeyText.getLength())
672 nLang = MsLangId::convertIsoStringToLanguage( aKeyText );
674 GetSpellCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below
675 pSpellDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames );
678 else if (0 == rName.compareTo( aGrammarCheckerList, aGrammarCheckerList.getLength() ))
680 // delete old cached data, needs to be acquired new on demand
681 delete pAvailGrammarSvcs; pAvailGrammarSvcs = 0;
683 OUString aNode( aGrammarCheckerList );
684 if (lcl_SeqHasString( aGrammarCheckerListEntries, aKeyText ))
686 OUString aPropName( aNode );
687 aPropName += OUString::valueOf( (sal_Unicode) '/' );
688 aPropName += aKeyText;
689 pNames[0] = aPropName;
690 aValues = /*aCfg.*/GetProperties( aNames );
691 uno::Sequence< OUString > aSvcImplNames;
692 if (aValues.getLength())
693 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
695 LanguageType nLang = LANGUAGE_NONE;
696 if (0 != aKeyText.getLength())
697 nLang = MsLangId::convertIsoStringToLanguage( aKeyText );
699 if (SvtLinguConfig().HasGrammarChecker())
701 GetGrammarCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below
702 pGrammarDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames );
706 else if (0 == rName.compareTo( aHyphenatorList, aHyphenatorList.getLength() ))
708 // delete old cached data, needs to be acquired new on demand
709 delete pAvailHyphSvcs; pAvailHyphSvcs = 0;
711 OUString aNode( aHyphenatorList );
712 if (lcl_SeqHasString( aHyphenatorListEntries, aKeyText ))
714 OUString aPropName( aNode );
715 aPropName += OUString::valueOf( (sal_Unicode) '/' );
716 aPropName += aKeyText;
717 pNames[0] = aPropName;
718 aValues = /*aCfg.*/GetProperties( aNames );
719 uno::Sequence< OUString > aSvcImplNames;
720 if (aValues.getLength())
721 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
723 LanguageType nLang = LANGUAGE_NONE;
724 if (0 != aKeyText.getLength())
725 nLang = MsLangId::convertIsoStringToLanguage( aKeyText );
727 GetHyphenatorDsp_Impl( sal_False ); // don't set service list, it will be done below
728 pHyphDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames );
731 else if (0 == rName.compareTo( aThesaurusList, aThesaurusList.getLength() ))
733 // delete old cached data, needs to be acquired new on demand
734 delete pAvailThesSvcs; pAvailThesSvcs = 0;
736 OUString aNode( aThesaurusList );
737 if (lcl_SeqHasString( aThesaurusListEntries, aKeyText ))
739 OUString aPropName( aNode );
740 aPropName += OUString::valueOf( (sal_Unicode) '/' );
741 aPropName += aKeyText;
742 pNames[0] = aPropName;
743 aValues = /*aCfg.*/GetProperties( aNames );
744 uno::Sequence< OUString > aSvcImplNames;
745 if (aValues.getLength())
746 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
748 LanguageType nLang = LANGUAGE_NONE;
749 if (0 != aKeyText.getLength())
750 nLang = MsLangId::convertIsoStringToLanguage( aKeyText );
752 GetThesaurusDsp_Impl( sal_False ); // don't set service list, it will be done below
753 pThesDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames );
756 else
758 DBG_ASSERT( 0, "nofified for unexpected property" );
764 void LngSvcMgr::Commit()
766 // everything necessary should have already been done by 'SaveCfgSvcs'
767 // called from within 'setConfiguredServices'.
768 // Also this class usually exits only when the Office i sbeing shutdown.
772 void LngSvcMgr::GetListenerHelper_Impl()
774 if (!pListenerHelper)
776 pListenerHelper = new LngSvcMgrListenerHelper( *this,
777 (XLinguServiceManager *) this, linguistic::GetDictionaryList() );
778 xListenerHelper = (linguistic2::XLinguServiceEventListener *) pListenerHelper;
783 void LngSvcMgr::GetSpellCheckerDsp_Impl( sal_Bool bSetSvcList )
785 if (!pSpellDsp)
787 pSpellDsp = new SpellCheckerDispatcher( *this );
788 xSpellDsp = pSpellDsp;
789 if (bSetSvcList)
790 SetCfgServiceLists( *pSpellDsp );
795 void LngSvcMgr::GetGrammarCheckerDsp_Impl( sal_Bool bSetSvcList )
797 if (!pGrammarDsp && SvtLinguConfig().HasGrammarChecker())
799 //! since the grammar checking iterator needs to be a one instance service
800 //! we need to create it the correct way!
801 uno::Reference< linguistic2::XProofreadingIterator > xGCI;
804 uno::Reference< lang::XMultiServiceFactory > xMgr(
805 utl::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
806 xGCI = uno::Reference< linguistic2::XProofreadingIterator >(
807 xMgr->createInstance( A2OU( SN_GRAMMARCHECKINGITERATOR ) ), uno::UNO_QUERY_THROW );
809 catch (uno::Exception &)
812 DBG_ASSERT( xGCI.is(), "instantiating grammar checking iterator failed" );
814 if (xGCI.is())
816 pGrammarDsp = dynamic_cast< GrammarCheckingIterator * >(xGCI.get());
817 xGrammarDsp = xGCI;
818 DBG_ASSERT( pGrammarDsp, "failed to get implementation" );
819 if (bSetSvcList)
820 SetCfgServiceLists( *pGrammarDsp );
826 void LngSvcMgr::GetHyphenatorDsp_Impl( sal_Bool bSetSvcList )
828 if (!pHyphDsp)
830 pHyphDsp = new HyphenatorDispatcher( *this );
831 xHyphDsp = pHyphDsp;
832 if (bSetSvcList)
833 SetCfgServiceLists( *pHyphDsp );
838 void LngSvcMgr::GetThesaurusDsp_Impl( sal_Bool bSetSvcList )
840 if (!pThesDsp)
842 pThesDsp = new ThesaurusDispatcher;
843 xThesDsp = pThesDsp;
844 if (bSetSvcList)
845 SetCfgServiceLists( *pThesDsp );
850 void LngSvcMgr::GetAvailableSpellSvcs_Impl()
852 if (!pAvailSpellSvcs)
854 pAvailSpellSvcs = new SvcInfoArray;
856 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() );
857 if (xFac.is())
859 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
860 uno::Reference< container::XEnumeration > xEnum;
861 if (xEnumAccess.is())
862 xEnum = xEnumAccess->createContentEnumeration(
863 A2OU( SN_SPELLCHECKER ) );
865 if (xEnum.is())
867 while (xEnum->hasMoreElements())
869 uno::Any aCurrent = xEnum->nextElement();
870 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
871 uno::Reference< lang::XSingleServiceFactory > xFactory;
873 uno::Reference< linguistic2::XSpellChecker > xSvc;
874 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
878 uno::Reference < uno::XComponentContext > xContext;
879 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY );
881 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
882 xSvc = uno::Reference< linguistic2::XSpellChecker >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
884 catch (uno::Exception &rEx)
886 (void) rEx;
887 DBG_ASSERT( 0, "createInstance failed" );
891 if (xSvc.is())
893 OUString aImplName;
894 uno::Sequence< INT16 > aLanguages;
895 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
896 if (xInfo.is())
897 aImplName = xInfo->getImplementationName();
898 DBG_ASSERT( aImplName.getLength(),
899 "empty implementation name" );
900 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
901 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
902 if (xSuppLoc.is()) {
903 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
904 aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
907 pAvailSpellSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
916 void LngSvcMgr::GetAvailableGrammarSvcs_Impl()
918 if (!pAvailGrammarSvcs)
920 pAvailGrammarSvcs = new SvcInfoArray;
922 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() );
923 if (xFac.is())
925 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
926 uno::Reference< container::XEnumeration > xEnum;
927 if (xEnumAccess.is())
928 xEnum = xEnumAccess->createContentEnumeration(
929 A2OU( SN_GRAMMARCHECKER ) );
931 if (xEnum.is())
933 while (xEnum->hasMoreElements())
935 uno::Any aCurrent = xEnum->nextElement();
936 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
937 uno::Reference< lang::XSingleServiceFactory > xFactory;
939 uno::Reference< linguistic2::XProofreader > xSvc;
940 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
944 uno::Reference < uno::XComponentContext > xContext;
945 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY );
947 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
948 xSvc = uno::Reference< linguistic2::XProofreader >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
950 catch (uno::Exception &rEx)
952 (void) rEx;
953 DBG_ASSERT( 0, "createInstance failed" );
957 if (xSvc.is())
959 OUString aImplName;
960 uno::Sequence< INT16 > aLanguages;
961 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
962 if (xInfo.is())
963 aImplName = xInfo->getImplementationName();
964 DBG_ASSERT( aImplName.getLength(),
965 "empty implementation name" );
966 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
967 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
968 if (xSuppLoc.is()) {
969 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
970 aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
973 pAvailGrammarSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
982 void LngSvcMgr::GetAvailableHyphSvcs_Impl()
984 if (!pAvailHyphSvcs)
986 pAvailHyphSvcs = new SvcInfoArray;
987 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() );
988 if (xFac.is())
990 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
991 uno::Reference< container::XEnumeration > xEnum;
992 if (xEnumAccess.is())
993 xEnum = xEnumAccess->createContentEnumeration( A2OU( SN_HYPHENATOR ) );
995 if (xEnum.is())
997 while (xEnum->hasMoreElements())
999 uno::Any aCurrent = xEnum->nextElement();
1000 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1001 uno::Reference< lang::XSingleServiceFactory > xFactory;
1003 uno::Reference< linguistic2::XHyphenator > xSvc;
1004 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1008 uno::Reference < uno::XComponentContext > xContext;
1009 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY );
1011 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
1012 xSvc = uno::Reference< linguistic2::XHyphenator >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
1015 catch (uno::Exception &rEx)
1017 (void) rEx;
1018 DBG_ASSERT( 0, "createInstance failed" );
1022 if (xSvc.is())
1024 OUString aImplName;
1025 uno::Sequence< INT16 > aLanguages;
1026 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1027 if (xInfo.is())
1028 aImplName = xInfo->getImplementationName();
1029 DBG_ASSERT( aImplName.getLength(),
1030 "empty implementation name" );
1031 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1032 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1033 if (xSuppLoc.is()) {
1034 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1035 aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1038 pAvailHyphSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1047 void LngSvcMgr::GetAvailableThesSvcs_Impl()
1049 if (!pAvailThesSvcs)
1051 pAvailThesSvcs = new SvcInfoArray;
1053 uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() );
1054 if (xFac.is())
1056 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY );
1057 uno::Reference< container::XEnumeration > xEnum;
1058 if (xEnumAccess.is())
1059 xEnum = xEnumAccess->createContentEnumeration(
1060 A2OU( SN_THESAURUS ) );
1062 if (xEnum.is())
1064 while (xEnum->hasMoreElements())
1066 uno::Any aCurrent = xEnum->nextElement();
1068 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1069 uno::Reference< lang::XSingleServiceFactory > xFactory;
1071 uno::Reference< linguistic2::XThesaurus > xSvc;
1072 if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) )
1076 uno::Reference < uno::XComponentContext > xContext;
1077 uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY );
1079 xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
1080 xSvc = uno::Reference< linguistic2::XThesaurus >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
1082 catch (uno::Exception &rEx)
1084 (void) rEx;
1085 DBG_ASSERT( 0, "createInstance failed" );
1089 if (xSvc.is())
1091 OUString aImplName;
1092 uno::Sequence< INT16 > aLanguages;
1093 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1094 if (xInfo.is())
1095 aImplName = xInfo->getImplementationName();
1096 DBG_ASSERT( aImplName.getLength(),
1097 "empty implementation name" );
1098 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1099 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1100 if (xSuppLoc.is()) {
1101 uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales());
1102 aLanguages = LocaleSeqToLangSeq( aLocaleSequence );
1105 pAvailThesSvcs->push_back( new SvcInfo( aImplName, aLanguages ) );
1114 void LngSvcMgr::SetCfgServiceLists( SpellCheckerDispatcher &rSpellDsp )
1116 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Spell" );
1118 String aNode( String::CreateFromAscii( "ServiceManager/SpellCheckerList" ) );
1119 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1120 OUString *pNames = aNames.getArray();
1121 INT32 nLen = aNames.getLength();
1123 // append path prefix need for 'GetProperties' call below
1124 String aPrefix( aNode );
1125 aPrefix.Append( (sal_Unicode) '/' );
1126 for (int i = 0; i < nLen; ++i)
1128 OUString aTmp( aPrefix );
1129 aTmp += pNames[i];
1130 pNames[i] = aTmp;
1133 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1134 if (nLen && nLen == aValues.getLength())
1136 const uno::Any *pValues = aValues.getConstArray();
1137 for (INT32 i = 0; i < nLen; ++i)
1139 uno::Sequence< OUString > aSvcImplNames;
1140 if (pValues[i] >>= aSvcImplNames)
1142 #if OSL_DEBUG_LEVEL > 1
1143 // INT32 nSvcs = aSvcImplNames.getLength();
1144 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray();
1145 #endif
1146 String aLocaleStr( pNames[i] );
1147 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1148 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1149 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) );
1150 rSpellDsp.SetServiceList( aLocale, aSvcImplNames );
1157 void LngSvcMgr::SetCfgServiceLists( GrammarCheckingIterator &rGrammarDsp )
1159 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Grammar" );
1161 String aNode( String::CreateFromAscii( "ServiceManager/GrammarCheckerList" ) );
1162 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1163 OUString *pNames = aNames.getArray();
1164 INT32 nLen = aNames.getLength();
1166 // append path prefix need for 'GetProperties' call below
1167 String aPrefix( aNode );
1168 aPrefix.Append( (sal_Unicode) '/' );
1169 for (int i = 0; i < nLen; ++i)
1171 OUString aTmp( aPrefix );
1172 aTmp += pNames[i];
1173 pNames[i] = aTmp;
1176 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1177 if (nLen && nLen == aValues.getLength())
1179 const uno::Any *pValues = aValues.getConstArray();
1180 for (INT32 i = 0; i < nLen; ++i)
1182 uno::Sequence< OUString > aSvcImplNames;
1183 if (pValues[i] >>= aSvcImplNames)
1185 // there should only be one grammar checker in use per language...
1186 if (aSvcImplNames.getLength() > 1)
1187 aSvcImplNames.realloc(1);
1189 #if OSL_DEBUG_LEVEL > 1
1190 // INT32 nSvcs = aSvcImplNames.getLength();
1191 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray();
1192 #endif
1193 String aLocaleStr( pNames[i] );
1194 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1195 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1196 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) );
1197 rGrammarDsp.SetServiceList( aLocale, aSvcImplNames );
1204 void LngSvcMgr::SetCfgServiceLists( HyphenatorDispatcher &rHyphDsp )
1206 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Hyph" );
1208 String aNode( String::CreateFromAscii( "ServiceManager/HyphenatorList" ) );
1209 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1210 OUString *pNames = aNames.getArray();
1211 INT32 nLen = aNames.getLength();
1213 // append path prefix need for 'GetProperties' call below
1214 String aPrefix( aNode );
1215 aPrefix.Append( (sal_Unicode) '/' );
1216 for (int i = 0; i < nLen; ++i)
1218 OUString aTmp( aPrefix );
1219 aTmp += pNames[i];
1220 pNames[i] = aTmp;
1223 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1224 if (nLen && nLen == aValues.getLength())
1226 const uno::Any *pValues = aValues.getConstArray();
1227 for (INT32 i = 0; i < nLen; ++i)
1229 uno::Sequence< OUString > aSvcImplNames;
1230 if (pValues[i] >>= aSvcImplNames)
1232 // there should only be one hyphenator in use per language...
1233 if (aSvcImplNames.getLength() > 1)
1234 aSvcImplNames.realloc(1);
1236 #if OSL_DEBUG_LEVEL > 1
1237 // INT32 nSvcs = aSvcImplNames.getLength();
1238 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray();
1239 #endif
1240 String aLocaleStr( pNames[i] );
1241 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1242 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1243 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) );
1244 rHyphDsp.SetServiceList( aLocale, aSvcImplNames );
1251 void LngSvcMgr::SetCfgServiceLists( ThesaurusDispatcher &rThesDsp )
1253 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Thes" );
1255 String aNode( String::CreateFromAscii( "ServiceManager/ThesaurusList" ) );
1256 uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) );
1257 OUString *pNames = aNames.getArray();
1258 INT32 nLen = aNames.getLength();
1260 // append path prefix need for 'GetProperties' call below
1261 String aPrefix( aNode );
1262 aPrefix.Append( (sal_Unicode) '/' );
1263 for (int i = 0; i < nLen; ++i)
1265 OUString aTmp( aPrefix );
1266 aTmp += pNames[i];
1267 pNames[i] = aTmp;
1270 uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) );
1271 if (nLen && nLen == aValues.getLength())
1273 const uno::Any *pValues = aValues.getConstArray();
1274 for (INT32 i = 0; i < nLen; ++i)
1276 uno::Sequence< OUString > aSvcImplNames;
1277 if (pValues[i] >>= aSvcImplNames)
1279 #if OSL_DEBUG_LEVEL > 1
1280 // INT32 nSvcs = aSvcImplNames.getLength();
1281 // const OUString *pSvcImplNames = aSvcImplNames.getConstArray();
1282 #endif
1283 String aLocaleStr( pNames[i] );
1284 xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) );
1285 aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 );
1286 lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) );
1287 rThesDsp.SetServiceList( aLocale, aSvcImplNames );
1294 uno::Reference< linguistic2::XSpellChecker > SAL_CALL
1295 LngSvcMgr::getSpellChecker()
1296 throw(uno::RuntimeException)
1298 osl::MutexGuard aGuard( GetLinguMutex() );
1299 #if OSL_DEBUG_LEVEL > 1
1300 getAvailableLocales( A2OU( SN_SPELLCHECKER ));
1301 #endif
1303 uno::Reference< linguistic2::XSpellChecker > xRes;
1304 if (!bDisposing)
1306 if (!xSpellDsp.is())
1307 GetSpellCheckerDsp_Impl();
1308 xRes = xSpellDsp;
1310 return xRes;
1314 uno::Reference< linguistic2::XHyphenator > SAL_CALL
1315 LngSvcMgr::getHyphenator()
1316 throw(uno::RuntimeException)
1318 osl::MutexGuard aGuard( GetLinguMutex() );
1319 #if OSL_DEBUG_LEVEL > 1
1320 getAvailableLocales( A2OU( SN_HYPHENATOR ));
1321 #endif
1323 uno::Reference< linguistic2::XHyphenator > xRes;
1324 if (!bDisposing)
1326 if (!xHyphDsp.is())
1327 GetHyphenatorDsp_Impl();
1328 xRes = xHyphDsp;
1330 return xRes;
1334 uno::Reference< linguistic2::XThesaurus > SAL_CALL
1335 LngSvcMgr::getThesaurus()
1336 throw(uno::RuntimeException)
1338 osl::MutexGuard aGuard( GetLinguMutex() );
1339 #if OSL_DEBUG_LEVEL > 1
1340 getAvailableLocales( A2OU( SN_THESAURUS ));
1341 #endif
1343 uno::Reference< linguistic2::XThesaurus > xRes;
1344 if (!bDisposing)
1346 if (!xThesDsp.is())
1347 GetThesaurusDsp_Impl();
1348 xRes = xThesDsp;
1350 return xRes;
1354 sal_Bool SAL_CALL
1355 LngSvcMgr::addLinguServiceManagerListener(
1356 const uno::Reference< lang::XEventListener >& xListener )
1357 throw(uno::RuntimeException)
1359 osl::MutexGuard aGuard( GetLinguMutex() );
1361 BOOL bRes = FALSE;
1362 if (!bDisposing && xListener.is())
1364 if (!pListenerHelper)
1365 GetListenerHelper_Impl();
1366 bRes = pListenerHelper->AddLngSvcMgrListener( xListener );
1368 return bRes;
1372 sal_Bool SAL_CALL
1373 LngSvcMgr::removeLinguServiceManagerListener(
1374 const uno::Reference< lang::XEventListener >& xListener )
1375 throw(uno::RuntimeException)
1377 osl::MutexGuard aGuard( GetLinguMutex() );
1379 BOOL bRes = FALSE;
1380 if (!bDisposing && xListener.is())
1382 DBG_ASSERT( pListenerHelper, "listener removed without being added" );
1383 if (!pListenerHelper)
1384 GetListenerHelper_Impl();
1385 bRes = pListenerHelper->RemoveLngSvcMgrListener( xListener );
1387 return bRes;
1391 uno::Sequence< OUString > SAL_CALL
1392 LngSvcMgr::getAvailableServices(
1393 const OUString& rServiceName,
1394 const lang::Locale& rLocale )
1395 throw(uno::RuntimeException)
1397 osl::MutexGuard aGuard( GetLinguMutex() );
1399 uno::Sequence< OUString > aRes;
1400 const SvcInfoArray *pInfoArray = 0;
1402 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1404 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries
1405 // already found without the need to restart the office
1406 delete pAvailSpellSvcs; pAvailSpellSvcs = 0;
1407 GetAvailableSpellSvcs_Impl();
1408 pInfoArray = pAvailSpellSvcs;
1410 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1412 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries
1413 // already found without the need to restart the office
1414 delete pAvailGrammarSvcs; pAvailGrammarSvcs = 0;
1415 GetAvailableGrammarSvcs_Impl();
1416 pInfoArray = pAvailGrammarSvcs;
1418 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1420 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries
1421 // already found without the need to restart the office
1422 delete pAvailHyphSvcs; pAvailHyphSvcs = 0;
1423 GetAvailableHyphSvcs_Impl();
1424 pInfoArray = pAvailHyphSvcs;
1426 else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1428 // don't used cached data here (force re-evaluation in order to have downloaded dictionaries
1429 // already found without the need to restart the office
1430 delete pAvailThesSvcs; pAvailThesSvcs = 0;
1431 GetAvailableThesSvcs_Impl();
1432 pInfoArray = pAvailThesSvcs;
1435 if (pInfoArray)
1437 // resize to max number of entries
1438 size_t nMaxCnt = pInfoArray->size();
1439 aRes.realloc( nMaxCnt );
1440 OUString *pImplName = aRes.getArray();
1442 USHORT nCnt = 0;
1443 LanguageType nLanguage = LocaleToLanguage( rLocale );
1444 for (size_t i = 0; i < nMaxCnt; ++i)
1446 const SvcInfo *pInfo = (*pInfoArray)[i];
1447 if (LANGUAGE_NONE == nLanguage
1448 || (pInfo && pInfo->HasLanguage( nLanguage )))
1450 pImplName[ nCnt++ ] = pInfo->aSvcImplName;
1454 // resize to actual number of entries
1455 if (nCnt != nMaxCnt)
1456 aRes.realloc( nCnt );
1459 return aRes;
1463 uno::Sequence< lang::Locale > SAL_CALL
1464 LngSvcMgr::getAvailableLocales(
1465 const OUString& rServiceName )
1466 throw(uno::RuntimeException)
1468 osl::MutexGuard aGuard( GetLinguMutex() );
1470 uno::Sequence< lang::Locale > aRes;
1472 uno::Sequence< lang::Locale > *pAvailLocales = NULL;
1473 BOOL *pHasAvailLocales = NULL;
1474 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1476 pAvailLocales = &aAvailSpellLocales;
1477 pHasAvailLocales = &bHasAvailSpellLocales;
1479 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1481 pAvailLocales = &aAvailGrammarLocales;
1482 pHasAvailLocales = &bHasAvailGrammarLocales;
1484 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1486 pAvailLocales = &aAvailHyphLocales;
1487 pHasAvailLocales = &bHasAvailHyphLocales;
1489 else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1491 pAvailLocales = &aAvailThesLocales;
1492 pHasAvailLocales = &bHasAvailThesLocales;
1495 // about pHasAvailLocales: nowadays (with OOo lingu in SO) we want to know immediately about
1496 // new downloaded dictionaries and have them ready right away if the Tools/Options...
1497 // is used to activate them. Thus we can not rely anymore on buffered data.
1498 if (pAvailLocales /*&& pHasAvailLocales */)
1500 // if (!*pHasAvailLocales)
1501 // {
1502 *pAvailLocales = GetAvailLocales(
1503 getAvailableServices( rServiceName, lang::Locale() ) );
1504 // *pHasAvailLocales = TRUE;
1505 // }
1506 aRes = *pAvailLocales;
1509 return aRes;
1512 static BOOL IsEqSvcList( const uno::Sequence< OUString > &rList1,
1513 const uno::Sequence< OUString > &rList2 )
1515 // returns TRUE iff both sequences are equal
1517 BOOL bRes = FALSE;
1518 INT32 nLen = rList1.getLength();
1519 if (rList2.getLength() == nLen)
1521 const OUString *pStr1 = rList1.getConstArray();
1522 const OUString *pStr2 = rList2.getConstArray();
1523 bRes = TRUE;
1524 for (INT32 i = 0; i < nLen && bRes; ++i)
1526 if (*pStr1++ != *pStr2++)
1527 bRes = FALSE;
1530 return bRes;
1534 void SAL_CALL
1535 LngSvcMgr::setConfiguredServices(
1536 const OUString& rServiceName,
1537 const lang::Locale& rLocale,
1538 const uno::Sequence< OUString >& rServiceImplNames )
1539 throw(uno::RuntimeException)
1541 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::setConfiguredServices" );
1543 osl::MutexGuard aGuard( GetLinguMutex() );
1545 #if OSL_DEBUG_LEVEL > 1
1546 // const OUString *pImplNames = rServiceImplNames.getConstArray();
1547 #endif
1549 LanguageType nLanguage = LocaleToLanguage( rLocale );
1550 if (LANGUAGE_NONE != nLanguage)
1552 if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER ))
1554 if (!xSpellDsp.is())
1555 GetSpellCheckerDsp_Impl();
1556 BOOL bChanged = !IsEqSvcList( rServiceImplNames,
1557 pSpellDsp->GetServiceList( rLocale ) );
1558 if (bChanged)
1560 pSpellDsp->SetServiceList( rLocale, rServiceImplNames );
1561 SaveCfgSvcs( A2OU( SN_SPELLCHECKER ) );
1563 if (pListenerHelper && bChanged)
1564 pListenerHelper->AddLngSvcEvt(
1565 linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN |
1566 linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN );
1569 else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ))
1571 if (!xGrammarDsp.is())
1572 GetGrammarCheckerDsp_Impl();
1573 BOOL bChanged = !IsEqSvcList( rServiceImplNames,
1574 pGrammarDsp->GetServiceList( rLocale ) );
1575 if (bChanged)
1577 pGrammarDsp->SetServiceList( rLocale, rServiceImplNames );
1578 SaveCfgSvcs( A2OU( SN_GRAMMARCHECKER ) );
1580 if (pListenerHelper && bChanged)
1581 pListenerHelper->AddLngSvcEvt(
1582 linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN );
1585 else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR ))
1587 if (!xHyphDsp.is())
1588 GetHyphenatorDsp_Impl();
1589 BOOL bChanged = !IsEqSvcList( rServiceImplNames,
1590 pHyphDsp->GetServiceList( rLocale ) );
1591 if (bChanged)
1593 pHyphDsp->SetServiceList( rLocale, rServiceImplNames );
1594 SaveCfgSvcs( A2OU( SN_HYPHENATOR ) );
1596 if (pListenerHelper && bChanged)
1597 pListenerHelper->AddLngSvcEvt(
1598 linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN );
1601 else if (0 == rServiceName.compareToAscii( SN_THESAURUS ))
1603 if (!xThesDsp.is())
1604 GetThesaurusDsp_Impl();
1605 BOOL bChanged = !IsEqSvcList( rServiceImplNames,
1606 pThesDsp->GetServiceList( rLocale ) );
1607 if (bChanged)
1609 pThesDsp->SetServiceList( rLocale, rServiceImplNames );
1610 SaveCfgSvcs( A2OU( SN_THESAURUS ) );
1617 BOOL LngSvcMgr::SaveCfgSvcs( const String &rServiceName )
1619 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs" );
1621 BOOL bRes = FALSE;
1623 LinguDispatcher *pDsp = 0;
1624 uno::Sequence< lang::Locale > aLocales;
1626 if (0 == rServiceName.CompareToAscii( SN_SPELLCHECKER ))
1628 if (!pSpellDsp)
1629 GetSpellCheckerDsp_Impl();
1630 pDsp = pSpellDsp;
1631 aLocales = getAvailableLocales( A2OU( SN_SPELLCHECKER ) );
1633 else if (0 == rServiceName.CompareToAscii( SN_GRAMMARCHECKER ))
1635 if (!pGrammarDsp)
1636 GetGrammarCheckerDsp_Impl();
1637 pDsp = pGrammarDsp;
1638 aLocales = getAvailableLocales( A2OU( SN_GRAMMARCHECKER ) );
1640 else if (0 == rServiceName.CompareToAscii( SN_HYPHENATOR ))
1642 if (!pHyphDsp)
1643 GetHyphenatorDsp_Impl();
1644 pDsp = pHyphDsp;
1645 aLocales = getAvailableLocales( A2OU( SN_HYPHENATOR ) );
1647 else if (0 == rServiceName.CompareToAscii( SN_THESAURUS ))
1649 if (!pThesDsp)
1650 GetThesaurusDsp_Impl();
1651 pDsp = pThesDsp;
1652 aLocales = getAvailableLocales( A2OU( SN_THESAURUS ) );
1655 if (pDsp && aLocales.getLength())
1657 INT32 nLen = aLocales.getLength();
1658 const lang::Locale *pLocale = aLocales.getConstArray();
1660 uno::Sequence< beans::PropertyValue > aValues( nLen );
1661 beans::PropertyValue *pValues = aValues.getArray();
1662 beans::PropertyValue *pValue = pValues;
1664 // get node name to be used
1665 const char *pNodeName = NULL;
1666 if (pDsp == pSpellDsp)
1667 pNodeName = "ServiceManager/SpellCheckerList";
1668 else if (pDsp == pGrammarDsp)
1669 pNodeName = "ServiceManager/GrammarCheckerList";
1670 else if (pDsp == pHyphDsp)
1671 pNodeName = "ServiceManager/HyphenatorList";
1672 else if (pDsp == pThesDsp)
1673 pNodeName = "ServiceManager/ThesaurusList";
1674 else
1676 DBG_ASSERT( 0, "node name missing" );
1678 OUString aNodeName( A2OU(pNodeName) );
1680 for (INT32 i = 0; i < nLen; ++i)
1682 uno::Sequence< OUString > aSvcImplNames;
1683 aSvcImplNames = pDsp->GetServiceList( pLocale[i] );
1685 #if OSL_DEBUG_LEVEL > 1
1686 INT32 nSvcs = aSvcImplNames.getLength();
1687 const OUString *pSvcImplName = aSvcImplNames.getConstArray();
1688 for (INT32 j = 0; j < nSvcs; ++j)
1690 OUString aImplName( pSvcImplName[j] );
1692 #endif
1693 // build value to be written back to configuration
1694 uno::Any aCfgAny;
1695 if ((pDsp == pHyphDsp || pDsp == pGrammarDsp) && aSvcImplNames.getLength() > 1)
1696 aSvcImplNames.realloc(1); // there should be only one entry for hyphenators or grammar checkers (because they are not chained)
1697 aCfgAny <<= aSvcImplNames;
1698 DBG_ASSERT( aCfgAny.hasValue(), "missing value for 'Any' type" );
1700 OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString(
1701 LocaleToLanguage( pLocale[i] ) ) );
1702 pValue->Value = aCfgAny;
1703 pValue->Name = aNodeName;
1704 pValue->Name += OUString::valueOf( (sal_Unicode) '/' );
1705 pValue->Name += aCfgLocaleStr;
1706 pValue++;
1709 RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs - ReplaceSetProperties" );
1710 // change, add new or replace existing entries.
1711 bRes |= /*aCfg.*/ReplaceSetProperties( aNodeName, aValues );
1715 return bRes;
1719 static uno::Sequence< OUString > GetLangSvcList( const uno::Any &rVal )
1721 uno::Sequence< OUString > aRes;
1723 if (rVal.hasValue())
1725 rVal >>= aRes;
1726 #if OSL_DEBUG_LEVEL > 1
1727 INT32 nSvcs = aRes.getLength();
1728 if (nSvcs)
1730 const OUString *pSvcName = aRes.getConstArray();
1731 for (INT32 j = 0; j < nSvcs; ++j)
1733 OUString aImplName( pSvcName[j] );
1734 DBG_ASSERT( aImplName.getLength(), "service impl-name missing" );
1737 #endif
1740 return aRes;
1744 static uno::Sequence< OUString > GetLangSvc( const uno::Any &rVal )
1746 uno::Sequence< OUString > aRes;
1747 if (!rVal.hasValue())
1748 return aRes;
1750 // allowing for a sequence here as well (even though it should only
1751 // be a string) makes coding easier in other places since one needs
1752 // not make a special case for writing a string only and not a
1753 // sequence of strings.
1754 if (rVal >>= aRes)
1756 // but only the first string should be used.
1757 if (aRes.getLength() > 1)
1758 aRes.realloc(1);
1760 else
1762 OUString aImplName;
1763 if ((rVal >>= aImplName) && aImplName.getLength() != 0)
1765 aRes.realloc(1);
1766 aRes.getArray()[0] = aImplName;
1768 else
1770 DBG_ASSERT( 0, "GetLangSvc: unexpected type encountered" );
1774 return aRes;
1778 ///////////////////////////////////////////////////////////////////////////
1780 uno::Sequence< OUString > SAL_CALL
1781 LngSvcMgr::getConfiguredServices(
1782 const OUString& rServiceName,
1783 const lang::Locale& rLocale )
1784 throw(uno::RuntimeException)
1786 osl::MutexGuard aGuard( GetLinguMutex() );
1788 uno::Sequence< OUString > aSvcImplNames;
1790 LanguageType nLanguage = LocaleToLanguage( rLocale );
1791 OUString aCfgLocale( MsLangId::convertLanguageToIsoString( nLanguage ) );
1793 uno::Sequence< uno::Any > aValues;
1794 uno::Sequence< OUString > aNames( 1 );
1795 OUString *pNames = aNames.getArray();
1796 if ( 0 == rServiceName.compareToAscii( SN_SPELLCHECKER ) )
1798 OUString aNode( OUString::createFromAscii( "ServiceManager/SpellCheckerList" ));
1799 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1800 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1802 OUString aPropName( aNode );
1803 aPropName += OUString::valueOf( (sal_Unicode) '/' );
1804 aPropName += aCfgLocale;
1805 pNames[0] = aPropName;
1806 aValues = /*aCfg.*/GetProperties( aNames );
1807 if (aValues.getLength())
1808 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
1811 else if ( 0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ) )
1813 OUString aNode( OUString::createFromAscii( "ServiceManager/GrammarCheckerList" ));
1814 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1815 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1817 OUString aPropName( aNode );
1818 aPropName += OUString::valueOf( (sal_Unicode) '/' );
1819 aPropName += aCfgLocale;
1820 pNames[0] = aPropName;
1821 aValues = /*aCfg.*/GetProperties( aNames );
1822 if (aValues.getLength())
1823 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
1826 else if ( 0 == rServiceName.compareToAscii( SN_HYPHENATOR ) )
1828 OUString aNode( OUString::createFromAscii( "ServiceManager/HyphenatorList" ));
1829 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1830 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1832 OUString aPropName( aNode );
1833 aPropName += OUString::valueOf( (sal_Unicode) '/' );
1834 aPropName += aCfgLocale;
1835 pNames[0] = aPropName;
1836 aValues = /*aCfg.*/GetProperties( aNames );
1837 if (aValues.getLength())
1838 aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] );
1841 else if ( 0 == rServiceName.compareToAscii( SN_THESAURUS ) )
1843 OUString aNode( OUString::createFromAscii( "ServiceManager/ThesaurusList" ));
1844 const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) );
1845 if (lcl_SeqHasString( aNodeEntries, aCfgLocale ))
1847 OUString aPropName( aNode );
1848 aPropName += OUString::valueOf( (sal_Unicode) '/' );
1849 aPropName += aCfgLocale;
1850 pNames[0] = aPropName;
1851 aValues = /*aCfg.*/GetProperties( aNames );
1852 if (aValues.getLength())
1853 aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] );
1857 #if OSL_DEBUG_LEVEL > 1
1858 const OUString *pImplNames = aSvcImplNames.getConstArray();
1859 (void) pImplNames;
1860 #endif
1861 return aSvcImplNames;
1865 void SAL_CALL
1866 LngSvcMgr::dispose()
1867 throw(uno::RuntimeException)
1869 osl::MutexGuard aGuard( GetLinguMutex() );
1871 if (!bDisposing)
1873 bDisposing = TRUE;
1875 // require listeners to release this object
1876 lang::EventObject aEvtObj( (XLinguServiceManager *) this );
1877 aEvtListeners.disposeAndClear( aEvtObj );
1879 if (pListenerHelper)
1880 pListenerHelper->DisposeAndClear( aEvtObj );
1885 void SAL_CALL
1886 LngSvcMgr::addEventListener(
1887 const uno::Reference< lang::XEventListener >& xListener )
1888 throw(uno::RuntimeException)
1890 osl::MutexGuard aGuard( GetLinguMutex() );
1892 if (!bDisposing && xListener.is())
1894 aEvtListeners.addInterface( xListener );
1899 void SAL_CALL
1900 LngSvcMgr::removeEventListener(
1901 const uno::Reference< lang::XEventListener >& xListener )
1902 throw(uno::RuntimeException)
1904 osl::MutexGuard aGuard( GetLinguMutex() );
1906 if (xListener.is())
1908 aEvtListeners.removeInterface( xListener );
1913 BOOL LngSvcMgr::AddLngSvcEvtBroadcaster(
1914 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
1916 BOOL bRes = FALSE;
1917 if (rxBroadcaster.is())
1919 if (!pListenerHelper)
1920 GetListenerHelper_Impl();
1921 bRes = pListenerHelper->AddLngSvcEvtBroadcaster( rxBroadcaster );
1923 return bRes;
1927 BOOL LngSvcMgr::RemoveLngSvcEvtBroadcaster(
1928 const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster )
1930 BOOL bRes = FALSE;
1931 if (rxBroadcaster.is())
1933 DBG_ASSERT( pListenerHelper, "pListenerHelper non existent" );
1934 if (!pListenerHelper)
1935 GetListenerHelper_Impl();
1936 bRes = pListenerHelper->RemoveLngSvcEvtBroadcaster( rxBroadcaster );
1938 return bRes;
1942 OUString SAL_CALL
1943 LngSvcMgr::getImplementationName()
1944 throw(uno::RuntimeException)
1946 osl::MutexGuard aGuard( GetLinguMutex() );
1947 return getImplementationName_Static();
1951 sal_Bool SAL_CALL
1952 LngSvcMgr::supportsService( const OUString& ServiceName )
1953 throw(uno::RuntimeException)
1955 osl::MutexGuard aGuard( GetLinguMutex() );
1957 uno::Sequence< OUString > aSNL = getSupportedServiceNames();
1958 const OUString * pArray = aSNL.getConstArray();
1959 for( INT32 i = 0; i < aSNL.getLength(); i++ )
1960 if( pArray[i] == ServiceName )
1961 return TRUE;
1962 return FALSE;
1966 uno::Sequence< OUString > SAL_CALL
1967 LngSvcMgr::getSupportedServiceNames()
1968 throw(uno::RuntimeException)
1970 osl::MutexGuard aGuard( GetLinguMutex() );
1971 return getSupportedServiceNames_Static();
1975 uno::Sequence< OUString > LngSvcMgr::getSupportedServiceNames_Static()
1976 throw()
1978 osl::MutexGuard aGuard( GetLinguMutex() );
1980 uno::Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich
1981 aSNS.getArray()[0] = A2OU( SN_LINGU_SERVCICE_MANAGER );
1982 return aSNS;
1986 uno::Reference< uno::XInterface > SAL_CALL LngSvcMgr_CreateInstance(
1987 const uno::Reference< lang::XMultiServiceFactory > & /*rSMgr*/ )
1988 throw(uno::Exception)
1990 uno::Reference< uno::XInterface > xService = (cppu::OWeakObject*) new LngSvcMgr;
1991 return xService;
1996 sal_Bool SAL_CALL LngSvcMgr_writeInfo(
1997 void * /*pServiceManager*/,
1998 registry::XRegistryKey * pRegistryKey )
2002 String aImpl( '/' );
2003 aImpl += LngSvcMgr::getImplementationName_Static().getStr();
2004 aImpl.AppendAscii( "/UNO/SERVICES" );
2005 uno::Reference< registry::XRegistryKey > xNewKey =
2006 pRegistryKey->createKey( aImpl );
2007 uno::Sequence< OUString > aServices = LngSvcMgr::getSupportedServiceNames_Static();
2008 for( INT32 i = 0; i < aServices.getLength(); i++ )
2009 xNewKey->createKey( aServices.getConstArray()[i] );
2011 return sal_True;
2013 catch(uno::Exception &)
2015 return sal_False;
2019 void * SAL_CALL LngSvcMgr_getFactory(
2020 const sal_Char * pImplName,
2021 lang::XMultiServiceFactory * pServiceManager,
2022 void * /*pRegistryKey*/ )
2025 void * pRet = 0;
2026 if ( !LngSvcMgr::getImplementationName_Static().compareToAscii( pImplName ) )
2028 uno::Reference< lang::XSingleServiceFactory > xFactory =
2029 cppu::createOneInstanceFactory(
2030 pServiceManager,
2031 LngSvcMgr::getImplementationName_Static(),
2032 LngSvcMgr_CreateInstance,
2033 LngSvcMgr::getSupportedServiceNames_Static());
2034 // acquire, because we return an interface pointer instead of a reference
2035 xFactory->acquire();
2036 pRet = xFactory.get();
2038 return pRet;
2042 ///////////////////////////////////////////////////////////////////////////