diff options
Diffstat (limited to 'linguistic/source/lngsvcmgr.cxx')
-rw-r--r-- | linguistic/source/lngsvcmgr.cxx | 2046 |
1 files changed, 2046 insertions, 0 deletions
diff --git a/linguistic/source/lngsvcmgr.cxx b/linguistic/source/lngsvcmgr.cxx new file mode 100644 index 000000000000..3a8e3e017fae --- /dev/null +++ b/linguistic/source/lngsvcmgr.cxx @@ -0,0 +1,2046 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: lngsvcmgr.cxx,v $ + * $Revision: 1.32 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_linguistic.hxx" + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/linguistic2/XSupportedLocales.hpp> +#include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp> +#include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp> + +#include <tools/solar.h> +#include <unotools/lingucfg.hxx> +#include <unotools/processfactory.hxx> +#include <i18npool/lang.h> +#include <i18npool/mslangid.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/extract.hxx> +#include <rtl/logfile.hxx> + +#include "lngsvcmgr.hxx" +#include "lngopt.hxx" +#include "misc.hxx" +#include "spelldsp.hxx" +#include "hyphdsp.hxx" +#include "thesdsp.hxx" +#include "gciterator.hxx" + + +using namespace com::sun::star; +using namespace linguistic; +using ::rtl::OUString; + +// forward declarations +uno::Sequence< OUString > static GetLangSvcList( const uno::Any &rVal ); +uno::Sequence< OUString > static GetLangSvc( const uno::Any &rVal ); + +/////////////////////////////////////////////////////////////////////////// + +static BOOL lcl_SeqHasString( const uno::Sequence< OUString > &rSeq, const OUString &rText ) +{ + BOOL bRes = FALSE; + + INT32 nLen = rSeq.getLength(); + if (nLen == 0 || rText.getLength() == 0) + return bRes; + + const OUString *pSeq = rSeq.getConstArray(); + for (INT32 i = 0; i < nLen && !bRes; ++i) + { + if (rText == pSeq[i]) + bRes = TRUE; + } + return bRes; +} + +/////////////////////////////////////////////////////////////////////////// + +static uno::Sequence< lang::Locale > GetAvailLocales( + const uno::Sequence< OUString > &rSvcImplNames ) +{ + uno::Sequence< lang::Locale > aRes; + + uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); + INT32 nNames = rSvcImplNames.getLength(); + if (nNames && xFac.is()) + { + std::set< LanguageType > aLanguages; + + //! since we're going to create one-instance services we have to + //! supply their arguments even if we would not need them here... + uno::Sequence< uno::Any > aArgs(2); + aArgs.getArray()[0] <<= GetLinguProperties(); + + // check all services for the supported languages and new + // languages to the result + const OUString *pImplNames = rSvcImplNames.getConstArray(); + INT32 i; + + for (i = 0; i < nNames; ++i) + { + uno::Reference< linguistic2::XSupportedLocales > xSuppLoc; + try + { + xSuppLoc = uno::Reference< linguistic2::XSupportedLocales >( + xFac->createInstanceWithArguments( pImplNames[i], aArgs ), uno::UNO_QUERY ); + } + catch (uno::Exception &) + { + DBG_ASSERT( 0, "createInstanceWithArguments failed" ); + } + + if (xSuppLoc.is()) + { + uno::Sequence< lang::Locale > aLoc( xSuppLoc->getLocales() ); + INT32 nLoc = aLoc.getLength(); + for (INT32 k = 0; k < nLoc; ++k) + { + const lang::Locale *pLoc = aLoc.getConstArray(); + LanguageType nLang = LocaleToLanguage( pLoc[k] ); + + // language not already added? + if (aLanguages.find( nLang ) == aLanguages.end()) + aLanguages.insert( nLang ); + } + } + else + { + DBG_ASSERT( 0, "interface not supported by service" ); + } + } + + // build return sequence + INT32 nLanguages = static_cast< INT32 >(aLanguages.size()); + aRes.realloc( nLanguages ); + lang::Locale *pRes = aRes.getArray(); + std::set< LanguageType >::const_iterator aIt( aLanguages.begin() ); + for (i = 0; aIt != aLanguages.end(); ++aIt, ++i) + { + LanguageType nLang = *aIt; + pRes[i] = CreateLocale( nLang ); + } + } + + return aRes; +} + +/////////////////////////////////////////////////////////////////////////// + +struct SvcInfo +{ + const OUString aSvcImplName; + const uno::Sequence< INT16 > aSuppLanguages; + + SvcInfo( const OUString &rSvcImplName, + const uno::Sequence< INT16 > &rSuppLanguages ) : + aSvcImplName (rSvcImplName), + aSuppLanguages (rSuppLanguages) + { + } + + BOOL HasLanguage( INT16 nLanguage ) const; +}; + + +BOOL SvcInfo::HasLanguage( INT16 nLanguage ) const +{ + INT32 nCnt = aSuppLanguages.getLength(); + const INT16 *pLang = aSuppLanguages.getConstArray(); + INT32 i; + + for ( i = 0; i < nCnt; ++i) + { + if (nLanguage == pLang[i]) + break; + } + return i < nCnt; +} + + +/////////////////////////////////////////////////////////////////////////// + + +void LngSvcMgr::SetAvailableCfgServiceLists( LinguDispatcher &rDispatcher, + const SvcInfoArray &rAvailSvcs ) +{ + // get list of nodenames to look at for their service list + const char *pEntryName = 0; + BOOL bHasLangSvcList = TRUE; + switch (rDispatcher.GetDspType()) + { + case LinguDispatcher::DSP_SPELL : pEntryName = "ServiceManager/SpellCheckerList"; break; + case LinguDispatcher::DSP_GRAMMAR : pEntryName = "ServiceManager/GrammarCheckerList"; + bHasLangSvcList = FALSE; + break; + case LinguDispatcher::DSP_HYPH : pEntryName = "ServiceManager/HyphenatorList"; + bHasLangSvcList = FALSE; + break; + case LinguDispatcher::DSP_THES : pEntryName = "ServiceManager/ThesaurusList"; break; + default : + DBG_ASSERT( 0, "unexpected case" ); + } + String aNode( String::CreateFromAscii( pEntryName ) ); + uno::Sequence < OUString > aNodeNames( /*aCfg.*/GetNodeNames( aNode ) ); + + + INT32 nLen = aNodeNames.getLength(); + const OUString *pNodeNames = aNodeNames.getConstArray(); + for (INT32 i = 0; i < nLen; ++i) + { + uno::Sequence< OUString > aSvcImplNames; + + uno::Sequence< OUString > aNames( 1 ); + OUString *pNames = aNames.getArray(); + + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += pNodeNames[i]; + pNames[0] = aPropName; + + uno::Sequence< uno::Any > aValues = /*aCfg.*/GetProperties( aNames ); + if (aValues.getLength()) + { + // get list of configured service names for the + // current node (language) + const uno::Any &rValue = aValues.getConstArray()[0]; + if (bHasLangSvcList) + aSvcImplNames = GetLangSvcList( rValue ); + else + aSvcImplNames = GetLangSvc( rValue ); + + INT32 nSvcs = aSvcImplNames.getLength(); + if (nSvcs) + { + const OUString *pImplNames = aSvcImplNames.getConstArray(); + + LanguageType nLang = MsLangId::convertIsoStringToLanguage( pNodeNames[i] ); + + // build list of available services from those + INT32 nCnt = 0; + uno::Sequence< OUString > aAvailSvcs( nSvcs ); + OUString *pAvailSvcs = aAvailSvcs.getArray(); + for (INT32 k = 0; k < nSvcs; ++k) + { + // check for availability of the service + size_t nAvailSvcs = rAvailSvcs.size(); + for (size_t m = 0; m < nAvailSvcs; ++m) + { + const SvcInfo &rSvcInfo = *rAvailSvcs[m]; + if (rSvcInfo.aSvcImplName == pImplNames[k] && + rSvcInfo.HasLanguage( nLang )) + { + pAvailSvcs[ nCnt++ ] = rSvcInfo.aSvcImplName; + break; + } + } + } + + if (nCnt) + { + aAvailSvcs.realloc( nCnt ); + rDispatcher.SetServiceList( CreateLocale( nLang ), aAvailSvcs ); + } + } + } + } +} + + +/////////////////////////////////////////////////////////////////////////// + + +class LngSvcMgrListenerHelper : + public cppu::WeakImplHelper2 + < + linguistic2::XLinguServiceEventListener, + linguistic2::XDictionaryListEventListener + > +{ + LngSvcMgr &rMyManager; +// Timer aLaunchTimer; + + //cppu::OMultiTypeInterfaceContainerHelper aListeners; + ::cppu::OInterfaceContainerHelper aLngSvcMgrListeners; + ::cppu::OInterfaceContainerHelper aLngSvcEvtBroadcasters; + uno::Reference< linguistic2::XDictionaryList > xDicList; + uno::Reference< uno::XInterface > xMyEvtObj; + + INT16 nCombinedLngSvcEvt; + + // disallow copy-constructor and assignment-operator for now + LngSvcMgrListenerHelper(const LngSvcMgrListenerHelper &); + LngSvcMgrListenerHelper & operator = (const LngSvcMgrListenerHelper &); + + void LaunchEvent( INT16 nLngSvcEvtFlags ); + +// DECL_LINK( TimeOut, Timer* ); + long Timeout(); + +public: + LngSvcMgrListenerHelper( LngSvcMgr &rLngSvcMgr, + const uno::Reference< uno::XInterface > &rxSource, + const uno::Reference< linguistic2::XDictionaryList > &rxDicList ); + + // lang::XEventListener + virtual void SAL_CALL + disposing( const lang::EventObject& rSource ) + throw(uno::RuntimeException); + + // linguistic2::XLinguServiceEventListener + virtual void SAL_CALL + processLinguServiceEvent( const linguistic2::LinguServiceEvent& aLngSvcEvent ) + throw(uno::RuntimeException); + + // linguistic2::XDictionaryListEventListener + virtual void SAL_CALL + processDictionaryListEvent( + const linguistic2::DictionaryListEvent& rDicListEvent ) + throw(uno::RuntimeException); + + inline BOOL AddLngSvcMgrListener( + const uno::Reference< lang::XEventListener >& rxListener ); + inline BOOL RemoveLngSvcMgrListener( + const uno::Reference< lang::XEventListener >& rxListener ); + void DisposeAndClear( const lang::EventObject &rEvtObj ); + BOOL AddLngSvcEvtBroadcaster( + const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ); + BOOL RemoveLngSvcEvtBroadcaster( + const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ); + + void AddLngSvcEvt( INT16 nLngSvcEvt ); +}; + + +LngSvcMgrListenerHelper::LngSvcMgrListenerHelper( + LngSvcMgr &rLngSvcMgr, + const uno::Reference< uno::XInterface > &rxSource, + const uno::Reference< linguistic2::XDictionaryList > &rxDicList ) : + rMyManager ( rLngSvcMgr ), + aLngSvcMgrListeners ( GetLinguMutex() ), + aLngSvcEvtBroadcasters ( GetLinguMutex() ), + xDicList ( rxDicList ), + xMyEvtObj ( rxSource ) +{ + if (xDicList.is()) + { + xDicList->addDictionaryListEventListener( + (linguistic2::XDictionaryListEventListener *) this, FALSE ); + } + + //! The timer is used to 'sum up' different events in order to reduce the + //! number of events forwarded. + //! (This may happen already if a property was changed that has several + //! listeners, and each of them is launching an event of it's own!) + //! Thus this behaviour is necessary to avoid unecessary actions of + //! this objects listeners! +// aLaunchTimer.SetTimeout( 2000 ); +// aLaunchTimer.SetTimeoutHdl( LINK( this, LngSvcMgrListenerHelper, TimeOut ) ); + nCombinedLngSvcEvt = 0; +} + + +void SAL_CALL LngSvcMgrListenerHelper::disposing( const lang::EventObject& rSource ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Reference< uno::XInterface > xRef( rSource.Source ); + if ( xRef.is() ) + { + aLngSvcMgrListeners .removeInterface( xRef ); + aLngSvcEvtBroadcasters.removeInterface( xRef ); + if (xDicList == xRef) + xDicList = 0; + } +} + + +//IMPL_LINK( LngSvcMgrListenerHelper, TimeOut, Timer*, pTimer ) +long LngSvcMgrListenerHelper::Timeout() +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + +// if (&aLaunchTimer == pTimer) + { + // change event source to LinguServiceManager since the listeners + // probably do not know (and need not to know) about the specific + // SpellChecker's or Hyphenator's. + linguistic2::LinguServiceEvent aEvtObj( xMyEvtObj, nCombinedLngSvcEvt ); + nCombinedLngSvcEvt = 0; + + if (rMyManager.pSpellDsp) + rMyManager.pSpellDsp->FlushSpellCache(); + + // pass event on to linguistic2::XLinguServiceEventListener's + cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners ); + while (aIt.hasMoreElements()) + { + uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY ); + if (xRef.is()) + xRef->processLinguServiceEvent( aEvtObj ); + } + } + return 0; +} + + +void LngSvcMgrListenerHelper::AddLngSvcEvt( INT16 nLngSvcEvt ) +{ + nCombinedLngSvcEvt |= nLngSvcEvt; +// aLaunchTimer.Start(); + Timeout(); +} + + +void SAL_CALL + LngSvcMgrListenerHelper::processLinguServiceEvent( + const linguistic2::LinguServiceEvent& rLngSvcEvent ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + AddLngSvcEvt( rLngSvcEvent.nEvent ); +} + + +void SAL_CALL + LngSvcMgrListenerHelper::processDictionaryListEvent( + const linguistic2::DictionaryListEvent& rDicListEvent ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + INT16 nDlEvt = rDicListEvent.nCondensedEvent; + if (0 == nDlEvt) + return; + + // we do keep the original event source here though... + + // pass event on to linguistic2::XDictionaryListEventListener's + cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners ); + while (aIt.hasMoreElements()) + { + uno::Reference< linguistic2::XDictionaryListEventListener > xRef( aIt.next(), uno::UNO_QUERY ); + if (xRef.is()) + xRef->processDictionaryListEvent( rDicListEvent ); + } + + // + // "translate" DictionaryList event into linguistic2::LinguServiceEvent + // + INT16 nLngSvcEvt = 0; + // + INT16 nSpellCorrectFlags = + linguistic2::DictionaryListEventFlags::ADD_NEG_ENTRY | + linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY | + linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC | + linguistic2::DictionaryListEventFlags::DEACTIVATE_POS_DIC; + if (0 != (nDlEvt & nSpellCorrectFlags)) + nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN; + // + INT16 nSpellWrongFlags = + linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY | + linguistic2::DictionaryListEventFlags::DEL_NEG_ENTRY | + linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC | + linguistic2::DictionaryListEventFlags::DEACTIVATE_NEG_DIC; + if (0 != (nDlEvt & nSpellWrongFlags)) + nLngSvcEvt |= linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN; + // + INT16 nHyphenateFlags = + linguistic2::DictionaryListEventFlags::ADD_POS_ENTRY | + linguistic2::DictionaryListEventFlags::DEL_POS_ENTRY | + linguistic2::DictionaryListEventFlags::ACTIVATE_POS_DIC | + linguistic2::DictionaryListEventFlags::ACTIVATE_NEG_DIC; + if (0 != (nDlEvt & nHyphenateFlags)) + nLngSvcEvt |= linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN; + + if (rMyManager.pSpellDsp) + rMyManager.pSpellDsp->FlushSpellCache(); + if (nLngSvcEvt) + LaunchEvent( nLngSvcEvt ); +} + + +void LngSvcMgrListenerHelper::LaunchEvent( INT16 nLngSvcEvtFlags ) +{ + linguistic2::LinguServiceEvent aEvt( xMyEvtObj, nLngSvcEvtFlags ); + + // pass event on to linguistic2::XLinguServiceEventListener's + cppu::OInterfaceIteratorHelper aIt( aLngSvcMgrListeners ); + while (aIt.hasMoreElements()) + { + uno::Reference< linguistic2::XLinguServiceEventListener > xRef( aIt.next(), uno::UNO_QUERY ); + if (xRef.is()) + xRef->processLinguServiceEvent( aEvt ); + } +} + + +inline BOOL LngSvcMgrListenerHelper::AddLngSvcMgrListener( + const uno::Reference< lang::XEventListener >& rxListener ) +{ + aLngSvcMgrListeners.addInterface( rxListener ); + return TRUE; +} + + +inline BOOL LngSvcMgrListenerHelper::RemoveLngSvcMgrListener( + const uno::Reference< lang::XEventListener >& rxListener ) +{ + aLngSvcMgrListeners.removeInterface( rxListener ); + return TRUE; +} + + +void LngSvcMgrListenerHelper::DisposeAndClear( const lang::EventObject &rEvtObj ) +{ + // call "disposing" for all listeners and clear list + aLngSvcMgrListeners .disposeAndClear( rEvtObj ); + + // remove references to this object hold by the broadcasters + cppu::OInterfaceIteratorHelper aIt( aLngSvcEvtBroadcasters ); + while (aIt.hasMoreElements()) + { + uno::Reference< linguistic2::XLinguServiceEventBroadcaster > xRef( aIt.next(), uno::UNO_QUERY ); + if (xRef.is()) + RemoveLngSvcEvtBroadcaster( xRef ); + } + + // remove refernce to this object hold by the dictionary-list + if (xDicList.is()) + { + xDicList->removeDictionaryListEventListener( + (linguistic2::XDictionaryListEventListener *) this ); + xDicList = 0; + } +} + + +BOOL LngSvcMgrListenerHelper::AddLngSvcEvtBroadcaster( + const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) +{ + BOOL bRes = FALSE; + if (rxBroadcaster.is()) + { + aLngSvcEvtBroadcasters.addInterface( rxBroadcaster ); + rxBroadcaster->addLinguServiceEventListener( + (linguistic2::XLinguServiceEventListener *) this ); + } + return bRes; +} + + +BOOL LngSvcMgrListenerHelper::RemoveLngSvcEvtBroadcaster( + const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) +{ + BOOL bRes = FALSE; + if (rxBroadcaster.is()) + { + aLngSvcEvtBroadcasters.removeInterface( rxBroadcaster ); + rxBroadcaster->removeLinguServiceEventListener( + (linguistic2::XLinguServiceEventListener *) this ); + } + return bRes; +} + + +/////////////////////////////////////////////////////////////////////////// + + +LngSvcMgr::LngSvcMgr() : + utl::ConfigItem( String::CreateFromAscii( "Office.Linguistic" ) ), + aEvtListeners ( GetLinguMutex() ) +{ + bHasAvailSpellLocales = + bHasAvailGrammarLocales = + bHasAvailHyphLocales = + bHasAvailThesLocales = + bDisposing = FALSE; + + pSpellDsp = 0; + pGrammarDsp = 0; + pHyphDsp = 0; + pThesDsp = 0; + + pAvailSpellSvcs = 0; + pAvailGrammarSvcs = 0; + pAvailHyphSvcs = 0; + pAvailThesSvcs = 0; + pListenerHelper = 0; + + // request notify events when properties (i.e. something in the subtree) changes + uno::Sequence< OUString > aNames(4); + OUString *pNames = aNames.getArray(); + pNames[0] = A2OU( "ServiceManager/SpellCheckerList" ); + pNames[1] = A2OU( "ServiceManager/GrammarCheckerList" ); + pNames[2] = A2OU( "ServiceManager/HyphenatorList" ); + pNames[3] = A2OU( "ServiceManager/ThesaurusList" ); + EnableNotification( aNames ); +} + + +LngSvcMgr::~LngSvcMgr() +{ + // memory for pSpellDsp, pHyphDsp, pThesDsp, pListenerHelper + // will be freed in the destructor of the respective Reference's + // xSpellDsp, xGrammarDsp, xHyphDsp, xThesDsp + + delete pAvailSpellSvcs; + delete pAvailGrammarSvcs; + delete pAvailHyphSvcs; + delete pAvailThesSvcs; +} + + +void LngSvcMgr::Notify( const uno::Sequence< OUString > &rPropertyNames ) +{ + const OUString aSpellCheckerList( A2OU("ServiceManager/SpellCheckerList") ); + const OUString aGrammarCheckerList( A2OU("ServiceManager/GrammarCheckerList") ); + const OUString aHyphenatorList( A2OU("ServiceManager/HyphenatorList") ); + const OUString aThesaurusList( A2OU("ServiceManager/ThesaurusList") ); + + const uno::Sequence< OUString > aSpellCheckerListEntries( GetNodeNames( aSpellCheckerList ) ); + const uno::Sequence< OUString > aGrammarCheckerListEntries( GetNodeNames( aGrammarCheckerList ) ); + const uno::Sequence< OUString > aHyphenatorListEntries( GetNodeNames( aHyphenatorList ) ); + const uno::Sequence< OUString > aThesaurusListEntries( GetNodeNames( aThesaurusList ) ); + + uno::Sequence< uno::Any > aValues; + uno::Sequence< OUString > aNames( 1 ); + OUString *pNames = aNames.getArray(); + + sal_Int32 nLen = rPropertyNames.getLength(); + const OUString *pPropertyNames = rPropertyNames.getConstArray(); + for (sal_Int32 i = 0; i < nLen; ++i) + { + // property names look like + // "ServiceManager/ThesaurusList/cfg:any['de-CH']" + + const OUString &rName = pPropertyNames[i]; + sal_Int32 nKeyStart, nKeyEnd; + nKeyStart = rName.indexOf( A2OU("['"), 0 ); + nKeyEnd = rName.indexOf( A2OU("']"), nKeyStart + 2); + OUString aKeyText; + if (nKeyStart != -1 && nKeyEnd != -1) + aKeyText = rName.copy( nKeyStart + 2, nKeyEnd - nKeyStart - 2); + DBG_ASSERT( aKeyText.getLength() != 0, "unexpected key (lang::Locale) string" ); + if (0 == rName.compareTo( aSpellCheckerList, aSpellCheckerList.getLength() )) + { + // delete old cached data, needs to be acquired new on demand + delete pAvailSpellSvcs; pAvailSpellSvcs = 0; + + OUString aNode( aSpellCheckerList ); + if (lcl_SeqHasString( aSpellCheckerListEntries, aKeyText )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aKeyText; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + uno::Sequence< OUString > aSvcImplNames; + if (aValues.getLength()) + aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); + + LanguageType nLang = LANGUAGE_NONE; + if (0 != aKeyText.getLength()) + nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); + + GetSpellCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below + pSpellDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); + } + } + else if (0 == rName.compareTo( aGrammarCheckerList, aGrammarCheckerList.getLength() )) + { + // delete old cached data, needs to be acquired new on demand + delete pAvailGrammarSvcs; pAvailGrammarSvcs = 0; + + OUString aNode( aGrammarCheckerList ); + if (lcl_SeqHasString( aGrammarCheckerListEntries, aKeyText )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aKeyText; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + uno::Sequence< OUString > aSvcImplNames; + if (aValues.getLength()) + aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); + + LanguageType nLang = LANGUAGE_NONE; + if (0 != aKeyText.getLength()) + nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); + + if (SvtLinguConfig().HasGrammarChecker()) + { + GetGrammarCheckerDsp_Impl( sal_False ); // don't set service list, it will be done below + pGrammarDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); + } + } + } + else if (0 == rName.compareTo( aHyphenatorList, aHyphenatorList.getLength() )) + { + // delete old cached data, needs to be acquired new on demand + delete pAvailHyphSvcs; pAvailHyphSvcs = 0; + + OUString aNode( aHyphenatorList ); + if (lcl_SeqHasString( aHyphenatorListEntries, aKeyText )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aKeyText; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + uno::Sequence< OUString > aSvcImplNames; + if (aValues.getLength()) + aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); + + LanguageType nLang = LANGUAGE_NONE; + if (0 != aKeyText.getLength()) + nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); + + GetHyphenatorDsp_Impl( sal_False ); // don't set service list, it will be done below + pHyphDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); + } + } + else if (0 == rName.compareTo( aThesaurusList, aThesaurusList.getLength() )) + { + // delete old cached data, needs to be acquired new on demand + delete pAvailThesSvcs; pAvailThesSvcs = 0; + + OUString aNode( aThesaurusList ); + if (lcl_SeqHasString( aThesaurusListEntries, aKeyText )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aKeyText; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + uno::Sequence< OUString > aSvcImplNames; + if (aValues.getLength()) + aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); + + LanguageType nLang = LANGUAGE_NONE; + if (0 != aKeyText.getLength()) + nLang = MsLangId::convertIsoStringToLanguage( aKeyText ); + + GetThesaurusDsp_Impl( sal_False ); // don't set service list, it will be done below + pThesDsp->SetServiceList( CreateLocale(nLang), aSvcImplNames ); + } + } + else + { + DBG_ASSERT( 0, "nofified for unexpected property" ); + } + } +} + + +void LngSvcMgr::Commit() +{ + // everything necessary should have already been done by 'SaveCfgSvcs' + // called from within 'setConfiguredServices'. + // Also this class usually exits only when the Office i sbeing shutdown. +} + + +void LngSvcMgr::GetListenerHelper_Impl() +{ + if (!pListenerHelper) + { + pListenerHelper = new LngSvcMgrListenerHelper( *this, + (XLinguServiceManager *) this, linguistic::GetDictionaryList() ); + xListenerHelper = (linguistic2::XLinguServiceEventListener *) pListenerHelper; + } +} + + +void LngSvcMgr::GetSpellCheckerDsp_Impl( sal_Bool bSetSvcList ) +{ + if (!pSpellDsp) + { + pSpellDsp = new SpellCheckerDispatcher( *this ); + xSpellDsp = pSpellDsp; + if (bSetSvcList) + SetCfgServiceLists( *pSpellDsp ); + } +} + + +void LngSvcMgr::GetGrammarCheckerDsp_Impl( sal_Bool bSetSvcList ) +{ + if (!pGrammarDsp && SvtLinguConfig().HasGrammarChecker()) + { + //! since the grammar checking iterator needs to be a one instance service + //! we need to create it the correct way! + uno::Reference< linguistic2::XProofreadingIterator > xGCI; + try + { + uno::Reference< lang::XMultiServiceFactory > xMgr( + utl::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + xGCI = uno::Reference< linguistic2::XProofreadingIterator >( + xMgr->createInstance( A2OU( SN_GRAMMARCHECKINGITERATOR ) ), uno::UNO_QUERY_THROW ); + } + catch (uno::Exception &) + { + } + DBG_ASSERT( xGCI.is(), "instantiating grammar checking iterator failed" ); + + if (xGCI.is()) + { + pGrammarDsp = dynamic_cast< GrammarCheckingIterator * >(xGCI.get()); + xGrammarDsp = xGCI; + DBG_ASSERT( pGrammarDsp, "failed to get implementation" ); + if (bSetSvcList) + SetCfgServiceLists( *pGrammarDsp ); + } + } +} + + +void LngSvcMgr::GetHyphenatorDsp_Impl( sal_Bool bSetSvcList ) +{ + if (!pHyphDsp) + { + pHyphDsp = new HyphenatorDispatcher( *this ); + xHyphDsp = pHyphDsp; + if (bSetSvcList) + SetCfgServiceLists( *pHyphDsp ); + } +} + + +void LngSvcMgr::GetThesaurusDsp_Impl( sal_Bool bSetSvcList ) +{ + if (!pThesDsp) + { + pThesDsp = new ThesaurusDispatcher; + xThesDsp = pThesDsp; + if (bSetSvcList) + SetCfgServiceLists( *pThesDsp ); + } +} + + +void LngSvcMgr::GetAvailableSpellSvcs_Impl() +{ + if (!pAvailSpellSvcs) + { + pAvailSpellSvcs = new SvcInfoArray; + + uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); + if (xFac.is()) + { + uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); + uno::Reference< container::XEnumeration > xEnum; + if (xEnumAccess.is()) + xEnum = xEnumAccess->createContentEnumeration( + A2OU( SN_SPELLCHECKER ) ); + + if (xEnum.is()) + { + while (xEnum->hasMoreElements()) + { + uno::Any aCurrent = xEnum->nextElement(); + uno::Reference< lang::XSingleComponentFactory > xCompFactory; + uno::Reference< lang::XSingleServiceFactory > xFactory; + + uno::Reference< linguistic2::XSpellChecker > xSvc; + if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) + { + try + { + uno::Reference < uno::XComponentContext > xContext; + uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); + + xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + xSvc = uno::Reference< linguistic2::XSpellChecker >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); + } + catch (uno::Exception &rEx) + { + (void) rEx; + DBG_ASSERT( 0, "createInstance failed" ); + } + } + + if (xSvc.is()) + { + OUString aImplName; + uno::Sequence< INT16 > aLanguages; + uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); + if (xInfo.is()) + aImplName = xInfo->getImplementationName(); + DBG_ASSERT( aImplName.getLength(), + "empty implementation name" ); + uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); + DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); + if (xSuppLoc.is()) { + uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); + aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); + } + + pAvailSpellSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); + } + } + } + } + } +} + + +void LngSvcMgr::GetAvailableGrammarSvcs_Impl() +{ + if (!pAvailGrammarSvcs) + { + pAvailGrammarSvcs = new SvcInfoArray; + + uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); + if (xFac.is()) + { + uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); + uno::Reference< container::XEnumeration > xEnum; + if (xEnumAccess.is()) + xEnum = xEnumAccess->createContentEnumeration( + A2OU( SN_GRAMMARCHECKER ) ); + + if (xEnum.is()) + { + while (xEnum->hasMoreElements()) + { + uno::Any aCurrent = xEnum->nextElement(); + uno::Reference< lang::XSingleComponentFactory > xCompFactory; + uno::Reference< lang::XSingleServiceFactory > xFactory; + + uno::Reference< linguistic2::XProofreader > xSvc; + if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) + { + try + { + uno::Reference < uno::XComponentContext > xContext; + uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); + + xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + xSvc = uno::Reference< linguistic2::XProofreader >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); + } + catch (uno::Exception &rEx) + { + (void) rEx; + DBG_ASSERT( 0, "createInstance failed" ); + } + } + + if (xSvc.is()) + { + OUString aImplName; + uno::Sequence< INT16 > aLanguages; + uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); + if (xInfo.is()) + aImplName = xInfo->getImplementationName(); + DBG_ASSERT( aImplName.getLength(), + "empty implementation name" ); + uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); + DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); + if (xSuppLoc.is()) { + uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); + aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); + } + + pAvailGrammarSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); + } + } + } + } + } +} + + +void LngSvcMgr::GetAvailableHyphSvcs_Impl() +{ + if (!pAvailHyphSvcs) + { + pAvailHyphSvcs = new SvcInfoArray; + uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); + if (xFac.is()) + { + uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); + uno::Reference< container::XEnumeration > xEnum; + if (xEnumAccess.is()) + xEnum = xEnumAccess->createContentEnumeration( A2OU( SN_HYPHENATOR ) ); + + if (xEnum.is()) + { + while (xEnum->hasMoreElements()) + { + uno::Any aCurrent = xEnum->nextElement(); + uno::Reference< lang::XSingleComponentFactory > xCompFactory; + uno::Reference< lang::XSingleServiceFactory > xFactory; + + uno::Reference< linguistic2::XHyphenator > xSvc; + if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) + { + try + { + uno::Reference < uno::XComponentContext > xContext; + uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); + + xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + xSvc = uno::Reference< linguistic2::XHyphenator >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); + + } + catch (uno::Exception &rEx) + { + (void) rEx; + DBG_ASSERT( 0, "createInstance failed" ); + } + } + + if (xSvc.is()) + { + OUString aImplName; + uno::Sequence< INT16 > aLanguages; + uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); + if (xInfo.is()) + aImplName = xInfo->getImplementationName(); + DBG_ASSERT( aImplName.getLength(), + "empty implementation name" ); + uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); + DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); + if (xSuppLoc.is()) { + uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); + aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); + } + + pAvailHyphSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); + } + } + } + } + } +} + + +void LngSvcMgr::GetAvailableThesSvcs_Impl() +{ + if (!pAvailThesSvcs) + { + pAvailThesSvcs = new SvcInfoArray; + + uno::Reference< lang::XMultiServiceFactory > xFac( utl::getProcessServiceFactory() ); + if (xFac.is()) + { + uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xFac, uno::UNO_QUERY ); + uno::Reference< container::XEnumeration > xEnum; + if (xEnumAccess.is()) + xEnum = xEnumAccess->createContentEnumeration( + A2OU( SN_THESAURUS ) ); + + if (xEnum.is()) + { + while (xEnum->hasMoreElements()) + { + uno::Any aCurrent = xEnum->nextElement(); + + uno::Reference< lang::XSingleComponentFactory > xCompFactory; + uno::Reference< lang::XSingleServiceFactory > xFactory; + + uno::Reference< linguistic2::XThesaurus > xSvc; + if ( cppu::extractInterface( xCompFactory, aCurrent ) || ::cppu::extractInterface( xFactory, aCurrent ) ) + { + try + { + uno::Reference < uno::XComponentContext > xContext; + uno::Reference< beans::XPropertySet > xProps( xFac, uno::UNO_QUERY ); + + xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + xSvc = uno::Reference< linguistic2::XThesaurus >( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY ); + } + catch (uno::Exception &rEx) + { + (void) rEx; + DBG_ASSERT( 0, "createInstance failed" ); + } + } + + if (xSvc.is()) + { + OUString aImplName; + uno::Sequence< INT16 > aLanguages; + uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY ); + if (xInfo.is()) + aImplName = xInfo->getImplementationName(); + DBG_ASSERT( aImplName.getLength(), + "empty implementation name" ); + uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY ); + DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" ); + if (xSuppLoc.is()) { + uno::Sequence<lang::Locale> aLocaleSequence(xSuppLoc->getLocales()); + aLanguages = LocaleSeqToLangSeq( aLocaleSequence ); + } + + pAvailThesSvcs->push_back( new SvcInfo( aImplName, aLanguages ) ); + } + } + } + } + } +} + + +void LngSvcMgr::SetCfgServiceLists( SpellCheckerDispatcher &rSpellDsp ) +{ + RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Spell" ); + + String aNode( String::CreateFromAscii( "ServiceManager/SpellCheckerList" ) ); + uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); + OUString *pNames = aNames.getArray(); + INT32 nLen = aNames.getLength(); + + // append path prefix need for 'GetProperties' call below + String aPrefix( aNode ); + aPrefix.Append( (sal_Unicode) '/' ); + for (int i = 0; i < nLen; ++i) + { + OUString aTmp( aPrefix ); + aTmp += pNames[i]; + pNames[i] = aTmp; + } + + uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); + if (nLen && nLen == aValues.getLength()) + { + const uno::Any *pValues = aValues.getConstArray(); + for (INT32 i = 0; i < nLen; ++i) + { + uno::Sequence< OUString > aSvcImplNames; + if (pValues[i] >>= aSvcImplNames) + { +#if OSL_DEBUG_LEVEL > 1 +// INT32 nSvcs = aSvcImplNames.getLength(); +// const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); +#endif + String aLocaleStr( pNames[i] ); + xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); + aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); + lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); + rSpellDsp.SetServiceList( aLocale, aSvcImplNames ); + } + } + } +} + + +void LngSvcMgr::SetCfgServiceLists( GrammarCheckingIterator &rGrammarDsp ) +{ + RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Grammar" ); + + String aNode( String::CreateFromAscii( "ServiceManager/GrammarCheckerList" ) ); + uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); + OUString *pNames = aNames.getArray(); + INT32 nLen = aNames.getLength(); + + // append path prefix need for 'GetProperties' call below + String aPrefix( aNode ); + aPrefix.Append( (sal_Unicode) '/' ); + for (int i = 0; i < nLen; ++i) + { + OUString aTmp( aPrefix ); + aTmp += pNames[i]; + pNames[i] = aTmp; + } + + uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); + if (nLen && nLen == aValues.getLength()) + { + const uno::Any *pValues = aValues.getConstArray(); + for (INT32 i = 0; i < nLen; ++i) + { + uno::Sequence< OUString > aSvcImplNames; + if (pValues[i] >>= aSvcImplNames) + { + // there should only be one grammar checker in use per language... + if (aSvcImplNames.getLength() > 1) + aSvcImplNames.realloc(1); + +#if OSL_DEBUG_LEVEL > 1 +// INT32 nSvcs = aSvcImplNames.getLength(); +// const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); +#endif + String aLocaleStr( pNames[i] ); + xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); + aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); + lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); + rGrammarDsp.SetServiceList( aLocale, aSvcImplNames ); + } + } + } +} + + +void LngSvcMgr::SetCfgServiceLists( HyphenatorDispatcher &rHyphDsp ) +{ + RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Hyph" ); + + String aNode( String::CreateFromAscii( "ServiceManager/HyphenatorList" ) ); + uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); + OUString *pNames = aNames.getArray(); + INT32 nLen = aNames.getLength(); + + // append path prefix need for 'GetProperties' call below + String aPrefix( aNode ); + aPrefix.Append( (sal_Unicode) '/' ); + for (int i = 0; i < nLen; ++i) + { + OUString aTmp( aPrefix ); + aTmp += pNames[i]; + pNames[i] = aTmp; + } + + uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); + if (nLen && nLen == aValues.getLength()) + { + const uno::Any *pValues = aValues.getConstArray(); + for (INT32 i = 0; i < nLen; ++i) + { + uno::Sequence< OUString > aSvcImplNames; + if (pValues[i] >>= aSvcImplNames) + { + // there should only be one hyphenator in use per language... + if (aSvcImplNames.getLength() > 1) + aSvcImplNames.realloc(1); + +#if OSL_DEBUG_LEVEL > 1 +// INT32 nSvcs = aSvcImplNames.getLength(); +// const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); +#endif + String aLocaleStr( pNames[i] ); + xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); + aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); + lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); + rHyphDsp.SetServiceList( aLocale, aSvcImplNames ); + } + } + } +} + + +void LngSvcMgr::SetCfgServiceLists( ThesaurusDispatcher &rThesDsp ) +{ + RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SetCfgServiceLists - Thes" ); + + String aNode( String::CreateFromAscii( "ServiceManager/ThesaurusList" ) ); + uno::Sequence< OUString > aNames( /*aCfg.*/GetNodeNames( aNode ) ); + OUString *pNames = aNames.getArray(); + INT32 nLen = aNames.getLength(); + + // append path prefix need for 'GetProperties' call below + String aPrefix( aNode ); + aPrefix.Append( (sal_Unicode) '/' ); + for (int i = 0; i < nLen; ++i) + { + OUString aTmp( aPrefix ); + aTmp += pNames[i]; + pNames[i] = aTmp; + } + + uno::Sequence< uno::Any > aValues( /*aCfg.*/GetProperties( aNames ) ); + if (nLen && nLen == aValues.getLength()) + { + const uno::Any *pValues = aValues.getConstArray(); + for (INT32 i = 0; i < nLen; ++i) + { + uno::Sequence< OUString > aSvcImplNames; + if (pValues[i] >>= aSvcImplNames) + { +#if OSL_DEBUG_LEVEL > 1 +// INT32 nSvcs = aSvcImplNames.getLength(); +// const OUString *pSvcImplNames = aSvcImplNames.getConstArray(); +#endif + String aLocaleStr( pNames[i] ); + xub_StrLen nSeperatorPos = aLocaleStr.SearchBackward( sal_Unicode( '/' ) ); + aLocaleStr = aLocaleStr.Copy( nSeperatorPos + 1 ); + lang::Locale aLocale( CreateLocale( MsLangId::convertIsoStringToLanguage(aLocaleStr) ) ); + rThesDsp.SetServiceList( aLocale, aSvcImplNames ); + } + } + } +} + + +uno::Reference< linguistic2::XSpellChecker > SAL_CALL + LngSvcMgr::getSpellChecker() + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); +#if OSL_DEBUG_LEVEL > 1 + getAvailableLocales( A2OU( SN_SPELLCHECKER )); +#endif + + uno::Reference< linguistic2::XSpellChecker > xRes; + if (!bDisposing) + { + if (!xSpellDsp.is()) + GetSpellCheckerDsp_Impl(); + xRes = xSpellDsp; + } + return xRes; +} + + +uno::Reference< linguistic2::XHyphenator > SAL_CALL + LngSvcMgr::getHyphenator() + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); +#if OSL_DEBUG_LEVEL > 1 + getAvailableLocales( A2OU( SN_HYPHENATOR )); +#endif + + uno::Reference< linguistic2::XHyphenator > xRes; + if (!bDisposing) + { + if (!xHyphDsp.is()) + GetHyphenatorDsp_Impl(); + xRes = xHyphDsp; + } + return xRes; +} + + +uno::Reference< linguistic2::XThesaurus > SAL_CALL + LngSvcMgr::getThesaurus() + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); +#if OSL_DEBUG_LEVEL > 1 + getAvailableLocales( A2OU( SN_THESAURUS )); +#endif + + uno::Reference< linguistic2::XThesaurus > xRes; + if (!bDisposing) + { + if (!xThesDsp.is()) + GetThesaurusDsp_Impl(); + xRes = xThesDsp; + } + return xRes; +} + + +sal_Bool SAL_CALL + LngSvcMgr::addLinguServiceManagerListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + BOOL bRes = FALSE; + if (!bDisposing && xListener.is()) + { + if (!pListenerHelper) + GetListenerHelper_Impl(); + bRes = pListenerHelper->AddLngSvcMgrListener( xListener ); + } + return bRes; +} + + +sal_Bool SAL_CALL + LngSvcMgr::removeLinguServiceManagerListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + BOOL bRes = FALSE; + if (!bDisposing && xListener.is()) + { + DBG_ASSERT( pListenerHelper, "listener removed without being added" ); + if (!pListenerHelper) + GetListenerHelper_Impl(); + bRes = pListenerHelper->RemoveLngSvcMgrListener( xListener ); + } + return bRes; +} + + +uno::Sequence< OUString > SAL_CALL + LngSvcMgr::getAvailableServices( + const OUString& rServiceName, + const lang::Locale& rLocale ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Sequence< OUString > aRes; + const SvcInfoArray *pInfoArray = 0; + + if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) + { + // don't used cached data here (force re-evaluation in order to have downloaded dictionaries + // already found without the need to restart the office + delete pAvailSpellSvcs; pAvailSpellSvcs = 0; + GetAvailableSpellSvcs_Impl(); + pInfoArray = pAvailSpellSvcs; + } + else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) + { + // don't used cached data here (force re-evaluation in order to have downloaded dictionaries + // already found without the need to restart the office + delete pAvailGrammarSvcs; pAvailGrammarSvcs = 0; + GetAvailableGrammarSvcs_Impl(); + pInfoArray = pAvailGrammarSvcs; + } + else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) + { + // don't used cached data here (force re-evaluation in order to have downloaded dictionaries + // already found without the need to restart the office + delete pAvailHyphSvcs; pAvailHyphSvcs = 0; + GetAvailableHyphSvcs_Impl(); + pInfoArray = pAvailHyphSvcs; + } + else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) + { + // don't used cached data here (force re-evaluation in order to have downloaded dictionaries + // already found without the need to restart the office + delete pAvailThesSvcs; pAvailThesSvcs = 0; + GetAvailableThesSvcs_Impl(); + pInfoArray = pAvailThesSvcs; + } + + if (pInfoArray) + { + // resize to max number of entries + size_t nMaxCnt = pInfoArray->size(); + aRes.realloc( nMaxCnt ); + OUString *pImplName = aRes.getArray(); + + USHORT nCnt = 0; + LanguageType nLanguage = LocaleToLanguage( rLocale ); + for (size_t i = 0; i < nMaxCnt; ++i) + { + const SvcInfo *pInfo = (*pInfoArray)[i]; + if (LANGUAGE_NONE == nLanguage + || (pInfo && pInfo->HasLanguage( nLanguage ))) + { + pImplName[ nCnt++ ] = pInfo->aSvcImplName; + } + } + + // resize to actual number of entries + if (nCnt != nMaxCnt) + aRes.realloc( nCnt ); + } + + return aRes; +} + + +uno::Sequence< lang::Locale > SAL_CALL + LngSvcMgr::getAvailableLocales( + const OUString& rServiceName ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Sequence< lang::Locale > aRes; + + uno::Sequence< lang::Locale > *pAvailLocales = NULL; + BOOL *pHasAvailLocales = NULL; + if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) + { + pAvailLocales = &aAvailSpellLocales; + pHasAvailLocales = &bHasAvailSpellLocales; + } + else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) + { + pAvailLocales = &aAvailGrammarLocales; + pHasAvailLocales = &bHasAvailGrammarLocales; + } + else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) + { + pAvailLocales = &aAvailHyphLocales; + pHasAvailLocales = &bHasAvailHyphLocales; + } + else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) + { + pAvailLocales = &aAvailThesLocales; + pHasAvailLocales = &bHasAvailThesLocales; + } + + // about pHasAvailLocales: nowadays (with OOo lingu in SO) we want to know immediately about + // new downloaded dictionaries and have them ready right away if the Tools/Options... + // is used to activate them. Thus we can not rely anymore on buffered data. + if (pAvailLocales /*&& pHasAvailLocales */) + { +// if (!*pHasAvailLocales) +// { + *pAvailLocales = GetAvailLocales( + getAvailableServices( rServiceName, lang::Locale() ) ); +// *pHasAvailLocales = TRUE; +// } + aRes = *pAvailLocales; + } + + return aRes; +} + +static BOOL IsEqSvcList( const uno::Sequence< OUString > &rList1, + const uno::Sequence< OUString > &rList2 ) +{ + // returns TRUE iff both sequences are equal + + BOOL bRes = FALSE; + INT32 nLen = rList1.getLength(); + if (rList2.getLength() == nLen) + { + const OUString *pStr1 = rList1.getConstArray(); + const OUString *pStr2 = rList2.getConstArray(); + bRes = TRUE; + for (INT32 i = 0; i < nLen && bRes; ++i) + { + if (*pStr1++ != *pStr2++) + bRes = FALSE; + } + } + return bRes; +} + + +void SAL_CALL + LngSvcMgr::setConfiguredServices( + const OUString& rServiceName, + const lang::Locale& rLocale, + const uno::Sequence< OUString >& rServiceImplNames ) + throw(uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::setConfiguredServices" ); + + osl::MutexGuard aGuard( GetLinguMutex() ); + +#if OSL_DEBUG_LEVEL > 1 +// const OUString *pImplNames = rServiceImplNames.getConstArray(); +#endif + + LanguageType nLanguage = LocaleToLanguage( rLocale ); + if (LANGUAGE_NONE != nLanguage) + { + if (0 == rServiceName.compareToAscii( SN_SPELLCHECKER )) + { + if (!xSpellDsp.is()) + GetSpellCheckerDsp_Impl(); + BOOL bChanged = !IsEqSvcList( rServiceImplNames, + pSpellDsp->GetServiceList( rLocale ) ); + if (bChanged) + { + pSpellDsp->SetServiceList( rLocale, rServiceImplNames ); + SaveCfgSvcs( A2OU( SN_SPELLCHECKER ) ); + + if (pListenerHelper && bChanged) + pListenerHelper->AddLngSvcEvt( + linguistic2::LinguServiceEventFlags::SPELL_CORRECT_WORDS_AGAIN | + linguistic2::LinguServiceEventFlags::SPELL_WRONG_WORDS_AGAIN ); + } + } + else if (0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER )) + { + if (!xGrammarDsp.is()) + GetGrammarCheckerDsp_Impl(); + BOOL bChanged = !IsEqSvcList( rServiceImplNames, + pGrammarDsp->GetServiceList( rLocale ) ); + if (bChanged) + { + pGrammarDsp->SetServiceList( rLocale, rServiceImplNames ); + SaveCfgSvcs( A2OU( SN_GRAMMARCHECKER ) ); + + if (pListenerHelper && bChanged) + pListenerHelper->AddLngSvcEvt( + linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN ); + } + } + else if (0 == rServiceName.compareToAscii( SN_HYPHENATOR )) + { + if (!xHyphDsp.is()) + GetHyphenatorDsp_Impl(); + BOOL bChanged = !IsEqSvcList( rServiceImplNames, + pHyphDsp->GetServiceList( rLocale ) ); + if (bChanged) + { + pHyphDsp->SetServiceList( rLocale, rServiceImplNames ); + SaveCfgSvcs( A2OU( SN_HYPHENATOR ) ); + + if (pListenerHelper && bChanged) + pListenerHelper->AddLngSvcEvt( + linguistic2::LinguServiceEventFlags::HYPHENATE_AGAIN ); + } + } + else if (0 == rServiceName.compareToAscii( SN_THESAURUS )) + { + if (!xThesDsp.is()) + GetThesaurusDsp_Impl(); + BOOL bChanged = !IsEqSvcList( rServiceImplNames, + pThesDsp->GetServiceList( rLocale ) ); + if (bChanged) + { + pThesDsp->SetServiceList( rLocale, rServiceImplNames ); + SaveCfgSvcs( A2OU( SN_THESAURUS ) ); + } + } + } +} + + +BOOL LngSvcMgr::SaveCfgSvcs( const String &rServiceName ) +{ + RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs" ); + + BOOL bRes = FALSE; + + LinguDispatcher *pDsp = 0; + uno::Sequence< lang::Locale > aLocales; + + if (0 == rServiceName.CompareToAscii( SN_SPELLCHECKER )) + { + if (!pSpellDsp) + GetSpellCheckerDsp_Impl(); + pDsp = pSpellDsp; + aLocales = getAvailableLocales( A2OU( SN_SPELLCHECKER ) ); + } + else if (0 == rServiceName.CompareToAscii( SN_GRAMMARCHECKER )) + { + if (!pGrammarDsp) + GetGrammarCheckerDsp_Impl(); + pDsp = pGrammarDsp; + aLocales = getAvailableLocales( A2OU( SN_GRAMMARCHECKER ) ); + } + else if (0 == rServiceName.CompareToAscii( SN_HYPHENATOR )) + { + if (!pHyphDsp) + GetHyphenatorDsp_Impl(); + pDsp = pHyphDsp; + aLocales = getAvailableLocales( A2OU( SN_HYPHENATOR ) ); + } + else if (0 == rServiceName.CompareToAscii( SN_THESAURUS )) + { + if (!pThesDsp) + GetThesaurusDsp_Impl(); + pDsp = pThesDsp; + aLocales = getAvailableLocales( A2OU( SN_THESAURUS ) ); + } + + if (pDsp && aLocales.getLength()) + { + INT32 nLen = aLocales.getLength(); + const lang::Locale *pLocale = aLocales.getConstArray(); + + uno::Sequence< beans::PropertyValue > aValues( nLen ); + beans::PropertyValue *pValues = aValues.getArray(); + beans::PropertyValue *pValue = pValues; + + // get node name to be used + const char *pNodeName = NULL; + if (pDsp == pSpellDsp) + pNodeName = "ServiceManager/SpellCheckerList"; + else if (pDsp == pGrammarDsp) + pNodeName = "ServiceManager/GrammarCheckerList"; + else if (pDsp == pHyphDsp) + pNodeName = "ServiceManager/HyphenatorList"; + else if (pDsp == pThesDsp) + pNodeName = "ServiceManager/ThesaurusList"; + else + { + DBG_ASSERT( 0, "node name missing" ); + } + OUString aNodeName( A2OU(pNodeName) ); + + for (INT32 i = 0; i < nLen; ++i) + { + uno::Sequence< OUString > aSvcImplNames; + aSvcImplNames = pDsp->GetServiceList( pLocale[i] ); + +#if OSL_DEBUG_LEVEL > 1 + INT32 nSvcs = aSvcImplNames.getLength(); + const OUString *pSvcImplName = aSvcImplNames.getConstArray(); + for (INT32 j = 0; j < nSvcs; ++j) + { + OUString aImplName( pSvcImplName[j] ); + } +#endif + // build value to be written back to configuration + uno::Any aCfgAny; + if ((pDsp == pHyphDsp || pDsp == pGrammarDsp) && aSvcImplNames.getLength() > 1) + aSvcImplNames.realloc(1); // there should be only one entry for hyphenators or grammar checkers (because they are not chained) + aCfgAny <<= aSvcImplNames; + DBG_ASSERT( aCfgAny.hasValue(), "missing value for 'Any' type" ); + + OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString( + LocaleToLanguage( pLocale[i] ) ) ); + pValue->Value = aCfgAny; + pValue->Name = aNodeName; + pValue->Name += OUString::valueOf( (sal_Unicode) '/' ); + pValue->Name += aCfgLocaleStr; + pValue++; + } + { + RTL_LOGFILE_CONTEXT( aLog, "linguistic: LngSvcMgr::SaveCfgSvcs - ReplaceSetProperties" ); + // change, add new or replace existing entries. + bRes |= /*aCfg.*/ReplaceSetProperties( aNodeName, aValues ); + } + } + + return bRes; +} + + +static uno::Sequence< OUString > GetLangSvcList( const uno::Any &rVal ) +{ + uno::Sequence< OUString > aRes; + + if (rVal.hasValue()) + { + rVal >>= aRes; +#if OSL_DEBUG_LEVEL > 1 + INT32 nSvcs = aRes.getLength(); + if (nSvcs) + { + const OUString *pSvcName = aRes.getConstArray(); + for (INT32 j = 0; j < nSvcs; ++j) + { + OUString aImplName( pSvcName[j] ); + DBG_ASSERT( aImplName.getLength(), "service impl-name missing" ); + } + } +#endif + } + + return aRes; +} + + +static uno::Sequence< OUString > GetLangSvc( const uno::Any &rVal ) +{ + uno::Sequence< OUString > aRes; + if (!rVal.hasValue()) + return aRes; + + // allowing for a sequence here as well (even though it should only + // be a string) makes coding easier in other places since one needs + // not make a special case for writing a string only and not a + // sequence of strings. + if (rVal >>= aRes) + { + // but only the first string should be used. + if (aRes.getLength() > 1) + aRes.realloc(1); + } + else + { + OUString aImplName; + if ((rVal >>= aImplName) && aImplName.getLength() != 0) + { + aRes.realloc(1); + aRes.getArray()[0] = aImplName; + } + else + { + DBG_ASSERT( 0, "GetLangSvc: unexpected type encountered" ); + } + } + + return aRes; +} + + +/////////////////////////////////////////////////////////////////////////// + +uno::Sequence< OUString > SAL_CALL + LngSvcMgr::getConfiguredServices( + const OUString& rServiceName, + const lang::Locale& rLocale ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Sequence< OUString > aSvcImplNames; + + LanguageType nLanguage = LocaleToLanguage( rLocale ); + OUString aCfgLocale( MsLangId::convertLanguageToIsoString( nLanguage ) ); + + uno::Sequence< uno::Any > aValues; + uno::Sequence< OUString > aNames( 1 ); + OUString *pNames = aNames.getArray(); + if ( 0 == rServiceName.compareToAscii( SN_SPELLCHECKER ) ) + { + OUString aNode( OUString::createFromAscii( "ServiceManager/SpellCheckerList" )); + const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); + if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aCfgLocale; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + if (aValues.getLength()) + aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); + } + } + else if ( 0 == rServiceName.compareToAscii( SN_GRAMMARCHECKER ) ) + { + OUString aNode( OUString::createFromAscii( "ServiceManager/GrammarCheckerList" )); + const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); + if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aCfgLocale; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + if (aValues.getLength()) + aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); + } + } + else if ( 0 == rServiceName.compareToAscii( SN_HYPHENATOR ) ) + { + OUString aNode( OUString::createFromAscii( "ServiceManager/HyphenatorList" )); + const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); + if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aCfgLocale; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + if (aValues.getLength()) + aSvcImplNames = GetLangSvc( aValues.getConstArray()[0] ); + } + } + else if ( 0 == rServiceName.compareToAscii( SN_THESAURUS ) ) + { + OUString aNode( OUString::createFromAscii( "ServiceManager/ThesaurusList" )); + const uno::Sequence< OUString > aNodeEntries( GetNodeNames( aNode ) ); + if (lcl_SeqHasString( aNodeEntries, aCfgLocale )) + { + OUString aPropName( aNode ); + aPropName += OUString::valueOf( (sal_Unicode) '/' ); + aPropName += aCfgLocale; + pNames[0] = aPropName; + aValues = /*aCfg.*/GetProperties( aNames ); + if (aValues.getLength()) + aSvcImplNames = GetLangSvcList( aValues.getConstArray()[0] ); + } + } + +#if OSL_DEBUG_LEVEL > 1 + const OUString *pImplNames = aSvcImplNames.getConstArray(); + (void) pImplNames; +#endif + return aSvcImplNames; +} + + +void SAL_CALL + LngSvcMgr::dispose() + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (!bDisposing) + { + bDisposing = TRUE; + + // require listeners to release this object + lang::EventObject aEvtObj( (XLinguServiceManager *) this ); + aEvtListeners.disposeAndClear( aEvtObj ); + + if (pListenerHelper) + pListenerHelper->DisposeAndClear( aEvtObj ); + } +} + + +void SAL_CALL + LngSvcMgr::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (!bDisposing && xListener.is()) + { + aEvtListeners.addInterface( xListener ); + } +} + + +void SAL_CALL + LngSvcMgr::removeEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (xListener.is()) + { + aEvtListeners.removeInterface( xListener ); + } +} + + +BOOL LngSvcMgr::AddLngSvcEvtBroadcaster( + const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) +{ + BOOL bRes = FALSE; + if (rxBroadcaster.is()) + { + if (!pListenerHelper) + GetListenerHelper_Impl(); + bRes = pListenerHelper->AddLngSvcEvtBroadcaster( rxBroadcaster ); + } + return bRes; +} + + +BOOL LngSvcMgr::RemoveLngSvcEvtBroadcaster( + const uno::Reference< linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster ) +{ + BOOL bRes = FALSE; + if (rxBroadcaster.is()) + { + DBG_ASSERT( pListenerHelper, "pListenerHelper non existent" ); + if (!pListenerHelper) + GetListenerHelper_Impl(); + bRes = pListenerHelper->RemoveLngSvcEvtBroadcaster( rxBroadcaster ); + } + return bRes; +} + + +OUString SAL_CALL + LngSvcMgr::getImplementationName() + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return getImplementationName_Static(); +} + + +sal_Bool SAL_CALL + LngSvcMgr::supportsService( const OUString& ServiceName ) + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + for( INT32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return TRUE; + return FALSE; +} + + +uno::Sequence< OUString > SAL_CALL + LngSvcMgr::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return getSupportedServiceNames_Static(); +} + + +uno::Sequence< OUString > LngSvcMgr::getSupportedServiceNames_Static() + throw() +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich + aSNS.getArray()[0] = A2OU( SN_LINGU_SERVCICE_MANAGER ); + return aSNS; +} + + +uno::Reference< uno::XInterface > SAL_CALL LngSvcMgr_CreateInstance( + const uno::Reference< lang::XMultiServiceFactory > & /*rSMgr*/ ) + throw(uno::Exception) +{ + uno::Reference< uno::XInterface > xService = (cppu::OWeakObject*) new LngSvcMgr; + return xService; +} + + + +sal_Bool SAL_CALL LngSvcMgr_writeInfo( + void * /*pServiceManager*/, + registry::XRegistryKey * pRegistryKey ) +{ + try + { + String aImpl( '/' ); + aImpl += LngSvcMgr::getImplementationName_Static().getStr(); + aImpl.AppendAscii( "/UNO/SERVICES" ); + uno::Reference< registry::XRegistryKey > xNewKey = + pRegistryKey->createKey( aImpl ); + uno::Sequence< OUString > aServices = LngSvcMgr::getSupportedServiceNames_Static(); + for( INT32 i = 0; i < aServices.getLength(); i++ ) + xNewKey->createKey( aServices.getConstArray()[i] ); + + return sal_True; + } + catch(uno::Exception &) + { + return sal_False; + } +} + +void * SAL_CALL LngSvcMgr_getFactory( + const sal_Char * pImplName, + lang::XMultiServiceFactory * pServiceManager, + void * /*pRegistryKey*/ ) +{ + + void * pRet = 0; + if ( !LngSvcMgr::getImplementationName_Static().compareToAscii( pImplName ) ) + { + uno::Reference< lang::XSingleServiceFactory > xFactory = + cppu::createOneInstanceFactory( + pServiceManager, + LngSvcMgr::getImplementationName_Static(), + LngSvcMgr_CreateInstance, + LngSvcMgr::getSupportedServiceNames_Static()); + // acquire, because we return an interface pointer instead of a reference + xFactory->acquire(); + pRet = xFactory.get(); + } + return pRet; +} + + +/////////////////////////////////////////////////////////////////////////// + |