Update ooo320-m1
[ooovba.git] / linguistic / source / dlistimp.cxx
blob0436504c2b141210c99e595e06834e98d7fc0810
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dlistimp.cxx,v $
10 * $Revision: 1.21 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_linguistic.hxx"
33 #include "dlistimp.hxx"
34 #include "dicimp.hxx"
35 #include "lngopt.hxx"
37 #include <osl/file.hxx>
38 #include <tools/fsys.hxx>
39 #include <tools/stream.hxx>
40 #include <tools/urlobj.hxx>
41 #include <i18npool/mslangid.hxx>
42 #include <svtools/pathoptions.hxx>
43 #include <svtools/useroptions.hxx>
44 #include <sfx2/docfile.hxx>
45 #include <vcl/svapp.hxx>
46 #include <cppuhelper/factory.hxx> // helper for factories
47 #include <unotools/localfilehelper.hxx>
48 #include <com/sun/star/frame/XStorable.hpp>
49 #include <com/sun/star/lang/Locale.hpp>
50 #include <com/sun/star/uno/Reference.h>
51 #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
52 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
53 #include <com/sun/star/registry/XRegistryKey.hpp>
55 //using namespace utl;
56 using namespace osl;
57 using namespace rtl;
58 using namespace com::sun::star;
59 using namespace com::sun::star::lang;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::linguistic2;
62 using namespace linguistic;
64 ///////////////////////////////////////////////////////////////////////////
66 static BOOL IsVers2OrNewer( const String& rFileURL, USHORT& nLng, BOOL& bNeg );
68 static void AddInternal( const uno::Reference< XDictionary > &rDic,
69 const rtl::OUString& rNew );
70 static void AddUserData( const uno::Reference< XDictionary > &rDic );
72 ///////////////////////////////////////////////////////////////////////////
74 class DicEvtListenerHelper :
75 public cppu::WeakImplHelper1
77 XDictionaryEventListener
80 cppu::OInterfaceContainerHelper aDicListEvtListeners;
81 uno::Sequence< DictionaryEvent > aCollectDicEvt;
82 uno::Reference< XDictionaryList > xMyDicList;
84 INT16 nCondensedEvt;
85 INT16 nNumCollectEvtListeners,
86 nNumVerboseListeners;
88 public:
89 DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList );
90 virtual ~DicEvtListenerHelper();
92 // XEventListener
93 virtual void SAL_CALL
94 disposing( const EventObject& rSource )
95 throw(RuntimeException);
97 // XDictionaryEventListener
98 virtual void SAL_CALL
99 processDictionaryEvent( const DictionaryEvent& rDicEvent )
100 throw(RuntimeException);
102 // non-UNO functions
103 void DisposeAndClear( const EventObject &rEvtObj );
105 BOOL AddDicListEvtListener(
106 const uno::Reference< XDictionaryListEventListener >& rxListener,
107 BOOL bReceiveVerbose );
108 BOOL RemoveDicListEvtListener(
109 const uno::Reference< XDictionaryListEventListener >& rxListener );
110 INT16 BeginCollectEvents();
111 INT16 EndCollectEvents();
112 INT16 FlushEvents();
113 void ClearEvents() { nCondensedEvt = 0; }
117 DicEvtListenerHelper::DicEvtListenerHelper(
118 const uno::Reference< XDictionaryList > &rxDicList ) :
119 aDicListEvtListeners ( GetLinguMutex() ),
120 xMyDicList ( rxDicList )
122 nCondensedEvt = 0;
123 nNumCollectEvtListeners = nNumVerboseListeners = 0;
127 DicEvtListenerHelper::~DicEvtListenerHelper()
129 DBG_ASSERT(aDicListEvtListeners.getLength() == 0,
130 "lng : event listeners are still existing");
134 void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj )
136 aDicListEvtListeners.disposeAndClear( rEvtObj );
140 void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource )
141 throw(RuntimeException)
143 osl::MutexGuard aGuard( GetLinguMutex() );
145 uno::Reference< XInterface > xSrc( rSource.Source );
147 // remove event object from EventListener list
148 if (xSrc.is())
149 aDicListEvtListeners.removeInterface( xSrc );
151 // if object is a dictionary then remove it from the dictionary list
152 // Note: this will probably happen only if someone makes a XDictionary
153 // implementation of his own that is also a XComponent.
154 uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY );
155 if (xDic.is())
157 xMyDicList->removeDictionary( xDic );
162 void SAL_CALL DicEvtListenerHelper::processDictionaryEvent(
163 const DictionaryEvent& rDicEvent )
164 throw(RuntimeException)
166 osl::MutexGuard aGuard( GetLinguMutex() );
168 uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY );
169 DBG_ASSERT(xDic.is(), "lng : missing event source");
171 // assert that there is a corresponding dictionary entry if one was
172 // added or deleted
173 uno::Reference< XDictionaryEntry > xDicEntry( rDicEvent.xDictionaryEntry, UNO_QUERY );
174 DBG_ASSERT( !(rDicEvent.nEvent &
175 (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY))
176 || xDicEntry.is(),
177 "lng : missing dictionary entry" );
179 /*BOOL bActiveDicsModified = FALSE;*/
181 // evaluate DictionaryEvents and update data for next DictionaryListEvent
183 DictionaryType eDicType = xDic->getDictionaryType();
184 DBG_ASSERT(eDicType != DictionaryType_MIXED,
185 "lng : unexpected dictionary type");
186 if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive())
187 nCondensedEvt |= xDicEntry->isNegative() ?
188 DictionaryListEventFlags::ADD_NEG_ENTRY :
189 DictionaryListEventFlags::ADD_POS_ENTRY;
190 if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive())
191 nCondensedEvt |= xDicEntry->isNegative() ?
192 DictionaryListEventFlags::DEL_NEG_ENTRY :
193 DictionaryListEventFlags::DEL_POS_ENTRY;
194 if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive())
195 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
196 DictionaryListEventFlags::DEL_NEG_ENTRY :
197 DictionaryListEventFlags::DEL_POS_ENTRY;
198 if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive())
199 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
200 DictionaryListEventFlags::DEACTIVATE_NEG_DIC
201 | DictionaryListEventFlags::ACTIVATE_NEG_DIC :
202 DictionaryListEventFlags::DEACTIVATE_POS_DIC
203 | DictionaryListEventFlags::ACTIVATE_POS_DIC;
204 if ((rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC))
205 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
206 DictionaryListEventFlags::ACTIVATE_NEG_DIC :
207 DictionaryListEventFlags::ACTIVATE_POS_DIC;
208 if ((rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC))
209 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
210 DictionaryListEventFlags::DEACTIVATE_NEG_DIC :
211 DictionaryListEventFlags::DEACTIVATE_POS_DIC;
213 // update list of collected events if needs to be
214 if (nNumVerboseListeners > 0)
216 INT32 nColEvts = aCollectDicEvt.getLength();
217 aCollectDicEvt.realloc( nColEvts + 1 );
218 aCollectDicEvt.getArray()[ nColEvts ] = rDicEvent;
221 if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0)
222 FlushEvents();
226 BOOL DicEvtListenerHelper::AddDicListEvtListener(
227 const uno::Reference< XDictionaryListEventListener >& xListener,
228 BOOL /*bReceiveVerbose*/ )
230 DBG_ASSERT( xListener.is(), "empty reference" );
231 INT32 nCount = aDicListEvtListeners.getLength();
232 return aDicListEvtListeners.addInterface( xListener ) != nCount;
236 BOOL DicEvtListenerHelper::RemoveDicListEvtListener(
237 const uno::Reference< XDictionaryListEventListener >& xListener )
239 DBG_ASSERT( xListener.is(), "empty reference" );
240 INT32 nCount = aDicListEvtListeners.getLength();
241 return aDicListEvtListeners.removeInterface( xListener ) != nCount;
245 INT16 DicEvtListenerHelper::BeginCollectEvents()
247 return ++nNumCollectEvtListeners;
251 INT16 DicEvtListenerHelper::EndCollectEvents()
253 DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call");
254 if (nNumCollectEvtListeners > 0)
256 FlushEvents();
257 nNumCollectEvtListeners--;
260 return nNumCollectEvtListeners;
264 INT16 DicEvtListenerHelper::FlushEvents()
266 if (0 != nCondensedEvt)
268 // build DictionaryListEvent to pass on to listeners
269 uno::Sequence< DictionaryEvent > aDicEvents;
270 if (nNumVerboseListeners > 0)
271 aDicEvents = aCollectDicEvt;
272 DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents );
274 // pass on event
275 cppu::OInterfaceIteratorHelper aIt( aDicListEvtListeners );
276 while (aIt.hasMoreElements())
278 uno::Reference< XDictionaryListEventListener > xRef( aIt.next(), UNO_QUERY );
279 if (xRef.is())
280 xRef->processDictionaryListEvent( aEvent );
283 // clear "list" of events
284 nCondensedEvt = 0;
285 aCollectDicEvt.realloc( 0 );
288 return nNumCollectEvtListeners;
292 ///////////////////////////////////////////////////////////////////////////
295 void DicList::MyAppExitListener::AtExit()
297 rMyDicList.SaveDics();
301 DicList::DicList() :
302 aEvtListeners ( GetLinguMutex() )
304 pDicEvtLstnrHelper = new DicEvtListenerHelper( this );
305 xDicEvtLstnrHelper = pDicEvtLstnrHelper;
306 bDisposing = FALSE;
307 bInCreation = FALSE;
309 pExitListener = new MyAppExitListener( *this );
310 xExitListener = pExitListener;
311 pExitListener->Activate();
314 DicList::~DicList()
316 pExitListener->Deactivate();
320 void DicList::SearchForDictionaries(
321 DictionaryVec_t&rDicList,
322 const String &rDicDirURL,
323 BOOL bIsWriteablePath )
325 osl::MutexGuard aGuard( GetLinguMutex() );
327 const uno::Sequence< rtl::OUString > aDirCnt( utl::LocalFileHelper::
328 GetFolderContents( rDicDirURL, FALSE ) );
329 const rtl::OUString *pDirCnt = aDirCnt.getConstArray();
330 INT32 nEntries = aDirCnt.getLength();
332 String aDCN( String::CreateFromAscii( "dcn" ) );
333 String aDCP( String::CreateFromAscii( "dcp" ) );
334 for (INT32 i = 0; i < nEntries; ++i)
336 String aURL( pDirCnt[i] );
337 USHORT nLang = LANGUAGE_NONE;
338 BOOL bNeg = FALSE;
340 if(!::IsVers2OrNewer( aURL, nLang, bNeg ))
342 // Wenn kein
343 xub_StrLen nPos = aURL.Search('.');
344 String aExt(aURL.Copy(nPos + 1));
345 aExt.ToLowerAscii();
347 if(aExt == aDCN) // negativ
348 bNeg = TRUE;
349 else if(aExt == aDCP) // positiv
350 bNeg = FALSE;
351 else
352 continue; // andere Files
355 // Aufnehmen in die Liste der Dictionaries
356 // Wenn existent nicht aufnehmen
358 INT16 nSystemLanguage = MsLangId::getSystemLanguage();
359 String aTmp1 = ToLower( aURL, nSystemLanguage );
360 xub_StrLen nPos = aTmp1.SearchBackward( '/' );
361 if (STRING_NOTFOUND != nPos)
362 aTmp1 = aTmp1.Copy( nPos + 1 );
363 String aTmp2;
364 size_t j;
365 size_t nCount = rDicList.size();
366 for(j = 0; j < nCount; j++)
368 aTmp2 = rDicList[j]->getName().getStr();
369 aTmp2 = ToLower( aTmp2, nSystemLanguage );
370 if(aTmp1 == aTmp2)
371 break;
373 if(j >= nCount) // dictionary not yet in DicList
375 // get decoded dictionary file name
376 INetURLObject aURLObj( aURL );
377 String aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT,
378 true, INetURLObject::DECODE_WITH_CHARSET,
379 RTL_TEXTENCODING_UTF8 );
381 DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
382 uno::Reference< XDictionary > xDic =
383 new DictionaryNeo( aDicName, nLang, eType, aURL, bIsWriteablePath );
385 addDictionary( xDic );
386 nCount++;
392 INT32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic)
394 osl::MutexGuard aGuard( GetLinguMutex() );
396 INT32 nPos = -1;
397 DictionaryVec_t& rDicList = GetOrCreateDicList();
398 size_t n = rDicList.size();
399 for (size_t i = 0; i < n; i++)
401 if ( rDicList[i] == xDic )
402 return i;
404 return nPos;
408 uno::Reference< XInterface > SAL_CALL
409 DicList_CreateInstance( const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ )
410 throw(Exception)
412 uno::Reference< XInterface > xService = (cppu::OWeakObject *) new DicList;
413 return xService;
416 sal_Int16 SAL_CALL DicList::getCount() throw(RuntimeException)
418 osl::MutexGuard aGuard( GetLinguMutex() );
419 return static_cast< sal_Int16 >(GetOrCreateDicList().size());
422 uno::Sequence< uno::Reference< XDictionary > > SAL_CALL
423 DicList::getDictionaries()
424 throw(RuntimeException)
426 osl::MutexGuard aGuard( GetLinguMutex() );
428 DictionaryVec_t& rDicList = GetOrCreateDicList();
430 uno::Sequence< uno::Reference< XDictionary > > aDics( rDicList.size() );
431 uno::Reference< XDictionary > *pDic = aDics.getArray();
433 INT32 n = (USHORT) aDics.getLength();
434 for (INT32 i = 0; i < n; i++)
435 pDic[i] = rDicList[i];
437 return aDics;
440 uno::Reference< XDictionary > SAL_CALL
441 DicList::getDictionaryByName( const rtl::OUString& aDictionaryName )
442 throw(RuntimeException)
444 osl::MutexGuard aGuard( GetLinguMutex() );
446 uno::Reference< XDictionary > xDic;
447 DictionaryVec_t& rDicList = GetOrCreateDicList();
448 size_t nCount = rDicList.size();
449 for (size_t i = 0; i < nCount; i++)
451 const uno::Reference< XDictionary > &rDic = rDicList[i];
452 if (rDic.is() && rDic->getName() == aDictionaryName)
454 xDic = rDic;
455 break;
459 return xDic;
462 sal_Bool SAL_CALL DicList::addDictionary(
463 const uno::Reference< XDictionary >& xDictionary )
464 throw(RuntimeException)
466 osl::MutexGuard aGuard( GetLinguMutex() );
468 if (bDisposing)
469 return FALSE;
471 BOOL bRes = FALSE;
472 if (xDictionary.is())
474 DictionaryVec_t& rDicList = GetOrCreateDicList();
475 rDicList.push_back( xDictionary );
476 bRes = TRUE;
478 // add listener helper to the dictionaries listener lists
479 xDictionary->addDictionaryEventListener( xDicEvtLstnrHelper );
481 return bRes;
484 sal_Bool SAL_CALL
485 DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary )
486 throw(RuntimeException)
488 osl::MutexGuard aGuard( GetLinguMutex() );
490 if (bDisposing)
491 return FALSE;
493 BOOL bRes = FALSE;
494 INT32 nPos = GetDicPos( xDictionary );
495 if (nPos >= 0)
497 // remove dictionary list from the dictionaries listener lists
498 DictionaryVec_t& rDicList = GetOrCreateDicList();
499 uno::Reference< XDictionary > xDic( rDicList[ nPos ] );
500 DBG_ASSERT(xDic.is(), "lng : empty reference");
501 if (xDic.is())
503 // deactivate dictionary if not already done
504 xDic->setActive( FALSE );
506 xDic->removeDictionaryEventListener( xDicEvtLstnrHelper );
509 // remove element at nPos
510 rDicList.erase( rDicList.begin() + nPos );
511 bRes = TRUE;
513 return bRes;
516 sal_Bool SAL_CALL DicList::addDictionaryListEventListener(
517 const uno::Reference< XDictionaryListEventListener >& xListener,
518 sal_Bool bReceiveVerbose )
519 throw(RuntimeException)
521 osl::MutexGuard aGuard( GetLinguMutex() );
523 if (bDisposing)
524 return FALSE;
526 DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported");
528 BOOL bRes = FALSE;
529 if (xListener.is()) //! don't add empty references
531 bRes = pDicEvtLstnrHelper->
532 AddDicListEvtListener( xListener, bReceiveVerbose );
534 return bRes;
537 sal_Bool SAL_CALL DicList::removeDictionaryListEventListener(
538 const uno::Reference< XDictionaryListEventListener >& xListener )
539 throw(RuntimeException)
541 osl::MutexGuard aGuard( GetLinguMutex() );
543 if (bDisposing)
544 return FALSE;
546 BOOL bRes = FALSE;
547 if(xListener.is())
549 bRes = pDicEvtLstnrHelper->RemoveDicListEvtListener( xListener );
551 return bRes;
554 sal_Int16 SAL_CALL DicList::beginCollectEvents() throw(RuntimeException)
556 osl::MutexGuard aGuard( GetLinguMutex() );
557 return pDicEvtLstnrHelper->BeginCollectEvents();
560 sal_Int16 SAL_CALL DicList::endCollectEvents() throw(RuntimeException)
562 osl::MutexGuard aGuard( GetLinguMutex() );
563 return pDicEvtLstnrHelper->EndCollectEvents();
566 sal_Int16 SAL_CALL DicList::flushEvents() throw(RuntimeException)
568 osl::MutexGuard aGuard( GetLinguMutex() );
569 return pDicEvtLstnrHelper->FlushEvents();
572 uno::Reference< XDictionary > SAL_CALL
573 DicList::createDictionary( const rtl::OUString& rName, const Locale& rLocale,
574 DictionaryType eDicType, const rtl::OUString& rURL )
575 throw(RuntimeException)
577 osl::MutexGuard aGuard( GetLinguMutex() );
579 INT16 nLanguage = LocaleToLanguage( rLocale );
580 bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath(), 0 );
581 return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath );
585 uno::Reference< XDictionaryEntry > SAL_CALL
586 DicList::queryDictionaryEntry( const rtl::OUString& rWord, const Locale& rLocale,
587 sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry )
588 throw(RuntimeException)
590 osl::MutexGuard aGuard( GetLinguMutex() );
591 return SearchDicList( this, rWord, LocaleToLanguage( rLocale ),
592 bSearchPosDics, bSearchSpellEntry );
596 void SAL_CALL
597 DicList::dispose()
598 throw(RuntimeException)
600 osl::MutexGuard aGuard( GetLinguMutex() );
602 if (!bDisposing)
604 bDisposing = TRUE;
605 EventObject aEvtObj( (XDictionaryList *) this );
607 aEvtListeners.disposeAndClear( aEvtObj );
608 if (pDicEvtLstnrHelper)
609 pDicEvtLstnrHelper->DisposeAndClear( aEvtObj );
611 //! avoid creation of dictionaries if not already done
612 if (aDicList.size() > 0)
614 DictionaryVec_t& rDicList = GetOrCreateDicList();
615 size_t nCount = rDicList.size();
616 for (size_t i = 0; i < nCount; i++)
618 uno::Reference< XDictionary > xDic( rDicList[i], UNO_QUERY );
620 // save (modified) dictionaries
621 uno::Reference< frame::XStorable > xStor( xDic , UNO_QUERY );
622 if (xStor.is())
626 if (!xStor->isReadonly() && xStor->hasLocation())
627 xStor->store();
629 catch(Exception &)
634 // release references to (members of) this object hold by
635 // dictionaries
636 if (xDic.is())
637 xDic->removeDictionaryEventListener( xDicEvtLstnrHelper );
643 void SAL_CALL
644 DicList::addEventListener( const uno::Reference< XEventListener >& rxListener )
645 throw(RuntimeException)
647 osl::MutexGuard aGuard( GetLinguMutex() );
649 if (!bDisposing && rxListener.is())
650 aEvtListeners.addInterface( rxListener );
653 void SAL_CALL
654 DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener )
655 throw(RuntimeException)
657 osl::MutexGuard aGuard( GetLinguMutex() );
659 if (!bDisposing && rxListener.is())
660 aEvtListeners.removeInterface( rxListener );
663 void DicList::_CreateDicList()
665 bInCreation = TRUE;
667 // look for dictionaries
668 const rtl::OUString aWriteablePath( GetDictionaryWriteablePath() );
669 uno::Sequence< rtl::OUString > aPaths( GetDictionaryPaths() );
670 const rtl::OUString *pPaths = aPaths.getConstArray();
671 for (sal_Int32 i = 0; i < aPaths.getLength(); ++i)
673 const BOOL bIsWriteablePath = (pPaths[i] == aWriteablePath);
674 SearchForDictionaries( aDicList, pPaths[i], bIsWriteablePath );
677 // create IgnoreAllList dictionary with empty URL (non persistent)
678 // and add it to list
679 rtl::OUString aDicName( A2OU( "IgnoreAllList" ) );
680 uno::Reference< XDictionary > xIgnAll(
681 createDictionary( aDicName, CreateLocale( LANGUAGE_NONE ),
682 DictionaryType_POSITIVE, rtl::OUString() ) );
683 if (xIgnAll.is())
685 AddUserData( xIgnAll );
686 xIgnAll->setActive( TRUE );
687 addDictionary( xIgnAll );
691 // evaluate list of dictionaries to be activated from configuration
693 //! to suppress overwriting the list of active dictionaries in the
694 //! configuration with incorrect arguments during the following
695 //! activation of the dictionaries
696 pDicEvtLstnrHelper->BeginCollectEvents();
698 const uno::Sequence< rtl::OUString > aActiveDics( aOpt.GetActiveDics() );
699 const rtl::OUString *pActiveDic = aActiveDics.getConstArray();
700 INT32 nLen = aActiveDics.getLength();
701 for (INT32 i = 0; i < nLen; ++i)
703 if (pActiveDic[i].getLength())
705 uno::Reference< XDictionary > xDic( getDictionaryByName( pActiveDic[i] ) );
706 if (xDic.is())
707 xDic->setActive( TRUE );
711 // suppress collected events during creation of the dictionary list.
712 // there should be no events during creation.
713 pDicEvtLstnrHelper->ClearEvents();
715 pDicEvtLstnrHelper->EndCollectEvents();
717 bInCreation = FALSE;
721 void DicList::SaveDics()
723 // save dics only if they have already been used/created.
724 //! don't create them just for the purpose of saving them !
725 if (aDicList.size() > 0)
727 // save (modified) dictionaries
728 DictionaryVec_t& rDicList = GetOrCreateDicList();
729 size_t nCount = rDicList.size();;
730 for (size_t i = 0; i < nCount; i++)
732 // save (modified) dictionaries
733 uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY );
734 if (xStor.is())
738 if (!xStor->isReadonly() && xStor->hasLocation())
739 xStor->store();
741 catch(Exception &)
750 ///////////////////////////////////////////////////////////////////////////
751 // Service specific part
754 rtl::OUString SAL_CALL DicList::getImplementationName( ) throw(RuntimeException)
756 osl::MutexGuard aGuard( GetLinguMutex() );
757 return getImplementationName_Static();
761 sal_Bool SAL_CALL DicList::supportsService( const rtl::OUString& ServiceName )
762 throw(RuntimeException)
764 osl::MutexGuard aGuard( GetLinguMutex() );
766 uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
767 const rtl::OUString * pArray = aSNL.getConstArray();
768 for( INT32 i = 0; i < aSNL.getLength(); i++ )
769 if( pArray[i] == ServiceName )
770 return TRUE;
771 return FALSE;
775 uno::Sequence< rtl::OUString > SAL_CALL DicList::getSupportedServiceNames( )
776 throw(RuntimeException)
778 osl::MutexGuard aGuard( GetLinguMutex() );
779 return getSupportedServiceNames_Static();
783 uno::Sequence< rtl::OUString > DicList::getSupportedServiceNames_Static() throw()
785 osl::MutexGuard aGuard( GetLinguMutex() );
787 uno::Sequence< rtl::OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich
788 aSNS.getArray()[0] = A2OU( SN_DICTIONARY_LIST );
789 return aSNS;
793 sal_Bool SAL_CALL DicList_writeInfo(
794 void * /*pServiceManager*/, registry::XRegistryKey * pRegistryKey )
798 String aImpl( '/' );
799 aImpl += DicList::getImplementationName_Static().getStr();
800 aImpl.AppendAscii( "/UNO/SERVICES" );
801 uno::Reference< registry::XRegistryKey > xNewKey =
802 pRegistryKey->createKey(aImpl );
803 uno::Sequence< rtl::OUString > aServices =
804 DicList::getSupportedServiceNames_Static();
805 for( INT32 i = 0; i < aServices.getLength(); i++ )
806 xNewKey->createKey( aServices.getConstArray()[i]);
808 return sal_True;
810 catch(Exception &)
812 return sal_False;
817 void * SAL_CALL DicList_getFactory( const sal_Char * pImplName,
818 XMultiServiceFactory * pServiceManager, void * )
820 void * pRet = 0;
821 if ( !DicList::getImplementationName_Static().compareToAscii( pImplName ) )
823 uno::Reference< XSingleServiceFactory > xFactory =
824 cppu::createOneInstanceFactory(
825 pServiceManager,
826 DicList::getImplementationName_Static(),
827 DicList_CreateInstance,
828 DicList::getSupportedServiceNames_Static());
829 // acquire, because we return an interface pointer instead of a reference
830 xFactory->acquire();
831 pRet = xFactory.get();
833 return pRet;
836 ///////////////////////////////////////////////////////////////////////////
838 xub_StrLen lcl_GetToken( String &rToken,
839 const String &rText, xub_StrLen nPos, const String &rDelim )
841 xub_StrLen nRes = STRING_LEN;
843 if (rText.Len() == 0 || nPos >= rText.Len())
844 rToken = String();
845 else if (rDelim.Len() == 0)
847 rToken = rText;
848 if (rToken.Len())
849 nRes = rText.Len();
851 else
853 xub_StrLen i;
854 for (i = nPos; i < rText.Len(); ++i)
856 if (STRING_NOTFOUND != rDelim.Search( rText.GetChar(i) ))
857 break;
860 if (i >= rText.Len()) // delimeter not found
861 rToken = rText.Copy( nPos );
862 else
863 rToken = rText.Copy( nPos, sal::static_int_cast< xub_StrLen >((INT32) i - nPos) );
864 nRes = i + 1; // continue after found delimeter
867 return nRes;
871 static void AddInternal(
872 const uno::Reference<XDictionary> &rDic,
873 const rtl::OUString& rNew )
875 if (rDic.is())
877 //! TL TODO: word iterator should be used to break up the text
878 static const char *pDefWordDelim =
879 "!\"#$%&'()*+,-./:;<=>?[]\\_^`{|}~\t \n";
880 ByteString aDummy( pDefWordDelim );
881 String aDelim( aDummy, osl_getThreadTextEncoding() );
882 aDelim.EraseAllChars( '.' );
884 String aToken;
885 xub_StrLen nPos = 0;
886 while (STRING_LEN !=
887 (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim )))
889 if( aToken.Len() && !IsNumeric( aToken ) )
891 rDic->add( aToken, FALSE, rtl::OUString() );
897 static void AddUserData( const uno::Reference< XDictionary > &rDic )
899 if (rDic.is())
901 SvtUserOptions aUserOpt;
902 AddInternal( rDic, aUserOpt.GetFullName() );
903 AddInternal( rDic, aUserOpt.GetCompany() );
904 AddInternal( rDic, aUserOpt.GetStreet() );
905 AddInternal( rDic, aUserOpt.GetCity() );
906 AddInternal( rDic, aUserOpt.GetTitle() );
907 AddInternal( rDic, aUserOpt.GetPosition() );
908 AddInternal( rDic, aUserOpt.GetEmail() );
912 ///////////////////////////////////////////////////////////////////////////
914 #if defined _MSC_VER
915 #pragma optimize("g",off)
916 #endif
918 static BOOL IsVers2OrNewer( const String& rFileURL, USHORT& nLng, BOOL& bNeg )
920 if (rFileURL.Len() == 0)
921 return FALSE;
922 String aDIC( GetDicExtension() );
923 String aExt;
924 xub_StrLen nPos = rFileURL.SearchBackward( '.' );
925 if (STRING_NOTFOUND != nPos)
926 aExt = rFileURL.Copy( nPos + 1 );
927 aExt.ToLowerAscii();
929 if(aExt != aDIC)
930 return FALSE;
932 // get stream to be used
933 SfxMedium aMedium( rFileURL, STREAM_READ | STREAM_SHARE_DENYWRITE, FALSE );
934 SvStream *pStream = aMedium.GetInStream();
936 int nDicVersion = ReadDicVersion (pStream, nLng, bNeg);
937 if (2 == nDicVersion || nDicVersion >= 5)
938 return TRUE;
940 return FALSE;
943 ///////////////////////////////////////////////////////////////////////////