summaryrefslogtreecommitdiff
path: root/linguistic/source/dlistimp.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'linguistic/source/dlistimp.cxx')
-rw-r--r--linguistic/source/dlistimp.cxx944
1 files changed, 944 insertions, 0 deletions
diff --git a/linguistic/source/dlistimp.cxx b/linguistic/source/dlistimp.cxx
new file mode 100644
index 000000000000..14255d99d349
--- /dev/null
+++ b/linguistic/source/dlistimp.cxx
@@ -0,0 +1,944 @@
+/* -*- 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 );
+ }
+ }
+ }
+}
+
+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: */