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 <osl/file.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/stream.hxx>
25 #include <tools/urlobj.hxx>
26 #include <unotools/useroptions.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <cppuhelper/weak.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/uno/Reference.h>
35 #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
36 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
37 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
38 #include <svtools/strings.hrc>
39 #include <unotools/resmgr.hxx>
40 #include <unotools/charclass.hxx>
41 #include <sal/log.hxx>
44 #include "dlistimp.hxx"
49 using namespace com::sun::star
;
50 using namespace com::sun::star::lang
;
51 using namespace com::sun::star::uno
;
52 using namespace com::sun::star::linguistic2
;
53 using namespace linguistic
;
56 static bool IsVers2OrNewer( const OUString
& rFileURL
, LanguageType
& nLng
, bool& bNeg
, OUString
& aDicName
);
58 static void AddInternal( const uno::Reference
< XDictionary
> &rDic
,
59 const OUString
& rNew
);
60 static void AddUserData( const uno::Reference
< XDictionary
> &rDic
);
63 class DicEvtListenerHelper
:
64 public cppu::WeakImplHelper
66 XDictionaryEventListener
69 comphelper::OInterfaceContainerHelper3
<XDictionaryListEventListener
> aDicListEvtListeners
;
70 uno::Reference
< XDictionaryList
> xMyDicList
;
72 sal_Int16 nCondensedEvt
;
73 sal_Int16 nNumCollectEvtListeners
;
76 explicit DicEvtListenerHelper( uno::Reference
< XDictionaryList
> xDicList
);
77 virtual ~DicEvtListenerHelper() override
;
81 disposing( const EventObject
& rSource
) override
;
83 // XDictionaryEventListener
85 processDictionaryEvent( const DictionaryEvent
& rDicEvent
) override
;
88 void DisposeAndClear( const EventObject
&rEvtObj
);
90 bool AddDicListEvtListener(
91 const uno::Reference
< XDictionaryListEventListener
>& rxListener
);
92 bool RemoveDicListEvtListener(
93 const uno::Reference
< XDictionaryListEventListener
>& rxListener
);
94 sal_Int16
BeginCollectEvents() { return ++nNumCollectEvtListeners
;}
95 sal_Int16
EndCollectEvents();
96 sal_Int16
FlushEvents();
97 void ClearEvents() { nCondensedEvt
= 0; }
101 DicEvtListenerHelper::DicEvtListenerHelper(
102 uno::Reference
< XDictionaryList
> xDicList
) :
103 aDicListEvtListeners ( GetLinguMutex() ),
104 xMyDicList (std::move( xDicList
)),
105 nCondensedEvt(0), nNumCollectEvtListeners(0)
110 DicEvtListenerHelper::~DicEvtListenerHelper()
112 DBG_ASSERT(aDicListEvtListeners
.getLength() == 0,
113 "lng : event listeners are still existing");
117 void DicEvtListenerHelper::DisposeAndClear( const EventObject
&rEvtObj
)
119 aDicListEvtListeners
.disposeAndClear( rEvtObj
);
123 void SAL_CALL
DicEvtListenerHelper::disposing( const EventObject
& rSource
)
125 osl::MutexGuard
aGuard( GetLinguMutex() );
127 uno::Reference
< XDictionaryListEventListener
> xSrc( rSource
.Source
, UNO_QUERY
);
129 // remove event object from EventListener list
131 aDicListEvtListeners
.removeInterface( xSrc
);
133 // if object is a dictionary then remove it from the dictionary list
134 // Note: this will probably happen only if someone makes a XDictionary
135 // implementation of his own that is also a XComponent.
136 uno::Reference
< XDictionary
> xDic( rSource
.Source
, UNO_QUERY
);
139 xMyDicList
->removeDictionary( xDic
);
144 void SAL_CALL
DicEvtListenerHelper::processDictionaryEvent(
145 const DictionaryEvent
& rDicEvent
)
147 osl::MutexGuard
aGuard( GetLinguMutex() );
149 uno::Reference
< XDictionary
> xDic( rDicEvent
.Source
, UNO_QUERY
);
150 DBG_ASSERT(xDic
.is(), "lng : missing event source");
152 // assert that there is a corresponding dictionary entry if one was
154 DBG_ASSERT( !(rDicEvent
.nEvent
&
155 (DictionaryEventFlags::ADD_ENTRY
| DictionaryEventFlags::DEL_ENTRY
))
156 || rDicEvent
.xDictionaryEntry
.is(),
157 "lng : missing dictionary entry" );
159 // evaluate DictionaryEvents and update data for next DictionaryListEvent
160 DictionaryType eDicType
= xDic
->getDictionaryType();
161 DBG_ASSERT(eDicType
!= DictionaryType_MIXED
,
162 "lng : unexpected dictionary type");
163 if ((rDicEvent
.nEvent
& DictionaryEventFlags::ADD_ENTRY
) && xDic
->isActive())
164 nCondensedEvt
|= rDicEvent
.xDictionaryEntry
->isNegative() ?
165 DictionaryListEventFlags::ADD_NEG_ENTRY
:
166 DictionaryListEventFlags::ADD_POS_ENTRY
;
167 if ((rDicEvent
.nEvent
& DictionaryEventFlags::DEL_ENTRY
) && xDic
->isActive())
168 nCondensedEvt
|= rDicEvent
.xDictionaryEntry
->isNegative() ?
169 DictionaryListEventFlags::DEL_NEG_ENTRY
:
170 DictionaryListEventFlags::DEL_POS_ENTRY
;
171 if ((rDicEvent
.nEvent
& DictionaryEventFlags::ENTRIES_CLEARED
) && xDic
->isActive())
172 nCondensedEvt
|= eDicType
== DictionaryType_NEGATIVE
?
173 DictionaryListEventFlags::DEL_NEG_ENTRY
:
174 DictionaryListEventFlags::DEL_POS_ENTRY
;
175 if ((rDicEvent
.nEvent
& DictionaryEventFlags::CHG_LANGUAGE
) && xDic
->isActive())
176 nCondensedEvt
|= eDicType
== DictionaryType_NEGATIVE
?
177 DictionaryListEventFlags::DEACTIVATE_NEG_DIC
178 | DictionaryListEventFlags::ACTIVATE_NEG_DIC
:
179 DictionaryListEventFlags::DEACTIVATE_POS_DIC
180 | DictionaryListEventFlags::ACTIVATE_POS_DIC
;
181 if (rDicEvent
.nEvent
& DictionaryEventFlags::ACTIVATE_DIC
)
182 nCondensedEvt
|= eDicType
== DictionaryType_NEGATIVE
?
183 DictionaryListEventFlags::ACTIVATE_NEG_DIC
:
184 DictionaryListEventFlags::ACTIVATE_POS_DIC
;
185 if (rDicEvent
.nEvent
& DictionaryEventFlags::DEACTIVATE_DIC
)
186 nCondensedEvt
|= eDicType
== DictionaryType_NEGATIVE
?
187 DictionaryListEventFlags::DEACTIVATE_NEG_DIC
:
188 DictionaryListEventFlags::DEACTIVATE_POS_DIC
;
190 if (nNumCollectEvtListeners
== 0 && nCondensedEvt
!= 0)
195 bool DicEvtListenerHelper::AddDicListEvtListener(
196 const uno::Reference
< XDictionaryListEventListener
>& xListener
)
198 DBG_ASSERT( xListener
.is(), "empty reference" );
199 sal_Int32 nCount
= aDicListEvtListeners
.getLength();
200 return aDicListEvtListeners
.addInterface( xListener
) != nCount
;
204 bool DicEvtListenerHelper::RemoveDicListEvtListener(
205 const uno::Reference
< XDictionaryListEventListener
>& xListener
)
207 DBG_ASSERT( xListener
.is(), "empty reference" );
208 sal_Int32 nCount
= aDicListEvtListeners
.getLength();
209 return aDicListEvtListeners
.removeInterface( xListener
) != nCount
;
213 sal_Int16
DicEvtListenerHelper::EndCollectEvents()
215 DBG_ASSERT(nNumCollectEvtListeners
> 0, "lng: mismatched function call");
216 if (nNumCollectEvtListeners
> 0)
219 nNumCollectEvtListeners
--;
222 return nNumCollectEvtListeners
;
226 sal_Int16
DicEvtListenerHelper::FlushEvents()
228 if (0 != nCondensedEvt
)
230 // build DictionaryListEvent to pass on to listeners
231 uno::Sequence
< DictionaryEvent
> aDicEvents
;
232 DictionaryListEvent
aEvent( xMyDicList
, nCondensedEvt
, aDicEvents
);
235 aDicListEvtListeners
.notifyEach( &XDictionaryListEventListener::processDictionaryListEvent
, aEvent
);
237 // clear "list" of events
241 return nNumCollectEvtListeners
;
245 void DicList::MyAppExitListener::AtExit()
247 rMyDicList
.SaveDics();
252 aEvtListeners ( GetLinguMutex() )
254 mxDicEvtLstnrHelper
= new DicEvtListenerHelper( this );
258 mxExitListener
= new MyAppExitListener( *this );
259 mxExitListener
->Activate();
264 mxExitListener
->Deactivate();
268 void DicList::SearchForDictionaries(
269 DictionaryVec_t
&rDicList
,
270 const OUString
&rDicDirURL
,
271 bool bIsWriteablePath
)
273 osl::MutexGuard
aGuard( GetLinguMutex() );
275 const uno::Sequence
< OUString
> aDirCnt( utl::LocalFileHelper::
276 GetFolderContents( rDicDirURL
, false ) );
277 SvtSysLocale aSysLocale
;
279 for (const OUString
& aURL
: aDirCnt
)
281 LanguageType nLang
= LANGUAGE_NONE
;
283 OUString aDicTitle
= "";
285 if(!::IsVers2OrNewer( aURL
, nLang
, bNeg
, aDicTitle
))
288 sal_Int32 nPos
= aURL
.indexOf('.');
289 OUString
aExt( aURL
.copy(nPos
+ 1).toAsciiLowerCase() );
291 if ("dcn" == aExt
) // negative
293 else if ("dcp" == aExt
) // positive
296 continue; // other files
299 // Record in the list of Dictionaries
300 // When it already exists don't record
301 OUString aTmp1
= aSysLocale
.GetCharClass().lowercase( aURL
);
302 sal_Int32 nPos
= aTmp1
.lastIndexOf( '/' );
304 aTmp1
= aTmp1
.copy( nPos
+ 1 );
307 size_t nCount
= rDicList
.size();
308 for(j
= 0; j
< nCount
; j
++)
310 aTmp2
= rDicList
[j
]->getName();
311 aTmp2
= aSysLocale
.GetCharClass().lowercase( aTmp2
);
315 if(j
>= nCount
) // dictionary not yet in DicList
317 // get decoded dictionary file name
318 INetURLObject
aURLObj( aURL
);
319 OUString aDicName
= aURLObj
.getName( INetURLObject::LAST_SEGMENT
,
320 true, INetURLObject::DecodeMechanism::WithCharset
);
322 DictionaryType eType
= bNeg
? DictionaryType_NEGATIVE
: DictionaryType_POSITIVE
;
323 uno::Reference
< XDictionary
> xDic
=
324 new DictionaryNeo( aDicTitle
.isEmpty() ? aDicName
: aDicTitle
, nLang
, eType
, aURL
, bIsWriteablePath
);
326 addDictionary( xDic
);
333 sal_Int32
DicList::GetDicPos(const uno::Reference
< XDictionary
> &xDic
)
335 osl::MutexGuard
aGuard( GetLinguMutex() );
337 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
338 size_t n
= rDicList
.size();
339 for (size_t i
= 0; i
< n
; i
++)
341 if ( rDicList
[i
] == xDic
)
347 sal_Int16 SAL_CALL
DicList::getCount()
349 osl::MutexGuard
aGuard( GetLinguMutex() );
350 return static_cast< sal_Int16
>(GetOrCreateDicList().size());
353 uno::Sequence
< uno::Reference
< XDictionary
> > SAL_CALL
354 DicList::getDictionaries()
356 osl::MutexGuard
aGuard( GetLinguMutex() );
358 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
360 return comphelper::containerToSequence(rDicList
);
363 uno::Reference
< XDictionary
> SAL_CALL
364 DicList::getDictionaryByName( const OUString
& aDictionaryName
)
366 osl::MutexGuard
aGuard( GetLinguMutex() );
368 uno::Reference
< XDictionary
> xDic
;
369 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
370 size_t nCount
= rDicList
.size();
371 for (size_t i
= 0; i
< nCount
; i
++)
373 const uno::Reference
< XDictionary
> &rDic
= rDicList
[i
];
374 if (rDic
.is() && rDic
->getName() == aDictionaryName
)
384 sal_Bool SAL_CALL
DicList::addDictionary(
385 const uno::Reference
< XDictionary
>& xDictionary
)
387 osl::MutexGuard
aGuard( GetLinguMutex() );
393 if (xDictionary
.is())
395 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
396 rDicList
.push_back( xDictionary
);
399 // add listener helper to the dictionaries listener lists
400 xDictionary
->addDictionaryEventListener( mxDicEvtLstnrHelper
);
406 DicList::removeDictionary( const uno::Reference
< XDictionary
>& xDictionary
)
408 osl::MutexGuard
aGuard( GetLinguMutex() );
414 sal_Int32 nPos
= GetDicPos( xDictionary
);
417 // remove dictionary list from the dictionaries listener lists
418 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
419 uno::Reference
< XDictionary
> xDic( rDicList
[ nPos
] );
420 DBG_ASSERT(xDic
.is(), "lng : empty reference");
423 // deactivate dictionary if not already done
424 xDic
->setActive( false );
426 xDic
->removeDictionaryEventListener( mxDicEvtLstnrHelper
);
429 // remove element at nPos
430 rDicList
.erase( rDicList
.begin() + nPos
);
436 sal_Bool SAL_CALL
DicList::addDictionaryListEventListener(
437 const uno::Reference
< XDictionaryListEventListener
>& xListener
,
438 sal_Bool bReceiveVerbose
)
440 osl::MutexGuard
aGuard( GetLinguMutex() );
445 DBG_ASSERT(!bReceiveVerbose
, "lng : not yet supported");
448 if (xListener
.is()) //! don't add empty references
450 bRes
= mxDicEvtLstnrHelper
->AddDicListEvtListener( xListener
);
455 sal_Bool SAL_CALL
DicList::removeDictionaryListEventListener(
456 const uno::Reference
< XDictionaryListEventListener
>& xListener
)
458 osl::MutexGuard
aGuard( GetLinguMutex() );
466 bRes
= mxDicEvtLstnrHelper
->RemoveDicListEvtListener( xListener
);
471 sal_Int16 SAL_CALL
DicList::beginCollectEvents()
473 osl::MutexGuard
aGuard( GetLinguMutex() );
474 return mxDicEvtLstnrHelper
->BeginCollectEvents();
477 sal_Int16 SAL_CALL
DicList::endCollectEvents()
479 osl::MutexGuard
aGuard( GetLinguMutex() );
480 return mxDicEvtLstnrHelper
->EndCollectEvents();
483 sal_Int16 SAL_CALL
DicList::flushEvents()
485 osl::MutexGuard
aGuard( GetLinguMutex() );
486 return mxDicEvtLstnrHelper
->FlushEvents();
489 uno::Reference
< XDictionary
> SAL_CALL
490 DicList::createDictionary( const OUString
& rName
, const Locale
& rLocale
,
491 DictionaryType eDicType
, const OUString
& rURL
)
493 osl::MutexGuard
aGuard( GetLinguMutex() );
495 LanguageType nLanguage
= LinguLocaleToLanguage( rLocale
);
496 bool bIsWriteablePath
= rURL
.match( GetDictionaryWriteablePath() );
497 return new DictionaryNeo( rName
, nLanguage
, eDicType
, rURL
, bIsWriteablePath
);
501 uno::Reference
< XDictionaryEntry
> SAL_CALL
502 DicList::queryDictionaryEntry( const OUString
& rWord
, const Locale
& rLocale
,
503 sal_Bool bSearchPosDics
, sal_Bool bSearchSpellEntry
)
505 osl::MutexGuard
aGuard( GetLinguMutex() );
506 return SearchDicList( this, rWord
, LinguLocaleToLanguage( rLocale
),
507 bSearchPosDics
, bSearchSpellEntry
);
514 osl::MutexGuard
aGuard( GetLinguMutex() );
520 EventObject
aEvtObj( static_cast<XDictionaryList
*>(this) );
522 aEvtListeners
.disposeAndClear( aEvtObj
);
523 if (mxDicEvtLstnrHelper
.is())
524 mxDicEvtLstnrHelper
->DisposeAndClear( aEvtObj
);
526 //! avoid creation of dictionaries if not already done
527 if ( !aDicList
.empty() )
529 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
530 size_t nCount
= rDicList
.size();
531 for (size_t i
= 0; i
< nCount
; i
++)
533 // save (modified) dictionaries
534 uno::Reference
< frame::XStorable
> xStor( rDicList
[i
] , UNO_QUERY
);
539 if (!xStor
->isReadonly() && xStor
->hasLocation())
547 // release references to (members of) this object hold by
549 if (rDicList
[i
].is())
550 rDicList
[i
]->removeDictionaryEventListener( mxDicEvtLstnrHelper
);
553 mxDicEvtLstnrHelper
.clear();
557 DicList::addEventListener( const uno::Reference
< XEventListener
>& rxListener
)
559 osl::MutexGuard
aGuard( GetLinguMutex() );
561 if (!bDisposing
&& rxListener
.is())
562 aEvtListeners
.addInterface( rxListener
);
566 DicList::removeEventListener( const uno::Reference
< XEventListener
>& rxListener
)
568 osl::MutexGuard
aGuard( GetLinguMutex() );
570 if (!bDisposing
&& rxListener
.is())
571 aEvtListeners
.removeInterface( rxListener
);
574 void DicList::CreateDicList()
578 // look for dictionaries
579 const OUString
aWriteablePath( GetDictionaryWriteablePath() );
580 std::vector
< OUString
> aPaths( GetDictionaryPaths() );
581 for (const OUString
& aPath
: aPaths
)
583 const bool bIsWriteablePath
= (aPath
== aWriteablePath
);
584 SearchForDictionaries( aDicList
, aPath
, bIsWriteablePath
);
587 // create IgnoreAllList dictionary with empty URL (non persistent)
588 // and add it to list
589 std::locale
loc(Translate::Create("svt"));
590 uno::Reference
< XDictionary
> xIgnAll(
591 createDictionary( Translate::get(STR_DESCRIPTION_IGNOREALLLIST
, loc
), LinguLanguageToLocale( LANGUAGE_NONE
),
592 DictionaryType_POSITIVE
, OUString() ) );
595 AddUserData( xIgnAll
);
596 xIgnAll
->setActive( true );
597 addDictionary( xIgnAll
);
601 // evaluate list of dictionaries to be activated from configuration
602 //! to suppress overwriting the list of active dictionaries in the
603 //! configuration with incorrect arguments during the following
604 //! activation of the dictionaries
605 mxDicEvtLstnrHelper
->BeginCollectEvents();
606 const uno::Sequence
< OUString
> aActiveDics( aOpt
.GetActiveDics() );
607 for (const OUString
& rActiveDic
: aActiveDics
)
609 if (!rActiveDic
.isEmpty())
611 uno::Reference
< XDictionary
> xDic( getDictionaryByName( rActiveDic
) );
613 xDic
->setActive( true );
617 // suppress collected events during creation of the dictionary list.
618 // there should be no events during creation.
619 mxDicEvtLstnrHelper
->ClearEvents();
621 mxDicEvtLstnrHelper
->EndCollectEvents();
627 void DicList::SaveDics()
629 // save dics only if they have already been used/created.
630 //! don't create them just for the purpose of saving them !
631 if ( aDicList
.empty() )
634 // save (modified) dictionaries
635 DictionaryVec_t
& rDicList
= GetOrCreateDicList();
636 size_t nCount
= rDicList
.size();
637 for (size_t i
= 0; i
< nCount
; i
++)
639 // save (modified) dictionaries
640 uno::Reference
< frame::XStorable
> xStor( rDicList
[i
], UNO_QUERY
);
645 if (!xStor
->isReadonly() && xStor
->hasLocation())
656 // Service specific part
658 OUString SAL_CALL
DicList::getImplementationName( )
660 return "com.sun.star.lingu2.DicList";
664 sal_Bool SAL_CALL
DicList::supportsService( const OUString
& ServiceName
)
666 return cppu::supportsService(this, ServiceName
);
669 uno::Sequence
< OUString
> SAL_CALL
DicList::getSupportedServiceNames( )
671 return { "com.sun.star.linguistic2.DictionaryList" };
676 static sal_Int32
lcl_GetToken( OUString
&rToken
,
677 const OUString
&rText
, sal_Int32 nPos
, std::u16string_view rDelim
)
681 if (rText
.isEmpty() || nPos
>= rText
.getLength())
683 else if (rDelim
.empty())
686 if (!rToken
.isEmpty())
687 nRes
= rText
.getLength();
692 for (i
= nPos
; i
< rText
.getLength(); ++i
)
694 if (std::string_view::npos
!= rDelim
.find( rText
[i
] ))
698 if (i
>= rText
.getLength()) // delimiter not found
699 rToken
= rText
.copy( nPos
);
701 rToken
= rText
.copy( nPos
, i
- nPos
);
702 nRes
= i
+ 1; // continue after found delimiter
709 static void AddInternal(
710 const uno::Reference
<XDictionary
> &rDic
,
711 const OUString
& rNew
)
716 //! TL TODO: word iterator should be used to break up the text
717 OUString
aDelim("!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n");
718 OSL_ENSURE(aDelim
.indexOf(u
'.') == -1,
723 while (-1 != (nPos
= lcl_GetToken( aToken
, rNew
, nPos
, aDelim
)))
725 if( !aToken
.isEmpty() && !IsNumeric( aToken
) )
727 rDic
->add( aToken
, false, OUString() );
732 static void AddUserData( const uno::Reference
< XDictionary
> &rDic
)
736 SvtUserOptions aUserOpt
;
737 AddInternal( rDic
, aUserOpt
.GetFullName() );
738 AddInternal( rDic
, aUserOpt
.GetCompany() );
739 AddInternal( rDic
, aUserOpt
.GetStreet() );
740 AddInternal( rDic
, aUserOpt
.GetCity() );
741 AddInternal( rDic
, aUserOpt
.GetTitle() );
742 AddInternal( rDic
, aUserOpt
.GetPosition() );
743 AddInternal( rDic
, aUserOpt
.GetEmail() );
747 static bool IsVers2OrNewer( const OUString
& rFileURL
, LanguageType
& nLng
, bool& bNeg
, OUString
& aDicName
)
749 if (rFileURL
.isEmpty())
752 sal_Int32 nPos
= rFileURL
.lastIndexOf( '.' );
754 aExt
= rFileURL
.copy( nPos
+ 1 ).toAsciiLowerCase();
759 // get stream to be used
760 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
762 // get XInputStream stream
763 uno::Reference
< io::XInputStream
> xStream
;
766 uno::Reference
< ucb::XSimpleFileAccess3
> xAccess( ucb::SimpleFileAccess::create(xContext
) );
767 xStream
= xAccess
->openFileRead( rFileURL
);
769 catch (const uno::Exception
&)
771 SAL_WARN( "linguistic", "failed to get input stream" );
773 DBG_ASSERT( xStream
.is(), "failed to get stream for read" );
777 std::unique_ptr
<SvStream
> pStream( utl::UcbStreamHelper::CreateStream( xStream
) );
779 int nDicVersion
= ReadDicVersion(*pStream
, nLng
, bNeg
, aDicName
);
780 return 2 == nDicVersion
|| nDicVersion
>= 5;
783 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
784 linguistic_DicList_get_implementation(
785 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
787 return cppu::acquire(new DicList());
790 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */