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