File: | home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx |
Warning: | line 255, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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/debug.hxx> | |||
25 | #include <tools/stream.hxx> | |||
26 | #include <tools/urlobj.hxx> | |||
27 | #include <unotools/useroptions.hxx> | |||
28 | #include <cppuhelper/supportsservice.hxx> | |||
29 | #include <cppuhelper/weak.hxx> | |||
30 | #include <unotools/localfilehelper.hxx> | |||
31 | #include <comphelper/processfactory.hxx> | |||
32 | #include <comphelper/sequence.hxx> | |||
33 | #include <unotools/ucbstreamhelper.hxx> | |||
34 | #include <com/sun/star/frame/XStorable.hpp> | |||
35 | #include <com/sun/star/lang/XSingleServiceFactory.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/ucb/SimpleFileAccess.hpp> | |||
40 | #include <svtools/strings.hrc> | |||
41 | #include <unotools/resmgr.hxx> | |||
42 | #include <sal/log.hxx> | |||
43 | ||||
44 | #include "defs.hxx" | |||
45 | #include "dlistimp.hxx" | |||
46 | #include "dicimp.hxx" | |||
47 | #include "lngopt.hxx" | |||
48 | ||||
49 | using namespace osl; | |||
50 | using namespace com::sun::star; | |||
51 | using namespace com::sun::star::lang; | |||
52 | using namespace com::sun::star::uno; | |||
53 | using namespace com::sun::star::linguistic2; | |||
54 | using namespace linguistic; | |||
55 | ||||
56 | ||||
57 | static bool IsVers2OrNewer( const OUString& rFileURL, LanguageType& nLng, bool& bNeg, OUString& aDicName ); | |||
58 | ||||
59 | static void AddInternal( const uno::Reference< XDictionary > &rDic, | |||
60 | const OUString& rNew ); | |||
61 | static void AddUserData( const uno::Reference< XDictionary > &rDic ); | |||
62 | ||||
63 | ||||
64 | class DicEvtListenerHelper : | |||
65 | public cppu::WeakImplHelper | |||
66 | < | |||
67 | XDictionaryEventListener | |||
68 | > | |||
69 | { | |||
70 | comphelper::OInterfaceContainerHelper2 aDicListEvtListeners; | |||
71 | uno::Reference< XDictionaryList > xMyDicList; | |||
72 | ||||
73 | sal_Int16 nCondensedEvt; | |||
74 | sal_Int16 nNumCollectEvtListeners; | |||
75 | ||||
76 | public: | |||
77 | explicit DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList ); | |||
78 | virtual ~DicEvtListenerHelper() override; | |||
79 | ||||
80 | // XEventListener | |||
81 | virtual void SAL_CALL | |||
82 | disposing( const EventObject& rSource ) override; | |||
83 | ||||
84 | // XDictionaryEventListener | |||
85 | virtual void SAL_CALL | |||
86 | processDictionaryEvent( const DictionaryEvent& rDicEvent ) override; | |||
87 | ||||
88 | // non-UNO functions | |||
89 | void DisposeAndClear( const EventObject &rEvtObj ); | |||
90 | ||||
91 | bool AddDicListEvtListener( | |||
92 | const uno::Reference< XDictionaryListEventListener >& rxListener ); | |||
93 | bool RemoveDicListEvtListener( | |||
94 | const uno::Reference< XDictionaryListEventListener >& rxListener ); | |||
95 | sal_Int16 BeginCollectEvents() { return ++nNumCollectEvtListeners;} | |||
96 | sal_Int16 EndCollectEvents(); | |||
97 | sal_Int16 FlushEvents(); | |||
98 | void ClearEvents() { nCondensedEvt = 0; } | |||
99 | }; | |||
100 | ||||
101 | ||||
102 | DicEvtListenerHelper::DicEvtListenerHelper( | |||
103 | const uno::Reference< XDictionaryList > &rxDicList ) : | |||
104 | aDicListEvtListeners ( GetLinguMutex() ), | |||
105 | xMyDicList ( rxDicList ), | |||
106 | nCondensedEvt(0), nNumCollectEvtListeners(0) | |||
107 | { | |||
108 | } | |||
109 | ||||
110 | ||||
111 | DicEvtListenerHelper::~DicEvtListenerHelper() | |||
112 | { | |||
113 | DBG_ASSERT(aDicListEvtListeners.getLength() == 0,do { if (true && (!(aDicListEvtListeners.getLength() == 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools" ), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "114" ": "), "%s", "lng : event listeners are still existing" ); } } while (false) | |||
114 | "lng : event listeners are still existing")do { if (true && (!(aDicListEvtListeners.getLength() == 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools" ), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "114" ": "), "%s", "lng : event listeners are still existing" ); } } while (false); | |||
115 | } | |||
116 | ||||
117 | ||||
118 | void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj ) | |||
119 | { | |||
120 | aDicListEvtListeners.disposeAndClear( rEvtObj ); | |||
121 | } | |||
122 | ||||
123 | ||||
124 | void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource ) | |||
125 | { | |||
126 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
127 | ||||
128 | uno::Reference< XInterface > xSrc( rSource.Source ); | |||
129 | ||||
130 | // remove event object from EventListener list | |||
131 | if (xSrc.is()) | |||
132 | aDicListEvtListeners.removeInterface( xSrc ); | |||
133 | ||||
134 | // if object is a dictionary then remove it from the dictionary list | |||
135 | // Note: this will probably happen only if someone makes a XDictionary | |||
136 | // implementation of his own that is also a XComponent. | |||
137 | uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY ); | |||
138 | if (xDic.is()) | |||
139 | { | |||
140 | xMyDicList->removeDictionary( xDic ); | |||
141 | } | |||
142 | } | |||
143 | ||||
144 | ||||
145 | void SAL_CALL DicEvtListenerHelper::processDictionaryEvent( | |||
146 | const DictionaryEvent& rDicEvent ) | |||
147 | { | |||
148 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
149 | ||||
150 | uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY ); | |||
151 | DBG_ASSERT(xDic.is(), "lng : missing event source")do { if (true && (!(xDic.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "151" ": "), "%s", "lng : missing event source"); } } while (false); | |||
152 | ||||
153 | // assert that there is a corresponding dictionary entry if one was | |||
154 | // added or deleted | |||
155 | DBG_ASSERT( !(rDicEvent.nEvent &do { if (true && (!(!(rDicEvent.nEvent & (DictionaryEventFlags ::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY)) || rDicEvent. xDictionaryEntry.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "158" ": "), "%s", "lng : missing dictionary entry"); } } while (false) | |||
156 | (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY))do { if (true && (!(!(rDicEvent.nEvent & (DictionaryEventFlags ::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY)) || rDicEvent. xDictionaryEntry.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "158" ": "), "%s", "lng : missing dictionary entry"); } } while (false) | |||
157 | || rDicEvent.xDictionaryEntry.is(),do { if (true && (!(!(rDicEvent.nEvent & (DictionaryEventFlags ::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY)) || rDicEvent. xDictionaryEntry.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "158" ": "), "%s", "lng : missing dictionary entry"); } } while (false) | |||
158 | "lng : missing dictionary entry" )do { if (true && (!(!(rDicEvent.nEvent & (DictionaryEventFlags ::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY)) || rDicEvent. xDictionaryEntry.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "158" ": "), "%s", "lng : missing dictionary entry"); } } while (false); | |||
159 | ||||
160 | // evaluate DictionaryEvents and update data for next DictionaryListEvent | |||
161 | DictionaryType eDicType = xDic->getDictionaryType(); | |||
162 | DBG_ASSERT(eDicType != DictionaryType_MIXED,do { if (true && (!(eDicType != DictionaryType_MIXED) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools" ), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "163" ": "), "%s", "lng : unexpected dictionary type"); } } while (false) | |||
163 | "lng : unexpected dictionary type")do { if (true && (!(eDicType != DictionaryType_MIXED) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools" ), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "163" ": "), "%s", "lng : unexpected dictionary type"); } } while (false); | |||
164 | if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive()) | |||
165 | nCondensedEvt |= rDicEvent.xDictionaryEntry->isNegative() ? | |||
166 | DictionaryListEventFlags::ADD_NEG_ENTRY : | |||
167 | DictionaryListEventFlags::ADD_POS_ENTRY; | |||
168 | if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive()) | |||
169 | nCondensedEvt |= rDicEvent.xDictionaryEntry->isNegative() ? | |||
170 | DictionaryListEventFlags::DEL_NEG_ENTRY : | |||
171 | DictionaryListEventFlags::DEL_POS_ENTRY; | |||
172 | if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive()) | |||
173 | nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? | |||
174 | DictionaryListEventFlags::DEL_NEG_ENTRY : | |||
175 | DictionaryListEventFlags::DEL_POS_ENTRY; | |||
176 | if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive()) | |||
177 | nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? | |||
178 | DictionaryListEventFlags::DEACTIVATE_NEG_DIC | |||
179 | | DictionaryListEventFlags::ACTIVATE_NEG_DIC : | |||
180 | DictionaryListEventFlags::DEACTIVATE_POS_DIC | |||
181 | | DictionaryListEventFlags::ACTIVATE_POS_DIC; | |||
182 | if (rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC) | |||
183 | nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? | |||
184 | DictionaryListEventFlags::ACTIVATE_NEG_DIC : | |||
185 | DictionaryListEventFlags::ACTIVATE_POS_DIC; | |||
186 | if (rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC) | |||
187 | nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? | |||
188 | DictionaryListEventFlags::DEACTIVATE_NEG_DIC : | |||
189 | DictionaryListEventFlags::DEACTIVATE_POS_DIC; | |||
190 | ||||
191 | if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0) | |||
192 | FlushEvents(); | |||
193 | } | |||
194 | ||||
195 | ||||
196 | bool DicEvtListenerHelper::AddDicListEvtListener( | |||
197 | const uno::Reference< XDictionaryListEventListener >& xListener ) | |||
198 | { | |||
199 | DBG_ASSERT( xListener.is(), "empty reference" )do { if (true && (!(xListener.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "199" ": "), "%s", "empty reference"); } } while (false); | |||
200 | sal_Int32 nCount = aDicListEvtListeners.getLength(); | |||
201 | return aDicListEvtListeners.addInterface( xListener ) != nCount; | |||
202 | } | |||
203 | ||||
204 | ||||
205 | bool DicEvtListenerHelper::RemoveDicListEvtListener( | |||
206 | const uno::Reference< XDictionaryListEventListener >& xListener ) | |||
207 | { | |||
208 | DBG_ASSERT( xListener.is(), "empty reference" )do { if (true && (!(xListener.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "208" ": "), "%s", "empty reference"); } } while (false); | |||
209 | sal_Int32 nCount = aDicListEvtListeners.getLength(); | |||
210 | return aDicListEvtListeners.removeInterface( xListener ) != nCount; | |||
211 | } | |||
212 | ||||
213 | ||||
214 | sal_Int16 DicEvtListenerHelper::EndCollectEvents() | |||
215 | { | |||
216 | DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call")do { if (true && (!(nNumCollectEvtListeners > 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools" ), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "216" ": "), "%s", "lng: mismatched function call"); } } while (false); | |||
217 | if (nNumCollectEvtListeners > 0) | |||
218 | { | |||
219 | FlushEvents(); | |||
220 | nNumCollectEvtListeners--; | |||
221 | } | |||
222 | ||||
223 | return nNumCollectEvtListeners; | |||
224 | } | |||
225 | ||||
226 | ||||
227 | sal_Int16 DicEvtListenerHelper::FlushEvents() | |||
228 | { | |||
229 | if (0 != nCondensedEvt) | |||
230 | { | |||
231 | // build DictionaryListEvent to pass on to listeners | |||
232 | uno::Sequence< DictionaryEvent > aDicEvents; | |||
233 | DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents ); | |||
234 | ||||
235 | // pass on event | |||
236 | aDicListEvtListeners.notifyEach( &XDictionaryListEventListener::processDictionaryListEvent, aEvent ); | |||
237 | ||||
238 | // clear "list" of events | |||
239 | nCondensedEvt = 0; | |||
240 | } | |||
241 | ||||
242 | return nNumCollectEvtListeners; | |||
243 | } | |||
244 | ||||
245 | ||||
246 | void DicList::MyAppExitListener::AtExit() | |||
247 | { | |||
248 | rMyDicList.SaveDics(); | |||
249 | } | |||
250 | ||||
251 | ||||
252 | DicList::DicList() : | |||
253 | aEvtListeners ( GetLinguMutex() ) | |||
254 | { | |||
255 | mxDicEvtLstnrHelper = new DicEvtListenerHelper( this ); | |||
| ||||
256 | bDisposing = false; | |||
257 | bInCreation = false; | |||
258 | ||||
259 | mxExitListener = new MyAppExitListener( *this ); | |||
260 | mxExitListener->Activate(); | |||
261 | } | |||
262 | ||||
263 | DicList::~DicList() | |||
264 | { | |||
265 | mxExitListener->Deactivate(); | |||
266 | } | |||
267 | ||||
268 | ||||
269 | void DicList::SearchForDictionaries( | |||
270 | DictionaryVec_t&rDicList, | |||
271 | const OUString &rDicDirURL, | |||
272 | bool bIsWriteablePath ) | |||
273 | { | |||
274 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
275 | ||||
276 | const uno::Sequence< OUString > aDirCnt( utl::LocalFileHelper:: | |||
277 | GetFolderContents( rDicDirURL, false ) ); | |||
278 | ||||
279 | for (const OUString& aURL : aDirCnt) | |||
280 | { | |||
281 | LanguageType nLang = LANGUAGE_NONELanguageType(0x00FF); | |||
282 | bool bNeg = false; | |||
283 | OUString aDicTitle = ""; | |||
284 | ||||
285 | if(!::IsVers2OrNewer( aURL, nLang, bNeg, aDicTitle )) | |||
286 | { | |||
287 | // When not | |||
288 | sal_Int32 nPos = aURL.indexOf('.'); | |||
289 | OUString aExt( aURL.copy(nPos + 1).toAsciiLowerCase() ); | |||
290 | ||||
291 | if ("dcn" == aExt) // negative | |||
292 | bNeg = true; | |||
293 | else if ("dcp" == aExt) // positive | |||
294 | bNeg = false; | |||
295 | else | |||
296 | continue; // other files | |||
297 | } | |||
298 | ||||
299 | // Record in the list of Dictionaries | |||
300 | // When it already exists don't record | |||
301 | LanguageType nSystemLanguage = MsLangId::getSystemLanguage(); | |||
302 | OUString aTmp1 = ToLower( aURL, nSystemLanguage ); | |||
303 | sal_Int32 nPos = aTmp1.lastIndexOf( '/' ); | |||
304 | if (-1 != nPos) | |||
305 | aTmp1 = aTmp1.copy( nPos + 1 ); | |||
306 | OUString aTmp2; | |||
307 | size_t j; | |||
308 | size_t nCount = rDicList.size(); | |||
309 | for(j = 0; j < nCount; j++) | |||
310 | { | |||
311 | aTmp2 = rDicList[j]->getName(); | |||
312 | aTmp2 = ToLower( aTmp2, nSystemLanguage ); | |||
313 | if(aTmp1 == aTmp2) | |||
314 | break; | |||
315 | } | |||
316 | if(j >= nCount) // dictionary not yet in DicList | |||
317 | { | |||
318 | // get decoded dictionary file name | |||
319 | INetURLObject aURLObj( aURL ); | |||
320 | OUString aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT, | |||
321 | true, INetURLObject::DecodeMechanism::WithCharset ); | |||
322 | ||||
323 | DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE; | |||
324 | uno::Reference< XDictionary > xDic = | |||
325 | new DictionaryNeo( aDicTitle.isEmpty() ? aDicName : aDicTitle, nLang, eType, aURL, bIsWriteablePath ); | |||
326 | ||||
327 | addDictionary( xDic ); | |||
328 | nCount++; | |||
329 | } | |||
330 | } | |||
331 | } | |||
332 | ||||
333 | ||||
334 | sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic) | |||
335 | { | |||
336 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
337 | ||||
338 | DictionaryVec_t& rDicList = GetOrCreateDicList(); | |||
339 | size_t n = rDicList.size(); | |||
340 | for (size_t i = 0; i < n; i++) | |||
341 | { | |||
342 | if ( rDicList[i] == xDic ) | |||
343 | return i; | |||
344 | } | |||
345 | return -1; | |||
346 | } | |||
347 | ||||
348 | sal_Int16 SAL_CALL DicList::getCount() | |||
349 | { | |||
350 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
351 | return static_cast< sal_Int16 >(GetOrCreateDicList().size()); | |||
352 | } | |||
353 | ||||
354 | uno::Sequence< uno::Reference< XDictionary > > SAL_CALL | |||
355 | DicList::getDictionaries() | |||
356 | { | |||
357 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
358 | ||||
359 | DictionaryVec_t& rDicList = GetOrCreateDicList(); | |||
360 | ||||
361 | return comphelper::containerToSequence(rDicList); | |||
362 | } | |||
363 | ||||
364 | uno::Reference< XDictionary > SAL_CALL | |||
365 | DicList::getDictionaryByName( const OUString& aDictionaryName ) | |||
366 | { | |||
367 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
368 | ||||
369 | uno::Reference< XDictionary > xDic; | |||
370 | DictionaryVec_t& rDicList = GetOrCreateDicList(); | |||
371 | size_t nCount = rDicList.size(); | |||
372 | for (size_t i = 0; i < nCount; i++) | |||
373 | { | |||
374 | const uno::Reference< XDictionary > &rDic = rDicList[i]; | |||
375 | if (rDic.is() && rDic->getName() == aDictionaryName) | |||
376 | { | |||
377 | xDic = rDic; | |||
378 | break; | |||
379 | } | |||
380 | } | |||
381 | ||||
382 | return xDic; | |||
383 | } | |||
384 | ||||
385 | sal_Bool SAL_CALL DicList::addDictionary( | |||
386 | const uno::Reference< XDictionary >& xDictionary ) | |||
387 | { | |||
388 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
389 | ||||
390 | if (bDisposing) | |||
391 | return false; | |||
392 | ||||
393 | bool bRes = false; | |||
394 | if (xDictionary.is()) | |||
395 | { | |||
396 | DictionaryVec_t& rDicList = GetOrCreateDicList(); | |||
397 | rDicList.push_back( xDictionary ); | |||
398 | bRes = true; | |||
399 | ||||
400 | // add listener helper to the dictionaries listener lists | |||
401 | xDictionary->addDictionaryEventListener( mxDicEvtLstnrHelper.get() ); | |||
402 | } | |||
403 | return bRes; | |||
404 | } | |||
405 | ||||
406 | sal_Bool SAL_CALL | |||
407 | DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary ) | |||
408 | { | |||
409 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
410 | ||||
411 | if (bDisposing) | |||
412 | return false; | |||
413 | ||||
414 | bool bRes = false; | |||
415 | sal_Int32 nPos = GetDicPos( xDictionary ); | |||
416 | if (nPos >= 0) | |||
417 | { | |||
418 | // remove dictionary list from the dictionaries listener lists | |||
419 | DictionaryVec_t& rDicList = GetOrCreateDicList(); | |||
420 | uno::Reference< XDictionary > xDic( rDicList[ nPos ] ); | |||
421 | DBG_ASSERT(xDic.is(), "lng : empty reference")do { if (true && (!(xDic.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "421" ": "), "%s", "lng : empty reference"); } } while ( false); | |||
422 | if (xDic.is()) | |||
423 | { | |||
424 | // deactivate dictionary if not already done | |||
425 | xDic->setActive( false ); | |||
426 | ||||
427 | xDic->removeDictionaryEventListener( mxDicEvtLstnrHelper.get() ); | |||
428 | } | |||
429 | ||||
430 | // remove element at nPos | |||
431 | rDicList.erase( rDicList.begin() + nPos ); | |||
432 | bRes = true; | |||
433 | } | |||
434 | return bRes; | |||
435 | } | |||
436 | ||||
437 | sal_Bool SAL_CALL DicList::addDictionaryListEventListener( | |||
438 | const uno::Reference< XDictionaryListEventListener >& xListener, | |||
439 | sal_Bool bReceiveVerbose ) | |||
440 | { | |||
441 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
442 | ||||
443 | if (bDisposing) | |||
444 | return false; | |||
445 | ||||
446 | DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported")do { if (true && (!(!bReceiveVerbose))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "446" ": "), "%s", "lng : not yet supported"); } } while (false); | |||
447 | ||||
448 | bool bRes = false; | |||
449 | if (xListener.is()) //! don't add empty references | |||
450 | { | |||
451 | bRes = mxDicEvtLstnrHelper->AddDicListEvtListener( xListener ); | |||
452 | } | |||
453 | return bRes; | |||
454 | } | |||
455 | ||||
456 | sal_Bool SAL_CALL DicList::removeDictionaryListEventListener( | |||
457 | const uno::Reference< XDictionaryListEventListener >& xListener ) | |||
458 | { | |||
459 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
460 | ||||
461 | if (bDisposing) | |||
462 | return false; | |||
463 | ||||
464 | bool bRes = false; | |||
465 | if(xListener.is()) | |||
466 | { | |||
467 | bRes = mxDicEvtLstnrHelper->RemoveDicListEvtListener( xListener ); | |||
468 | } | |||
469 | return bRes; | |||
470 | } | |||
471 | ||||
472 | sal_Int16 SAL_CALL DicList::beginCollectEvents() | |||
473 | { | |||
474 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
475 | return mxDicEvtLstnrHelper->BeginCollectEvents(); | |||
476 | } | |||
477 | ||||
478 | sal_Int16 SAL_CALL DicList::endCollectEvents() | |||
479 | { | |||
480 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
481 | return mxDicEvtLstnrHelper->EndCollectEvents(); | |||
482 | } | |||
483 | ||||
484 | sal_Int16 SAL_CALL DicList::flushEvents() | |||
485 | { | |||
486 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
487 | return mxDicEvtLstnrHelper->FlushEvents(); | |||
488 | } | |||
489 | ||||
490 | uno::Reference< XDictionary > SAL_CALL | |||
491 | DicList::createDictionary( const OUString& rName, const Locale& rLocale, | |||
492 | DictionaryType eDicType, const OUString& rURL ) | |||
493 | { | |||
494 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
495 | ||||
496 | LanguageType nLanguage = LinguLocaleToLanguage( rLocale ); | |||
497 | bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath() ); | |||
498 | return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath ); | |||
499 | } | |||
500 | ||||
501 | ||||
502 | uno::Reference< XDictionaryEntry > SAL_CALL | |||
503 | DicList::queryDictionaryEntry( const OUString& rWord, const Locale& rLocale, | |||
504 | sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry ) | |||
505 | { | |||
506 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
507 | return SearchDicList( this, rWord, LinguLocaleToLanguage( rLocale ), | |||
508 | bSearchPosDics, bSearchSpellEntry ); | |||
509 | } | |||
510 | ||||
511 | ||||
512 | void SAL_CALL | |||
513 | DicList::dispose() | |||
514 | { | |||
515 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
516 | ||||
517 | if (bDisposing) | |||
518 | return; | |||
519 | ||||
520 | bDisposing = true; | |||
521 | EventObject aEvtObj( static_cast<XDictionaryList *>(this) ); | |||
522 | ||||
523 | aEvtListeners.disposeAndClear( aEvtObj ); | |||
524 | if (mxDicEvtLstnrHelper.is()) | |||
525 | mxDicEvtLstnrHelper->DisposeAndClear( aEvtObj ); | |||
526 | ||||
527 | //! avoid creation of dictionaries if not already done | |||
528 | if ( !aDicList.empty() ) | |||
529 | { | |||
530 | DictionaryVec_t& rDicList = GetOrCreateDicList(); | |||
531 | size_t nCount = rDicList.size(); | |||
532 | for (size_t i = 0; i < nCount; i++) | |||
533 | { | |||
534 | // save (modified) dictionaries | |||
535 | uno::Reference< frame::XStorable > xStor( rDicList[i] , UNO_QUERY ); | |||
536 | if (xStor.is()) | |||
537 | { | |||
538 | try | |||
539 | { | |||
540 | if (!xStor->isReadonly() && xStor->hasLocation()) | |||
541 | xStor->store(); | |||
542 | } | |||
543 | catch(Exception &) | |||
544 | { | |||
545 | } | |||
546 | } | |||
547 | ||||
548 | // release references to (members of) this object hold by | |||
549 | // dictionaries | |||
550 | if (rDicList[i].is()) | |||
551 | rDicList[i]->removeDictionaryEventListener( mxDicEvtLstnrHelper.get() ); | |||
552 | } | |||
553 | } | |||
554 | mxDicEvtLstnrHelper.clear(); | |||
555 | } | |||
556 | ||||
557 | void SAL_CALL | |||
558 | DicList::addEventListener( const uno::Reference< XEventListener >& rxListener ) | |||
559 | { | |||
560 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
561 | ||||
562 | if (!bDisposing && rxListener.is()) | |||
563 | aEvtListeners.addInterface( rxListener ); | |||
564 | } | |||
565 | ||||
566 | void SAL_CALL | |||
567 | DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener ) | |||
568 | { | |||
569 | osl::MutexGuard aGuard( GetLinguMutex() ); | |||
570 | ||||
571 | if (!bDisposing && rxListener.is()) | |||
572 | aEvtListeners.removeInterface( rxListener ); | |||
573 | } | |||
574 | ||||
575 | void DicList::CreateDicList() | |||
576 | { | |||
577 | bInCreation = true; | |||
578 | ||||
579 | // look for dictionaries | |||
580 | const OUString aWriteablePath( GetDictionaryWriteablePath() ); | |||
581 | std::vector< OUString > aPaths( GetDictionaryPaths() ); | |||
582 | for (const OUString & aPath : aPaths) | |||
583 | { | |||
584 | const bool bIsWriteablePath = (aPath == aWriteablePath); | |||
585 | SearchForDictionaries( aDicList, aPath, bIsWriteablePath ); | |||
586 | } | |||
587 | ||||
588 | // create IgnoreAllList dictionary with empty URL (non persistent) | |||
589 | // and add it to list | |||
590 | std::locale loc(Translate::Create("svt")); | |||
591 | uno::Reference< XDictionary > xIgnAll( | |||
592 | createDictionary( Translate::get(STR_DESCRIPTION_IGNOREALLLISTreinterpret_cast<char const *>("STR_DESCRIPTION_IGNOREALLLIST" "\004" u8"List of Ignored Words"), loc), LinguLanguageToLocale( LANGUAGE_NONELanguageType(0x00FF) ), | |||
593 | DictionaryType_POSITIVE, OUString() ) ); | |||
594 | if (xIgnAll.is()) | |||
595 | { | |||
596 | AddUserData( xIgnAll ); | |||
597 | xIgnAll->setActive( true ); | |||
598 | addDictionary( xIgnAll ); | |||
599 | } | |||
600 | ||||
601 | ||||
602 | // evaluate list of dictionaries to be activated from configuration | |||
603 | //! to suppress overwriting the list of active dictionaries in the | |||
604 | //! configuration with incorrect arguments during the following | |||
605 | //! activation of the dictionaries | |||
606 | mxDicEvtLstnrHelper->BeginCollectEvents(); | |||
607 | const uno::Sequence< OUString > aActiveDics( aOpt.GetActiveDics() ); | |||
608 | for (const OUString& rActiveDic : aActiveDics) | |||
609 | { | |||
610 | if (!rActiveDic.isEmpty()) | |||
611 | { | |||
612 | uno::Reference< XDictionary > xDic( getDictionaryByName( rActiveDic ) ); | |||
613 | if (xDic.is()) | |||
614 | xDic->setActive( true ); | |||
615 | } | |||
616 | } | |||
617 | ||||
618 | // suppress collected events during creation of the dictionary list. | |||
619 | // there should be no events during creation. | |||
620 | mxDicEvtLstnrHelper->ClearEvents(); | |||
621 | ||||
622 | mxDicEvtLstnrHelper->EndCollectEvents(); | |||
623 | ||||
624 | bInCreation = false; | |||
625 | } | |||
626 | ||||
627 | ||||
628 | void DicList::SaveDics() | |||
629 | { | |||
630 | // save dics only if they have already been used/created. | |||
631 | //! don't create them just for the purpose of saving them ! | |||
632 | if ( aDicList.empty() ) | |||
633 | return; | |||
634 | ||||
635 | // save (modified) dictionaries | |||
636 | DictionaryVec_t& rDicList = GetOrCreateDicList(); | |||
637 | size_t nCount = rDicList.size(); | |||
638 | for (size_t i = 0; i < nCount; i++) | |||
639 | { | |||
640 | // save (modified) dictionaries | |||
641 | uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY ); | |||
642 | if (xStor.is()) | |||
643 | { | |||
644 | try | |||
645 | { | |||
646 | if (!xStor->isReadonly() && xStor->hasLocation()) | |||
647 | xStor->store(); | |||
648 | } | |||
649 | catch(Exception &) | |||
650 | { | |||
651 | } | |||
652 | } | |||
653 | } | |||
654 | } | |||
655 | ||||
656 | ||||
657 | // Service specific part | |||
658 | ||||
659 | OUString SAL_CALL DicList::getImplementationName( ) | |||
660 | { | |||
661 | return "com.sun.star.lingu2.DicList"; | |||
662 | } | |||
663 | ||||
664 | ||||
665 | sal_Bool SAL_CALL DicList::supportsService( const OUString& ServiceName ) | |||
666 | { | |||
667 | return cppu::supportsService(this, ServiceName); | |||
668 | } | |||
669 | ||||
670 | uno::Sequence< OUString > SAL_CALL DicList::getSupportedServiceNames( ) | |||
671 | { | |||
672 | return { "com.sun.star.linguistic2.DictionaryList" }; | |||
673 | } | |||
674 | ||||
675 | ||||
676 | ||||
677 | static sal_Int32 lcl_GetToken( OUString &rToken, | |||
678 | const OUString &rText, sal_Int32 nPos, const OUString &rDelim ) | |||
679 | { | |||
680 | sal_Int32 nRes = -1; | |||
681 | ||||
682 | if (rText.isEmpty() || nPos >= rText.getLength()) | |||
683 | rToken.clear(); | |||
684 | else if (rDelim.isEmpty()) | |||
685 | { | |||
686 | rToken = rText; | |||
687 | if (!rToken.isEmpty()) | |||
688 | nRes = rText.getLength(); | |||
689 | } | |||
690 | else | |||
691 | { | |||
692 | sal_Int32 i; | |||
693 | for (i = nPos; i < rText.getLength(); ++i) | |||
694 | { | |||
695 | if (-1 != rDelim.indexOf( rText[i] )) | |||
696 | break; | |||
697 | } | |||
698 | ||||
699 | if (i >= rText.getLength()) // delimiter not found | |||
700 | rToken = rText.copy( nPos ); | |||
701 | else | |||
702 | rToken = rText.copy( nPos, i - nPos ); | |||
703 | nRes = i + 1; // continue after found delimiter | |||
704 | } | |||
705 | ||||
706 | return nRes; | |||
707 | } | |||
708 | ||||
709 | ||||
710 | static void AddInternal( | |||
711 | const uno::Reference<XDictionary> &rDic, | |||
712 | const OUString& rNew ) | |||
713 | { | |||
714 | if (!rDic.is()) | |||
715 | return; | |||
716 | ||||
717 | //! TL TODO: word iterator should be used to break up the text | |||
718 | OUString aDelim("!\"#$%&'()*+,-/:;<=>?[]\\_^`{|}~\t \n"); | |||
719 | OSL_ENSURE(aDelim.indexOf(u'.') == -1,do { if (true && (!(aDelim.indexOf(u'.') == -1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "720" ": "), "%s", "ensure no '.'"); } } while (false) | |||
720 | "ensure no '.'")do { if (true && (!(aDelim.indexOf(u'.') == -1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "720" ": "), "%s", "ensure no '.'"); } } while (false); | |||
721 | ||||
722 | OUString aToken; | |||
723 | sal_Int32 nPos = 0; | |||
724 | while (-1 != (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim ))) | |||
725 | { | |||
726 | if( !aToken.isEmpty() && !IsNumeric( aToken ) ) | |||
727 | { | |||
728 | rDic->add( aToken, false, OUString() ); | |||
729 | } | |||
730 | } | |||
731 | } | |||
732 | ||||
733 | static void AddUserData( const uno::Reference< XDictionary > &rDic ) | |||
734 | { | |||
735 | if (rDic.is()) | |||
736 | { | |||
737 | SvtUserOptions aUserOpt; | |||
738 | AddInternal( rDic, aUserOpt.GetFullName() ); | |||
739 | AddInternal( rDic, aUserOpt.GetCompany() ); | |||
740 | AddInternal( rDic, aUserOpt.GetStreet() ); | |||
741 | AddInternal( rDic, aUserOpt.GetCity() ); | |||
742 | AddInternal( rDic, aUserOpt.GetTitle() ); | |||
743 | AddInternal( rDic, aUserOpt.GetPosition() ); | |||
744 | AddInternal( rDic, aUserOpt.GetEmail() ); | |||
745 | } | |||
746 | } | |||
747 | ||||
748 | static bool IsVers2OrNewer( const OUString& rFileURL, LanguageType& nLng, bool& bNeg, OUString& aDicName ) | |||
749 | { | |||
750 | if (rFileURL.isEmpty()) | |||
751 | return false; | |||
752 | OUString aExt; | |||
753 | sal_Int32 nPos = rFileURL.lastIndexOf( '.' ); | |||
754 | if (-1 != nPos) | |||
755 | aExt = rFileURL.copy( nPos + 1 ).toAsciiLowerCase(); | |||
756 | ||||
757 | if (aExt != "dic") | |||
758 | return false; | |||
759 | ||||
760 | // get stream to be used | |||
761 | uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); | |||
762 | ||||
763 | // get XInputStream stream | |||
764 | uno::Reference< io::XInputStream > xStream; | |||
765 | try | |||
766 | { | |||
767 | uno::Reference< ucb::XSimpleFileAccess3 > xAccess( ucb::SimpleFileAccess::create(xContext) ); | |||
768 | xStream = xAccess->openFileRead( rFileURL ); | |||
769 | } | |||
770 | catch (const uno::Exception &) | |||
771 | { | |||
772 | SAL_WARN( "linguistic", "failed to get input stream" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "linguistic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "failed to get input stream" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("linguistic" ), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "772" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "failed to get input stream"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "failed to get input stream"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("linguistic"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "772" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "failed to get input stream") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("linguistic"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "772" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "failed to get input stream"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "failed to get input stream"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("linguistic"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "772" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
773 | } | |||
774 | DBG_ASSERT( xStream.is(), "failed to get stream for read" )do { if (true && (!(xStream.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/linguistic/source/dlistimp.cxx" ":" "774" ": "), "%s", "failed to get stream for read"); } } while (false); | |||
775 | if (!xStream.is()) | |||
776 | return false; | |||
777 | ||||
778 | std::unique_ptr<SvStream> pStream( utl::UcbStreamHelper::CreateStream( xStream ) ); | |||
779 | ||||
780 | int nDicVersion = ReadDicVersion(*pStream, nLng, bNeg, aDicName); | |||
781 | return 2 == nDicVersion || nDicVersion >= 5; | |||
782 | } | |||
783 | ||||
784 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface* | |||
785 | linguistic_DicList_get_implementation( | |||
786 | css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) | |||
787 | { | |||
788 | return cppu::acquire(static_cast<cppu::OWeakObject*>(new DicList())); | |||
| ||||
789 | } | |||
790 | ||||
791 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |