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