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