Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
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>
39 :
40 : #include "defs.hxx"
41 : #include "dlistimp.hxx"
42 : #include "dicimp.hxx"
43 : #include "lngopt.hxx"
44 : #include "lngreg.hxx"
45 :
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;
52 :
53 :
54 :
55 : static bool IsVers2OrNewer( const OUString& rFileURL, sal_uInt16& nLng, bool& bNeg );
56 :
57 : static void AddInternal( const uno::Reference< XDictionary > &rDic,
58 : const OUString& rNew );
59 : static void AddUserData( const uno::Reference< XDictionary > &rDic );
60 :
61 :
62 : class DicEvtListenerHelper :
63 : public cppu::WeakImplHelper1
64 : <
65 : XDictionaryEventListener
66 : >
67 : {
68 : cppu::OInterfaceContainerHelper aDicListEvtListeners;
69 : uno::Sequence< DictionaryEvent > aCollectDicEvt;
70 : uno::Reference< XDictionaryList > xMyDicList;
71 :
72 : sal_Int16 nCondensedEvt;
73 : sal_Int16 nNumCollectEvtListeners,
74 : nNumVerboseListeners;
75 :
76 : public:
77 : DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList );
78 : virtual ~DicEvtListenerHelper();
79 :
80 : // XEventListener
81 : virtual void SAL_CALL
82 : disposing( const EventObject& rSource )
83 : throw(RuntimeException, std::exception) SAL_OVERRIDE;
84 :
85 : // XDictionaryEventListener
86 : virtual void SAL_CALL
87 : processDictionaryEvent( const DictionaryEvent& rDicEvent )
88 : throw(RuntimeException, std::exception) SAL_OVERRIDE;
89 :
90 : // non-UNO functions
91 : void DisposeAndClear( const EventObject &rEvtObj );
92 :
93 : bool AddDicListEvtListener(
94 : const uno::Reference< XDictionaryListEventListener >& rxListener,
95 : bool bReceiveVerbose );
96 : bool RemoveDicListEvtListener(
97 : const uno::Reference< XDictionaryListEventListener >& rxListener );
98 40 : sal_Int16 BeginCollectEvents() { return ++nNumCollectEvtListeners;}
99 : sal_Int16 EndCollectEvents();
100 : sal_Int16 FlushEvents();
101 38 : void ClearEvents() { nCondensedEvt = 0; }
102 : };
103 :
104 :
105 76 : DicEvtListenerHelper::DicEvtListenerHelper(
106 : const uno::Reference< XDictionaryList > &rxDicList ) :
107 76 : aDicListEvtListeners ( GetLinguMutex() ),
108 152 : xMyDicList ( rxDicList )
109 : {
110 76 : nCondensedEvt = 0;
111 76 : nNumCollectEvtListeners = nNumVerboseListeners = 0;
112 76 : }
113 :
114 :
115 152 : DicEvtListenerHelper::~DicEvtListenerHelper()
116 : {
117 : DBG_ASSERT(aDicListEvtListeners.getLength() == 0,
118 : "lng : event listeners are still existing");
119 152 : }
120 :
121 :
122 76 : void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj )
123 : {
124 76 : aDicListEvtListeners.disposeAndClear( rEvtObj );
125 76 : }
126 :
127 :
128 0 : void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource )
129 : throw(RuntimeException, std::exception)
130 : {
131 0 : osl::MutexGuard aGuard( GetLinguMutex() );
132 :
133 0 : uno::Reference< XInterface > xSrc( rSource.Source );
134 :
135 : // remove event object from EventListener list
136 0 : if (xSrc.is())
137 0 : aDicListEvtListeners.removeInterface( xSrc );
138 :
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 0 : uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY );
143 0 : if (xDic.is())
144 : {
145 0 : xMyDicList->removeDictionary( xDic );
146 0 : }
147 0 : }
148 :
149 :
150 179 : void SAL_CALL DicEvtListenerHelper::processDictionaryEvent(
151 : const DictionaryEvent& rDicEvent )
152 : throw(RuntimeException, std::exception)
153 : {
154 179 : osl::MutexGuard aGuard( GetLinguMutex() );
155 :
156 358 : uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY );
157 : DBG_ASSERT(xDic.is(), "lng : missing event source");
158 :
159 : // assert that there is a corresponding dictionary entry if one was
160 : // added or deleted
161 358 : 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" );
166 :
167 : // evaluate DictionaryEvents and update data for next DictionaryListEvent
168 179 : DictionaryType eDicType = xDic->getDictionaryType();
169 : DBG_ASSERT(eDicType != DictionaryType_MIXED,
170 : "lng : unexpected dictionary type");
171 179 : if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive())
172 0 : nCondensedEvt |= xDicEntry->isNegative() ?
173 : DictionaryListEventFlags::ADD_NEG_ENTRY :
174 0 : DictionaryListEventFlags::ADD_POS_ENTRY;
175 179 : if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive())
176 0 : nCondensedEvt |= xDicEntry->isNegative() ?
177 : DictionaryListEventFlags::DEL_NEG_ENTRY :
178 0 : DictionaryListEventFlags::DEL_POS_ENTRY;
179 179 : if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive())
180 : nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
181 : DictionaryListEventFlags::DEL_NEG_ENTRY :
182 0 : DictionaryListEventFlags::DEL_POS_ENTRY;
183 179 : 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 0 : | DictionaryListEventFlags::ACTIVATE_POS_DIC;
189 179 : if ((rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC))
190 : nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
191 : DictionaryListEventFlags::ACTIVATE_NEG_DIC :
192 167 : DictionaryListEventFlags::ACTIVATE_POS_DIC;
193 179 : if ((rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC))
194 : nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ?
195 : DictionaryListEventFlags::DEACTIVATE_NEG_DIC :
196 6 : DictionaryListEventFlags::DEACTIVATE_POS_DIC;
197 :
198 : // update list of collected events if needs to be
199 179 : if (nNumVerboseListeners > 0)
200 : {
201 0 : sal_Int32 nColEvts = aCollectDicEvt.getLength();
202 0 : aCollectDicEvt.realloc( nColEvts + 1 );
203 0 : aCollectDicEvt.getArray()[ nColEvts ] = rDicEvent;
204 : }
205 :
206 179 : if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0)
207 192 : FlushEvents();
208 179 : }
209 :
210 :
211 108 : bool DicEvtListenerHelper::AddDicListEvtListener(
212 : const uno::Reference< XDictionaryListEventListener >& xListener,
213 : bool /*bReceiveVerbose*/ )
214 : {
215 : DBG_ASSERT( xListener.is(), "empty reference" );
216 108 : sal_Int32 nCount = aDicListEvtListeners.getLength();
217 108 : return aDicListEvtListeners.addInterface( xListener ) != nCount;
218 : }
219 :
220 :
221 107 : bool DicEvtListenerHelper::RemoveDicListEvtListener(
222 : const uno::Reference< XDictionaryListEventListener >& xListener )
223 : {
224 : DBG_ASSERT( xListener.is(), "empty reference" );
225 107 : sal_Int32 nCount = aDicListEvtListeners.getLength();
226 107 : return aDicListEvtListeners.removeInterface( xListener ) != nCount;
227 : }
228 :
229 :
230 :
231 :
232 40 : sal_Int16 DicEvtListenerHelper::EndCollectEvents()
233 : {
234 : DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call");
235 40 : if (nNumCollectEvtListeners > 0)
236 : {
237 40 : FlushEvents();
238 40 : nNumCollectEvtListeners--;
239 : }
240 :
241 40 : return nNumCollectEvtListeners;
242 : }
243 :
244 :
245 61 : sal_Int16 DicEvtListenerHelper::FlushEvents()
246 : {
247 61 : if (0 != nCondensedEvt)
248 : {
249 : // build DictionaryListEvent to pass on to listeners
250 15 : uno::Sequence< DictionaryEvent > aDicEvents;
251 15 : if (nNumVerboseListeners > 0)
252 0 : aDicEvents = aCollectDicEvt;
253 30 : DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents );
254 :
255 : // pass on event
256 30 : cppu::OInterfaceIteratorHelper aIt( aDicListEvtListeners );
257 39 : while (aIt.hasMoreElements())
258 : {
259 9 : uno::Reference< XDictionaryListEventListener > xRef( aIt.next(), UNO_QUERY );
260 9 : if (xRef.is())
261 9 : xRef->processDictionaryListEvent( aEvent );
262 9 : }
263 :
264 : // clear "list" of events
265 15 : nCondensedEvt = 0;
266 30 : aCollectDicEvt.realloc( 0 );
267 : }
268 :
269 61 : return nNumCollectEvtListeners;
270 : }
271 :
272 :
273 :
274 :
275 36 : void DicList::MyAppExitListener::AtExit()
276 : {
277 36 : rMyDicList.SaveDics();
278 36 : }
279 :
280 :
281 76 : DicList::DicList() :
282 76 : aEvtListeners ( GetLinguMutex() )
283 : {
284 76 : pDicEvtLstnrHelper = new DicEvtListenerHelper( this );
285 76 : xDicEvtLstnrHelper = pDicEvtLstnrHelper;
286 76 : bDisposing = false;
287 76 : bInCreation = false;
288 :
289 76 : pExitListener = new MyAppExitListener( *this );
290 76 : xExitListener = pExitListener;
291 76 : pExitListener->Activate();
292 76 : }
293 :
294 219 : DicList::~DicList()
295 : {
296 73 : pExitListener->Deactivate();
297 146 : }
298 :
299 :
300 76 : void DicList::SearchForDictionaries(
301 : DictionaryVec_t&rDicList,
302 : const OUString &rDicDirURL,
303 : bool bIsWriteablePath )
304 : {
305 76 : osl::MutexGuard aGuard( GetLinguMutex() );
306 :
307 : const uno::Sequence< OUString > aDirCnt( utl::LocalFileHelper::
308 152 : GetFolderContents( rDicDirURL, false ) );
309 76 : const OUString *pDirCnt = aDirCnt.getConstArray();
310 76 : sal_Int32 nEntries = aDirCnt.getLength();
311 :
312 152 : OUString aDCN("dcn");
313 152 : OUString aDCP("dcp");
314 256 : for (sal_Int32 i = 0; i < nEntries; ++i)
315 : {
316 180 : OUString aURL( pDirCnt[i] );
317 180 : sal_uInt16 nLang = LANGUAGE_NONE;
318 180 : bool bNeg = false;
319 :
320 180 : if(!::IsVers2OrNewer( aURL, nLang, bNeg ))
321 : {
322 : // When not
323 0 : sal_Int32 nPos = aURL.indexOf('.');
324 0 : OUString aExt( aURL.copy(nPos + 1).toAsciiLowerCase() );
325 :
326 0 : if (aDCN.equals(aExt)) // negativ
327 0 : bNeg = true;
328 0 : else if (aDCP.equals(aExt)) // positiv
329 0 : bNeg = false;
330 : else
331 0 : continue; // andere Files
332 : }
333 :
334 : // Record in the list of Dictoinaries
335 : // When it already exists don't record
336 180 : sal_Int16 nSystemLanguage = MsLangId::getSystemLanguage();
337 360 : OUString aTmp1 = ToLower( aURL, nSystemLanguage );
338 180 : sal_Int32 nPos = aTmp1.lastIndexOf( '/' );
339 180 : if (-1 != nPos)
340 180 : aTmp1 = aTmp1.copy( nPos + 1 );
341 360 : OUString aTmp2;
342 : size_t j;
343 180 : size_t nCount = rDicList.size();
344 468 : for(j = 0; j < nCount; j++)
345 : {
346 312 : aTmp2 = rDicList[j]->getName().getStr();
347 312 : aTmp2 = ToLower( aTmp2, nSystemLanguage );
348 312 : if(aTmp1 == aTmp2)
349 24 : break;
350 : }
351 180 : if(j >= nCount) // dictionary not yet in DicList
352 : {
353 : // get decoded dictionary file name
354 156 : INetURLObject aURLObj( aURL );
355 : OUString aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT,
356 : true, INetURLObject::DECODE_WITH_CHARSET,
357 312 : RTL_TEXTENCODING_UTF8 );
358 :
359 156 : DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
360 : uno::Reference< XDictionary > xDic =
361 312 : new DictionaryNeo( aDicName, nLang, eType, aURL, bIsWriteablePath );
362 :
363 156 : addDictionary( xDic );
364 312 : nCount++;
365 : }
366 256 : }
367 76 : }
368 :
369 :
370 10 : sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic)
371 : {
372 10 : osl::MutexGuard aGuard( GetLinguMutex() );
373 :
374 10 : sal_Int32 nPos = -1;
375 10 : DictionaryVec_t& rDicList = GetOrCreateDicList();
376 10 : size_t n = rDicList.size();
377 76 : for (size_t i = 0; i < n; i++)
378 : {
379 74 : if ( rDicList[i] == xDic )
380 8 : return i;
381 : }
382 2 : return nPos;
383 : }
384 :
385 :
386 : uno::Reference< XInterface > SAL_CALL
387 76 : DicList_CreateInstance( const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ )
388 : throw(Exception)
389 : {
390 76 : uno::Reference< XInterface > xService = (cppu::OWeakObject *) new DicList;
391 76 : return xService;
392 : }
393 :
394 54776 : sal_Int16 SAL_CALL DicList::getCount() throw(RuntimeException, std::exception)
395 : {
396 54776 : osl::MutexGuard aGuard( GetLinguMutex() );
397 54776 : return static_cast< sal_Int16 >(GetOrCreateDicList().size());
398 : }
399 :
400 : uno::Sequence< uno::Reference< XDictionary > > SAL_CALL
401 54770 : DicList::getDictionaries()
402 : throw(RuntimeException, std::exception)
403 : {
404 54770 : osl::MutexGuard aGuard( GetLinguMutex() );
405 :
406 54770 : DictionaryVec_t& rDicList = GetOrCreateDicList();
407 :
408 54770 : uno::Sequence< uno::Reference< XDictionary > > aDics( rDicList.size() );
409 54770 : uno::Reference< XDictionary > *pDic = aDics.getArray();
410 :
411 54770 : sal_Int32 n = (sal_uInt16) aDics.getLength();
412 328662 : for (sal_Int32 i = 0; i < n; i++)
413 273892 : pDic[i] = rDicList[i];
414 :
415 54770 : return aDics;
416 : }
417 :
418 : uno::Reference< XDictionary > SAL_CALL
419 16818 : DicList::getDictionaryByName( const OUString& aDictionaryName )
420 : throw(RuntimeException, std::exception)
421 : {
422 16818 : osl::MutexGuard aGuard( GetLinguMutex() );
423 :
424 16818 : uno::Reference< XDictionary > xDic;
425 16818 : DictionaryVec_t& rDicList = GetOrCreateDicList();
426 16818 : size_t nCount = rDicList.size();
427 83770 : for (size_t i = 0; i < nCount; i++)
428 : {
429 83733 : const uno::Reference< XDictionary > &rDic = rDicList[i];
430 83733 : if (rDic.is() && rDic->getName() == aDictionaryName)
431 : {
432 16781 : xDic = rDic;
433 16781 : break;
434 : }
435 : }
436 :
437 16818 : return xDic;
438 : }
439 :
440 207 : sal_Bool SAL_CALL DicList::addDictionary(
441 : const uno::Reference< XDictionary >& xDictionary )
442 : throw(RuntimeException, std::exception)
443 : {
444 207 : osl::MutexGuard aGuard( GetLinguMutex() );
445 :
446 207 : if (bDisposing)
447 0 : return sal_False;
448 :
449 207 : bool bRes = false;
450 207 : if (xDictionary.is())
451 : {
452 207 : DictionaryVec_t& rDicList = GetOrCreateDicList();
453 207 : rDicList.push_back( xDictionary );
454 207 : bRes = true;
455 :
456 : // add listener helper to the dictionaries listener lists
457 207 : xDictionary->addDictionaryEventListener( xDicEvtLstnrHelper );
458 : }
459 207 : return bRes;
460 : }
461 :
462 : sal_Bool SAL_CALL
463 10 : DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary )
464 : throw(RuntimeException, std::exception)
465 : {
466 10 : osl::MutexGuard aGuard( GetLinguMutex() );
467 :
468 10 : if (bDisposing)
469 0 : return sal_False;
470 :
471 10 : bool bRes = false;
472 10 : sal_Int32 nPos = GetDicPos( xDictionary );
473 10 : if (nPos >= 0)
474 : {
475 : // remove dictionary list from the dictionaries listener lists
476 8 : DictionaryVec_t& rDicList = GetOrCreateDicList();
477 8 : uno::Reference< XDictionary > xDic( rDicList[ nPos ] );
478 : DBG_ASSERT(xDic.is(), "lng : empty reference");
479 8 : if (xDic.is())
480 : {
481 : // deactivate dictionary if not already done
482 8 : xDic->setActive( sal_False );
483 :
484 8 : xDic->removeDictionaryEventListener( xDicEvtLstnrHelper );
485 : }
486 :
487 : // remove element at nPos
488 8 : rDicList.erase( rDicList.begin() + nPos );
489 8 : bRes = true;
490 : }
491 10 : return bRes;
492 : }
493 :
494 108 : sal_Bool SAL_CALL DicList::addDictionaryListEventListener(
495 : const uno::Reference< XDictionaryListEventListener >& xListener,
496 : sal_Bool bReceiveVerbose )
497 : throw(RuntimeException, std::exception)
498 : {
499 108 : osl::MutexGuard aGuard( GetLinguMutex() );
500 :
501 108 : if (bDisposing)
502 0 : return sal_False;
503 :
504 : DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported");
505 :
506 108 : bool bRes = false;
507 108 : if (xListener.is()) //! don't add empty references
508 : {
509 : bRes = pDicEvtLstnrHelper->
510 108 : AddDicListEvtListener( xListener, bReceiveVerbose );
511 : }
512 108 : return bRes;
513 : }
514 :
515 108 : sal_Bool SAL_CALL DicList::removeDictionaryListEventListener(
516 : const uno::Reference< XDictionaryListEventListener >& xListener )
517 : throw(RuntimeException, std::exception)
518 : {
519 108 : osl::MutexGuard aGuard( GetLinguMutex() );
520 :
521 108 : if (bDisposing)
522 1 : return sal_False;
523 :
524 107 : bool bRes = false;
525 107 : if(xListener.is())
526 : {
527 107 : bRes = pDicEvtLstnrHelper->RemoveDicListEvtListener( xListener );
528 : }
529 107 : return bRes;
530 : }
531 :
532 2 : sal_Int16 SAL_CALL DicList::beginCollectEvents() throw(RuntimeException, std::exception)
533 : {
534 2 : osl::MutexGuard aGuard( GetLinguMutex() );
535 2 : return pDicEvtLstnrHelper->BeginCollectEvents();
536 : }
537 :
538 2 : sal_Int16 SAL_CALL DicList::endCollectEvents() throw(RuntimeException, std::exception)
539 : {
540 2 : osl::MutexGuard aGuard( GetLinguMutex() );
541 2 : return pDicEvtLstnrHelper->EndCollectEvents();
542 : }
543 :
544 8 : sal_Int16 SAL_CALL DicList::flushEvents() throw(RuntimeException, std::exception)
545 : {
546 8 : osl::MutexGuard aGuard( GetLinguMutex() );
547 8 : return pDicEvtLstnrHelper->FlushEvents();
548 : }
549 :
550 : uno::Reference< XDictionary > SAL_CALL
551 81 : DicList::createDictionary( const OUString& rName, const Locale& rLocale,
552 : DictionaryType eDicType, const OUString& rURL )
553 : throw(RuntimeException, std::exception)
554 : {
555 81 : osl::MutexGuard aGuard( GetLinguMutex() );
556 :
557 81 : sal_Int16 nLanguage = LinguLocaleToLanguage( rLocale );
558 81 : bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath(), 0 );
559 81 : return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath );
560 : }
561 :
562 :
563 : uno::Reference< XDictionaryEntry > SAL_CALL
564 21602 : DicList::queryDictionaryEntry( const OUString& rWord, const Locale& rLocale,
565 : sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry )
566 : throw(RuntimeException, std::exception)
567 : {
568 21602 : osl::MutexGuard aGuard( GetLinguMutex() );
569 21602 : return SearchDicList( this, rWord, LinguLocaleToLanguage( rLocale ),
570 43204 : bSearchPosDics, bSearchSpellEntry );
571 : }
572 :
573 :
574 : void SAL_CALL
575 80 : DicList::dispose()
576 : throw(RuntimeException, std::exception)
577 : {
578 80 : osl::MutexGuard aGuard( GetLinguMutex() );
579 :
580 80 : if (!bDisposing)
581 : {
582 76 : bDisposing = true;
583 76 : EventObject aEvtObj( (XDictionaryList *) this );
584 :
585 76 : aEvtListeners.disposeAndClear( aEvtObj );
586 76 : if (pDicEvtLstnrHelper)
587 76 : pDicEvtLstnrHelper->DisposeAndClear( aEvtObj );
588 :
589 : //! avoid creation of dictionaries if not already done
590 76 : if ( !aDicList.empty() )
591 : {
592 38 : DictionaryVec_t& rDicList = GetOrCreateDicList();
593 38 : size_t nCount = rDicList.size();
594 237 : for (size_t i = 0; i < nCount; i++)
595 : {
596 199 : uno::Reference< XDictionary > xDic( rDicList[i], UNO_QUERY );
597 :
598 : // save (modified) dictionaries
599 398 : uno::Reference< frame::XStorable > xStor( xDic , UNO_QUERY );
600 199 : if (xStor.is())
601 : {
602 : try
603 : {
604 199 : if (!xStor->isReadonly() && xStor->hasLocation())
605 29 : xStor->store();
606 : }
607 0 : catch(Exception &)
608 : {
609 : }
610 : }
611 :
612 : // release references to (members of) this object hold by
613 : // dictionaries
614 199 : if (xDic.is())
615 199 : xDic->removeDictionaryEventListener( xDicEvtLstnrHelper );
616 199 : }
617 : }
618 76 : xDicEvtLstnrHelper.clear();
619 80 : }
620 80 : }
621 :
622 : void SAL_CALL
623 4 : DicList::addEventListener( const uno::Reference< XEventListener >& rxListener )
624 : throw(RuntimeException, std::exception)
625 : {
626 4 : osl::MutexGuard aGuard( GetLinguMutex() );
627 :
628 4 : if (!bDisposing && rxListener.is())
629 4 : aEvtListeners.addInterface( rxListener );
630 4 : }
631 :
632 : void SAL_CALL
633 2 : DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener )
634 : throw(RuntimeException, std::exception)
635 : {
636 2 : osl::MutexGuard aGuard( GetLinguMutex() );
637 :
638 2 : if (!bDisposing && rxListener.is())
639 2 : aEvtListeners.removeInterface( rxListener );
640 2 : }
641 :
642 38 : void DicList::_CreateDicList()
643 : {
644 38 : bInCreation = true;
645 :
646 : // look for dictionaries
647 38 : const OUString aWriteablePath( GetDictionaryWriteablePath() );
648 76 : uno::Sequence< OUString > aPaths( GetDictionaryPaths() );
649 38 : const OUString *pPaths = aPaths.getConstArray();
650 114 : for (sal_Int32 i = 0; i < aPaths.getLength(); ++i)
651 : {
652 76 : const bool bIsWriteablePath = (pPaths[i] == aWriteablePath);
653 76 : SearchForDictionaries( aDicList, pPaths[i], bIsWriteablePath );
654 : }
655 :
656 : // create IgnoreAllList dictionary with empty URL (non persistent)
657 : // and add it to list
658 76 : OUString aDicName( "IgnoreAllList" );
659 : uno::Reference< XDictionary > xIgnAll(
660 : createDictionary( aDicName, LinguLanguageToLocale( LANGUAGE_NONE ),
661 76 : DictionaryType_POSITIVE, OUString() ) );
662 38 : if (xIgnAll.is())
663 : {
664 38 : AddUserData( xIgnAll );
665 38 : xIgnAll->setActive( sal_True );
666 38 : addDictionary( xIgnAll );
667 : }
668 :
669 :
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 38 : pDicEvtLstnrHelper->BeginCollectEvents();
675 76 : const uno::Sequence< OUString > aActiveDics( aOpt.GetActiveDics() );
676 38 : const OUString *pActiveDic = aActiveDics.getConstArray();
677 38 : sal_Int32 nLen = aActiveDics.getLength();
678 266 : for (sal_Int32 i = 0; i < nLen; ++i)
679 : {
680 228 : if (!pActiveDic[i].isEmpty())
681 : {
682 228 : uno::Reference< XDictionary > xDic( getDictionaryByName( pActiveDic[i] ) );
683 228 : if (xDic.is())
684 194 : xDic->setActive( sal_True );
685 : }
686 : }
687 :
688 : // suppress collected events during creation of the dictionary list.
689 : // there should be no events during creation.
690 38 : pDicEvtLstnrHelper->ClearEvents();
691 :
692 38 : pDicEvtLstnrHelper->EndCollectEvents();
693 :
694 76 : bInCreation = false;
695 38 : }
696 :
697 :
698 36 : void DicList::SaveDics()
699 : {
700 : // save dics only if they have already been used/created.
701 : //! don't create them just for the purpose of saving them !
702 36 : if ( !aDicList.empty() )
703 : {
704 : // save (modified) dictionaries
705 34 : DictionaryVec_t& rDicList = GetOrCreateDicList();
706 34 : size_t nCount = rDicList.size();;
707 210 : for (size_t i = 0; i < nCount; i++)
708 : {
709 : // save (modified) dictionaries
710 176 : uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY );
711 176 : if (xStor.is())
712 : {
713 : try
714 : {
715 176 : if (!xStor->isReadonly() && xStor->hasLocation())
716 10 : xStor->store();
717 : }
718 0 : catch(Exception &)
719 : {
720 : }
721 : }
722 176 : }
723 : }
724 36 : }
725 :
726 :
727 : // Service specific part
728 :
729 4 : OUString SAL_CALL DicList::getImplementationName( ) throw(RuntimeException, std::exception)
730 : {
731 4 : osl::MutexGuard aGuard( GetLinguMutex() );
732 4 : return getImplementationName_Static();
733 : }
734 :
735 :
736 2 : sal_Bool SAL_CALL DicList::supportsService( const OUString& ServiceName )
737 : throw(RuntimeException, std::exception)
738 : {
739 2 : return cppu::supportsService(this, ServiceName);
740 : }
741 :
742 6 : uno::Sequence< OUString > SAL_CALL DicList::getSupportedServiceNames( )
743 : throw(RuntimeException, std::exception)
744 : {
745 6 : osl::MutexGuard aGuard( GetLinguMutex() );
746 6 : return getSupportedServiceNames_Static();
747 : }
748 :
749 :
750 82 : uno::Sequence< OUString > DicList::getSupportedServiceNames_Static() throw()
751 : {
752 82 : osl::MutexGuard aGuard( GetLinguMutex() );
753 :
754 82 : uno::Sequence< OUString > aSNS( 1 ); // more than 1 service possible
755 82 : aSNS.getArray()[0] = "com.sun.star.linguistic2.DictionaryList";
756 82 : return aSNS;
757 : }
758 :
759 82 : void * SAL_CALL DicList_getFactory( const sal_Char * pImplName,
760 : XMultiServiceFactory * pServiceManager, void * )
761 : {
762 82 : void * pRet = 0;
763 82 : if ( DicList::getImplementationName_Static().equalsAscii( pImplName ) )
764 : {
765 : uno::Reference< XSingleServiceFactory > xFactory =
766 : cppu::createOneInstanceFactory(
767 : pServiceManager,
768 : DicList::getImplementationName_Static(),
769 : DicList_CreateInstance,
770 76 : DicList::getSupportedServiceNames_Static());
771 : // acquire, because we return an interface pointer instead of a reference
772 76 : xFactory->acquire();
773 76 : pRet = xFactory.get();
774 : }
775 82 : return pRet;
776 : }
777 :
778 :
779 266 : static sal_Int32 lcl_GetToken( OUString &rToken,
780 : const OUString &rText, sal_Int32 nPos, const OUString &rDelim )
781 : {
782 266 : sal_Int32 nRes = -1;
783 :
784 266 : if (rText.isEmpty() || nPos >= rText.getLength())
785 266 : rToken = "";
786 0 : else if (rDelim.isEmpty())
787 : {
788 0 : rToken = rText;
789 0 : if (!rToken.isEmpty())
790 0 : nRes = rText.getLength();
791 : }
792 : else
793 : {
794 : sal_Int32 i;
795 0 : for (i = nPos; i < rText.getLength(); ++i)
796 : {
797 0 : if (-1 != rDelim.indexOf( rText[i] ))
798 0 : break;
799 : }
800 :
801 0 : if (i >= rText.getLength()) // delimiter not found
802 0 : rToken = rText.copy( nPos );
803 : else
804 0 : rToken = rText.copy( nPos, i - nPos );
805 0 : nRes = i + 1; // continue after found delimiter
806 : }
807 :
808 266 : return nRes;
809 : }
810 :
811 :
812 266 : static void AddInternal(
813 : const uno::Reference<XDictionary> &rDic,
814 : const OUString& rNew )
815 : {
816 266 : if (rDic.is())
817 : {
818 : //! TL TODO: word iterator should be used to break up the text
819 : static const char aDefWordDelim[] =
820 : "!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n";
821 266 : OUString aDelim(aDefWordDelim);
822 : OSL_ENSURE(aDelim.indexOf(static_cast<sal_Unicode>('.')) == -1,
823 : "ensure no '.'");
824 :
825 532 : OUString aToken;
826 266 : sal_Int32 nPos = 0;
827 532 : while (-1 !=
828 : (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim )))
829 : {
830 0 : if( !aToken.isEmpty() && !IsNumeric( aToken ) )
831 : {
832 0 : rDic->add( aToken, sal_False, OUString() );
833 : }
834 266 : }
835 : }
836 266 : }
837 :
838 38 : static void AddUserData( const uno::Reference< XDictionary > &rDic )
839 : {
840 38 : if (rDic.is())
841 : {
842 38 : SvtUserOptions aUserOpt;
843 38 : AddInternal( rDic, aUserOpt.GetFullName() );
844 38 : AddInternal( rDic, aUserOpt.GetCompany() );
845 38 : AddInternal( rDic, aUserOpt.GetStreet() );
846 38 : AddInternal( rDic, aUserOpt.GetCity() );
847 38 : AddInternal( rDic, aUserOpt.GetTitle() );
848 38 : AddInternal( rDic, aUserOpt.GetPosition() );
849 38 : AddInternal( rDic, aUserOpt.GetEmail() );
850 : }
851 38 : }
852 :
853 180 : static bool IsVers2OrNewer( const OUString& rFileURL, sal_uInt16& nLng, bool& bNeg )
854 : {
855 180 : if (rFileURL.isEmpty())
856 0 : return false;
857 180 : OUString aDIC("dic");
858 360 : OUString aExt;
859 180 : sal_Int32 nPos = rFileURL.lastIndexOf( '.' );
860 180 : if (-1 != nPos)
861 180 : aExt = rFileURL.copy( nPos + 1 ).toAsciiLowerCase();
862 :
863 180 : if (aDIC != aExt)
864 0 : return false;
865 :
866 : // get stream to be used
867 360 : uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
868 :
869 : // get XInputStream stream
870 360 : uno::Reference< io::XInputStream > xStream;
871 : try
872 : {
873 180 : uno::Reference< ucb::XSimpleFileAccess3 > xAccess( ucb::SimpleFileAccess::create(xContext) );
874 180 : xStream = xAccess->openFileRead( rFileURL );
875 : }
876 0 : catch (const uno::Exception &)
877 : {
878 : DBG_ASSERT( false, "failed to get input stream" );
879 : }
880 : DBG_ASSERT( xStream.is(), "failed to get stream for read" );
881 180 : if (!xStream.is())
882 0 : return false;
883 :
884 360 : SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) );
885 :
886 180 : int nDicVersion = ReadDicVersion(pStream, nLng, bNeg);
887 180 : if (2 == nDicVersion || nDicVersion >= 5)
888 180 : return true;
889 :
890 180 : return false;
891 : }
892 :
893 :
894 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|