Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / linguistic / source / dlistimp.cxx
blobe1b92d4a41a1f60070e73a81043f7f91287fb069
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/stream.hxx>
25 #include <tools/urlobj.hxx>
26 #include <unotools/pathoptions.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/Locale.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/registry/XRegistryKey.hpp>
39 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
40 #include <svtools/strings.hrc>
41 #include <unotools/resmgr.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 std::vector< DictionaryEvent > aCollectDicEvt;
72 uno::Reference< XDictionaryList > xMyDicList;
74 sal_Int16 nCondensedEvt;
75 sal_Int16 nNumCollectEvtListeners,
76 nNumVerboseListeners;
78 public:
79 explicit DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList );
80 virtual ~DicEvtListenerHelper() override;
82 // XEventListener
83 virtual void SAL_CALL
84 disposing( const EventObject& rSource ) override;
86 // XDictionaryEventListener
87 virtual void SAL_CALL
88 processDictionaryEvent( const DictionaryEvent& rDicEvent ) override;
90 // non-UNO functions
91 void DisposeAndClear( const EventObject &rEvtObj );
93 bool AddDicListEvtListener(
94 const uno::Reference< XDictionaryListEventListener >& rxListener );
95 bool RemoveDicListEvtListener(
96 const uno::Reference< XDictionaryListEventListener >& rxListener );
97 sal_Int16 BeginCollectEvents() { return ++nNumCollectEvtListeners;}
98 sal_Int16 EndCollectEvents();
99 sal_Int16 FlushEvents();
100 void ClearEvents() { nCondensedEvt = 0; }
104 DicEvtListenerHelper::DicEvtListenerHelper(
105 const uno::Reference< XDictionaryList > &rxDicList ) :
106 aDicListEvtListeners ( GetLinguMutex() ),
107 xMyDicList ( rxDicList )
109 nCondensedEvt = 0;
110 nNumCollectEvtListeners = nNumVerboseListeners = 0;
114 DicEvtListenerHelper::~DicEvtListenerHelper()
116 DBG_ASSERT(aDicListEvtListeners.getLength() == 0,
117 "lng : event listeners are still existing");
121 void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj )
123 aDicListEvtListeners.disposeAndClear( rEvtObj );
127 void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource )
129 osl::MutexGuard aGuard( GetLinguMutex() );
131 uno::Reference< XInterface > xSrc( rSource.Source );
133 // remove event object from EventListener list
134 if (xSrc.is())
135 aDicListEvtListeners.removeInterface( xSrc );
137 // if object is a dictionary then remove it from the dictionary list
138 // Note: this will probably happen only if someone makes a XDictionary
139 // implementation of his own that is also a XComponent.
140 uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY );
141 if (xDic.is())
143 xMyDicList->removeDictionary( xDic );
148 void SAL_CALL DicEvtListenerHelper::processDictionaryEvent(
149 const DictionaryEvent& rDicEvent )
151 osl::MutexGuard aGuard( GetLinguMutex() );
153 uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY );
154 DBG_ASSERT(xDic.is(), "lng : missing event source");
156 // assert that there is a corresponding dictionary entry if one was
157 // added or deleted
158 uno::Reference< XDictionaryEntry > xDicEntry( rDicEvent.xDictionaryEntry, UNO_QUERY );
159 DBG_ASSERT( !(rDicEvent.nEvent &
160 (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY))
161 || xDicEntry.is(),
162 "lng : missing dictionary entry" );
164 // evaluate DictionaryEvents and update data for next DictionaryListEvent
165 DictionaryType eDicType = xDic->getDictionaryType();
166 DBG_ASSERT(eDicType != DictionaryType_MIXED,
167 "lng : unexpected dictionary type");
168 if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive())
169 nCondensedEvt |= xDicEntry->isNegative() ?
170 DictionaryListEventFlags::ADD_NEG_ENTRY :
171 DictionaryListEventFlags::ADD_POS_ENTRY;
172 if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive())
173 nCondensedEvt |= xDicEntry->isNegative() ?
174 DictionaryListEventFlags::DEL_NEG_ENTRY :
175 DictionaryListEventFlags::DEL_POS_ENTRY;
176 if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive())
177 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
178 DictionaryListEventFlags::DEL_NEG_ENTRY :
179 DictionaryListEventFlags::DEL_POS_ENTRY;
180 if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive())
181 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
182 DictionaryListEventFlags::DEACTIVATE_NEG_DIC
183 | DictionaryListEventFlags::ACTIVATE_NEG_DIC :
184 DictionaryListEventFlags::DEACTIVATE_POS_DIC
185 | DictionaryListEventFlags::ACTIVATE_POS_DIC;
186 if (rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC)
187 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
188 DictionaryListEventFlags::ACTIVATE_NEG_DIC :
189 DictionaryListEventFlags::ACTIVATE_POS_DIC;
190 if (rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC)
191 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
192 DictionaryListEventFlags::DEACTIVATE_NEG_DIC :
193 DictionaryListEventFlags::DEACTIVATE_POS_DIC;
195 // update list of collected events if needs to be
196 if (nNumVerboseListeners > 0)
198 aCollectDicEvt.push_back(rDicEvent);
201 if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0)
202 FlushEvents();
206 bool DicEvtListenerHelper::AddDicListEvtListener(
207 const uno::Reference< XDictionaryListEventListener >& xListener )
209 DBG_ASSERT( xListener.is(), "empty reference" );
210 sal_Int32 nCount = aDicListEvtListeners.getLength();
211 return aDicListEvtListeners.addInterface( xListener ) != nCount;
215 bool DicEvtListenerHelper::RemoveDicListEvtListener(
216 const uno::Reference< XDictionaryListEventListener >& xListener )
218 DBG_ASSERT( xListener.is(), "empty reference" );
219 sal_Int32 nCount = aDicListEvtListeners.getLength();
220 return aDicListEvtListeners.removeInterface( xListener ) != nCount;
224 sal_Int16 DicEvtListenerHelper::EndCollectEvents()
226 DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call");
227 if (nNumCollectEvtListeners > 0)
229 FlushEvents();
230 nNumCollectEvtListeners--;
233 return nNumCollectEvtListeners;
237 sal_Int16 DicEvtListenerHelper::FlushEvents()
239 if (0 != nCondensedEvt)
241 // build DictionaryListEvent to pass on to listeners
242 uno::Sequence< DictionaryEvent > aDicEvents;
243 if (nNumVerboseListeners > 0)
244 aDicEvents = comphelper::containerToSequence(aCollectDicEvt);
245 DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents );
247 // pass on event
248 aDicListEvtListeners.notifyEach( &XDictionaryListEventListener::processDictionaryListEvent, aEvent );
250 // clear "list" of events
251 nCondensedEvt = 0;
252 aCollectDicEvt.clear();
255 return nNumCollectEvtListeners;
259 void DicList::MyAppExitListener::AtExit()
261 rMyDicList.SaveDics();
265 DicList::DicList() :
266 aEvtListeners ( GetLinguMutex() )
268 mxDicEvtLstnrHelper = new DicEvtListenerHelper( this );
269 bDisposing = false;
270 bInCreation = false;
272 mxExitListener = new MyAppExitListener( *this );
273 mxExitListener->Activate();
276 DicList::~DicList()
278 mxExitListener->Deactivate();
282 void DicList::SearchForDictionaries(
283 DictionaryVec_t&rDicList,
284 const OUString &rDicDirURL,
285 bool bIsWriteablePath )
287 osl::MutexGuard aGuard( GetLinguMutex() );
289 const uno::Sequence< OUString > aDirCnt( utl::LocalFileHelper::
290 GetFolderContents( rDicDirURL, false ) );
291 const OUString *pDirCnt = aDirCnt.getConstArray();
292 sal_Int32 nEntries = aDirCnt.getLength();
294 for (sal_Int32 i = 0; i < nEntries; ++i)
296 OUString aURL( pDirCnt[i] );
297 LanguageType nLang = LANGUAGE_NONE;
298 bool bNeg = false;
299 OUString aDicTitle = "";
301 if(!::IsVers2OrNewer( aURL, nLang, bNeg, aDicTitle ))
303 // When not
304 sal_Int32 nPos = aURL.indexOf('.');
305 OUString aExt( aURL.copy(nPos + 1).toAsciiLowerCase() );
307 if ("dcn" == aExt) // negative
308 bNeg = true;
309 else if ("dcp" == aExt) // positive
310 bNeg = false;
311 else
312 continue; // other files
315 // Record in the list of Dictionaries
316 // When it already exists don't record
317 LanguageType nSystemLanguage = MsLangId::getSystemLanguage();
318 OUString aTmp1 = ToLower( aURL, nSystemLanguage );
319 sal_Int32 nPos = aTmp1.lastIndexOf( '/' );
320 if (-1 != nPos)
321 aTmp1 = aTmp1.copy( nPos + 1 );
322 OUString aTmp2;
323 size_t j;
324 size_t nCount = rDicList.size();
325 for(j = 0; j < nCount; j++)
327 aTmp2 = rDicList[j]->getName();
328 aTmp2 = ToLower( aTmp2, nSystemLanguage );
329 if(aTmp1 == aTmp2)
330 break;
332 if(j >= nCount) // dictionary not yet in DicList
334 // get decoded dictionary file name
335 INetURLObject aURLObj( aURL );
336 OUString aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT,
337 true, INetURLObject::DecodeMechanism::WithCharset );
339 DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
340 uno::Reference< XDictionary > xDic =
341 new DictionaryNeo( aDicTitle.isEmpty() ? aDicName : aDicTitle, nLang, eType, aURL, bIsWriteablePath );
343 addDictionary( xDic );
344 nCount++;
350 sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic)
352 osl::MutexGuard aGuard( GetLinguMutex() );
354 DictionaryVec_t& rDicList = GetOrCreateDicList();
355 size_t n = rDicList.size();
356 for (size_t i = 0; i < n; i++)
358 if ( rDicList[i] == xDic )
359 return i;
361 return -1;
364 /// @throws Exception
365 uno::Reference< XInterface >
366 DicList_CreateInstance( const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ )
368 uno::Reference< XInterface > xService = static_cast<cppu::OWeakObject *>(new DicList);
369 return xService;
372 sal_Int16 SAL_CALL DicList::getCount()
374 osl::MutexGuard aGuard( GetLinguMutex() );
375 return static_cast< sal_Int16 >(GetOrCreateDicList().size());
378 uno::Sequence< uno::Reference< XDictionary > > SAL_CALL
379 DicList::getDictionaries()
381 osl::MutexGuard aGuard( GetLinguMutex() );
383 DictionaryVec_t& rDicList = GetOrCreateDicList();
385 return comphelper::containerToSequence(rDicList);
388 uno::Reference< XDictionary > SAL_CALL
389 DicList::getDictionaryByName( const OUString& aDictionaryName )
391 osl::MutexGuard aGuard( GetLinguMutex() );
393 uno::Reference< XDictionary > xDic;
394 DictionaryVec_t& rDicList = GetOrCreateDicList();
395 size_t nCount = rDicList.size();
396 for (size_t i = 0; i < nCount; i++)
398 const uno::Reference< XDictionary > &rDic = rDicList[i];
399 if (rDic.is() && rDic->getName() == aDictionaryName)
401 xDic = rDic;
402 break;
406 return xDic;
409 sal_Bool SAL_CALL DicList::addDictionary(
410 const uno::Reference< XDictionary >& xDictionary )
412 osl::MutexGuard aGuard( GetLinguMutex() );
414 if (bDisposing)
415 return false;
417 bool bRes = false;
418 if (xDictionary.is())
420 DictionaryVec_t& rDicList = GetOrCreateDicList();
421 rDicList.push_back( xDictionary );
422 bRes = true;
424 // add listener helper to the dictionaries listener lists
425 xDictionary->addDictionaryEventListener( mxDicEvtLstnrHelper.get() );
427 return bRes;
430 sal_Bool SAL_CALL
431 DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary )
433 osl::MutexGuard aGuard( GetLinguMutex() );
435 if (bDisposing)
436 return false;
438 bool bRes = false;
439 sal_Int32 nPos = GetDicPos( xDictionary );
440 if (nPos >= 0)
442 // remove dictionary list from the dictionaries listener lists
443 DictionaryVec_t& rDicList = GetOrCreateDicList();
444 uno::Reference< XDictionary > xDic( rDicList[ nPos ] );
445 DBG_ASSERT(xDic.is(), "lng : empty reference");
446 if (xDic.is())
448 // deactivate dictionary if not already done
449 xDic->setActive( false );
451 xDic->removeDictionaryEventListener( mxDicEvtLstnrHelper.get() );
454 // remove element at nPos
455 rDicList.erase( rDicList.begin() + nPos );
456 bRes = true;
458 return bRes;
461 sal_Bool SAL_CALL DicList::addDictionaryListEventListener(
462 const uno::Reference< XDictionaryListEventListener >& xListener,
463 sal_Bool bReceiveVerbose )
465 osl::MutexGuard aGuard( GetLinguMutex() );
467 if (bDisposing)
468 return false;
470 DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported");
472 bool bRes = false;
473 if (xListener.is()) //! don't add empty references
475 bRes = mxDicEvtLstnrHelper->AddDicListEvtListener( xListener );
477 return bRes;
480 sal_Bool SAL_CALL DicList::removeDictionaryListEventListener(
481 const uno::Reference< XDictionaryListEventListener >& xListener )
483 osl::MutexGuard aGuard( GetLinguMutex() );
485 if (bDisposing)
486 return false;
488 bool bRes = false;
489 if(xListener.is())
491 bRes = mxDicEvtLstnrHelper->RemoveDicListEvtListener( xListener );
493 return bRes;
496 sal_Int16 SAL_CALL DicList::beginCollectEvents()
498 osl::MutexGuard aGuard( GetLinguMutex() );
499 return mxDicEvtLstnrHelper->BeginCollectEvents();
502 sal_Int16 SAL_CALL DicList::endCollectEvents()
504 osl::MutexGuard aGuard( GetLinguMutex() );
505 return mxDicEvtLstnrHelper->EndCollectEvents();
508 sal_Int16 SAL_CALL DicList::flushEvents()
510 osl::MutexGuard aGuard( GetLinguMutex() );
511 return mxDicEvtLstnrHelper->FlushEvents();
514 uno::Reference< XDictionary > SAL_CALL
515 DicList::createDictionary( const OUString& rName, const Locale& rLocale,
516 DictionaryType eDicType, const OUString& rURL )
518 osl::MutexGuard aGuard( GetLinguMutex() );
520 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
521 bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath() );
522 return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath );
526 uno::Reference< XDictionaryEntry > SAL_CALL
527 DicList::queryDictionaryEntry( const OUString& rWord, const Locale& rLocale,
528 sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry )
530 osl::MutexGuard aGuard( GetLinguMutex() );
531 return SearchDicList( this, rWord, LinguLocaleToLanguage( rLocale ),
532 bSearchPosDics, bSearchSpellEntry );
536 void SAL_CALL
537 DicList::dispose()
539 osl::MutexGuard aGuard( GetLinguMutex() );
541 if (!bDisposing)
543 bDisposing = true;
544 EventObject aEvtObj( static_cast<XDictionaryList *>(this) );
546 aEvtListeners.disposeAndClear( aEvtObj );
547 if (mxDicEvtLstnrHelper.is())
548 mxDicEvtLstnrHelper->DisposeAndClear( aEvtObj );
550 //! avoid creation of dictionaries if not already done
551 if ( !aDicList.empty() )
553 DictionaryVec_t& rDicList = GetOrCreateDicList();
554 size_t nCount = rDicList.size();
555 for (size_t i = 0; i < nCount; i++)
557 uno::Reference< XDictionary > xDic( rDicList[i], UNO_QUERY );
559 // save (modified) dictionaries
560 uno::Reference< frame::XStorable > xStor( xDic , UNO_QUERY );
561 if (xStor.is())
565 if (!xStor->isReadonly() && xStor->hasLocation())
566 xStor->store();
568 catch(Exception &)
573 // release references to (members of) this object hold by
574 // dictionaries
575 if (xDic.is())
576 xDic->removeDictionaryEventListener( mxDicEvtLstnrHelper.get() );
579 mxDicEvtLstnrHelper.clear();
583 void SAL_CALL
584 DicList::addEventListener( const uno::Reference< XEventListener >& rxListener )
586 osl::MutexGuard aGuard( GetLinguMutex() );
588 if (!bDisposing && rxListener.is())
589 aEvtListeners.addInterface( rxListener );
592 void SAL_CALL
593 DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener )
595 osl::MutexGuard aGuard( GetLinguMutex() );
597 if (!bDisposing && rxListener.is())
598 aEvtListeners.removeInterface( rxListener );
601 void DicList::CreateDicList()
603 bInCreation = true;
605 // look for dictionaries
606 const OUString aWriteablePath( GetDictionaryWriteablePath() );
607 std::vector< OUString > aPaths( GetDictionaryPaths() );
608 for (OUString & aPath : aPaths)
610 const bool bIsWriteablePath = (aPath == aWriteablePath);
611 SearchForDictionaries( aDicList, aPath, bIsWriteablePath );
614 // create IgnoreAllList dictionary with empty URL (non persistent)
615 // and add it to list
616 std::locale loc(Translate::Create("svt"));
617 uno::Reference< XDictionary > xIgnAll(
618 createDictionary( Translate::get(STR_DESCRIPTION_IGNOREALLLIST, loc), LinguLanguageToLocale( LANGUAGE_NONE ),
619 DictionaryType_POSITIVE, OUString() ) );
620 if (xIgnAll.is())
622 AddUserData( xIgnAll );
623 xIgnAll->setActive( true );
624 addDictionary( xIgnAll );
628 // evaluate list of dictionaries to be activated from configuration
629 //! to suppress overwriting the list of active dictionaries in the
630 //! configuration with incorrect arguments during the following
631 //! activation of the dictionaries
632 mxDicEvtLstnrHelper->BeginCollectEvents();
633 const uno::Sequence< OUString > aActiveDics( aOpt.GetActiveDics() );
634 const OUString *pActiveDic = aActiveDics.getConstArray();
635 sal_Int32 nLen = aActiveDics.getLength();
636 for (sal_Int32 i = 0; i < nLen; ++i)
638 if (!pActiveDic[i].isEmpty())
640 uno::Reference< XDictionary > xDic( getDictionaryByName( pActiveDic[i] ) );
641 if (xDic.is())
642 xDic->setActive( true );
646 // suppress collected events during creation of the dictionary list.
647 // there should be no events during creation.
648 mxDicEvtLstnrHelper->ClearEvents();
650 mxDicEvtLstnrHelper->EndCollectEvents();
652 bInCreation = false;
656 void DicList::SaveDics()
658 // save dics only if they have already been used/created.
659 //! don't create them just for the purpose of saving them !
660 if ( !aDicList.empty() )
662 // save (modified) dictionaries
663 DictionaryVec_t& rDicList = GetOrCreateDicList();
664 size_t nCount = rDicList.size();
665 for (size_t i = 0; i < nCount; i++)
667 // save (modified) dictionaries
668 uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY );
669 if (xStor.is())
673 if (!xStor->isReadonly() && xStor->hasLocation())
674 xStor->store();
676 catch(Exception &)
685 // Service specific part
687 OUString SAL_CALL DicList::getImplementationName( )
689 return getImplementationName_Static();
693 sal_Bool SAL_CALL DicList::supportsService( const OUString& ServiceName )
695 return cppu::supportsService(this, ServiceName);
698 uno::Sequence< OUString > SAL_CALL DicList::getSupportedServiceNames( )
700 return getSupportedServiceNames_Static();
704 uno::Sequence< OUString > DicList::getSupportedServiceNames_Static() throw()
706 uno::Sequence< OUString > aSNS { "com.sun.star.linguistic2.DictionaryList" };
707 return aSNS;
710 void * DicList_getFactory( const sal_Char * pImplName,
711 XMultiServiceFactory * pServiceManager )
713 void * pRet = nullptr;
714 if ( DicList::getImplementationName_Static().equalsAscii( pImplName ) )
716 uno::Reference< XSingleServiceFactory > xFactory =
717 cppu::createOneInstanceFactory(
718 pServiceManager,
719 DicList::getImplementationName_Static(),
720 DicList_CreateInstance,
721 DicList::getSupportedServiceNames_Static());
722 // acquire, because we return an interface pointer instead of a reference
723 xFactory->acquire();
724 pRet = xFactory.get();
726 return pRet;
730 static sal_Int32 lcl_GetToken( OUString &rToken,
731 const OUString &rText, sal_Int32 nPos, const OUString &rDelim )
733 sal_Int32 nRes = -1;
735 if (rText.isEmpty() || nPos >= rText.getLength())
736 rToken.clear();
737 else if (rDelim.isEmpty())
739 rToken = rText;
740 if (!rToken.isEmpty())
741 nRes = rText.getLength();
743 else
745 sal_Int32 i;
746 for (i = nPos; i < rText.getLength(); ++i)
748 if (-1 != rDelim.indexOf( rText[i] ))
749 break;
752 if (i >= rText.getLength()) // delimiter not found
753 rToken = rText.copy( nPos );
754 else
755 rToken = rText.copy( nPos, i - nPos );
756 nRes = i + 1; // continue after found delimiter
759 return nRes;
763 static void AddInternal(
764 const uno::Reference<XDictionary> &rDic,
765 const OUString& rNew )
767 if (rDic.is())
769 //! TL TODO: word iterator should be used to break up the text
770 OUString aDelim("!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n");
771 OSL_ENSURE(aDelim.indexOf(u'.') == -1,
772 "ensure no '.'");
774 OUString aToken;
775 sal_Int32 nPos = 0;
776 while (-1 != (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim )))
778 if( !aToken.isEmpty() && !IsNumeric( aToken ) )
780 rDic->add( aToken, false, OUString() );
786 static void AddUserData( const uno::Reference< XDictionary > &rDic )
788 if (rDic.is())
790 SvtUserOptions aUserOpt;
791 AddInternal( rDic, aUserOpt.GetFullName() );
792 AddInternal( rDic, aUserOpt.GetCompany() );
793 AddInternal( rDic, aUserOpt.GetStreet() );
794 AddInternal( rDic, aUserOpt.GetCity() );
795 AddInternal( rDic, aUserOpt.GetTitle() );
796 AddInternal( rDic, aUserOpt.GetPosition() );
797 AddInternal( rDic, aUserOpt.GetEmail() );
801 static bool IsVers2OrNewer( const OUString& rFileURL, LanguageType& nLng, bool& bNeg, OUString& aDicName )
803 if (rFileURL.isEmpty())
804 return false;
805 OUString aExt;
806 sal_Int32 nPos = rFileURL.lastIndexOf( '.' );
807 if (-1 != nPos)
808 aExt = rFileURL.copy( nPos + 1 ).toAsciiLowerCase();
810 if (aExt != "dic")
811 return false;
813 // get stream to be used
814 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
816 // get XInputStream stream
817 uno::Reference< io::XInputStream > xStream;
820 uno::Reference< ucb::XSimpleFileAccess3 > xAccess( ucb::SimpleFileAccess::create(xContext) );
821 xStream = xAccess->openFileRead( rFileURL );
823 catch (const uno::Exception &)
825 SAL_WARN( "linguistic", "failed to get input stream" );
827 DBG_ASSERT( xStream.is(), "failed to get stream for read" );
828 if (!xStream.is())
829 return false;
831 SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) );
833 int nDicVersion = ReadDicVersion(pStream, nLng, bNeg, aDicName);
834 return 2 == nDicVersion || nDicVersion >= 5;
838 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */