1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
44 #include "dlistimp.hxx"
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
,
79 explicit DicEvtListenerHelper( const uno::Reference
< XDictionaryList
> &rxDicList
);
80 virtual ~DicEvtListenerHelper() override
;
84 disposing( const EventObject
& rSource
) override
;
86 // XDictionaryEventListener
88 processDictionaryEvent( const DictionaryEvent
& rDicEvent
) override
;
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
)
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
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
);
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
158 uno::Reference
< XDictionaryEntry
> xDicEntry( rDicEvent
.xDictionaryEntry
, UNO_QUERY
);
159 DBG_ASSERT( !(rDicEvent
.nEvent
&
160 (DictionaryEventFlags::ADD_ENTRY
| DictionaryEventFlags::DEL_ENTRY
))
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)
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)
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
);
248 aDicListEvtListeners
.notifyEach( &XDictionaryListEventListener::processDictionaryListEvent
, aEvent
);
250 // clear "list" of events
252 aCollectDicEvt
.clear();
255 return nNumCollectEvtListeners
;
259 void DicList::MyAppExitListener::AtExit()
261 rMyDicList
.SaveDics();
266 aEvtListeners ( GetLinguMutex() )
268 mxDicEvtLstnrHelper
= new DicEvtListenerHelper( this );
272 mxExitListener
= new MyAppExitListener( *this );
273 mxExitListener
->Activate();
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
;
299 OUString aDicTitle
= "";
301 if(!::IsVers2OrNewer( aURL
, nLang
, bNeg
, aDicTitle
))
304 sal_Int32 nPos
= aURL
.indexOf('.');
305 OUString
aExt( aURL
.copy(nPos
+ 1).toAsciiLowerCase() );
307 if ("dcn" == aExt
) // negative
309 else if ("dcp" == aExt
) // positive
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( '/' );
321 aTmp1
= aTmp1
.copy( nPos
+ 1 );
324 size_t nCount
= rDicList
.size();
325 for(j
= 0; j
< nCount
; j
++)
327 aTmp2
= rDicList
[j
]->getName();
328 aTmp2
= ToLower( aTmp2
, nSystemLanguage
);
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
);
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
)
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
);
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
)
409 sal_Bool SAL_CALL
DicList::addDictionary(
410 const uno::Reference
< XDictionary
>& xDictionary
)
412 osl::MutexGuard
aGuard( GetLinguMutex() );
418 if (xDictionary
.is())
420 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
421 rDicList
.push_back( xDictionary
);
424 // add listener helper to the dictionaries listener lists
425 xDictionary
->addDictionaryEventListener( mxDicEvtLstnrHelper
.get() );
431 DicList::removeDictionary( const uno::Reference
< XDictionary
>& xDictionary
)
433 osl::MutexGuard
aGuard( GetLinguMutex() );
439 sal_Int32 nPos
= GetDicPos( xDictionary
);
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");
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
);
461 sal_Bool SAL_CALL
DicList::addDictionaryListEventListener(
462 const uno::Reference
< XDictionaryListEventListener
>& xListener
,
463 sal_Bool bReceiveVerbose
)
465 osl::MutexGuard
aGuard( GetLinguMutex() );
470 DBG_ASSERT(!bReceiveVerbose
, "lng : not yet supported");
473 if (xListener
.is()) //! don't add empty references
475 bRes
= mxDicEvtLstnrHelper
->AddDicListEvtListener( xListener
);
480 sal_Bool SAL_CALL
DicList::removeDictionaryListEventListener(
481 const uno::Reference
< XDictionaryListEventListener
>& xListener
)
483 osl::MutexGuard
aGuard( GetLinguMutex() );
491 bRes
= mxDicEvtLstnrHelper
->RemoveDicListEvtListener( xListener
);
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
);
539 osl::MutexGuard
aGuard( GetLinguMutex() );
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
);
565 if (!xStor
->isReadonly() && xStor
->hasLocation())
573 // release references to (members of) this object hold by
576 xDic
->removeDictionaryEventListener( mxDicEvtLstnrHelper
.get() );
579 mxDicEvtLstnrHelper
.clear();
584 DicList::addEventListener( const uno::Reference
< XEventListener
>& rxListener
)
586 osl::MutexGuard
aGuard( GetLinguMutex() );
588 if (!bDisposing
&& rxListener
.is())
589 aEvtListeners
.addInterface( rxListener
);
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()
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() ) );
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
] ) );
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();
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
);
673 if (!xStor
->isReadonly() && xStor
->hasLocation())
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" };
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(
719 DicList::getImplementationName_Static(),
720 DicList_CreateInstance
,
721 DicList::getSupportedServiceNames_Static());
722 // acquire, because we return an interface pointer instead of a reference
724 pRet
= xFactory
.get();
730 static sal_Int32
lcl_GetToken( OUString
&rToken
,
731 const OUString
&rText
, sal_Int32 nPos
, const OUString
&rDelim
)
735 if (rText
.isEmpty() || nPos
>= rText
.getLength())
737 else if (rDelim
.isEmpty())
740 if (!rToken
.isEmpty())
741 nRes
= rText
.getLength();
746 for (i
= nPos
; i
< rText
.getLength(); ++i
)
748 if (-1 != rDelim
.indexOf( rText
[i
] ))
752 if (i
>= rText
.getLength()) // delimiter not found
753 rToken
= rText
.copy( nPos
);
755 rToken
= rText
.copy( nPos
, i
- nPos
);
756 nRes
= i
+ 1; // continue after found delimiter
763 static void AddInternal(
764 const uno::Reference
<XDictionary
> &rDic
,
765 const OUString
& rNew
)
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,
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
)
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())
806 sal_Int32 nPos
= rFileURL
.lastIndexOf( '.' );
808 aExt
= rFileURL
.copy( nPos
+ 1 ).toAsciiLowerCase();
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" );
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: */