LCOV - code coverage report
Current view: top level - linguistic/source - dicimp.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 274 508 53.9 %
Date: 2012-08-25 Functions: 30 47 63.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 279 857 32.6 %

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

Generated by: LCOV version 1.10