diff options
Diffstat (limited to 'linguistic/source/dlistimp.cxx')
-rw-r--r-- | linguistic/source/dlistimp.cxx | 933 |
1 files changed, 933 insertions, 0 deletions
diff --git a/linguistic/source/dlistimp.cxx b/linguistic/source/dlistimp.cxx new file mode 100644 index 000000000000..319cd9d56be8 --- /dev/null +++ b/linguistic/source/dlistimp.cxx @@ -0,0 +1,933 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cppuhelper/factory.hxx> +#include <i18npool/mslangid.hxx> +#include <osl/file.hxx> +#include <tools/fsys.hxx> +#include <tools/stream.hxx> +#include <tools/urlobj.hxx> +#include <i18npool/mslangid.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/useroptions.hxx> +#include <cppuhelper/factory.hxx> // helper for factories +#include <unotools/localfilehelper.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/linguistic2/DictionaryEventFlags.hpp> +#include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> + +#include "defs.hxx" +#include "dlistimp.hxx" +#include "dicimp.hxx" +#include "lngopt.hxx" + +#include "defs.hxx" +#include "dlistimp.hxx" +#include "dicimp.hxx" +#include "lngopt.hxx" + +using namespace osl; +using namespace com::sun::star; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace com::sun::star::linguistic2; +using namespace linguistic; + +using ::rtl::OUString; + + +static sal_Bool IsVers2OrNewer( const String& rFileURL, sal_uInt16& nLng, sal_Bool& bNeg ); + +static void AddInternal( const uno::Reference< XDictionary > &rDic, + const rtl::OUString& rNew ); +static void AddUserData( const uno::Reference< XDictionary > &rDic ); + + +class DicEvtListenerHelper : + public cppu::WeakImplHelper1 + < + XDictionaryEventListener + > +{ + cppu::OInterfaceContainerHelper aDicListEvtListeners; + uno::Sequence< DictionaryEvent > aCollectDicEvt; + uno::Reference< XDictionaryList > xMyDicList; + + sal_Int16 nCondensedEvt; + sal_Int16 nNumCollectEvtListeners, + nNumVerboseListeners; + +public: + DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList ); + virtual ~DicEvtListenerHelper(); + + // XEventListener + virtual void SAL_CALL + disposing( const EventObject& rSource ) + throw(RuntimeException); + + // XDictionaryEventListener + virtual void SAL_CALL + processDictionaryEvent( const DictionaryEvent& rDicEvent ) + throw(RuntimeException); + + // non-UNO functions + void DisposeAndClear( const EventObject &rEvtObj ); + + sal_Bool AddDicListEvtListener( + const uno::Reference< XDictionaryListEventListener >& rxListener, + sal_Bool bReceiveVerbose ); + sal_Bool RemoveDicListEvtListener( + const uno::Reference< XDictionaryListEventListener >& rxListener ); + sal_Int16 BeginCollectEvents(); + sal_Int16 EndCollectEvents(); + sal_Int16 FlushEvents(); + void ClearEvents() { nCondensedEvt = 0; } +}; + + +DicEvtListenerHelper::DicEvtListenerHelper( + const uno::Reference< XDictionaryList > &rxDicList ) : + aDicListEvtListeners ( GetLinguMutex() ), + xMyDicList ( rxDicList ) +{ + nCondensedEvt = 0; + nNumCollectEvtListeners = nNumVerboseListeners = 0; +} + + +DicEvtListenerHelper::~DicEvtListenerHelper() +{ + DBG_ASSERT(aDicListEvtListeners.getLength() == 0, + "lng : event listeners are still existing"); +} + + +void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj ) +{ + aDicListEvtListeners.disposeAndClear( rEvtObj ); +} + + +void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Reference< XInterface > xSrc( rSource.Source ); + + // remove event object from EventListener list + if (xSrc.is()) + aDicListEvtListeners.removeInterface( xSrc ); + + // if object is a dictionary then remove it from the dictionary list + // Note: this will probably happen only if someone makes a XDictionary + // implementation of his own that is also a XComponent. + uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY ); + if (xDic.is()) + { + xMyDicList->removeDictionary( xDic ); + } +} + + +void SAL_CALL DicEvtListenerHelper::processDictionaryEvent( + const DictionaryEvent& rDicEvent ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY ); + DBG_ASSERT(xDic.is(), "lng : missing event source"); + + // assert that there is a corresponding dictionary entry if one was + // added or deleted + uno::Reference< XDictionaryEntry > xDicEntry( rDicEvent.xDictionaryEntry, UNO_QUERY ); + DBG_ASSERT( !(rDicEvent.nEvent & + (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY)) + || xDicEntry.is(), + "lng : missing dictionary entry" ); + + // evaluate DictionaryEvents and update data for next DictionaryListEvent + DictionaryType eDicType = xDic->getDictionaryType(); + DBG_ASSERT(eDicType != DictionaryType_MIXED, + "lng : unexpected dictionary type"); + if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive()) + nCondensedEvt |= xDicEntry->isNegative() ? + DictionaryListEventFlags::ADD_NEG_ENTRY : + DictionaryListEventFlags::ADD_POS_ENTRY; + if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive()) + nCondensedEvt |= xDicEntry->isNegative() ? + DictionaryListEventFlags::DEL_NEG_ENTRY : + DictionaryListEventFlags::DEL_POS_ENTRY; + if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive()) + nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? + DictionaryListEventFlags::DEL_NEG_ENTRY : + DictionaryListEventFlags::DEL_POS_ENTRY; + if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive()) + nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? + DictionaryListEventFlags::DEACTIVATE_NEG_DIC + | DictionaryListEventFlags::ACTIVATE_NEG_DIC : + DictionaryListEventFlags::DEACTIVATE_POS_DIC + | DictionaryListEventFlags::ACTIVATE_POS_DIC; + if ((rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC)) + nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? + DictionaryListEventFlags::ACTIVATE_NEG_DIC : + DictionaryListEventFlags::ACTIVATE_POS_DIC; + if ((rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC)) + nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? + DictionaryListEventFlags::DEACTIVATE_NEG_DIC : + DictionaryListEventFlags::DEACTIVATE_POS_DIC; + + // update list of collected events if needs to be + if (nNumVerboseListeners > 0) + { + sal_Int32 nColEvts = aCollectDicEvt.getLength(); + aCollectDicEvt.realloc( nColEvts + 1 ); + aCollectDicEvt.getArray()[ nColEvts ] = rDicEvent; + } + + if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0) + FlushEvents(); +} + + +sal_Bool DicEvtListenerHelper::AddDicListEvtListener( + const uno::Reference< XDictionaryListEventListener >& xListener, + sal_Bool /*bReceiveVerbose*/ ) +{ + DBG_ASSERT( xListener.is(), "empty reference" ); + sal_Int32 nCount = aDicListEvtListeners.getLength(); + return aDicListEvtListeners.addInterface( xListener ) != nCount; +} + + +sal_Bool DicEvtListenerHelper::RemoveDicListEvtListener( + const uno::Reference< XDictionaryListEventListener >& xListener ) +{ + DBG_ASSERT( xListener.is(), "empty reference" ); + sal_Int32 nCount = aDicListEvtListeners.getLength(); + return aDicListEvtListeners.removeInterface( xListener ) != nCount; +} + + +sal_Int16 DicEvtListenerHelper::BeginCollectEvents() +{ + return ++nNumCollectEvtListeners; +} + + +sal_Int16 DicEvtListenerHelper::EndCollectEvents() +{ + DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call"); + if (nNumCollectEvtListeners > 0) + { + FlushEvents(); + nNumCollectEvtListeners--; + } + + return nNumCollectEvtListeners; +} + + +sal_Int16 DicEvtListenerHelper::FlushEvents() +{ + if (0 != nCondensedEvt) + { + // build DictionaryListEvent to pass on to listeners + uno::Sequence< DictionaryEvent > aDicEvents; + if (nNumVerboseListeners > 0) + aDicEvents = aCollectDicEvt; + DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents ); + + // pass on event + cppu::OInterfaceIteratorHelper aIt( aDicListEvtListeners ); + while (aIt.hasMoreElements()) + { + uno::Reference< XDictionaryListEventListener > xRef( aIt.next(), UNO_QUERY ); + if (xRef.is()) + xRef->processDictionaryListEvent( aEvent ); + } + + // clear "list" of events + nCondensedEvt = 0; + aCollectDicEvt.realloc( 0 ); + } + + return nNumCollectEvtListeners; +} + + + + +void DicList::MyAppExitListener::AtExit() +{ + rMyDicList.SaveDics(); +} + + +DicList::DicList() : + aEvtListeners ( GetLinguMutex() ) +{ + pDicEvtLstnrHelper = new DicEvtListenerHelper( this ); + xDicEvtLstnrHelper = pDicEvtLstnrHelper; + bDisposing = sal_False; + bInCreation = sal_False; + + pExitListener = new MyAppExitListener( *this ); + xExitListener = pExitListener; + pExitListener->Activate(); +} + +DicList::~DicList() +{ + pExitListener->Deactivate(); +} + + +void DicList::SearchForDictionaries( + DictionaryVec_t&rDicList, + const String &rDicDirURL, + sal_Bool bIsWriteablePath ) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + const uno::Sequence< rtl::OUString > aDirCnt( utl::LocalFileHelper:: + GetFolderContents( rDicDirURL, sal_False ) ); + const rtl::OUString *pDirCnt = aDirCnt.getConstArray(); + sal_Int32 nEntries = aDirCnt.getLength(); + + String aDCN( String::CreateFromAscii( "dcn" ) ); + String aDCP( String::CreateFromAscii( "dcp" ) ); + for (sal_Int32 i = 0; i < nEntries; ++i) + { + String aURL( pDirCnt[i] ); + sal_uInt16 nLang = LANGUAGE_NONE; + sal_Bool bNeg = sal_False; + + if(!::IsVers2OrNewer( aURL, nLang, bNeg )) + { + // When not + xub_StrLen nPos = aURL.Search('.'); + String aExt(aURL.Copy(nPos + 1)); + aExt.ToLowerAscii(); + + if(aExt == aDCN) // negativ + bNeg = sal_True; + else if(aExt == aDCP) // positiv + bNeg = sal_False; + else + continue; // andere Files + } + + // Record in the list of Dictoinaries + // When it already exists don't record + sal_Int16 nSystemLanguage = MsLangId::getSystemLanguage(); + String aTmp1 = ToLower( aURL, nSystemLanguage ); + xub_StrLen nPos = aTmp1.SearchBackward( '/' ); + if (STRING_NOTFOUND != nPos) + aTmp1 = aTmp1.Copy( nPos + 1 ); + String aTmp2; + size_t j; + size_t nCount = rDicList.size(); + for(j = 0; j < nCount; j++) + { + aTmp2 = rDicList[j]->getName().getStr(); + aTmp2 = ToLower( aTmp2, nSystemLanguage ); + if(aTmp1 == aTmp2) + break; + } + if(j >= nCount) // dictionary not yet in DicList + { + // get decoded dictionary file name + INetURLObject aURLObj( aURL ); + String aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT, + true, INetURLObject::DECODE_WITH_CHARSET, + RTL_TEXTENCODING_UTF8 ); + + DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE; + uno::Reference< XDictionary > xDic = + new DictionaryNeo( aDicName, nLang, eType, aURL, bIsWriteablePath ); + + addDictionary( xDic ); + nCount++; + } + } +} + + +sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + sal_Int32 nPos = -1; + DictionaryVec_t& rDicList = GetOrCreateDicList(); + size_t n = rDicList.size(); + for (size_t i = 0; i < n; i++) + { + if ( rDicList[i] == xDic ) + return i; + } + return nPos; +} + + +uno::Reference< XInterface > SAL_CALL + DicList_CreateInstance( const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ ) + throw(Exception) +{ + uno::Reference< XInterface > xService = (cppu::OWeakObject *) new DicList; + return xService; +} + +sal_Int16 SAL_CALL DicList::getCount() throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return static_cast< sal_Int16 >(GetOrCreateDicList().size()); +} + +uno::Sequence< uno::Reference< XDictionary > > SAL_CALL + DicList::getDictionaries() + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + DictionaryVec_t& rDicList = GetOrCreateDicList(); + + uno::Sequence< uno::Reference< XDictionary > > aDics( rDicList.size() ); + uno::Reference< XDictionary > *pDic = aDics.getArray(); + + sal_Int32 n = (sal_uInt16) aDics.getLength(); + for (sal_Int32 i = 0; i < n; i++) + pDic[i] = rDicList[i]; + + return aDics; +} + +uno::Reference< XDictionary > SAL_CALL + DicList::getDictionaryByName( const rtl::OUString& aDictionaryName ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Reference< XDictionary > xDic; + DictionaryVec_t& rDicList = GetOrCreateDicList(); + size_t nCount = rDicList.size(); + for (size_t i = 0; i < nCount; i++) + { + const uno::Reference< XDictionary > &rDic = rDicList[i]; + if (rDic.is() && rDic->getName() == aDictionaryName) + { + xDic = rDic; + break; + } + } + + return xDic; +} + +sal_Bool SAL_CALL DicList::addDictionary( + const uno::Reference< XDictionary >& xDictionary ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (bDisposing) + return sal_False; + + sal_Bool bRes = sal_False; + if (xDictionary.is()) + { + DictionaryVec_t& rDicList = GetOrCreateDicList(); + rDicList.push_back( xDictionary ); + bRes = sal_True; + + // add listener helper to the dictionaries listener lists + xDictionary->addDictionaryEventListener( xDicEvtLstnrHelper ); + } + return bRes; +} + +sal_Bool SAL_CALL + DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (bDisposing) + return sal_False; + + sal_Bool bRes = sal_False; + sal_Int32 nPos = GetDicPos( xDictionary ); + if (nPos >= 0) + { + // remove dictionary list from the dictionaries listener lists + DictionaryVec_t& rDicList = GetOrCreateDicList(); + uno::Reference< XDictionary > xDic( rDicList[ nPos ] ); + DBG_ASSERT(xDic.is(), "lng : empty reference"); + if (xDic.is()) + { + // deactivate dictionary if not already done + xDic->setActive( sal_False ); + + xDic->removeDictionaryEventListener( xDicEvtLstnrHelper ); + } + + // remove element at nPos + rDicList.erase( rDicList.begin() + nPos ); + bRes = sal_True; + } + return bRes; +} + +sal_Bool SAL_CALL DicList::addDictionaryListEventListener( + const uno::Reference< XDictionaryListEventListener >& xListener, + sal_Bool bReceiveVerbose ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (bDisposing) + return sal_False; + + DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported"); + + sal_Bool bRes = sal_False; + if (xListener.is()) //! don't add empty references + { + bRes = pDicEvtLstnrHelper-> + AddDicListEvtListener( xListener, bReceiveVerbose ); + } + return bRes; +} + +sal_Bool SAL_CALL DicList::removeDictionaryListEventListener( + const uno::Reference< XDictionaryListEventListener >& xListener ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (bDisposing) + return sal_False; + + sal_Bool bRes = sal_False; + if(xListener.is()) + { + bRes = pDicEvtLstnrHelper->RemoveDicListEvtListener( xListener ); + } + return bRes; +} + +sal_Int16 SAL_CALL DicList::beginCollectEvents() throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return pDicEvtLstnrHelper->BeginCollectEvents(); +} + +sal_Int16 SAL_CALL DicList::endCollectEvents() throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return pDicEvtLstnrHelper->EndCollectEvents(); +} + +sal_Int16 SAL_CALL DicList::flushEvents() throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return pDicEvtLstnrHelper->FlushEvents(); +} + +uno::Reference< XDictionary > SAL_CALL + DicList::createDictionary( const rtl::OUString& rName, const Locale& rLocale, + DictionaryType eDicType, const rtl::OUString& rURL ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + sal_Int16 nLanguage = LocaleToLanguage( rLocale ); + bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath(), 0 ); + return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath ); +} + + +uno::Reference< XDictionaryEntry > SAL_CALL + DicList::queryDictionaryEntry( const rtl::OUString& rWord, const Locale& rLocale, + sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return SearchDicList( this, rWord, LocaleToLanguage( rLocale ), + bSearchPosDics, bSearchSpellEntry ); +} + + +void SAL_CALL + DicList::dispose() + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (!bDisposing) + { + bDisposing = sal_True; + EventObject aEvtObj( (XDictionaryList *) this ); + + aEvtListeners.disposeAndClear( aEvtObj ); + if (pDicEvtLstnrHelper) + pDicEvtLstnrHelper->DisposeAndClear( aEvtObj ); + + //! avoid creation of dictionaries if not already done + if (aDicList.size() > 0) + { + DictionaryVec_t& rDicList = GetOrCreateDicList(); + size_t nCount = rDicList.size(); + for (size_t i = 0; i < nCount; i++) + { + uno::Reference< XDictionary > xDic( rDicList[i], UNO_QUERY ); + + // save (modified) dictionaries + uno::Reference< frame::XStorable > xStor( xDic , UNO_QUERY ); + if (xStor.is()) + { + try + { + if (!xStor->isReadonly() && xStor->hasLocation()) + xStor->store(); + } + catch(Exception &) + { + } + } + + // release references to (members of) this object hold by + // dictionaries + if (xDic.is()) + xDic->removeDictionaryEventListener( xDicEvtLstnrHelper ); + } + } + xDicEvtLstnrHelper.clear(); + } +} + +void SAL_CALL + DicList::addEventListener( const uno::Reference< XEventListener >& rxListener ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (!bDisposing && rxListener.is()) + aEvtListeners.addInterface( rxListener ); +} + +void SAL_CALL + DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + if (!bDisposing && rxListener.is()) + aEvtListeners.removeInterface( rxListener ); +} + +void DicList::_CreateDicList() +{ + bInCreation = sal_True; + + // look for dictionaries + const rtl::OUString aWriteablePath( GetDictionaryWriteablePath() ); + uno::Sequence< rtl::OUString > aPaths( GetDictionaryPaths() ); + const rtl::OUString *pPaths = aPaths.getConstArray(); + for (sal_Int32 i = 0; i < aPaths.getLength(); ++i) + { + const sal_Bool bIsWriteablePath = (pPaths[i] == aWriteablePath); + SearchForDictionaries( aDicList, pPaths[i], bIsWriteablePath ); + } + + // create IgnoreAllList dictionary with empty URL (non persistent) + // and add it to list + rtl::OUString aDicName( A2OU( "IgnoreAllList" ) ); + uno::Reference< XDictionary > xIgnAll( + createDictionary( aDicName, CreateLocale( LANGUAGE_NONE ), + DictionaryType_POSITIVE, rtl::OUString() ) ); + if (xIgnAll.is()) + { + AddUserData( xIgnAll ); + xIgnAll->setActive( sal_True ); + addDictionary( xIgnAll ); + } + + + // evaluate list of dictionaries to be activated from configuration + //! to suppress overwriting the list of active dictionaries in the + //! configuration with incorrect arguments during the following + //! activation of the dictionaries + pDicEvtLstnrHelper->BeginCollectEvents(); + const uno::Sequence< rtl::OUString > aActiveDics( aOpt.GetActiveDics() ); + const rtl::OUString *pActiveDic = aActiveDics.getConstArray(); + sal_Int32 nLen = aActiveDics.getLength(); + for (sal_Int32 i = 0; i < nLen; ++i) + { + if (pActiveDic[i].getLength()) + { + uno::Reference< XDictionary > xDic( getDictionaryByName( pActiveDic[i] ) ); + if (xDic.is()) + xDic->setActive( sal_True ); + } + } + + // suppress collected events during creation of the dictionary list. + // there should be no events during creation. + pDicEvtLstnrHelper->ClearEvents(); + + pDicEvtLstnrHelper->EndCollectEvents(); + + bInCreation = sal_False; +} + + +void DicList::SaveDics() +{ + // save dics only if they have already been used/created. + //! don't create them just for the purpose of saving them ! + if (aDicList.size() > 0) + { + // save (modified) dictionaries + DictionaryVec_t& rDicList = GetOrCreateDicList(); + size_t nCount = rDicList.size();; + for (size_t i = 0; i < nCount; i++) + { + // save (modified) dictionaries + uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY ); + if (xStor.is()) + { + try + { + if (!xStor->isReadonly() && xStor->hasLocation()) + xStor->store(); + } + catch(Exception &) + { + } + } + } + } +} + + +// Service specific part + +rtl::OUString SAL_CALL DicList::getImplementationName( ) throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return getImplementationName_Static(); +} + + +sal_Bool SAL_CALL DicList::supportsService( const rtl::OUString& ServiceName ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); + const rtl::OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + + +uno::Sequence< rtl::OUString > SAL_CALL DicList::getSupportedServiceNames( ) + throw(RuntimeException) +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + return getSupportedServiceNames_Static(); +} + + +uno::Sequence< rtl::OUString > DicList::getSupportedServiceNames_Static() throw() +{ + osl::MutexGuard aGuard( GetLinguMutex() ); + + uno::Sequence< rtl::OUString > aSNS( 1 ); // more than 1 service possible + aSNS.getArray()[0] = A2OU( SN_DICTIONARY_LIST ); + return aSNS; +} + +void * SAL_CALL DicList_getFactory( const sal_Char * pImplName, + XMultiServiceFactory * pServiceManager, void * ) +{ + void * pRet = 0; + if ( !DicList::getImplementationName_Static().compareToAscii( pImplName ) ) + { + uno::Reference< XSingleServiceFactory > xFactory = + cppu::createOneInstanceFactory( + pServiceManager, + DicList::getImplementationName_Static(), + DicList_CreateInstance, + DicList::getSupportedServiceNames_Static()); + // acquire, because we return an interface pointer instead of a reference + xFactory->acquire(); + pRet = xFactory.get(); + } + return pRet; +} + + +xub_StrLen lcl_GetToken( String &rToken, + const String &rText, xub_StrLen nPos, const String &rDelim ) +{ + xub_StrLen nRes = STRING_LEN; + + if (rText.Len() == 0 || nPos >= rText.Len()) + rToken = String(); + else if (rDelim.Len() == 0) + { + rToken = rText; + if (rToken.Len()) + nRes = rText.Len(); + } + else + { + xub_StrLen i; + for (i = nPos; i < rText.Len(); ++i) + { + if (STRING_NOTFOUND != rDelim.Search( rText.GetChar(i) )) + break; + } + + if (i >= rText.Len()) // delimeter not found + rToken = rText.Copy( nPos ); + else + rToken = rText.Copy( nPos, sal::static_int_cast< xub_StrLen >((sal_Int32) i - nPos) ); + nRes = i + 1; // continue after found delimeter + } + + return nRes; +} + + +static void AddInternal( + const uno::Reference<XDictionary> &rDic, + const rtl::OUString& rNew ) +{ + if (rDic.is()) + { + //! TL TODO: word iterator should be used to break up the text + static const char *pDefWordDelim = + "!\"#$%&'()*+,-./:;<=>?[]\\_^`{|}~\t \n"; + ByteString aDummy( pDefWordDelim ); + String aDelim( aDummy, osl_getThreadTextEncoding() ); + aDelim.EraseAllChars( '.' ); + + String aToken; + xub_StrLen nPos = 0; + while (STRING_LEN != + (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim ))) + { + if( aToken.Len() && !IsNumeric( aToken ) ) + { + rDic->add( aToken, sal_False, rtl::OUString() ); + } + } + } +} + +static void AddUserData( const uno::Reference< XDictionary > &rDic ) +{ + if (rDic.is()) + { + SvtUserOptions aUserOpt; + AddInternal( rDic, aUserOpt.GetFullName() ); + AddInternal( rDic, aUserOpt.GetCompany() ); + AddInternal( rDic, aUserOpt.GetStreet() ); + AddInternal( rDic, aUserOpt.GetCity() ); + AddInternal( rDic, aUserOpt.GetTitle() ); + AddInternal( rDic, aUserOpt.GetPosition() ); + AddInternal( rDic, aUserOpt.GetEmail() ); + } +} + + +#if defined _MSC_VER +#pragma optimize("g",off) +#endif + +static sal_Bool IsVers2OrNewer( const String& rFileURL, sal_uInt16& nLng, sal_Bool& bNeg ) +{ + if (rFileURL.Len() == 0) + return sal_False; + String aDIC( GetDicExtension() ); + String aExt; + xub_StrLen nPos = rFileURL.SearchBackward( '.' ); + if (STRING_NOTFOUND != nPos) + aExt = rFileURL.Copy( nPos + 1 ); + aExt.ToLowerAscii(); + + if(aExt != aDIC) + return sal_False; + + // get stream to be used + uno::Reference< lang::XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() ); + + // get XInputStream stream + uno::Reference< io::XInputStream > xStream; + try + { + uno::Reference< ucb::XSimpleFileAccess > xAccess( xServiceFactory->createInstance( + A2OU( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW ); + xStream = xAccess->openFileRead( rFileURL ); + } + catch (uno::Exception & e) + { + DBG_ASSERT( 0, "failed to get input stream" ); + (void) e; + } + DBG_ASSERT( xStream.is(), "failed to get stream for read" ); + if (!xStream.is()) + return sal_False; + + SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) ); + + int nDicVersion = ReadDicVersion(pStream, nLng, bNeg); + if (2 == nDicVersion || nDicVersion >= 5) + return sal_True; + + return sal_False; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |