Bump version to 6.4.7.2.M8
[LibreOffice.git] / linguistic / source / dlistimp.cxx
blobd97957a304b90992fdb036490657548cbacb50fc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cppuhelper/factory.hxx>
22 #include <i18nlangtag/mslangid.hxx>
23 #include <osl/file.hxx>
24 #include <tools/debug.hxx>
25 #include <tools/stream.hxx>
26 #include <tools/urlobj.hxx>
27 #include <unotools/useroptions.hxx>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <unotools/localfilehelper.hxx>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/sequence.hxx>
32 #include <unotools/ucbstreamhelper.hxx>
33 #include <com/sun/star/frame/XStorable.hpp>
34 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35 #include <com/sun/star/uno/Reference.h>
36 #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
37 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
38 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
39 #include <svtools/strings.hrc>
40 #include <unotools/resmgr.hxx>
41 #include <sal/log.hxx>
43 #include "defs.hxx"
44 #include "dlistimp.hxx"
45 #include "dicimp.hxx"
46 #include "lngopt.hxx"
47 #include "lngreg.hxx"
49 using namespace osl;
50 using namespace com::sun::star;
51 using namespace com::sun::star::lang;
52 using namespace com::sun::star::uno;
53 using namespace com::sun::star::linguistic2;
54 using namespace linguistic;
57 static bool IsVers2OrNewer( const OUString& rFileURL, LanguageType& nLng, bool& bNeg, OUString& aDicName );
59 static void AddInternal( const uno::Reference< XDictionary > &rDic,
60 const OUString& rNew );
61 static void AddUserData( const uno::Reference< XDictionary > &rDic );
64 class DicEvtListenerHelper :
65 public cppu::WeakImplHelper
67 XDictionaryEventListener
70 comphelper::OInterfaceContainerHelper2 aDicListEvtListeners;
71 uno::Reference< XDictionaryList > xMyDicList;
73 sal_Int16 nCondensedEvt;
74 sal_Int16 nNumCollectEvtListeners;
76 public:
77 explicit DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList );
78 virtual ~DicEvtListenerHelper() override;
80 // XEventListener
81 virtual void SAL_CALL
82 disposing( const EventObject& rSource ) override;
84 // XDictionaryEventListener
85 virtual void SAL_CALL
86 processDictionaryEvent( const DictionaryEvent& rDicEvent ) override;
88 // non-UNO functions
89 void DisposeAndClear( const EventObject &rEvtObj );
91 bool AddDicListEvtListener(
92 const uno::Reference< XDictionaryListEventListener >& rxListener );
93 bool RemoveDicListEvtListener(
94 const uno::Reference< XDictionaryListEventListener >& rxListener );
95 sal_Int16 BeginCollectEvents() { return ++nNumCollectEvtListeners;}
96 sal_Int16 EndCollectEvents();
97 sal_Int16 FlushEvents();
98 void ClearEvents() { nCondensedEvt = 0; }
102 DicEvtListenerHelper::DicEvtListenerHelper(
103 const uno::Reference< XDictionaryList > &rxDicList ) :
104 aDicListEvtListeners ( GetLinguMutex() ),
105 xMyDicList ( rxDicList )
107 nCondensedEvt = 0;
108 nNumCollectEvtListeners = 0;
112 DicEvtListenerHelper::~DicEvtListenerHelper()
114 DBG_ASSERT(aDicListEvtListeners.getLength() == 0,
115 "lng : event listeners are still existing");
119 void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj )
121 aDicListEvtListeners.disposeAndClear( rEvtObj );
125 void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource )
127 osl::MutexGuard aGuard( GetLinguMutex() );
129 uno::Reference< XInterface > xSrc( rSource.Source );
131 // remove event object from EventListener list
132 if (xSrc.is())
133 aDicListEvtListeners.removeInterface( xSrc );
135 // if object is a dictionary then remove it from the dictionary list
136 // Note: this will probably happen only if someone makes a XDictionary
137 // implementation of his own that is also a XComponent.
138 uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY );
139 if (xDic.is())
141 xMyDicList->removeDictionary( xDic );
146 void SAL_CALL DicEvtListenerHelper::processDictionaryEvent(
147 const DictionaryEvent& rDicEvent )
149 osl::MutexGuard aGuard( GetLinguMutex() );
151 uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY );
152 DBG_ASSERT(xDic.is(), "lng : missing event source");
154 // assert that there is a corresponding dictionary entry if one was
155 // added or deleted
156 DBG_ASSERT( !(rDicEvent.nEvent &
157 (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY))
158 || rDicEvent.xDictionaryEntry.is(),
159 "lng : missing dictionary entry" );
161 // evaluate DictionaryEvents and update data for next DictionaryListEvent
162 DictionaryType eDicType = xDic->getDictionaryType();
163 DBG_ASSERT(eDicType != DictionaryType_MIXED,
164 "lng : unexpected dictionary type");
165 if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive())
166 nCondensedEvt |= rDicEvent.xDictionaryEntry->isNegative() ?
167 DictionaryListEventFlags::ADD_NEG_ENTRY :
168 DictionaryListEventFlags::ADD_POS_ENTRY;
169 if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive())
170 nCondensedEvt |= rDicEvent.xDictionaryEntry->isNegative() ?
171 DictionaryListEventFlags::DEL_NEG_ENTRY :
172 DictionaryListEventFlags::DEL_POS_ENTRY;
173 if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive())
174 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
175 DictionaryListEventFlags::DEL_NEG_ENTRY :
176 DictionaryListEventFlags::DEL_POS_ENTRY;
177 if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive())
178 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
179 DictionaryListEventFlags::DEACTIVATE_NEG_DIC
180 | DictionaryListEventFlags::ACTIVATE_NEG_DIC :
181 DictionaryListEventFlags::DEACTIVATE_POS_DIC
182 | DictionaryListEventFlags::ACTIVATE_POS_DIC;
183 if (rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC)
184 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
185 DictionaryListEventFlags::ACTIVATE_NEG_DIC :
186 DictionaryListEventFlags::ACTIVATE_POS_DIC;
187 if (rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC)
188 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
189 DictionaryListEventFlags::DEACTIVATE_NEG_DIC :
190 DictionaryListEventFlags::DEACTIVATE_POS_DIC;
192 if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0)
193 FlushEvents();
197 bool DicEvtListenerHelper::AddDicListEvtListener(
198 const uno::Reference< XDictionaryListEventListener >& xListener )
200 DBG_ASSERT( xListener.is(), "empty reference" );
201 sal_Int32 nCount = aDicListEvtListeners.getLength();
202 return aDicListEvtListeners.addInterface( xListener ) != nCount;
206 bool DicEvtListenerHelper::RemoveDicListEvtListener(
207 const uno::Reference< XDictionaryListEventListener >& xListener )
209 DBG_ASSERT( xListener.is(), "empty reference" );
210 sal_Int32 nCount = aDicListEvtListeners.getLength();
211 return aDicListEvtListeners.removeInterface( xListener ) != nCount;
215 sal_Int16 DicEvtListenerHelper::EndCollectEvents()
217 DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call");
218 if (nNumCollectEvtListeners > 0)
220 FlushEvents();
221 nNumCollectEvtListeners--;
224 return nNumCollectEvtListeners;
228 sal_Int16 DicEvtListenerHelper::FlushEvents()
230 if (0 != nCondensedEvt)
232 // build DictionaryListEvent to pass on to listeners
233 uno::Sequence< DictionaryEvent > aDicEvents;
234 DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents );
236 // pass on event
237 aDicListEvtListeners.notifyEach( &XDictionaryListEventListener::processDictionaryListEvent, aEvent );
239 // clear "list" of events
240 nCondensedEvt = 0;
243 return nNumCollectEvtListeners;
247 void DicList::MyAppExitListener::AtExit()
249 rMyDicList.SaveDics();
253 DicList::DicList() :
254 aEvtListeners ( GetLinguMutex() )
256 mxDicEvtLstnrHelper = new DicEvtListenerHelper( this );
257 bDisposing = false;
258 bInCreation = false;
260 mxExitListener = new MyAppExitListener( *this );
261 mxExitListener->Activate();
264 DicList::~DicList()
266 mxExitListener->Deactivate();
270 void DicList::SearchForDictionaries(
271 DictionaryVec_t&rDicList,
272 const OUString &rDicDirURL,
273 bool bIsWriteablePath )
275 osl::MutexGuard aGuard( GetLinguMutex() );
277 const uno::Sequence< OUString > aDirCnt( utl::LocalFileHelper::
278 GetFolderContents( rDicDirURL, false ) );
280 for (const OUString& aURL : aDirCnt)
282 LanguageType nLang = LANGUAGE_NONE;
283 bool bNeg = false;
284 OUString aDicTitle = "";
286 if(!::IsVers2OrNewer( aURL, nLang, bNeg, aDicTitle ))
288 // When not
289 sal_Int32 nPos = aURL.indexOf('.');
290 OUString aExt( aURL.copy(nPos + 1).toAsciiLowerCase() );
292 if ("dcn" == aExt) // negative
293 bNeg = true;
294 else if ("dcp" == aExt) // positive
295 bNeg = false;
296 else
297 continue; // other files
300 // Record in the list of Dictionaries
301 // When it already exists don't record
302 LanguageType nSystemLanguage = MsLangId::getSystemLanguage();
303 OUString aTmp1 = ToLower( aURL, nSystemLanguage );
304 sal_Int32 nPos = aTmp1.lastIndexOf( '/' );
305 if (-1 != nPos)
306 aTmp1 = aTmp1.copy( nPos + 1 );
307 OUString aTmp2;
308 size_t j;
309 size_t nCount = rDicList.size();
310 for(j = 0; j < nCount; j++)
312 aTmp2 = rDicList[j]->getName();
313 aTmp2 = ToLower( aTmp2, nSystemLanguage );
314 if(aTmp1 == aTmp2)
315 break;
317 if(j >= nCount) // dictionary not yet in DicList
319 // get decoded dictionary file name
320 INetURLObject aURLObj( aURL );
321 OUString aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT,
322 true, INetURLObject::DecodeMechanism::WithCharset );
324 DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
325 uno::Reference< XDictionary > xDic =
326 new DictionaryNeo( aDicTitle.isEmpty() ? aDicName : aDicTitle, nLang, eType, aURL, bIsWriteablePath );
328 addDictionary( xDic );
329 nCount++;
335 sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic)
337 osl::MutexGuard aGuard( GetLinguMutex() );
339 DictionaryVec_t& rDicList = GetOrCreateDicList();
340 size_t n = rDicList.size();
341 for (size_t i = 0; i < n; i++)
343 if ( rDicList[i] == xDic )
344 return i;
346 return -1;
349 /// @throws Exception
350 static uno::Reference< XInterface >
351 DicList_CreateInstance( const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ )
353 uno::Reference< XInterface > xService = static_cast<cppu::OWeakObject *>(new DicList);
354 return xService;
357 sal_Int16 SAL_CALL DicList::getCount()
359 osl::MutexGuard aGuard( GetLinguMutex() );
360 return static_cast< sal_Int16 >(GetOrCreateDicList().size());
363 uno::Sequence< uno::Reference< XDictionary > > SAL_CALL
364 DicList::getDictionaries()
366 osl::MutexGuard aGuard( GetLinguMutex() );
368 DictionaryVec_t& rDicList = GetOrCreateDicList();
370 return comphelper::containerToSequence(rDicList);
373 uno::Reference< XDictionary > SAL_CALL
374 DicList::getDictionaryByName( const OUString& aDictionaryName )
376 osl::MutexGuard aGuard( GetLinguMutex() );
378 uno::Reference< XDictionary > xDic;
379 DictionaryVec_t& rDicList = GetOrCreateDicList();
380 size_t nCount = rDicList.size();
381 for (size_t i = 0; i < nCount; i++)
383 const uno::Reference< XDictionary > &rDic = rDicList[i];
384 if (rDic.is() && rDic->getName() == aDictionaryName)
386 xDic = rDic;
387 break;
391 return xDic;
394 sal_Bool SAL_CALL DicList::addDictionary(
395 const uno::Reference< XDictionary >& xDictionary )
397 osl::MutexGuard aGuard( GetLinguMutex() );
399 if (bDisposing)
400 return false;
402 bool bRes = false;
403 if (xDictionary.is())
405 DictionaryVec_t& rDicList = GetOrCreateDicList();
406 rDicList.push_back( xDictionary );
407 bRes = true;
409 // add listener helper to the dictionaries listener lists
410 xDictionary->addDictionaryEventListener( mxDicEvtLstnrHelper.get() );
412 return bRes;
415 sal_Bool SAL_CALL
416 DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary )
418 osl::MutexGuard aGuard( GetLinguMutex() );
420 if (bDisposing)
421 return false;
423 bool bRes = false;
424 sal_Int32 nPos = GetDicPos( xDictionary );
425 if (nPos >= 0)
427 // remove dictionary list from the dictionaries listener lists
428 DictionaryVec_t& rDicList = GetOrCreateDicList();
429 uno::Reference< XDictionary > xDic( rDicList[ nPos ] );
430 DBG_ASSERT(xDic.is(), "lng : empty reference");
431 if (xDic.is())
433 // deactivate dictionary if not already done
434 xDic->setActive( false );
436 xDic->removeDictionaryEventListener( mxDicEvtLstnrHelper.get() );
439 // remove element at nPos
440 rDicList.erase( rDicList.begin() + nPos );
441 bRes = true;
443 return bRes;
446 sal_Bool SAL_CALL DicList::addDictionaryListEventListener(
447 const uno::Reference< XDictionaryListEventListener >& xListener,
448 sal_Bool bReceiveVerbose )
450 osl::MutexGuard aGuard( GetLinguMutex() );
452 if (bDisposing)
453 return false;
455 DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported");
457 bool bRes = false;
458 if (xListener.is()) //! don't add empty references
460 bRes = mxDicEvtLstnrHelper->AddDicListEvtListener( xListener );
462 return bRes;
465 sal_Bool SAL_CALL DicList::removeDictionaryListEventListener(
466 const uno::Reference< XDictionaryListEventListener >& xListener )
468 osl::MutexGuard aGuard( GetLinguMutex() );
470 if (bDisposing)
471 return false;
473 bool bRes = false;
474 if(xListener.is())
476 bRes = mxDicEvtLstnrHelper->RemoveDicListEvtListener( xListener );
478 return bRes;
481 sal_Int16 SAL_CALL DicList::beginCollectEvents()
483 osl::MutexGuard aGuard( GetLinguMutex() );
484 return mxDicEvtLstnrHelper->BeginCollectEvents();
487 sal_Int16 SAL_CALL DicList::endCollectEvents()
489 osl::MutexGuard aGuard( GetLinguMutex() );
490 return mxDicEvtLstnrHelper->EndCollectEvents();
493 sal_Int16 SAL_CALL DicList::flushEvents()
495 osl::MutexGuard aGuard( GetLinguMutex() );
496 return mxDicEvtLstnrHelper->FlushEvents();
499 uno::Reference< XDictionary > SAL_CALL
500 DicList::createDictionary( const OUString& rName, const Locale& rLocale,
501 DictionaryType eDicType, const OUString& rURL )
503 osl::MutexGuard aGuard( GetLinguMutex() );
505 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
506 bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath() );
507 return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath );
511 uno::Reference< XDictionaryEntry > SAL_CALL
512 DicList::queryDictionaryEntry( const OUString& rWord, const Locale& rLocale,
513 sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry )
515 osl::MutexGuard aGuard( GetLinguMutex() );
516 return SearchDicList( this, rWord, LinguLocaleToLanguage( rLocale ),
517 bSearchPosDics, bSearchSpellEntry );
521 void SAL_CALL
522 DicList::dispose()
524 osl::MutexGuard aGuard( GetLinguMutex() );
526 if (!bDisposing)
528 bDisposing = true;
529 EventObject aEvtObj( static_cast<XDictionaryList *>(this) );
531 aEvtListeners.disposeAndClear( aEvtObj );
532 if (mxDicEvtLstnrHelper.is())
533 mxDicEvtLstnrHelper->DisposeAndClear( aEvtObj );
535 //! avoid creation of dictionaries if not already done
536 if ( !aDicList.empty() )
538 DictionaryVec_t& rDicList = GetOrCreateDicList();
539 size_t nCount = rDicList.size();
540 for (size_t i = 0; i < nCount; i++)
542 uno::Reference< XDictionary > xDic( rDicList[i], UNO_QUERY );
544 // save (modified) dictionaries
545 uno::Reference< frame::XStorable > xStor( xDic , UNO_QUERY );
546 if (xStor.is())
550 if (!xStor->isReadonly() && xStor->hasLocation())
551 xStor->store();
553 catch(Exception &)
558 // release references to (members of) this object hold by
559 // dictionaries
560 if (xDic.is())
561 xDic->removeDictionaryEventListener( mxDicEvtLstnrHelper.get() );
564 mxDicEvtLstnrHelper.clear();
568 void SAL_CALL
569 DicList::addEventListener( const uno::Reference< XEventListener >& rxListener )
571 osl::MutexGuard aGuard( GetLinguMutex() );
573 if (!bDisposing && rxListener.is())
574 aEvtListeners.addInterface( rxListener );
577 void SAL_CALL
578 DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener )
580 osl::MutexGuard aGuard( GetLinguMutex() );
582 if (!bDisposing && rxListener.is())
583 aEvtListeners.removeInterface( rxListener );
586 void DicList::CreateDicList()
588 bInCreation = true;
590 // look for dictionaries
591 const OUString aWriteablePath( GetDictionaryWriteablePath() );
592 std::vector< OUString > aPaths( GetDictionaryPaths() );
593 for (const OUString & aPath : aPaths)
595 const bool bIsWriteablePath = (aPath == aWriteablePath);
596 SearchForDictionaries( aDicList, aPath, bIsWriteablePath );
599 // create IgnoreAllList dictionary with empty URL (non persistent)
600 // and add it to list
601 std::locale loc(Translate::Create("svt"));
602 uno::Reference< XDictionary > xIgnAll(
603 createDictionary( Translate::get(STR_DESCRIPTION_IGNOREALLLIST, loc), LinguLanguageToLocale( LANGUAGE_NONE ),
604 DictionaryType_POSITIVE, OUString() ) );
605 if (xIgnAll.is())
607 AddUserData( xIgnAll );
608 xIgnAll->setActive( true );
609 addDictionary( xIgnAll );
613 // evaluate list of dictionaries to be activated from configuration
614 //! to suppress overwriting the list of active dictionaries in the
615 //! configuration with incorrect arguments during the following
616 //! activation of the dictionaries
617 mxDicEvtLstnrHelper->BeginCollectEvents();
618 const uno::Sequence< OUString > aActiveDics( aOpt.GetActiveDics() );
619 for (const OUString& rActiveDic : aActiveDics)
621 if (!rActiveDic.isEmpty())
623 uno::Reference< XDictionary > xDic( getDictionaryByName( rActiveDic ) );
624 if (xDic.is())
625 xDic->setActive( true );
629 // suppress collected events during creation of the dictionary list.
630 // there should be no events during creation.
631 mxDicEvtLstnrHelper->ClearEvents();
633 mxDicEvtLstnrHelper->EndCollectEvents();
635 bInCreation = false;
639 void DicList::SaveDics()
641 // save dics only if they have already been used/created.
642 //! don't create them just for the purpose of saving them !
643 if ( !aDicList.empty() )
645 // save (modified) dictionaries
646 DictionaryVec_t& rDicList = GetOrCreateDicList();
647 size_t nCount = rDicList.size();
648 for (size_t i = 0; i < nCount; i++)
650 // save (modified) dictionaries
651 uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY );
652 if (xStor.is())
656 if (!xStor->isReadonly() && xStor->hasLocation())
657 xStor->store();
659 catch(Exception &)
668 // Service specific part
670 OUString SAL_CALL DicList::getImplementationName( )
672 return getImplementationName_Static();
676 sal_Bool SAL_CALL DicList::supportsService( const OUString& ServiceName )
678 return cppu::supportsService(this, ServiceName);
681 uno::Sequence< OUString > SAL_CALL DicList::getSupportedServiceNames( )
683 return getSupportedServiceNames_Static();
687 uno::Sequence< OUString > DicList::getSupportedServiceNames_Static() throw()
689 return { "com.sun.star.linguistic2.DictionaryList" };
692 void * DicList_getFactory( const sal_Char * pImplName,
693 XMultiServiceFactory * pServiceManager )
695 void * pRet = nullptr;
696 if ( DicList::getImplementationName_Static().equalsAscii( pImplName ) )
698 uno::Reference< XSingleServiceFactory > xFactory =
699 cppu::createOneInstanceFactory(
700 pServiceManager,
701 DicList::getImplementationName_Static(),
702 DicList_CreateInstance,
703 DicList::getSupportedServiceNames_Static());
704 // acquire, because we return an interface pointer instead of a reference
705 xFactory->acquire();
706 pRet = xFactory.get();
708 return pRet;
712 static sal_Int32 lcl_GetToken( OUString &rToken,
713 const OUString &rText, sal_Int32 nPos, const OUString &rDelim )
715 sal_Int32 nRes = -1;
717 if (rText.isEmpty() || nPos >= rText.getLength())
718 rToken.clear();
719 else if (rDelim.isEmpty())
721 rToken = rText;
722 if (!rToken.isEmpty())
723 nRes = rText.getLength();
725 else
727 sal_Int32 i;
728 for (i = nPos; i < rText.getLength(); ++i)
730 if (-1 != rDelim.indexOf( rText[i] ))
731 break;
734 if (i >= rText.getLength()) // delimiter not found
735 rToken = rText.copy( nPos );
736 else
737 rToken = rText.copy( nPos, i - nPos );
738 nRes = i + 1; // continue after found delimiter
741 return nRes;
745 static void AddInternal(
746 const uno::Reference<XDictionary> &rDic,
747 const OUString& rNew )
749 if (rDic.is())
751 //! TL TODO: word iterator should be used to break up the text
752 OUString aDelim("!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n");
753 OSL_ENSURE(aDelim.indexOf(u'.') == -1,
754 "ensure no '.'");
756 OUString aToken;
757 sal_Int32 nPos = 0;
758 while (-1 != (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim )))
760 if( !aToken.isEmpty() && !IsNumeric( aToken ) )
762 rDic->add( aToken, false, OUString() );
768 static void AddUserData( const uno::Reference< XDictionary > &rDic )
770 if (rDic.is())
772 SvtUserOptions aUserOpt;
773 AddInternal( rDic, aUserOpt.GetFullName() );
774 AddInternal( rDic, aUserOpt.GetCompany() );
775 AddInternal( rDic, aUserOpt.GetStreet() );
776 AddInternal( rDic, aUserOpt.GetCity() );
777 AddInternal( rDic, aUserOpt.GetTitle() );
778 AddInternal( rDic, aUserOpt.GetPosition() );
779 AddInternal( rDic, aUserOpt.GetEmail() );
783 static bool IsVers2OrNewer( const OUString& rFileURL, LanguageType& nLng, bool& bNeg, OUString& aDicName )
785 if (rFileURL.isEmpty())
786 return false;
787 OUString aExt;
788 sal_Int32 nPos = rFileURL.lastIndexOf( '.' );
789 if (-1 != nPos)
790 aExt = rFileURL.copy( nPos + 1 ).toAsciiLowerCase();
792 if (aExt != "dic")
793 return false;
795 // get stream to be used
796 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
798 // get XInputStream stream
799 uno::Reference< io::XInputStream > xStream;
802 uno::Reference< ucb::XSimpleFileAccess3 > xAccess( ucb::SimpleFileAccess::create(xContext) );
803 xStream = xAccess->openFileRead( rFileURL );
805 catch (const uno::Exception &)
807 SAL_WARN( "linguistic", "failed to get input stream" );
809 DBG_ASSERT( xStream.is(), "failed to get stream for read" );
810 if (!xStream.is())
811 return false;
813 SvStreamPtr pStream( utl::UcbStreamHelper::CreateStream( xStream ) );
815 int nDicVersion = ReadDicVersion(pStream, nLng, bNeg, aDicName);
816 return 2 == nDicVersion || nDicVersion >= 5;
820 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */