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