bump product version to 7.2.5.1
[LibreOffice.git] / linguistic / source / dlistimp.cxx
blob3fcb59f5d43c86c0e9688f417d223a794cd35047
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cppuhelper/factory.hxx>
22 #include <i18nlangtag/mslangid.hxx>
23 #include <osl/file.hxx>
24 #include <tools/debug.hxx>
25 #include <tools/stream.hxx>
26 #include <tools/urlobj.hxx>
27 #include <unotools/useroptions.hxx>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <cppuhelper/weak.hxx>
30 #include <unotools/localfilehelper.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/sequence.hxx>
33 #include <unotools/ucbstreamhelper.hxx>
34 #include <com/sun/star/frame/XStorable.hpp>
35 #include <com/sun/star/uno/Reference.h>
36 #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
37 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
38 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
39 #include <svtools/strings.hrc>
40 #include <unotools/resmgr.hxx>
41 #include <sal/log.hxx>
43 #include "dlistimp.hxx"
44 #include "dicimp.hxx"
45 #include "lngopt.hxx"
47 using namespace osl;
48 using namespace com::sun::star;
49 using namespace com::sun::star::lang;
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star::linguistic2;
52 using namespace linguistic;
55 static bool IsVers2OrNewer( const OUString& rFileURL, LanguageType& nLng, bool& bNeg, OUString& aDicName );
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::WeakImplHelper
65 XDictionaryEventListener
68 comphelper::OInterfaceContainerHelper2 aDicListEvtListeners;
69 uno::Reference< XDictionaryList > xMyDicList;
71 sal_Int16 nCondensedEvt;
72 sal_Int16 nNumCollectEvtListeners;
74 public:
75 explicit DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList );
76 virtual ~DicEvtListenerHelper() override;
78 // XEventListener
79 virtual void SAL_CALL
80 disposing( const EventObject& rSource ) override;
82 // XDictionaryEventListener
83 virtual void SAL_CALL
84 processDictionaryEvent( const DictionaryEvent& rDicEvent ) override;
86 // non-UNO functions
87 void DisposeAndClear( const EventObject &rEvtObj );
89 bool AddDicListEvtListener(
90 const uno::Reference< XDictionaryListEventListener >& rxListener );
91 bool RemoveDicListEvtListener(
92 const uno::Reference< XDictionaryListEventListener >& rxListener );
93 sal_Int16 BeginCollectEvents() { return ++nNumCollectEvtListeners;}
94 sal_Int16 EndCollectEvents();
95 sal_Int16 FlushEvents();
96 void ClearEvents() { nCondensedEvt = 0; }
100 DicEvtListenerHelper::DicEvtListenerHelper(
101 const uno::Reference< XDictionaryList > &rxDicList ) :
102 aDicListEvtListeners ( GetLinguMutex() ),
103 xMyDicList ( rxDicList ),
104 nCondensedEvt(0), nNumCollectEvtListeners(0)
109 DicEvtListenerHelper::~DicEvtListenerHelper()
111 DBG_ASSERT(aDicListEvtListeners.getLength() == 0,
112 "lng : event listeners are still existing");
116 void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj )
118 aDicListEvtListeners.disposeAndClear( rEvtObj );
122 void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource )
124 osl::MutexGuard aGuard( GetLinguMutex() );
126 uno::Reference< XInterface > xSrc( rSource.Source );
128 // remove event object from EventListener list
129 if (xSrc.is())
130 aDicListEvtListeners.removeInterface( xSrc );
132 // if object is a dictionary then remove it from the dictionary list
133 // Note: this will probably happen only if someone makes a XDictionary
134 // implementation of his own that is also a XComponent.
135 uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY );
136 if (xDic.is())
138 xMyDicList->removeDictionary( xDic );
143 void SAL_CALL DicEvtListenerHelper::processDictionaryEvent(
144 const DictionaryEvent& rDicEvent )
146 osl::MutexGuard aGuard( GetLinguMutex() );
148 uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY );
149 DBG_ASSERT(xDic.is(), "lng : missing event source");
151 // assert that there is a corresponding dictionary entry if one was
152 // added or deleted
153 DBG_ASSERT( !(rDicEvent.nEvent &
154 (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY))
155 || rDicEvent.xDictionaryEntry.is(),
156 "lng : missing dictionary entry" );
158 // evaluate DictionaryEvents and update data for next DictionaryListEvent
159 DictionaryType eDicType = xDic->getDictionaryType();
160 DBG_ASSERT(eDicType != DictionaryType_MIXED,
161 "lng : unexpected dictionary type");
162 if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive())
163 nCondensedEvt |= rDicEvent.xDictionaryEntry->isNegative() ?
164 DictionaryListEventFlags::ADD_NEG_ENTRY :
165 DictionaryListEventFlags::ADD_POS_ENTRY;
166 if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive())
167 nCondensedEvt |= rDicEvent.xDictionaryEntry->isNegative() ?
168 DictionaryListEventFlags::DEL_NEG_ENTRY :
169 DictionaryListEventFlags::DEL_POS_ENTRY;
170 if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive())
171 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
172 DictionaryListEventFlags::DEL_NEG_ENTRY :
173 DictionaryListEventFlags::DEL_POS_ENTRY;
174 if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive())
175 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
176 DictionaryListEventFlags::DEACTIVATE_NEG_DIC
177 | DictionaryListEventFlags::ACTIVATE_NEG_DIC :
178 DictionaryListEventFlags::DEACTIVATE_POS_DIC
179 | DictionaryListEventFlags::ACTIVATE_POS_DIC;
180 if (rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC)
181 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
182 DictionaryListEventFlags::ACTIVATE_NEG_DIC :
183 DictionaryListEventFlags::ACTIVATE_POS_DIC;
184 if (rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC)
185 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
186 DictionaryListEventFlags::DEACTIVATE_NEG_DIC :
187 DictionaryListEventFlags::DEACTIVATE_POS_DIC;
189 if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0)
190 FlushEvents();
194 bool DicEvtListenerHelper::AddDicListEvtListener(
195 const uno::Reference< XDictionaryListEventListener >& xListener )
197 DBG_ASSERT( xListener.is(), "empty reference" );
198 sal_Int32 nCount = aDicListEvtListeners.getLength();
199 return aDicListEvtListeners.addInterface( xListener ) != nCount;
203 bool DicEvtListenerHelper::RemoveDicListEvtListener(
204 const uno::Reference< XDictionaryListEventListener >& xListener )
206 DBG_ASSERT( xListener.is(), "empty reference" );
207 sal_Int32 nCount = aDicListEvtListeners.getLength();
208 return aDicListEvtListeners.removeInterface( xListener ) != nCount;
212 sal_Int16 DicEvtListenerHelper::EndCollectEvents()
214 DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call");
215 if (nNumCollectEvtListeners > 0)
217 FlushEvents();
218 nNumCollectEvtListeners--;
221 return nNumCollectEvtListeners;
225 sal_Int16 DicEvtListenerHelper::FlushEvents()
227 if (0 != nCondensedEvt)
229 // build DictionaryListEvent to pass on to listeners
230 uno::Sequence< DictionaryEvent > aDicEvents;
231 DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents );
233 // pass on event
234 aDicListEvtListeners.notifyEach( &XDictionaryListEventListener::processDictionaryListEvent, aEvent );
236 // clear "list" of events
237 nCondensedEvt = 0;
240 return nNumCollectEvtListeners;
244 void DicList::MyAppExitListener::AtExit()
246 rMyDicList.SaveDics();
250 DicList::DicList() :
251 aEvtListeners ( GetLinguMutex() )
253 mxDicEvtLstnrHelper = new DicEvtListenerHelper( this );
254 bDisposing = false;
255 bInCreation = false;
257 mxExitListener = new MyAppExitListener( *this );
258 mxExitListener->Activate();
261 DicList::~DicList()
263 mxExitListener->Deactivate();
267 void DicList::SearchForDictionaries(
268 DictionaryVec_t&rDicList,
269 const OUString &rDicDirURL,
270 bool bIsWriteablePath )
272 osl::MutexGuard aGuard( GetLinguMutex() );
274 const uno::Sequence< OUString > aDirCnt( utl::LocalFileHelper::
275 GetFolderContents( rDicDirURL, false ) );
277 for (const OUString& aURL : aDirCnt)
279 LanguageType nLang = LANGUAGE_NONE;
280 bool bNeg = false;
281 OUString aDicTitle = "";
283 if(!::IsVers2OrNewer( aURL, nLang, bNeg, aDicTitle ))
285 // When not
286 sal_Int32 nPos = aURL.indexOf('.');
287 OUString aExt( aURL.copy(nPos + 1).toAsciiLowerCase() );
289 if ("dcn" == aExt) // negative
290 bNeg = true;
291 else if ("dcp" == aExt) // positive
292 bNeg = false;
293 else
294 continue; // other files
297 // Record in the list of Dictionaries
298 // When it already exists don't record
299 LanguageType nSystemLanguage = MsLangId::getSystemLanguage();
300 OUString aTmp1 = ToLower( aURL, nSystemLanguage );
301 sal_Int32 nPos = aTmp1.lastIndexOf( '/' );
302 if (-1 != nPos)
303 aTmp1 = aTmp1.copy( nPos + 1 );
304 OUString aTmp2;
305 size_t j;
306 size_t nCount = rDicList.size();
307 for(j = 0; j < nCount; j++)
309 aTmp2 = rDicList[j]->getName();
310 aTmp2 = ToLower( aTmp2, nSystemLanguage );
311 if(aTmp1 == aTmp2)
312 break;
314 if(j >= nCount) // dictionary not yet in DicList
316 // get decoded dictionary file name
317 INetURLObject aURLObj( aURL );
318 OUString aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT,
319 true, INetURLObject::DecodeMechanism::WithCharset );
321 DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
322 uno::Reference< XDictionary > xDic =
323 new DictionaryNeo( aDicTitle.isEmpty() ? aDicName : aDicTitle, nLang, eType, aURL, bIsWriteablePath );
325 addDictionary( xDic );
326 nCount++;
332 sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic)
334 osl::MutexGuard aGuard( GetLinguMutex() );
336 DictionaryVec_t& rDicList = GetOrCreateDicList();
337 size_t n = rDicList.size();
338 for (size_t i = 0; i < n; i++)
340 if ( rDicList[i] == xDic )
341 return i;
343 return -1;
346 sal_Int16 SAL_CALL DicList::getCount()
348 osl::MutexGuard aGuard( GetLinguMutex() );
349 return static_cast< sal_Int16 >(GetOrCreateDicList().size());
352 uno::Sequence< uno::Reference< XDictionary > > SAL_CALL
353 DicList::getDictionaries()
355 osl::MutexGuard aGuard( GetLinguMutex() );
357 DictionaryVec_t& rDicList = GetOrCreateDicList();
359 return comphelper::containerToSequence(rDicList);
362 uno::Reference< XDictionary > SAL_CALL
363 DicList::getDictionaryByName( const OUString& aDictionaryName )
365 osl::MutexGuard aGuard( GetLinguMutex() );
367 uno::Reference< XDictionary > xDic;
368 DictionaryVec_t& rDicList = GetOrCreateDicList();
369 size_t nCount = rDicList.size();
370 for (size_t i = 0; i < nCount; i++)
372 const uno::Reference< XDictionary > &rDic = rDicList[i];
373 if (rDic.is() && rDic->getName() == aDictionaryName)
375 xDic = rDic;
376 break;
380 return xDic;
383 sal_Bool SAL_CALL DicList::addDictionary(
384 const uno::Reference< XDictionary >& xDictionary )
386 osl::MutexGuard aGuard( GetLinguMutex() );
388 if (bDisposing)
389 return false;
391 bool bRes = false;
392 if (xDictionary.is())
394 DictionaryVec_t& rDicList = GetOrCreateDicList();
395 rDicList.push_back( xDictionary );
396 bRes = true;
398 // add listener helper to the dictionaries listener lists
399 xDictionary->addDictionaryEventListener( mxDicEvtLstnrHelper );
401 return bRes;
404 sal_Bool SAL_CALL
405 DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary )
407 osl::MutexGuard aGuard( GetLinguMutex() );
409 if (bDisposing)
410 return false;
412 bool bRes = false;
413 sal_Int32 nPos = GetDicPos( xDictionary );
414 if (nPos >= 0)
416 // remove dictionary list from the dictionaries listener lists
417 DictionaryVec_t& rDicList = GetOrCreateDicList();
418 uno::Reference< XDictionary > xDic( rDicList[ nPos ] );
419 DBG_ASSERT(xDic.is(), "lng : empty reference");
420 if (xDic.is())
422 // deactivate dictionary if not already done
423 xDic->setActive( false );
425 xDic->removeDictionaryEventListener( mxDicEvtLstnrHelper );
428 // remove element at nPos
429 rDicList.erase( rDicList.begin() + nPos );
430 bRes = true;
432 return bRes;
435 sal_Bool SAL_CALL DicList::addDictionaryListEventListener(
436 const uno::Reference< XDictionaryListEventListener >& xListener,
437 sal_Bool bReceiveVerbose )
439 osl::MutexGuard aGuard( GetLinguMutex() );
441 if (bDisposing)
442 return false;
444 DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported");
446 bool bRes = false;
447 if (xListener.is()) //! don't add empty references
449 bRes = mxDicEvtLstnrHelper->AddDicListEvtListener( xListener );
451 return bRes;
454 sal_Bool SAL_CALL DicList::removeDictionaryListEventListener(
455 const uno::Reference< XDictionaryListEventListener >& xListener )
457 osl::MutexGuard aGuard( GetLinguMutex() );
459 if (bDisposing)
460 return false;
462 bool bRes = false;
463 if(xListener.is())
465 bRes = mxDicEvtLstnrHelper->RemoveDicListEvtListener( xListener );
467 return bRes;
470 sal_Int16 SAL_CALL DicList::beginCollectEvents()
472 osl::MutexGuard aGuard( GetLinguMutex() );
473 return mxDicEvtLstnrHelper->BeginCollectEvents();
476 sal_Int16 SAL_CALL DicList::endCollectEvents()
478 osl::MutexGuard aGuard( GetLinguMutex() );
479 return mxDicEvtLstnrHelper->EndCollectEvents();
482 sal_Int16 SAL_CALL DicList::flushEvents()
484 osl::MutexGuard aGuard( GetLinguMutex() );
485 return mxDicEvtLstnrHelper->FlushEvents();
488 uno::Reference< XDictionary > SAL_CALL
489 DicList::createDictionary( const OUString& rName, const Locale& rLocale,
490 DictionaryType eDicType, const OUString& rURL )
492 osl::MutexGuard aGuard( GetLinguMutex() );
494 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
495 bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath() );
496 return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath );
500 uno::Reference< XDictionaryEntry > SAL_CALL
501 DicList::queryDictionaryEntry( const OUString& rWord, const Locale& rLocale,
502 sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry )
504 osl::MutexGuard aGuard( GetLinguMutex() );
505 return SearchDicList( this, rWord, LinguLocaleToLanguage( rLocale ),
506 bSearchPosDics, bSearchSpellEntry );
510 void SAL_CALL
511 DicList::dispose()
513 osl::MutexGuard aGuard( GetLinguMutex() );
515 if (bDisposing)
516 return;
518 bDisposing = true;
519 EventObject aEvtObj( static_cast<XDictionaryList *>(this) );
521 aEvtListeners.disposeAndClear( aEvtObj );
522 if (mxDicEvtLstnrHelper.is())
523 mxDicEvtLstnrHelper->DisposeAndClear( aEvtObj );
525 //! avoid creation of dictionaries if not already done
526 if ( !aDicList.empty() )
528 DictionaryVec_t& rDicList = GetOrCreateDicList();
529 size_t nCount = rDicList.size();
530 for (size_t i = 0; i < nCount; i++)
532 // save (modified) dictionaries
533 uno::Reference< frame::XStorable > xStor( rDicList[i] , UNO_QUERY );
534 if (xStor.is())
538 if (!xStor->isReadonly() && xStor->hasLocation())
539 xStor->store();
541 catch(Exception &)
546 // release references to (members of) this object hold by
547 // dictionaries
548 if (rDicList[i].is())
549 rDicList[i]->removeDictionaryEventListener( mxDicEvtLstnrHelper );
552 mxDicEvtLstnrHelper.clear();
555 void SAL_CALL
556 DicList::addEventListener( const uno::Reference< XEventListener >& rxListener )
558 osl::MutexGuard aGuard( GetLinguMutex() );
560 if (!bDisposing && rxListener.is())
561 aEvtListeners.addInterface( rxListener );
564 void SAL_CALL
565 DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener )
567 osl::MutexGuard aGuard( GetLinguMutex() );
569 if (!bDisposing && rxListener.is())
570 aEvtListeners.removeInterface( rxListener );
573 void DicList::CreateDicList()
575 bInCreation = true;
577 // look for dictionaries
578 const OUString aWriteablePath( GetDictionaryWriteablePath() );
579 std::vector< OUString > aPaths( GetDictionaryPaths() );
580 for (const OUString & aPath : aPaths)
582 const bool bIsWriteablePath = (aPath == aWriteablePath);
583 SearchForDictionaries( aDicList, aPath, bIsWriteablePath );
586 // create IgnoreAllList dictionary with empty URL (non persistent)
587 // and add it to list
588 std::locale loc(Translate::Create("svt"));
589 uno::Reference< XDictionary > xIgnAll(
590 createDictionary( Translate::get(STR_DESCRIPTION_IGNOREALLLIST, loc), LinguLanguageToLocale( LANGUAGE_NONE ),
591 DictionaryType_POSITIVE, OUString() ) );
592 if (xIgnAll.is())
594 AddUserData( xIgnAll );
595 xIgnAll->setActive( true );
596 addDictionary( xIgnAll );
600 // evaluate list of dictionaries to be activated from configuration
601 //! to suppress overwriting the list of active dictionaries in the
602 //! configuration with incorrect arguments during the following
603 //! activation of the dictionaries
604 mxDicEvtLstnrHelper->BeginCollectEvents();
605 const uno::Sequence< OUString > aActiveDics( aOpt.GetActiveDics() );
606 for (const OUString& rActiveDic : aActiveDics)
608 if (!rActiveDic.isEmpty())
610 uno::Reference< XDictionary > xDic( getDictionaryByName( rActiveDic ) );
611 if (xDic.is())
612 xDic->setActive( true );
616 // suppress collected events during creation of the dictionary list.
617 // there should be no events during creation.
618 mxDicEvtLstnrHelper->ClearEvents();
620 mxDicEvtLstnrHelper->EndCollectEvents();
622 bInCreation = false;
626 void DicList::SaveDics()
628 // save dics only if they have already been used/created.
629 //! don't create them just for the purpose of saving them !
630 if ( aDicList.empty() )
631 return;
633 // save (modified) dictionaries
634 DictionaryVec_t& rDicList = GetOrCreateDicList();
635 size_t nCount = rDicList.size();
636 for (size_t i = 0; i < nCount; i++)
638 // save (modified) dictionaries
639 uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY );
640 if (xStor.is())
644 if (!xStor->isReadonly() && xStor->hasLocation())
645 xStor->store();
647 catch(Exception &)
655 // Service specific part
657 OUString SAL_CALL DicList::getImplementationName( )
659 return "com.sun.star.lingu2.DicList";
663 sal_Bool SAL_CALL DicList::supportsService( const OUString& ServiceName )
665 return cppu::supportsService(this, ServiceName);
668 uno::Sequence< OUString > SAL_CALL DicList::getSupportedServiceNames( )
670 return { "com.sun.star.linguistic2.DictionaryList" };
675 static sal_Int32 lcl_GetToken( OUString &rToken,
676 const OUString &rText, sal_Int32 nPos, const OUString &rDelim )
678 sal_Int32 nRes = -1;
680 if (rText.isEmpty() || nPos >= rText.getLength())
681 rToken.clear();
682 else if (rDelim.isEmpty())
684 rToken = rText;
685 if (!rToken.isEmpty())
686 nRes = rText.getLength();
688 else
690 sal_Int32 i;
691 for (i = nPos; i < rText.getLength(); ++i)
693 if (-1 != rDelim.indexOf( rText[i] ))
694 break;
697 if (i >= rText.getLength()) // delimiter not found
698 rToken = rText.copy( nPos );
699 else
700 rToken = rText.copy( nPos, i - nPos );
701 nRes = i + 1; // continue after found delimiter
704 return nRes;
708 static void AddInternal(
709 const uno::Reference<XDictionary> &rDic,
710 const OUString& rNew )
712 if (!rDic.is())
713 return;
715 //! TL TODO: word iterator should be used to break up the text
716 OUString aDelim("!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n");
717 OSL_ENSURE(aDelim.indexOf(u'.') == -1,
718 "ensure no '.'");
720 OUString aToken;
721 sal_Int32 nPos = 0;
722 while (-1 != (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim )))
724 if( !aToken.isEmpty() && !IsNumeric( aToken ) )
726 rDic->add( aToken, false, OUString() );
731 static void AddUserData( const uno::Reference< XDictionary > &rDic )
733 if (rDic.is())
735 SvtUserOptions aUserOpt;
736 AddInternal( rDic, aUserOpt.GetFullName() );
737 AddInternal( rDic, aUserOpt.GetCompany() );
738 AddInternal( rDic, aUserOpt.GetStreet() );
739 AddInternal( rDic, aUserOpt.GetCity() );
740 AddInternal( rDic, aUserOpt.GetTitle() );
741 AddInternal( rDic, aUserOpt.GetPosition() );
742 AddInternal( rDic, aUserOpt.GetEmail() );
746 static bool IsVers2OrNewer( const OUString& rFileURL, LanguageType& nLng, bool& bNeg, OUString& aDicName )
748 if (rFileURL.isEmpty())
749 return false;
750 OUString aExt;
751 sal_Int32 nPos = rFileURL.lastIndexOf( '.' );
752 if (-1 != nPos)
753 aExt = rFileURL.copy( nPos + 1 ).toAsciiLowerCase();
755 if (aExt != "dic")
756 return false;
758 // get stream to be used
759 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
761 // get XInputStream stream
762 uno::Reference< io::XInputStream > xStream;
765 uno::Reference< ucb::XSimpleFileAccess3 > xAccess( ucb::SimpleFileAccess::create(xContext) );
766 xStream = xAccess->openFileRead( rFileURL );
768 catch (const uno::Exception &)
770 SAL_WARN( "linguistic", "failed to get input stream" );
772 DBG_ASSERT( xStream.is(), "failed to get stream for read" );
773 if (!xStream.is())
774 return false;
776 std::unique_ptr<SvStream> pStream( utl::UcbStreamHelper::CreateStream( xStream ) );
778 int nDicVersion = ReadDicVersion(*pStream, nLng, bNeg, aDicName);
779 return 2 == nDicVersion || nDicVersion >= 5;
782 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
783 linguistic_DicList_get_implementation(
784 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
786 return cppu::acquire(new DicList());
789 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */