bump product version to 5.0.4.1
[LibreOffice.git] / linguistic / source / dlistimp.cxx
blob7d39be0e0c2e2caf2593f554158984ac4aa0ff5f
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 <unotools/ucbstreamhelper.hxx>
32 #include <com/sun/star/frame/XStorable.hpp>
33 #include <com/sun/star/lang/Locale.hpp>
34 #include <com/sun/star/uno/Reference.h>
35 #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
36 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
37 #include <com/sun/star/registry/XRegistryKey.hpp>
38 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
40 #include "defs.hxx"
41 #include "dlistimp.hxx"
42 #include "dicimp.hxx"
43 #include "lngopt.hxx"
44 #include "lngreg.hxx"
46 using namespace osl;
47 using namespace com::sun::star;
48 using namespace com::sun::star::lang;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::linguistic2;
51 using namespace linguistic;
55 static bool IsVers2OrNewer( const OUString& rFileURL, sal_uInt16& nLng, bool& bNeg );
57 static void AddInternal( const uno::Reference< XDictionary > &rDic,
58 const OUString& rNew );
59 static void AddUserData( const uno::Reference< XDictionary > &rDic );
62 class DicEvtListenerHelper :
63 public cppu::WeakImplHelper1
65 XDictionaryEventListener
68 cppu::OInterfaceContainerHelper aDicListEvtListeners;
69 uno::Sequence< DictionaryEvent > aCollectDicEvt;
70 uno::Reference< XDictionaryList > xMyDicList;
72 sal_Int16 nCondensedEvt;
73 sal_Int16 nNumCollectEvtListeners,
74 nNumVerboseListeners;
76 public:
77 DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList );
78 virtual ~DicEvtListenerHelper();
80 // XEventListener
81 virtual void SAL_CALL
82 disposing( const EventObject& rSource )
83 throw(RuntimeException, std::exception) SAL_OVERRIDE;
85 // XDictionaryEventListener
86 virtual void SAL_CALL
87 processDictionaryEvent( const DictionaryEvent& rDicEvent )
88 throw(RuntimeException, std::exception) SAL_OVERRIDE;
90 // non-UNO functions
91 void DisposeAndClear( const EventObject &rEvtObj );
93 bool AddDicListEvtListener(
94 const uno::Reference< XDictionaryListEventListener >& rxListener,
95 bool bReceiveVerbose );
96 bool RemoveDicListEvtListener(
97 const uno::Reference< XDictionaryListEventListener >& rxListener );
98 sal_Int16 BeginCollectEvents() { return ++nNumCollectEvtListeners;}
99 sal_Int16 EndCollectEvents();
100 sal_Int16 FlushEvents();
101 void ClearEvents() { nCondensedEvt = 0; }
105 DicEvtListenerHelper::DicEvtListenerHelper(
106 const uno::Reference< XDictionaryList > &rxDicList ) :
107 aDicListEvtListeners ( GetLinguMutex() ),
108 xMyDicList ( rxDicList )
110 nCondensedEvt = 0;
111 nNumCollectEvtListeners = nNumVerboseListeners = 0;
115 DicEvtListenerHelper::~DicEvtListenerHelper()
117 DBG_ASSERT(aDicListEvtListeners.getLength() == 0,
118 "lng : event listeners are still existing");
122 void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj )
124 aDicListEvtListeners.disposeAndClear( rEvtObj );
128 void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource )
129 throw(RuntimeException, std::exception)
131 osl::MutexGuard aGuard( GetLinguMutex() );
133 uno::Reference< XInterface > xSrc( rSource.Source );
135 // remove event object from EventListener list
136 if (xSrc.is())
137 aDicListEvtListeners.removeInterface( xSrc );
139 // if object is a dictionary then remove it from the dictionary list
140 // Note: this will probably happen only if someone makes a XDictionary
141 // implementation of his own that is also a XComponent.
142 uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY );
143 if (xDic.is())
145 xMyDicList->removeDictionary( xDic );
150 void SAL_CALL DicEvtListenerHelper::processDictionaryEvent(
151 const DictionaryEvent& rDicEvent )
152 throw(RuntimeException, std::exception)
154 osl::MutexGuard aGuard( GetLinguMutex() );
156 uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY );
157 DBG_ASSERT(xDic.is(), "lng : missing event source");
159 // assert that there is a corresponding dictionary entry if one was
160 // added or deleted
161 uno::Reference< XDictionaryEntry > xDicEntry( rDicEvent.xDictionaryEntry, UNO_QUERY );
162 DBG_ASSERT( !(rDicEvent.nEvent &
163 (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY))
164 || xDicEntry.is(),
165 "lng : missing dictionary entry" );
167 // evaluate DictionaryEvents and update data for next DictionaryListEvent
168 DictionaryType eDicType = xDic->getDictionaryType();
169 DBG_ASSERT(eDicType != DictionaryType_MIXED,
170 "lng : unexpected dictionary type");
171 if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive())
172 nCondensedEvt |= xDicEntry->isNegative() ?
173 DictionaryListEventFlags::ADD_NEG_ENTRY :
174 DictionaryListEventFlags::ADD_POS_ENTRY;
175 if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive())
176 nCondensedEvt |= xDicEntry->isNegative() ?
177 DictionaryListEventFlags::DEL_NEG_ENTRY :
178 DictionaryListEventFlags::DEL_POS_ENTRY;
179 if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive())
180 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
181 DictionaryListEventFlags::DEL_NEG_ENTRY :
182 DictionaryListEventFlags::DEL_POS_ENTRY;
183 if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive())
184 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
185 DictionaryListEventFlags::DEACTIVATE_NEG_DIC
186 | DictionaryListEventFlags::ACTIVATE_NEG_DIC :
187 DictionaryListEventFlags::DEACTIVATE_POS_DIC
188 | DictionaryListEventFlags::ACTIVATE_POS_DIC;
189 if ((rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC))
190 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
191 DictionaryListEventFlags::ACTIVATE_NEG_DIC :
192 DictionaryListEventFlags::ACTIVATE_POS_DIC;
193 if ((rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC))
194 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
195 DictionaryListEventFlags::DEACTIVATE_NEG_DIC :
196 DictionaryListEventFlags::DEACTIVATE_POS_DIC;
198 // update list of collected events if needs to be
199 if (nNumVerboseListeners > 0)
201 sal_Int32 nColEvts = aCollectDicEvt.getLength();
202 aCollectDicEvt.realloc( nColEvts + 1 );
203 aCollectDicEvt.getArray()[ nColEvts ] = rDicEvent;
206 if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0)
207 FlushEvents();
211 bool DicEvtListenerHelper::AddDicListEvtListener(
212 const uno::Reference< XDictionaryListEventListener >& xListener,
213 bool /*bReceiveVerbose*/ )
215 DBG_ASSERT( xListener.is(), "empty reference" );
216 sal_Int32 nCount = aDicListEvtListeners.getLength();
217 return aDicListEvtListeners.addInterface( xListener ) != nCount;
221 bool DicEvtListenerHelper::RemoveDicListEvtListener(
222 const uno::Reference< XDictionaryListEventListener >& xListener )
224 DBG_ASSERT( xListener.is(), "empty reference" );
225 sal_Int32 nCount = aDicListEvtListeners.getLength();
226 return aDicListEvtListeners.removeInterface( xListener ) != nCount;
232 sal_Int16 DicEvtListenerHelper::EndCollectEvents()
234 DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call");
235 if (nNumCollectEvtListeners > 0)
237 FlushEvents();
238 nNumCollectEvtListeners--;
241 return nNumCollectEvtListeners;
245 sal_Int16 DicEvtListenerHelper::FlushEvents()
247 if (0 != nCondensedEvt)
249 // build DictionaryListEvent to pass on to listeners
250 uno::Sequence< DictionaryEvent > aDicEvents;
251 if (nNumVerboseListeners > 0)
252 aDicEvents = aCollectDicEvt;
253 DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents );
255 // pass on event
256 cppu::OInterfaceIteratorHelper aIt( aDicListEvtListeners );
257 while (aIt.hasMoreElements())
259 uno::Reference< XDictionaryListEventListener > xRef( aIt.next(), UNO_QUERY );
260 if (xRef.is())
261 xRef->processDictionaryListEvent( aEvent );
264 // clear "list" of events
265 nCondensedEvt = 0;
266 aCollectDicEvt.realloc( 0 );
269 return nNumCollectEvtListeners;
275 void DicList::MyAppExitListener::AtExit()
277 rMyDicList.SaveDics();
281 DicList::DicList() :
282 aEvtListeners ( GetLinguMutex() )
284 pDicEvtLstnrHelper = new DicEvtListenerHelper( this );
285 xDicEvtLstnrHelper = pDicEvtLstnrHelper;
286 bDisposing = false;
287 bInCreation = false;
289 pExitListener = new MyAppExitListener( *this );
290 xExitListener = pExitListener;
291 pExitListener->Activate();
294 DicList::~DicList()
296 pExitListener->Deactivate();
300 void DicList::SearchForDictionaries(
301 DictionaryVec_t&rDicList,
302 const OUString &rDicDirURL,
303 bool bIsWriteablePath )
305 osl::MutexGuard aGuard( GetLinguMutex() );
307 const uno::Sequence< OUString > aDirCnt( utl::LocalFileHelper::
308 GetFolderContents( rDicDirURL, false ) );
309 const OUString *pDirCnt = aDirCnt.getConstArray();
310 sal_Int32 nEntries = aDirCnt.getLength();
312 OUString aDCN("dcn");
313 OUString aDCP("dcp");
314 for (sal_Int32 i = 0; i < nEntries; ++i)
316 OUString aURL( pDirCnt[i] );
317 sal_uInt16 nLang = LANGUAGE_NONE;
318 bool bNeg = false;
320 if(!::IsVers2OrNewer( aURL, nLang, bNeg ))
322 // When not
323 sal_Int32 nPos = aURL.indexOf('.');
324 OUString aExt( aURL.copy(nPos + 1).toAsciiLowerCase() );
326 if (aDCN.equals(aExt)) // negativ
327 bNeg = true;
328 else if (aDCP.equals(aExt)) // positiv
329 bNeg = false;
330 else
331 continue; // andere Files
334 // Record in the list of Dictoinaries
335 // When it already exists don't record
336 sal_Int16 nSystemLanguage = MsLangId::getSystemLanguage();
337 OUString aTmp1 = ToLower( aURL, nSystemLanguage );
338 sal_Int32 nPos = aTmp1.lastIndexOf( '/' );
339 if (-1 != nPos)
340 aTmp1 = aTmp1.copy( nPos + 1 );
341 OUString aTmp2;
342 size_t j;
343 size_t nCount = rDicList.size();
344 for(j = 0; j < nCount; j++)
346 aTmp2 = rDicList[j]->getName().getStr();
347 aTmp2 = ToLower( aTmp2, nSystemLanguage );
348 if(aTmp1 == aTmp2)
349 break;
351 if(j >= nCount) // dictionary not yet in DicList
353 // get decoded dictionary file name
354 INetURLObject aURLObj( aURL );
355 OUString aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT,
356 true, INetURLObject::DECODE_WITH_CHARSET,
357 RTL_TEXTENCODING_UTF8 );
359 DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
360 uno::Reference< XDictionary > xDic =
361 new DictionaryNeo( aDicName, nLang, eType, aURL, bIsWriteablePath );
363 addDictionary( xDic );
364 nCount++;
370 sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic)
372 osl::MutexGuard aGuard( GetLinguMutex() );
374 sal_Int32 nPos = -1;
375 DictionaryVec_t& rDicList = GetOrCreateDicList();
376 size_t n = rDicList.size();
377 for (size_t i = 0; i < n; i++)
379 if ( rDicList[i] == xDic )
380 return i;
382 return nPos;
386 uno::Reference< XInterface > SAL_CALL
387 DicList_CreateInstance( const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ )
388 throw(Exception)
390 uno::Reference< XInterface > xService = (cppu::OWeakObject *) new DicList;
391 return xService;
394 sal_Int16 SAL_CALL DicList::getCount() throw(RuntimeException, std::exception)
396 osl::MutexGuard aGuard( GetLinguMutex() );
397 return static_cast< sal_Int16 >(GetOrCreateDicList().size());
400 uno::Sequence< uno::Reference< XDictionary > > SAL_CALL
401 DicList::getDictionaries()
402 throw(RuntimeException, std::exception)
404 osl::MutexGuard aGuard( GetLinguMutex() );
406 DictionaryVec_t& rDicList = GetOrCreateDicList();
408 uno::Sequence< uno::Reference< XDictionary > > aDics( rDicList.size() );
409 uno::Reference< XDictionary > *pDic = aDics.getArray();
411 sal_Int32 n = (sal_uInt16) aDics.getLength();
412 for (sal_Int32 i = 0; i < n; i++)
413 pDic[i] = rDicList[i];
415 return aDics;
418 uno::Reference< XDictionary > SAL_CALL
419 DicList::getDictionaryByName( const OUString& aDictionaryName )
420 throw(RuntimeException, std::exception)
422 osl::MutexGuard aGuard( GetLinguMutex() );
424 uno::Reference< XDictionary > xDic;
425 DictionaryVec_t& rDicList = GetOrCreateDicList();
426 size_t nCount = rDicList.size();
427 for (size_t i = 0; i < nCount; i++)
429 const uno::Reference< XDictionary > &rDic = rDicList[i];
430 if (rDic.is() && rDic->getName() == aDictionaryName)
432 xDic = rDic;
433 break;
437 return xDic;
440 sal_Bool SAL_CALL DicList::addDictionary(
441 const uno::Reference< XDictionary >& xDictionary )
442 throw(RuntimeException, std::exception)
444 osl::MutexGuard aGuard( GetLinguMutex() );
446 if (bDisposing)
447 return sal_False;
449 bool bRes = false;
450 if (xDictionary.is())
452 DictionaryVec_t& rDicList = GetOrCreateDicList();
453 rDicList.push_back( xDictionary );
454 bRes = true;
456 // add listener helper to the dictionaries listener lists
457 xDictionary->addDictionaryEventListener( xDicEvtLstnrHelper );
459 return bRes;
462 sal_Bool SAL_CALL
463 DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary )
464 throw(RuntimeException, std::exception)
466 osl::MutexGuard aGuard( GetLinguMutex() );
468 if (bDisposing)
469 return sal_False;
471 bool bRes = false;
472 sal_Int32 nPos = GetDicPos( xDictionary );
473 if (nPos >= 0)
475 // remove dictionary list from the dictionaries listener lists
476 DictionaryVec_t& rDicList = GetOrCreateDicList();
477 uno::Reference< XDictionary > xDic( rDicList[ nPos ] );
478 DBG_ASSERT(xDic.is(), "lng : empty reference");
479 if (xDic.is())
481 // deactivate dictionary if not already done
482 xDic->setActive( sal_False );
484 xDic->removeDictionaryEventListener( xDicEvtLstnrHelper );
487 // remove element at nPos
488 rDicList.erase( rDicList.begin() + nPos );
489 bRes = true;
491 return bRes;
494 sal_Bool SAL_CALL DicList::addDictionaryListEventListener(
495 const uno::Reference< XDictionaryListEventListener >& xListener,
496 sal_Bool bReceiveVerbose )
497 throw(RuntimeException, std::exception)
499 osl::MutexGuard aGuard( GetLinguMutex() );
501 if (bDisposing)
502 return sal_False;
504 DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported");
506 bool bRes = false;
507 if (xListener.is()) //! don't add empty references
509 bRes = pDicEvtLstnrHelper->
510 AddDicListEvtListener( xListener, bReceiveVerbose );
512 return bRes;
515 sal_Bool SAL_CALL DicList::removeDictionaryListEventListener(
516 const uno::Reference< XDictionaryListEventListener >& xListener )
517 throw(RuntimeException, std::exception)
519 osl::MutexGuard aGuard( GetLinguMutex() );
521 if (bDisposing)
522 return sal_False;
524 bool bRes = false;
525 if(xListener.is())
527 bRes = pDicEvtLstnrHelper->RemoveDicListEvtListener( xListener );
529 return bRes;
532 sal_Int16 SAL_CALL DicList::beginCollectEvents() throw(RuntimeException, std::exception)
534 osl::MutexGuard aGuard( GetLinguMutex() );
535 return pDicEvtLstnrHelper->BeginCollectEvents();
538 sal_Int16 SAL_CALL DicList::endCollectEvents() throw(RuntimeException, std::exception)
540 osl::MutexGuard aGuard( GetLinguMutex() );
541 return pDicEvtLstnrHelper->EndCollectEvents();
544 sal_Int16 SAL_CALL DicList::flushEvents() throw(RuntimeException, std::exception)
546 osl::MutexGuard aGuard( GetLinguMutex() );
547 return pDicEvtLstnrHelper->FlushEvents();
550 uno::Reference< XDictionary > SAL_CALL
551 DicList::createDictionary( const OUString& rName, const Locale& rLocale,
552 DictionaryType eDicType, const OUString& rURL )
553 throw(RuntimeException, std::exception)
555 osl::MutexGuard aGuard( GetLinguMutex() );
557 sal_Int16 nLanguage = LinguLocaleToLanguage( rLocale );
558 bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath(), 0 );
559 return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath );
563 uno::Reference< XDictionaryEntry > SAL_CALL
564 DicList::queryDictionaryEntry( const OUString& rWord, const Locale& rLocale,
565 sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry )
566 throw(RuntimeException, std::exception)
568 osl::MutexGuard aGuard( GetLinguMutex() );
569 return SearchDicList( this, rWord, LinguLocaleToLanguage( rLocale ),
570 bSearchPosDics, bSearchSpellEntry );
574 void SAL_CALL
575 DicList::dispose()
576 throw(RuntimeException, std::exception)
578 osl::MutexGuard aGuard( GetLinguMutex() );
580 if (!bDisposing)
582 bDisposing = true;
583 EventObject aEvtObj( (XDictionaryList *) this );
585 aEvtListeners.disposeAndClear( aEvtObj );
586 if (pDicEvtLstnrHelper)
587 pDicEvtLstnrHelper->DisposeAndClear( aEvtObj );
589 //! avoid creation of dictionaries if not already done
590 if ( !aDicList.empty() )
592 DictionaryVec_t& rDicList = GetOrCreateDicList();
593 size_t nCount = rDicList.size();
594 for (size_t i = 0; i < nCount; i++)
596 uno::Reference< XDictionary > xDic( rDicList[i], UNO_QUERY );
598 // save (modified) dictionaries
599 uno::Reference< frame::XStorable > xStor( xDic , UNO_QUERY );
600 if (xStor.is())
604 if (!xStor->isReadonly() && xStor->hasLocation())
605 xStor->store();
607 catch(Exception &)
612 // release references to (members of) this object hold by
613 // dictionaries
614 if (xDic.is())
615 xDic->removeDictionaryEventListener( xDicEvtLstnrHelper );
618 xDicEvtLstnrHelper.clear();
622 void SAL_CALL
623 DicList::addEventListener( const uno::Reference< XEventListener >& rxListener )
624 throw(RuntimeException, std::exception)
626 osl::MutexGuard aGuard( GetLinguMutex() );
628 if (!bDisposing && rxListener.is())
629 aEvtListeners.addInterface( rxListener );
632 void SAL_CALL
633 DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener )
634 throw(RuntimeException, std::exception)
636 osl::MutexGuard aGuard( GetLinguMutex() );
638 if (!bDisposing && rxListener.is())
639 aEvtListeners.removeInterface( rxListener );
642 void DicList::_CreateDicList()
644 bInCreation = true;
646 // look for dictionaries
647 const OUString aWriteablePath( GetDictionaryWriteablePath() );
648 uno::Sequence< OUString > aPaths( GetDictionaryPaths() );
649 const OUString *pPaths = aPaths.getConstArray();
650 for (sal_Int32 i = 0; i < aPaths.getLength(); ++i)
652 const bool bIsWriteablePath = (pPaths[i] == aWriteablePath);
653 SearchForDictionaries( aDicList, pPaths[i], bIsWriteablePath );
656 // create IgnoreAllList dictionary with empty URL (non persistent)
657 // and add it to list
658 OUString aDicName( "IgnoreAllList" );
659 uno::Reference< XDictionary > xIgnAll(
660 createDictionary( aDicName, LinguLanguageToLocale( LANGUAGE_NONE ),
661 DictionaryType_POSITIVE, OUString() ) );
662 if (xIgnAll.is())
664 AddUserData( xIgnAll );
665 xIgnAll->setActive( sal_True );
666 addDictionary( xIgnAll );
670 // evaluate list of dictionaries to be activated from configuration
671 //! to suppress overwriting the list of active dictionaries in the
672 //! configuration with incorrect arguments during the following
673 //! activation of the dictionaries
674 pDicEvtLstnrHelper->BeginCollectEvents();
675 const uno::Sequence< OUString > aActiveDics( aOpt.GetActiveDics() );
676 const OUString *pActiveDic = aActiveDics.getConstArray();
677 sal_Int32 nLen = aActiveDics.getLength();
678 for (sal_Int32 i = 0; i < nLen; ++i)
680 if (!pActiveDic[i].isEmpty())
682 uno::Reference< XDictionary > xDic( getDictionaryByName( pActiveDic[i] ) );
683 if (xDic.is())
684 xDic->setActive( sal_True );
688 // suppress collected events during creation of the dictionary list.
689 // there should be no events during creation.
690 pDicEvtLstnrHelper->ClearEvents();
692 pDicEvtLstnrHelper->EndCollectEvents();
694 bInCreation = false;
698 void DicList::SaveDics()
700 // save dics only if they have already been used/created.
701 //! don't create them just for the purpose of saving them !
702 if ( !aDicList.empty() )
704 // save (modified) dictionaries
705 DictionaryVec_t& rDicList = GetOrCreateDicList();
706 size_t nCount = rDicList.size();;
707 for (size_t i = 0; i < nCount; i++)
709 // save (modified) dictionaries
710 uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY );
711 if (xStor.is())
715 if (!xStor->isReadonly() && xStor->hasLocation())
716 xStor->store();
718 catch(Exception &)
727 // Service specific part
729 OUString SAL_CALL DicList::getImplementationName( ) throw(RuntimeException, std::exception)
731 osl::MutexGuard aGuard( GetLinguMutex() );
732 return getImplementationName_Static();
736 sal_Bool SAL_CALL DicList::supportsService( const OUString& ServiceName )
737 throw(RuntimeException, std::exception)
739 return cppu::supportsService(this, ServiceName);
742 uno::Sequence< OUString > SAL_CALL DicList::getSupportedServiceNames( )
743 throw(RuntimeException, std::exception)
745 osl::MutexGuard aGuard( GetLinguMutex() );
746 return getSupportedServiceNames_Static();
750 uno::Sequence< OUString > DicList::getSupportedServiceNames_Static() throw()
752 osl::MutexGuard aGuard( GetLinguMutex() );
754 uno::Sequence< OUString > aSNS( 1 ); // more than 1 service possible
755 aSNS.getArray()[0] = "com.sun.star.linguistic2.DictionaryList";
756 return aSNS;
759 void * SAL_CALL DicList_getFactory( const sal_Char * pImplName,
760 XMultiServiceFactory * pServiceManager, void * )
762 void * pRet = 0;
763 if ( DicList::getImplementationName_Static().equalsAscii( pImplName ) )
765 uno::Reference< XSingleServiceFactory > xFactory =
766 cppu::createOneInstanceFactory(
767 pServiceManager,
768 DicList::getImplementationName_Static(),
769 DicList_CreateInstance,
770 DicList::getSupportedServiceNames_Static());
771 // acquire, because we return an interface pointer instead of a reference
772 xFactory->acquire();
773 pRet = xFactory.get();
775 return pRet;
779 static sal_Int32 lcl_GetToken( OUString &rToken,
780 const OUString &rText, sal_Int32 nPos, const OUString &rDelim )
782 sal_Int32 nRes = -1;
784 if (rText.isEmpty() || nPos >= rText.getLength())
785 rToken.clear();
786 else if (rDelim.isEmpty())
788 rToken = rText;
789 if (!rToken.isEmpty())
790 nRes = rText.getLength();
792 else
794 sal_Int32 i;
795 for (i = nPos; i < rText.getLength(); ++i)
797 if (-1 != rDelim.indexOf( rText[i] ))
798 break;
801 if (i >= rText.getLength()) // delimiter not found
802 rToken = rText.copy( nPos );
803 else
804 rToken = rText.copy( nPos, i - nPos );
805 nRes = i + 1; // continue after found delimiter
808 return nRes;
812 static void AddInternal(
813 const uno::Reference<XDictionary> &rDic,
814 const OUString& rNew )
816 if (rDic.is())
818 //! TL TODO: word iterator should be used to break up the text
819 static const char aDefWordDelim[] =
820 "!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n";
821 OUString aDelim(aDefWordDelim);
822 OSL_ENSURE(aDelim.indexOf(static_cast<sal_Unicode>('.')) == -1,
823 "ensure no '.'");
825 OUString aToken;
826 sal_Int32 nPos = 0;
827 while (-1 !=
828 (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim )))
830 if( !aToken.isEmpty() && !IsNumeric( aToken ) )
832 rDic->add( aToken, sal_False, OUString() );
838 static void AddUserData( const uno::Reference< XDictionary > &rDic )
840 if (rDic.is())
842 SvtUserOptions aUserOpt;
843 AddInternal( rDic, aUserOpt.GetFullName() );
844 AddInternal( rDic, aUserOpt.GetCompany() );
845 AddInternal( rDic, aUserOpt.GetStreet() );
846 AddInternal( rDic, aUserOpt.GetCity() );
847 AddInternal( rDic, aUserOpt.GetTitle() );
848 AddInternal( rDic, aUserOpt.GetPosition() );
849 AddInternal( rDic, aUserOpt.GetEmail() );
853 static bool IsVers2OrNewer( const OUString& rFileURL, sal_uInt16& nLng, bool& bNeg )
855 if (rFileURL.isEmpty())
856 return false;
857 OUString aDIC("dic");
858 OUString aExt;
859 sal_Int32 nPos = rFileURL.lastIndexOf( '.' );
860 if (-1 != nPos)
861 aExt = rFileURL.copy( nPos + 1 ).toAsciiLowerCase();
863 if (aDIC != aExt)
864 return false;
866 // get stream to be used
867 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
869 // get XInputStream stream
870 uno::Reference< io::XInputStream > xStream;
873 uno::Reference< ucb::XSimpleFileAccess3 > xAccess( ucb::SimpleFileAccess::create(xContext) );
874 xStream = xAccess->openFileRead( rFileURL );
876 catch (const uno::Exception &)
878 DBG_ASSERT( false, "failed to get input stream" );
880 DBG_ASSERT( xStream.is(), "failed to get stream for read" );
881 if (!xStream.is())
882 return false;
884 SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) );
886 int nDicVersion = ReadDicVersion(pStream, nLng, bNeg);
887 if (2 == nDicVersion || nDicVersion >= 5)
888 return true;
890 return false;
894 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */