| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 utl; |
| using namespace osl; |
| using namespace rtl; |
| 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; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| |
| 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" ); |
| |
| /*sal_Bool bActiveDicsModified = sal_False;*/ |
| // |
| // 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 )) |
| { |
| // Wenn kein |
| 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 |
| } |
| |
| // Aufnehmen in die Liste der Dictionaries |
| // Wenn existent nicht aufnehmen |
| // |
| 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 ); |
| } |
| } |
| } |
| } |
| |
| 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 ); // auch mehr als 1 Service moeglich |
| 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; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| |