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 <dicimp.hxx>
32 : : #include <hyphdsp.hxx>
33 : : #include <i18npool/lang.h>
34 : : #include <i18npool/mslangid.hxx>
35 : : #include <osl/mutex.hxx>
36 : : #include <tools/debug.hxx>
37 : : #include <tools/fsys.hxx>
38 : : #include <tools/stream.hxx>
39 : : #include <tools/string.hxx>
40 : : #include <tools/urlobj.hxx>
41 : : #include <comphelper/processfactory.hxx>
42 : : #include <comphelper/string.hxx>
43 : : #include <unotools/ucbstreamhelper.hxx>
44 : :
45 : : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
46 : : #include <com/sun/star/ucb/XSimpleFileAccess2.hpp>
47 : : #include <com/sun/star/linguistic2/DictionaryType.hpp>
48 : : #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
49 : : #include <com/sun/star/registry/XRegistryKey.hpp>
50 : : #include <com/sun/star/io/XInputStream.hpp>
51 : : #include <com/sun/star/io/XOutputStream.hpp>
52 : :
53 : : #include "defs.hxx"
54 : :
55 : :
56 : : using namespace utl;
57 : : using namespace osl;
58 : : using namespace com::sun::star;
59 : : using namespace com::sun::star::lang;
60 : : using namespace com::sun::star::uno;
61 : : using namespace com::sun::star::linguistic2;
62 : : using namespace linguistic;
63 : :
64 : : using ::rtl::OUString;
65 : :
66 : :
67 : : #define BUFSIZE 4096
68 : : #define VERS2_NOLANGUAGE 1024
69 : :
70 : : #define MAX_HEADER_LENGTH 16
71 : :
72 : : static const sal_Char* pVerStr2 = "WBSWG2";
73 : : static const sal_Char* pVerStr5 = "WBSWG5";
74 : : static const sal_Char* pVerStr6 = "WBSWG6";
75 : : static const sal_Char* pVerOOo7 = "OOoUserDict1";
76 : :
77 : : static const sal_Int16 DIC_VERSION_DONTKNOW = -1;
78 : : static const sal_Int16 DIC_VERSION_2 = 2;
79 : : static const sal_Int16 DIC_VERSION_5 = 5;
80 : : static const sal_Int16 DIC_VERSION_6 = 6;
81 : : static const sal_Int16 DIC_VERSION_7 = 7;
82 : :
83 : 1488 : static bool getTag(const rtl::OString &rLine, const sal_Char *pTagName,
84 : : rtl::OString &rTagValue)
85 : : {
86 : 1488 : sal_Int32 nPos = rLine.indexOf(pTagName);
87 [ + + ]: 1488 : if (nPos == -1)
88 : 992 : return false;
89 : :
90 : 496 : rTagValue = comphelper::string::strip(rLine.copy(nPos + rtl_str_getLength(pTagName)),
91 [ + - ]: 496 : ' ');
92 : 1488 : return true;
93 : : }
94 : :
95 : :
96 : 248 : sal_Int16 ReadDicVersion( SvStreamPtr &rpStream, sal_uInt16 &nLng, sal_Bool &bNeg )
97 : : {
98 : : // Sniff the header
99 : 248 : sal_Int16 nDicVersion = DIC_VERSION_DONTKNOW;
100 : : sal_Char pMagicHeader[MAX_HEADER_LENGTH];
101 : :
102 : 248 : nLng = LANGUAGE_NONE;
103 : 248 : bNeg = sal_False;
104 : :
105 [ + - ][ - + ]: 248 : if (!rpStream.get() || rpStream->GetError())
[ - + ]
106 : 0 : return -1;
107 : :
108 : 248 : sal_Size nSniffPos = rpStream->Tell();
109 [ + - ][ + + ]: 248 : static sal_Size nVerOOo7Len = sal::static_int_cast< sal_Size >(strlen( pVerOOo7 ));
110 : 248 : pMagicHeader[ nVerOOo7Len ] = '\0';
111 [ + - ][ + - ]: 248 : if ((rpStream->Read((void *) pMagicHeader, nVerOOo7Len) == nVerOOo7Len) &&
[ + - ][ + - ]
112 : 248 : !strcmp(pMagicHeader, pVerOOo7))
113 : : {
114 : : sal_Bool bSuccess;
115 : 248 : rtl::OString aLine;
116 : :
117 : 248 : nDicVersion = DIC_VERSION_7;
118 : :
119 : : // 1st skip magic / header line
120 [ + - ]: 248 : rpStream->ReadLine(aLine);
121 : :
122 : : // 2nd line: language all | en-US | pt-BR ...
123 [ + - ][ + - ]: 744 : while (sal_True == (bSuccess = rpStream->ReadLine(aLine)))
124 : : {
125 : 744 : rtl::OString aTagValue;
126 : :
127 [ - + ]: 744 : if (aLine[0] == '#') // skip comments
128 : 0 : continue;
129 : :
130 : : // lang: field
131 [ + - ][ + + ]: 744 : if (getTag(aLine, "lang: ", aTagValue))
132 : : {
133 [ + + ]: 248 : if (aTagValue.equalsL(RTL_CONSTASCII_STRINGPARAM("<none>")))
134 : 82 : nLng = LANGUAGE_NONE;
135 : : else
136 : : nLng = MsLangId::convertIsoStringToLanguage(rtl::OStringToOUString(
137 [ + - ][ + - ]: 166 : aTagValue, RTL_TEXTENCODING_ASCII_US));
138 : : }
139 : :
140 : : // type: negative / positive
141 [ + - ][ + + ]: 744 : if (getTag(aLine, "type: ", aTagValue))
142 : : {
143 [ - + ]: 248 : if (aTagValue.equalsL(RTL_CONSTASCII_STRINGPARAM("negative")))
144 : 0 : bNeg = sal_True;
145 : : else
146 : 248 : bNeg = sal_False;
147 : : }
148 : :
149 [ + + ]: 744 : if (aLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("---")) != -1) // end of header
150 : : break;
151 [ + - + ]: 744 : }
152 [ - + ]: 248 : if (!bSuccess)
153 [ + - ]: 248 : return -2;
154 : : }
155 : : else
156 : : {
157 : : sal_uInt16 nLen;
158 : :
159 [ # # ]: 0 : rpStream->Seek (nSniffPos );
160 : :
161 [ # # ]: 0 : *rpStream >> nLen;
162 [ # # ]: 0 : if (nLen >= MAX_HEADER_LENGTH)
163 : 0 : return -1;
164 : :
165 [ # # ]: 0 : rpStream->Read(pMagicHeader, nLen);
166 : 0 : pMagicHeader[nLen] = '\0';
167 : :
168 : : // Check version magic
169 [ # # ]: 0 : if (0 == strcmp( pMagicHeader, pVerStr6 ))
170 : 0 : nDicVersion = DIC_VERSION_6;
171 [ # # ]: 0 : else if (0 == strcmp( pMagicHeader, pVerStr5 ))
172 : 0 : nDicVersion = DIC_VERSION_5;
173 [ # # ]: 0 : else if (0 == strcmp( pMagicHeader, pVerStr2 ))
174 : 0 : nDicVersion = DIC_VERSION_2;
175 : : else
176 : 0 : nDicVersion = DIC_VERSION_DONTKNOW;
177 : :
178 [ # # ][ # # ]: 0 : if (DIC_VERSION_2 == nDicVersion ||
[ # # ]
179 : : DIC_VERSION_5 == nDicVersion ||
180 : : DIC_VERSION_6 == nDicVersion)
181 : : {
182 : : // The language of the dictionary
183 [ # # ]: 0 : *rpStream >> nLng;
184 : :
185 [ # # ]: 0 : if (VERS2_NOLANGUAGE == nLng)
186 : 0 : nLng = LANGUAGE_NONE;
187 : :
188 : : // Negative Flag
189 : : sal_Char nTmp;
190 [ # # ]: 0 : *rpStream >> nTmp;
191 : 0 : bNeg = (sal_Bool)nTmp;
192 : : }
193 : : }
194 : :
195 : 248 : return nDicVersion;
196 : : }
197 : :
198 : 0 : DictionaryNeo::DictionaryNeo() :
199 [ # # ]: 0 : aDicEvtListeners( GetLinguMutex() ),
200 : : eDicType (DictionaryType_POSITIVE),
201 [ # # ][ # # ]: 0 : nLanguage (LANGUAGE_NONE)
202 : : {
203 : 0 : nCount = 0;
204 : 0 : nDicVersion = DIC_VERSION_DONTKNOW;
205 : 0 : bNeedEntries = sal_False;
206 : 0 : bIsModified = bIsActive = sal_False;
207 : 0 : bIsReadonly = sal_False;
208 : 0 : }
209 : :
210 : 224 : DictionaryNeo::DictionaryNeo(const OUString &rName,
211 : : sal_Int16 nLang, DictionaryType eType,
212 : : const OUString &rMainURL,
213 : : sal_Bool bWriteable) :
214 [ + - ]: 224 : aDicEvtListeners( GetLinguMutex() ),
215 : : aDicName (rName),
216 : : aMainURL (rMainURL),
217 : : eDicType (eType),
218 [ + - ][ + - ]: 448 : nLanguage (nLang)
219 : : {
220 : 224 : nCount = 0;
221 : 224 : nDicVersion = DIC_VERSION_DONTKNOW;
222 : 224 : bNeedEntries = sal_True;
223 : 224 : bIsModified = bIsActive = sal_False;
224 : 224 : bIsReadonly = !bWriteable;
225 : :
226 [ + + ]: 224 : if( !rMainURL.isEmpty())
227 : : {
228 [ + - ][ + - ]: 168 : sal_Bool bExists = FileExists( rMainURL );
[ + - ]
229 [ - + ]: 168 : if( !bExists )
230 : : {
231 : : // save new dictionaries with in Format 7 (UTF8 plain text)
232 : 0 : nDicVersion = DIC_VERSION_7;
233 : :
234 : : //! create physical representation of an **empty** dictionary
235 : : //! that could be found by the dictionary-list implementation
236 : : // (Note: empty dictionaries are not just empty files!)
237 : : DBG_ASSERT( !bIsReadonly,
238 : : "DictionaryNeo: dictionaries should be writeable if they are to be saved" );
239 [ # # ]: 0 : if (!bIsReadonly)
240 [ # # ]: 0 : saveEntries( rMainURL );
241 : 0 : bNeedEntries = sal_False;
242 : : }
243 : : }
244 : : else
245 : : {
246 : : // non persistent dictionaries (like IgnoreAllList) should always be writable
247 : 56 : bIsReadonly = sal_False;
248 : 56 : bNeedEntries = sal_False;
249 : : }
250 : 224 : }
251 : :
252 [ + - ][ + - ]: 214 : DictionaryNeo::~DictionaryNeo()
253 : : {
254 [ - + ]: 428 : }
255 : :
256 : 80 : sal_uLong DictionaryNeo::loadEntries(const OUString &rMainURL)
257 : : {
258 [ + - ][ + - ]: 80 : MutexGuard aGuard( GetLinguMutex() );
259 : :
260 : : // counter check that it is safe to set bIsModified to sal_False at
261 : : // the end of the function
262 : : DBG_ASSERT(!bIsModified, "lng : dictionary already modified!");
263 : :
264 : : // function should only be called once in order to load entries from file
265 : 80 : bNeedEntries = sal_False;
266 : :
267 [ - + ]: 80 : if (rMainURL.isEmpty())
268 : 0 : return 0;
269 : :
270 [ + - ]: 80 : uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
271 : :
272 : : // get XInputStream stream
273 : 80 : uno::Reference< io::XInputStream > xStream;
274 : : try
275 : : {
276 [ + - ]: 80 : uno::Reference< ucb::XSimpleFileAccess2 > xAccess( ucb::SimpleFileAccess::create(xContext) );
277 [ + - ][ + - ]: 80 : xStream = xAccess->openFileRead( rMainURL );
[ + - ][ # # ]
278 : : }
279 [ # # ]: 0 : catch (const uno::Exception &)
280 : : {
281 : : DBG_ASSERT( 0, "failed to get input stream" );
282 : : }
283 [ - + ]: 80 : if (!xStream.is())
284 : 0 : return static_cast< sal_uLong >(-1);
285 : :
286 [ + - ][ + - ]: 80 : SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) );
287 : :
288 : 80 : sal_uLong nErr = sal::static_int_cast< sal_uLong >(-1);
289 : :
290 : : // read header
291 : : sal_Bool bNegativ;
292 : : sal_uInt16 nLang;
293 [ + - ]: 80 : nDicVersion = ReadDicVersion(pStream, nLang, bNegativ);
294 [ - + ]: 80 : if (0 != (nErr = pStream->GetError()))
295 : 0 : return nErr;
296 : :
297 : 80 : nLanguage = nLang;
298 : :
299 [ - + ]: 80 : eDicType = bNegativ ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
300 : :
301 [ + - ]: 80 : rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
302 [ + - ]: 80 : if (nDicVersion >= DIC_VERSION_6)
303 : 80 : eEnc = RTL_TEXTENCODING_UTF8;
304 : 80 : nCount = 0;
305 : :
306 [ + - ][ + - ]: 80 : if (DIC_VERSION_6 == nDicVersion ||
[ - + ]
307 : : DIC_VERSION_5 == nDicVersion ||
308 : : DIC_VERSION_2 == nDicVersion)
309 : : {
310 : 0 : sal_uInt16 nLen = 0;
311 : : sal_Char aWordBuf[ BUFSIZE ];
312 : :
313 : : // Read the first word
314 [ # # ]: 0 : if (!pStream->IsEof())
315 : : {
316 [ # # ]: 0 : *pStream >> nLen;
317 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
318 : 0 : return nErr;
319 [ # # ]: 0 : if ( nLen < BUFSIZE )
320 : : {
321 [ # # ]: 0 : pStream->Read(aWordBuf, nLen);
322 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
323 : 0 : return nErr;
324 : 0 : *(aWordBuf + nLen) = 0;
325 : : }
326 : : }
327 : :
328 [ # # ]: 0 : while(!pStream->IsEof())
329 : : {
330 : : // Read from file
331 : : // Paste in dictionary without converting
332 [ # # ]: 0 : if(*aWordBuf)
333 : : {
334 [ # # ]: 0 : rtl::OUString aText(aWordBuf, rtl_str_getLength(aWordBuf), eEnc);
335 : : uno::Reference< XDictionaryEntry > xEntry =
336 [ # # ][ # # ]: 0 : new DicEntry( aText, bNegativ );
[ # # ]
337 [ # # ]: 0 : addEntry_Impl( xEntry , sal_True ); //! don't launch events here
338 : : }
339 : :
340 [ # # ]: 0 : *pStream >> nLen;
341 [ # # ]: 0 : if (pStream->IsEof())
342 : 0 : break;
343 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
344 : 0 : return nErr;
345 : : #ifdef LINGU_EXCEPTIONS
346 : : if (nLen >= BUFSIZE)
347 : : throw io::IOException() ;
348 : : #endif
349 : :
350 [ # # ]: 0 : if (nLen < BUFSIZE)
351 : : {
352 [ # # ]: 0 : pStream->Read(aWordBuf, nLen);
353 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
354 : 0 : return nErr;
355 : : }
356 : : else
357 : 0 : return SVSTREAM_READ_ERROR;
358 : 0 : *(aWordBuf + nLen) = 0;
359 : 0 : }
360 : : }
361 [ + - ]: 80 : else if (DIC_VERSION_7 == nDicVersion)
362 : : {
363 : : sal_Bool bSuccess;
364 : 80 : rtl::OString aLine;
365 : :
366 : : // remaining lines - stock strings (a [==] b)
367 [ + - ][ + + ]: 10800 : while (sal_True == (bSuccess = pStream->ReadLine(aLine)))
368 : : {
369 [ - + ]: 10720 : if (aLine[0] == '#') // skip comments
370 : 0 : continue;
371 [ + - ]: 10720 : rtl::OUString aText = rtl::OStringToOUString(aLine, RTL_TEXTENCODING_UTF8);
372 : : uno::Reference< XDictionaryEntry > xEntry =
373 [ + - ][ + - ]: 10720 : new DicEntry( aText, eDicType == DictionaryType_NEGATIVE );
[ + - ]
374 [ + - ]: 10720 : addEntry_Impl( xEntry , sal_True ); //! don't launch events here
375 : 10800 : }
376 : : }
377 : :
378 : : DBG_ASSERT(isSorted(), "lng : dictionary is not sorted");
379 : :
380 : : // since this routine should be called only initialy (prior to any
381 : : // modification to be saved) we reset the bIsModified flag here that
382 : : // was implicitly set by addEntry_Impl
383 : 80 : bIsModified = sal_False;
384 : :
385 [ + - ][ + - ]: 80 : return pStream->GetError();
386 : : }
387 : :
388 : 0 : static rtl::OString formatForSave(const uno::Reference< XDictionaryEntry > &xEntry,
389 : : rtl_TextEncoding eEnc )
390 : : {
391 [ # # ][ # # ]: 0 : rtl::OStringBuffer aStr(rtl::OUStringToOString(xEntry->getDictionaryWord(), eEnc));
[ # # ][ # # ]
392 : :
393 [ # # ][ # # ]: 0 : if (xEntry->isNegative())
[ # # ]
394 : : {
395 [ # # ]: 0 : aStr.append(RTL_CONSTASCII_STRINGPARAM("=="));
396 [ # # ][ # # ]: 0 : aStr.append(rtl::OUStringToOString(xEntry->getReplacementText(), eEnc));
[ # # ][ # # ]
397 : : }
398 : 0 : return aStr.makeStringAndClear();
399 : : }
400 : :
401 : :
402 : 0 : sal_uLong DictionaryNeo::saveEntries(const OUString &rURL)
403 : : {
404 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
405 : :
406 [ # # ]: 0 : if (rURL.isEmpty())
407 : 0 : return 0;
408 : : DBG_ASSERT(!INetURLObject( rURL ).HasError(), "lng : invalid URL");
409 : :
410 [ # # ]: 0 : uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
411 : :
412 : : // get XOutputStream stream
413 : 0 : uno::Reference< io::XStream > xStream;
414 : : try
415 : : {
416 [ # # ]: 0 : uno::Reference< ucb::XSimpleFileAccess2 > xAccess( ucb::SimpleFileAccess::create(xContext) );
417 [ # # ][ # # ]: 0 : xStream = xAccess->openFileReadWrite( rURL );
[ # # ][ # # ]
418 : : }
419 [ # # ]: 0 : catch (const uno::Exception &)
420 : : {
421 : : DBG_ASSERT( 0, "failed to get input stream" );
422 : : }
423 [ # # ]: 0 : if (!xStream.is())
424 : 0 : return static_cast< sal_uLong >(-1);
425 : :
426 [ # # ][ # # ]: 0 : SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) );
427 : 0 : sal_uLong nErr = sal::static_int_cast< sal_uLong >(-1);
428 : :
429 : : //
430 : : // Always write as the latest version, i.e. DIC_VERSION_7
431 : : //
432 : 0 : rtl_TextEncoding eEnc = RTL_TEXTENCODING_UTF8;
433 [ # # ]: 0 : pStream->WriteLine(rtl::OString(pVerOOo7));
434 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
435 : 0 : return nErr;
436 [ # # ]: 0 : if (nLanguage == LANGUAGE_NONE)
437 [ # # ]: 0 : pStream->WriteLine(rtl::OString(RTL_CONSTASCII_STRINGPARAM("lang: <none>")));
438 : : else
439 : : {
440 [ # # ]: 0 : rtl::OStringBuffer aLine(RTL_CONSTASCII_STRINGPARAM("lang: "));
441 [ # # ][ # # ]: 0 : aLine.append(rtl::OUStringToOString(MsLangId::convertLanguageToIsoString(nLanguage), eEnc));
[ # # ]
442 [ # # ]: 0 : pStream->WriteLine(aLine.makeStringAndClear());
443 : : }
444 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
445 : 0 : return nErr;
446 [ # # ]: 0 : if (eDicType == DictionaryType_POSITIVE)
447 [ # # ]: 0 : pStream->WriteLine(rtl::OString(RTL_CONSTASCII_STRINGPARAM("type: positive")));
448 : : else
449 [ # # ]: 0 : pStream->WriteLine(rtl::OString(RTL_CONSTASCII_STRINGPARAM("type: negative")));
450 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
451 : 0 : return nErr;
452 [ # # ]: 0 : pStream->WriteLine(rtl::OString(RTL_CONSTASCII_STRINGPARAM("---")));
453 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
454 : 0 : return nErr;
455 : 0 : const uno::Reference< XDictionaryEntry > *pEntry = aEntries.getConstArray();
456 [ # # ]: 0 : for (sal_Int32 i = 0; i < nCount; i++)
457 : : {
458 [ # # ]: 0 : rtl::OString aOutStr = formatForSave(pEntry[i], eEnc);
459 [ # # ]: 0 : pStream->WriteLine (aOutStr);
460 [ # # ]: 0 : if (0 != (nErr = pStream->GetError()))
461 : 0 : return nErr;
462 [ # # ]: 0 : }
463 : :
464 : : //If we are migrating from an older version, then on first successful
465 : : //write, we're now converted to the latest version, i.e. DIC_VERSION_7
466 : 0 : nDicVersion = DIC_VERSION_7;
467 : :
468 [ # # ][ # # ]: 0 : return nErr;
469 : : }
470 : :
471 : 238 : void DictionaryNeo::launchEvent(sal_Int16 nEvent,
472 : : uno::Reference< XDictionaryEntry > xEntry)
473 : : {
474 [ + - ][ + - ]: 238 : MutexGuard aGuard( GetLinguMutex() );
475 : :
476 [ + - ]: 238 : DictionaryEvent aEvt;
477 [ + - ][ + - ]: 238 : aEvt.Source = uno::Reference< XDictionary >( this );
478 : 238 : aEvt.nEvent = nEvent;
479 [ + - ]: 238 : aEvt.xDictionaryEntry = xEntry;
480 : :
481 [ + - ]: 238 : cppu::OInterfaceIteratorHelper aIt( aDicEvtListeners );
482 [ + + ]: 428 : while (aIt.hasMoreElements())
483 : : {
484 [ + - ][ + - ]: 190 : uno::Reference< XDictionaryEventListener > xRef( aIt.next(), UNO_QUERY );
485 [ + - ]: 190 : if (xRef.is())
486 [ + - ][ + - ]: 190 : xRef->processDictionaryEvent( aEvt );
487 [ + - ][ + - ]: 428 : }
[ + - ]
488 : 238 : }
489 : :
490 : 930401 : int DictionaryNeo::cmpDicEntry(const OUString& rWord1,
491 : : const OUString &rWord2,
492 : : sal_Bool bSimilarOnly)
493 : : {
494 [ + - ][ + - ]: 930401 : MutexGuard aGuard( GetLinguMutex() );
495 : :
496 : : // returns 0 if rWord1 is equal to rWord2
497 : : // " a value < 0 if rWord1 is less than rWord2
498 : : // " a value > 0 if rWord1 is greater than rWord2
499 : :
500 : 930401 : int nRes = 0;
501 : :
502 : 930401 : OUString aWord1( rWord1 ),
503 : 930401 : aWord2( rWord2 );
504 : 930401 : sal_Int32 nLen1 = aWord1.getLength(),
505 : 930401 : nLen2 = aWord2.getLength();
506 [ + + ]: 930401 : if (bSimilarOnly)
507 : : {
508 : 864201 : const sal_Unicode cChar = '.';
509 [ + - ][ - + ]: 864201 : if (nLen1 && cChar == aWord1[ nLen1 - 1 ])
[ - + ]
510 : 0 : nLen1--;
511 [ + - ][ + + ]: 864201 : if (nLen2 && cChar == aWord2[ nLen2 - 1 ])
[ + + ]
512 : 2298 : nLen2--;
513 : : }
514 : :
515 : 930401 : const sal_Unicode cIgnChar = '=';
516 : 930401 : sal_Int32 nIdx1 = 0,
517 : 930401 : nIdx2 = 0,
518 : 930401 : nNumIgnChar1 = 0,
519 : 930401 : nNumIgnChar2 = 0;
520 : :
521 : 930401 : sal_Int32 nDiff = 0;
522 : 930401 : sal_Unicode cChar1 = '\0';
523 : 930401 : sal_Unicode cChar2 = '\0';
524 [ + + ][ + + ]: 343730 : do
[ + + ]
525 : : {
526 : : // skip chars to be ignored
527 [ + + ][ + + ]: 1271122 : while (nIdx1 < nLen1 && (cChar1 = aWord1[ nIdx1 ]) == cIgnChar)
[ + + ]
528 : : {
529 : 120 : nIdx1++;
530 : 120 : nNumIgnChar1++;
531 : : }
532 [ + - ][ - + ]: 1271002 : while (nIdx2 < nLen2 && (cChar2 = aWord2[ nIdx2 ]) == cIgnChar)
[ - + ]
533 : : {
534 : 0 : nIdx2++;
535 : 0 : nNumIgnChar2++;
536 : : }
537 : :
538 [ + + ][ + - ]: 1271002 : if (nIdx1 < nLen1 && nIdx2 < nLen2)
539 : : {
540 : 1270882 : nDiff = cChar1 - cChar2;
541 [ + + ]: 1270882 : if (nDiff)
542 : 927272 : break;
543 : 343610 : nIdx1++;
544 : 343610 : nIdx2++;
545 : : }
546 : : } while (nIdx1 < nLen1 && nIdx2 < nLen2);
547 : :
548 : :
549 [ + + ]: 930401 : if (nDiff)
550 : 927272 : nRes = nDiff;
551 : : else
552 : : { // the string with the smallest count of not ignored chars is the
553 : : // shorter one
554 : :
555 : : // count remaining IgnChars
556 [ + + ]: 10164 : while (nIdx1 < nLen1 )
557 : : {
558 [ + + ]: 7035 : if (aWord1[ nIdx1++ ] == cIgnChar)
559 : 228 : nNumIgnChar1++;
560 : : }
561 [ + + ]: 5009 : while (nIdx2 < nLen2 )
562 : : {
563 [ + + ]: 1880 : if (aWord2[ nIdx2++ ] == cIgnChar)
564 : 240 : nNumIgnChar2++;
565 : : }
566 : :
567 : 3129 : nRes = ((sal_Int32) nLen1 - nNumIgnChar1) - ((sal_Int32) nLen2 - nNumIgnChar2);
568 : : }
569 : :
570 [ + - ]: 930401 : return nRes;
571 : : }
572 : :
573 : 239202 : sal_Bool DictionaryNeo::seekEntry(const OUString &rWord,
574 : : sal_Int32 *pPos, sal_Bool bSimilarOnly)
575 : : {
576 : : // look for entry with binary search.
577 : : // return sal_True if found sal_False else.
578 : : // if pPos != NULL it will become the position of the found entry, or
579 : : // if that was not found the position where it has to be inserted
580 : : // to keep the entries sorted
581 : :
582 [ + - ][ + - ]: 239202 : MutexGuard aGuard( GetLinguMutex() );
583 : :
584 : 239202 : const uno::Reference< XDictionaryEntry > *pEntry = aEntries.getConstArray();
585 [ + - ]: 239202 : sal_Int32 nUpperIdx = getCount(),
586 : : nMidIdx,
587 : 239202 : nLowerIdx = 0;
588 [ + + ]: 239202 : if( nUpperIdx > 0 )
589 : : {
590 : 142304 : nUpperIdx--;
591 [ + + ]: 1060062 : while( nLowerIdx <= nUpperIdx )
592 : : {
593 : 930401 : nMidIdx = (nLowerIdx + nUpperIdx) / 2;
594 : : DBG_ASSERT(pEntry[nMidIdx].is(), "lng : empty entry encountered");
595 : :
596 [ + - ]: 930401 : int nCmp = - cmpDicEntry( pEntry[nMidIdx]->getDictionaryWord(),
597 [ + - ][ + - ]: 930401 : rWord, bSimilarOnly );
598 [ + + ]: 930401 : if(nCmp == 0)
599 : : {
600 [ + - ]: 1255 : if( pPos ) *pPos = nMidIdx;
601 : 1255 : return sal_True;
602 : : }
603 [ + + ]: 929146 : else if(nCmp > 0)
604 : 496877 : nLowerIdx = nMidIdx + 1;
605 [ + + ]: 432269 : else if( nMidIdx == 0 )
606 : : {
607 [ + - ]: 11388 : if( pPos ) *pPos = nLowerIdx;
608 : 11388 : return sal_False;
609 : : }
610 : : else
611 : 420881 : nUpperIdx = nMidIdx - 1;
612 : : }
613 : : }
614 [ + - ]: 226559 : if( pPos ) *pPos = nLowerIdx;
615 [ + - ]: 239202 : return sal_False;
616 : : }
617 : :
618 : 0 : sal_Bool DictionaryNeo::isSorted()
619 : : {
620 : 0 : sal_Bool bRes = sal_True;
621 : :
622 : 0 : const uno::Reference< XDictionaryEntry > *pEntry = aEntries.getConstArray();
623 : 0 : sal_Int32 nEntries = getCount();
624 : : sal_Int32 i;
625 [ # # ]: 0 : for (i = 1; i < nEntries; i++)
626 : : {
627 [ # # # # ]: 0 : if (cmpDicEntry( pEntry[i-1]->getDictionaryWord(),
628 [ # # ][ # # ]: 0 : pEntry[i]->getDictionaryWord() ) > 0)
629 : : {
630 : 0 : bRes = sal_False;
631 : 0 : break;
632 : : }
633 : : }
634 : 0 : return bRes;
635 : : }
636 : :
637 : 10732 : sal_Bool DictionaryNeo::addEntry_Impl(const uno::Reference< XDictionaryEntry > xDicEntry,
638 : : sal_Bool bIsLoadEntries)
639 : : {
640 [ + - ][ + - ]: 10732 : MutexGuard aGuard( GetLinguMutex() );
641 : :
642 : 10732 : sal_Bool bRes = sal_False;
643 : :
644 [ + + ][ + - ]: 10732 : if ( bIsLoadEntries || (!bIsReadonly && xDicEntry.is()) )
[ + - ][ + - ]
645 : : {
646 [ + - ][ + - ]: 10732 : sal_Bool bIsNegEntry = xDicEntry->isNegative();
647 [ + - ]: 10732 : sal_Bool bAddEntry = !isFull() &&
648 : : ( ( eDicType == DictionaryType_POSITIVE && !bIsNegEntry )
649 : : || ( eDicType == DictionaryType_NEGATIVE && bIsNegEntry )
650 [ + - ][ + + ]: 10732 : || ( eDicType == DictionaryType_MIXED ) );
[ - + ][ + - ]
[ - + ][ # # ]
651 : :
652 : : // look for position to insert entry at
653 : : // if there is already an entry do not insert the new one
654 : 10732 : sal_Int32 nPos = 0;
655 : 10732 : sal_Bool bFound = sal_False;
656 [ + - ]: 10732 : if (bAddEntry)
657 : : {
658 [ + - ][ + - ]: 10732 : bFound = seekEntry( xDicEntry->getDictionaryWord(), &nPos );
[ + - ]
659 [ - + ]: 10732 : if (bFound)
660 : 0 : bAddEntry = sal_False;
661 : : }
662 : :
663 [ + - ]: 10732 : if (bAddEntry)
664 : : {
665 : : DBG_ASSERT(!bNeedEntries, "lng : entries still not loaded");
666 : :
667 [ + + ]: 10732 : if (nCount >= aEntries.getLength())
668 [ + - ]: 252 : aEntries.realloc( Max(2 * nCount, nCount + 32) );
669 [ + - ]: 10732 : uno::Reference< XDictionaryEntry > *pEntry = aEntries.getArray();
670 : :
671 : : // shift old entries right
672 : : sal_Int32 i;
673 [ + + ]: 93092 : for (i = nCount - 1; i >= nPos; i--)
674 [ + - ]: 82360 : pEntry[ i+1 ] = pEntry[ i ];
675 : : // insert new entry at specified position
676 [ + - ]: 10732 : pEntry[ nPos ] = xDicEntry;
677 : : DBG_ASSERT(isSorted(), "lng : dictionary entries unsorted");
678 : :
679 : 10732 : nCount++;
680 : :
681 : 10732 : bIsModified = sal_True;
682 : 10732 : bRes = sal_True;
683 : :
684 [ + + ]: 10732 : if (!bIsLoadEntries)
685 [ + - ]: 10732 : launchEvent( DictionaryEventFlags::ADD_ENTRY, xDicEntry );
686 : : }
687 : : }
688 : :
689 [ + - ]: 10732 : return bRes;
690 : : }
691 : :
692 : :
693 : 0 : uno::Reference< XInterface > SAL_CALL DictionaryNeo_CreateInstance(
694 : : const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ )
695 : : throw(Exception)
696 : : {
697 : : uno::Reference< XInterface > xService =
698 [ # # ][ # # ]: 0 : (cppu::OWeakObject*) new DictionaryNeo;
699 : 0 : return xService;
700 : : }
701 : :
702 : 162049 : OUString SAL_CALL DictionaryNeo::getName( )
703 : : throw(RuntimeException)
704 : : {
705 [ + - ][ + - ]: 162049 : MutexGuard aGuard( GetLinguMutex() );
706 [ + - ]: 162049 : return aDicName;
707 : : }
708 : :
709 : 0 : void SAL_CALL DictionaryNeo::setName( const OUString& aName )
710 : : throw(RuntimeException)
711 : : {
712 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
713 : :
714 [ # # ]: 0 : if (aDicName != aName)
715 : : {
716 : 0 : aDicName = aName;
717 [ # # ][ # # ]: 0 : launchEvent(DictionaryEventFlags::CHG_NAME, NULL);
718 [ # # ]: 0 : }
719 : 0 : }
720 : :
721 : 487985 : DictionaryType SAL_CALL DictionaryNeo::getDictionaryType( )
722 : : throw(RuntimeException)
723 : : {
724 [ + - ][ + - ]: 487985 : MutexGuard aGuard( GetLinguMutex() );
725 : :
726 [ + - ]: 487985 : return eDicType;
727 : : }
728 : :
729 : 270 : void SAL_CALL DictionaryNeo::setActive( sal_Bool bActivate )
730 : : throw(RuntimeException)
731 : : {
732 [ + - ][ + - ]: 270 : MutexGuard aGuard( GetLinguMutex() );
733 : :
734 [ + + ]: 270 : if (bIsActive != bActivate)
735 : : {
736 : 226 : bIsActive = bActivate != 0;
737 : : sal_Int16 nEvent = bIsActive ?
738 [ + + ]: 226 : DictionaryEventFlags::ACTIVATE_DIC : DictionaryEventFlags::DEACTIVATE_DIC;
739 : :
740 : : // remove entries from memory if dictionary is deactivated
741 [ + + ]: 226 : if (bIsActive == sal_False)
742 : : {
743 : 6 : sal_Bool bIsEmpty = nCount == 0;
744 : :
745 : : // save entries first if necessary
746 [ + - ][ + - ]: 6 : if (bIsModified && hasLocation() && !isReadonly())
[ - + ][ # # ]
[ # # ][ - + ]
747 : : {
748 [ # # ]: 0 : store();
749 : :
750 [ # # ]: 0 : aEntries.realloc( 0 );
751 : 0 : nCount = 0;
752 : 0 : bNeedEntries = !bIsEmpty;
753 : : }
754 : : DBG_ASSERT( !bIsModified || !hasLocation() || isReadonly(),
755 : : "lng : dictionary is still modified" );
756 : : }
757 : :
758 [ + - ][ + - ]: 226 : launchEvent(nEvent, NULL);
759 [ + - ]: 270 : }
760 : 270 : }
761 : :
762 : 487801 : sal_Bool SAL_CALL DictionaryNeo::isActive( )
763 : : throw(RuntimeException)
764 : : {
765 [ + - ][ + - ]: 487801 : MutexGuard aGuard( GetLinguMutex() );
766 [ + - ]: 487801 : return bIsActive;
767 : : }
768 : :
769 : 239202 : sal_Int32 SAL_CALL DictionaryNeo::getCount( )
770 : : throw(RuntimeException)
771 : : {
772 [ + - ][ + - ]: 239202 : MutexGuard aGuard( GetLinguMutex() );
773 : :
774 [ - + ]: 239202 : if (bNeedEntries)
775 [ # # ]: 0 : loadEntries( aMainURL );
776 [ + - ]: 239202 : return nCount;
777 : : }
778 : :
779 : 487795 : Locale SAL_CALL DictionaryNeo::getLocale( )
780 : : throw(RuntimeException)
781 : : {
782 [ + - ][ + - ]: 487795 : MutexGuard aGuard( GetLinguMutex() );
783 : 487795 : Locale aRes;
784 [ + - ][ + - ]: 487795 : return LanguageToLocale( aRes, nLanguage );
785 : : }
786 : :
787 : 0 : void SAL_CALL DictionaryNeo::setLocale( const Locale& aLocale )
788 : : throw(RuntimeException)
789 : : {
790 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
791 [ # # ]: 0 : sal_Int16 nLanguageP = LocaleToLanguage( aLocale );
792 [ # # ][ # # ]: 0 : if (!bIsReadonly && nLanguage != nLanguageP)
793 : : {
794 : 0 : nLanguage = nLanguageP;
795 : 0 : bIsModified = sal_True; // new language needs to be saved with dictionary
796 : :
797 [ # # ][ # # ]: 0 : launchEvent( DictionaryEventFlags::CHG_LANGUAGE, NULL );
798 [ # # ]: 0 : }
799 : 0 : }
800 : :
801 : 228470 : uno::Reference< XDictionaryEntry > SAL_CALL DictionaryNeo::getEntry(
802 : : const OUString& aWord )
803 : : throw(RuntimeException)
804 : : {
805 [ + - ][ + - ]: 228470 : MutexGuard aGuard( GetLinguMutex() );
806 : :
807 [ + + ]: 228470 : if (bNeedEntries)
808 [ + - ]: 80 : loadEntries( aMainURL );
809 : :
810 : : sal_Int32 nPos;
811 [ + - ]: 228470 : sal_Bool bFound = seekEntry( aWord, &nPos, sal_True );
812 : : DBG_ASSERT( nCount <= aEntries.getLength(), "lng : wrong number of entries");
813 : : DBG_ASSERT(!bFound || nPos < nCount, "lng : index out of range");
814 : :
815 : 1255 : return bFound ? aEntries.getConstArray()[ nPos ]
816 [ + + ][ + - ]: 229725 : : uno::Reference< XDictionaryEntry >();
817 : : }
818 : :
819 : 0 : sal_Bool SAL_CALL DictionaryNeo::addEntry(
820 : : const uno::Reference< XDictionaryEntry >& xDicEntry )
821 : : throw(RuntimeException)
822 : : {
823 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
824 : :
825 : 0 : sal_Bool bRes = sal_False;
826 : :
827 [ # # ]: 0 : if (!bIsReadonly)
828 : : {
829 [ # # ]: 0 : if (bNeedEntries)
830 [ # # ]: 0 : loadEntries( aMainURL );
831 [ # # ]: 0 : bRes = addEntry_Impl( xDicEntry );
832 : : }
833 : :
834 [ # # ]: 0 : return bRes;
835 : : }
836 : :
837 : : sal_Bool SAL_CALL
838 : 12 : DictionaryNeo::add( const OUString& rWord, sal_Bool bIsNegative,
839 : : const OUString& rRplcText )
840 : : throw(RuntimeException)
841 : : {
842 [ + - ][ + - ]: 12 : MutexGuard aGuard( GetLinguMutex() );
843 : :
844 : 12 : sal_Bool bRes = sal_False;
845 : :
846 [ + - ]: 12 : if (!bIsReadonly)
847 : : {
848 : : uno::Reference< XDictionaryEntry > xEntry =
849 [ + - ][ + - ]: 12 : new DicEntry( rWord, bIsNegative, rRplcText );
[ + - ]
850 [ + - ]: 12 : bRes = addEntry_Impl( xEntry );
851 : : }
852 : :
853 [ + - ]: 12 : return bRes;
854 : : }
855 : :
856 : 0 : void lcl_SequenceRemoveElementAt(
857 : : uno::Sequence< uno::Reference< XDictionaryEntry > >& rEntries, int nPos )
858 : : {
859 : : //TODO: helper for SequenceRemoveElementAt available?
860 [ # # ]: 0 : if(nPos >= rEntries.getLength())
861 : 0 : return;
862 [ # # ]: 0 : uno::Sequence< uno::Reference< XDictionaryEntry > > aTmp(rEntries.getLength() - 1);
863 [ # # ]: 0 : uno::Reference< XDictionaryEntry > * pOrig = rEntries.getArray();
864 [ # # ]: 0 : uno::Reference< XDictionaryEntry > * pTemp = aTmp.getArray();
865 : 0 : int nOffset = 0;
866 [ # # ]: 0 : for(int i = 0; i < aTmp.getLength(); i++)
867 : : {
868 [ # # ]: 0 : if(nPos == i)
869 : 0 : nOffset++;
870 [ # # ]: 0 : pTemp[i] = pOrig[i + nOffset];
871 : : }
872 : :
873 [ # # ][ # # ]: 0 : rEntries = aTmp;
874 : : }
875 : :
876 : 0 : sal_Bool SAL_CALL DictionaryNeo::remove( const OUString& aWord )
877 : : throw(RuntimeException)
878 : : {
879 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
880 : :
881 : 0 : sal_Bool bRemoved = sal_False;
882 : :
883 [ # # ]: 0 : if (!bIsReadonly)
884 : : {
885 [ # # ]: 0 : if (bNeedEntries)
886 [ # # ]: 0 : loadEntries( aMainURL );
887 : :
888 : : sal_Int32 nPos;
889 [ # # ]: 0 : sal_Bool bFound = seekEntry( aWord, &nPos );
890 : : DBG_ASSERT( nCount < aEntries.getLength(),
891 : : "lng : wrong number of entries");
892 : : DBG_ASSERT(!bFound || nPos < nCount, "lng : index out of range");
893 : :
894 : : // remove element if found
895 [ # # ]: 0 : if (bFound)
896 : : {
897 : : // entry to be removed
898 : : uno::Reference< XDictionaryEntry >
899 : 0 : xDicEntry( aEntries.getConstArray()[ nPos ] );
900 : : DBG_ASSERT(xDicEntry.is(), "lng : dictionary entry is NULL");
901 : :
902 : 0 : nCount--;
903 : :
904 : : //! the following call reduces the length of the sequence by 1 also
905 [ # # ]: 0 : lcl_SequenceRemoveElementAt( aEntries, nPos );
906 : 0 : bRemoved = bIsModified = sal_True;
907 : :
908 [ # # ]: 0 : launchEvent( DictionaryEventFlags::DEL_ENTRY, xDicEntry );
909 : : }
910 : : }
911 : :
912 [ # # ]: 0 : return bRemoved;
913 : : }
914 : :
915 : 10732 : sal_Bool SAL_CALL DictionaryNeo::isFull( )
916 : : throw(RuntimeException)
917 : : {
918 [ + - ][ + - ]: 10732 : MutexGuard aGuard( GetLinguMutex() );
919 : :
920 [ - + ]: 10732 : if (bNeedEntries)
921 [ # # ]: 0 : loadEntries( aMainURL );
922 [ + - ]: 10732 : return nCount >= DIC_MAX_ENTRIES;
923 : : }
924 : :
925 : : uno::Sequence< uno::Reference< XDictionaryEntry > >
926 : 0 : SAL_CALL DictionaryNeo::getEntries( )
927 : : throw(RuntimeException)
928 : : {
929 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
930 : :
931 [ # # ]: 0 : if (bNeedEntries)
932 [ # # ]: 0 : loadEntries( aMainURL );
933 : : //! return sequence with length equal to the number of dictionary entries
934 : : //! (internal used sequence may have additional unused elements.)
935 : : return uno::Sequence< uno::Reference< XDictionaryEntry > >
936 [ # # ][ # # ]: 0 : (aEntries.getConstArray(), nCount);
937 : : }
938 : :
939 : :
940 : 0 : void SAL_CALL DictionaryNeo::clear( )
941 : : throw(RuntimeException)
942 : : {
943 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
944 : :
945 [ # # ][ # # ]: 0 : if (!bIsReadonly && nCount)
946 : : {
947 : : // release all references to old entries and provide space for new ones
948 [ # # ][ # # ]: 0 : aEntries = uno::Sequence< uno::Reference< XDictionaryEntry > > ( 32 );
[ # # ]
949 : :
950 : 0 : nCount = 0;
951 : 0 : bNeedEntries = sal_False;
952 : 0 : bIsModified = sal_True;
953 : :
954 [ # # ][ # # ]: 0 : launchEvent( DictionaryEventFlags::ENTRIES_CLEARED , NULL );
955 [ # # ]: 0 : }
956 : 0 : }
957 : :
958 : 222 : sal_Bool SAL_CALL DictionaryNeo::addDictionaryEventListener(
959 : : const uno::Reference< XDictionaryEventListener >& xListener )
960 : : throw(RuntimeException)
961 : : {
962 [ + - ][ + - ]: 222 : MutexGuard aGuard( GetLinguMutex() );
963 : :
964 : 222 : sal_Bool bRes = sal_False;
965 [ + - ]: 222 : if (xListener.is())
966 : : {
967 [ + - ]: 222 : sal_Int32 nLen = aDicEvtListeners.getLength();
968 [ + - ]: 222 : bRes = aDicEvtListeners.addInterface( xListener ) != nLen;
969 : : }
970 [ + - ]: 222 : return bRes;
971 : : }
972 : :
973 : 222 : sal_Bool SAL_CALL DictionaryNeo::removeDictionaryEventListener(
974 : : const uno::Reference< XDictionaryEventListener >& xListener )
975 : : throw(RuntimeException)
976 : : {
977 [ + - ][ + - ]: 222 : MutexGuard aGuard( GetLinguMutex() );
978 : :
979 : 222 : sal_Bool bRes = sal_False;
980 [ + - ]: 222 : if (xListener.is())
981 : : {
982 [ + - ]: 222 : sal_Int32 nLen = aDicEvtListeners.getLength();
983 [ + - ]: 222 : bRes = aDicEvtListeners.removeInterface( xListener ) != nLen;
984 : : }
985 [ + - ]: 222 : return bRes;
986 : : }
987 : :
988 : :
989 : 98 : sal_Bool SAL_CALL DictionaryNeo::hasLocation()
990 : : throw(RuntimeException)
991 : : {
992 [ + - ][ + - ]: 98 : MutexGuard aGuard( GetLinguMutex() );
993 [ + - ]: 98 : return !aMainURL.isEmpty();
994 : : }
995 : :
996 : 0 : OUString SAL_CALL DictionaryNeo::getLocation()
997 : : throw(RuntimeException)
998 : : {
999 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
1000 [ # # ]: 0 : return aMainURL;
1001 : : }
1002 : :
1003 : 428 : sal_Bool SAL_CALL DictionaryNeo::isReadonly()
1004 : : throw(RuntimeException)
1005 : : {
1006 [ + - ][ + - ]: 428 : MutexGuard aGuard( GetLinguMutex() );
1007 : :
1008 [ + - ]: 428 : return bIsReadonly;
1009 : : }
1010 : :
1011 : 0 : void SAL_CALL DictionaryNeo::store()
1012 : : throw(io::IOException, RuntimeException)
1013 : : {
1014 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
1015 : :
1016 [ # # ][ # # ]: 0 : if (bIsModified && hasLocation() && !isReadonly())
[ # # ][ # # ]
[ # # ][ # # ]
1017 : : {
1018 [ # # ][ # # ]: 0 : if (saveEntries( aMainURL ))
1019 : : {
1020 : : #ifdef LINGU_EXCEPTIONS
1021 : : throw io::IOException();
1022 : : #endif
1023 : : }
1024 : : else
1025 : 0 : bIsModified = sal_False;
1026 [ # # ]: 0 : }
1027 : 0 : }
1028 : :
1029 : 0 : void SAL_CALL DictionaryNeo::storeAsURL(
1030 : : const OUString& aURL,
1031 : : const uno::Sequence< beans::PropertyValue >& /*rArgs*/ )
1032 : : throw(io::IOException, RuntimeException)
1033 : : {
1034 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
1035 : :
1036 [ # # ][ # # ]: 0 : if (saveEntries( aURL ))
1037 : : {
1038 : : #ifdef LINGU_EXCEPTIONS
1039 : : throw io::IOException();
1040 : : #endif
1041 : : }
1042 : : else
1043 : : {
1044 : 0 : aMainURL = aURL;
1045 : 0 : bIsModified = sal_False;
1046 [ # # ][ # # ]: 0 : bIsReadonly = IsReadOnly( getLocation() );
[ # # ][ # # ]
1047 [ # # ]: 0 : }
1048 : 0 : }
1049 : :
1050 : 0 : void SAL_CALL DictionaryNeo::storeToURL(
1051 : : const OUString& aURL,
1052 : : const uno::Sequence< beans::PropertyValue >& /*rArgs*/ )
1053 : : throw(io::IOException, RuntimeException)
1054 : : {
1055 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
1056 : :
1057 [ # # ]: 0 : if (saveEntries( aURL ))
1058 : : {
1059 : : #ifdef LINGU_EXCEPTIONS
1060 : : throw io::IOException();
1061 : : #endif
1062 [ # # ]: 0 : }
1063 : 0 : }
1064 : :
1065 : :
1066 : 10720 : DicEntry::DicEntry(const OUString &rDicFileWord,
1067 : 10720 : sal_Bool bIsNegativWord)
1068 : : {
1069 [ + - ]: 10720 : if (!rDicFileWord.isEmpty())
1070 [ + - ]: 10720 : splitDicFileWord( rDicFileWord, aDicWord, aReplacement );
1071 : 10720 : bIsNegativ = bIsNegativWord;
1072 : 10720 : }
1073 : :
1074 : 12 : DicEntry::DicEntry(const OUString &rDicWord, sal_Bool bNegativ,
1075 : : const OUString &rRplcText) :
1076 : : aDicWord (rDicWord),
1077 : : aReplacement (rRplcText),
1078 : 12 : bIsNegativ (bNegativ)
1079 : : {
1080 : 12 : }
1081 : :
1082 : 10196 : DicEntry::~DicEntry()
1083 : : {
1084 [ - + ]: 20392 : }
1085 : :
1086 : 10720 : void DicEntry::splitDicFileWord(const OUString &rDicFileWord,
1087 : : OUString &rDicWord,
1088 : : OUString &rReplacement)
1089 : : {
1090 [ + - ][ + - ]: 10720 : MutexGuard aGuard( GetLinguMutex() );
1091 : :
1092 [ + + ][ + - ]: 10720 : static const OUString aDelim( A2OU( "==" ) );
[ + - ][ # # ]
1093 : :
1094 : 10720 : sal_Int32 nDelimPos = rDicFileWord.indexOf( aDelim );
1095 [ - + ]: 10720 : if (-1 != nDelimPos)
1096 : : {
1097 : 0 : sal_Int32 nTriplePos = nDelimPos + 2;
1098 [ # # # # ]: 0 : if ( nTriplePos < rDicFileWord.getLength()
[ # # ]
1099 : 0 : && rDicFileWord[ nTriplePos ] == '=' )
1100 : 0 : ++nDelimPos;
1101 : 0 : rDicWord = rDicFileWord.copy( 0, nDelimPos );
1102 : 0 : rReplacement = rDicFileWord.copy( nDelimPos + 2 );
1103 : : }
1104 : : else
1105 : : {
1106 : 10720 : rDicWord = rDicFileWord;
1107 : 10720 : rReplacement = OUString();
1108 [ + - ]: 10720 : }
1109 : 10720 : }
1110 : :
1111 : 941133 : OUString SAL_CALL DicEntry::getDictionaryWord( )
1112 : : throw(RuntimeException)
1113 : : {
1114 [ + - ][ + - ]: 941133 : MutexGuard aGuard( GetLinguMutex() );
1115 [ + - ]: 941133 : return aDicWord;
1116 : : }
1117 : :
1118 : 11987 : sal_Bool SAL_CALL DicEntry::isNegative( )
1119 : : throw(RuntimeException)
1120 : : {
1121 [ + - ][ + - ]: 11987 : MutexGuard aGuard( GetLinguMutex() );
1122 [ + - ]: 11987 : return bIsNegativ;
1123 : : }
1124 : :
1125 : 0 : OUString SAL_CALL DicEntry::getReplacementText( )
1126 : : throw(RuntimeException)
1127 : : {
1128 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
1129 [ # # ]: 0 : return aReplacement;
1130 : : }
1131 : :
1132 : :
1133 : :
1134 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|