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