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