/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include #include #include #include #include #include #include #include #include #include // helper for factories #include #include #include #include #include #include #include #include #include #include #include #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(); rtl::OUString aDCN("dcn"); rtl::OUString aDCP("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 (aDCN.equals(aExt)) // negativ bNeg = sal_True; else if (aDCP.equals(aExt)) // 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.empty() ) { 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].isEmpty()) { 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.empty() ) { // 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 &rDic, const rtl::OUString& rNew ) { if (rDic.is()) { //! TL TODO: word iterator should be used to break up the text static const char aDefWordDelim[] = "!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n"; rtl::OUString aDelim(RTL_CONSTASCII_USTRINGPARAM(aDefWordDelim)); OSL_ENSURE(aDelim.indexOf(static_cast('.')) == -1, "ensure no '.'"); 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; rtl::OUString aDIC("dic"); String aExt; xub_StrLen nPos = rFileURL.SearchBackward( '.' ); if (STRING_NOTFOUND != nPos) aExt = rFileURL.Copy( nPos + 1 ); aExt.ToLowerAscii(); if (!aDIC.equals(aExt)) return sal_False; // get stream to be used uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); // get XInputStream stream uno::Reference< io::XInputStream > xStream; try { uno::Reference< ucb::XSimpleFileAccess2 > xAccess( ucb::SimpleFileAccess::create(xContext) ); xStream = xAccess->openFileRead( rFileURL ); } catch (const uno::Exception &) { DBG_ASSERT( 0, "failed to get input stream" ); } 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: */