LCOV - code coverage report
Current view: top level - linguistic/source - spelldsp.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 142 360 39.4 %
Date: 2012-08-25 Functions: 13 29 44.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 185 828 22.3 %

           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 <com/sun/star/uno/Reference.h>
      31                 :            : #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
      32                 :            : #include <com/sun/star/linguistic2/SpellFailure.hpp>
      33                 :            : #include <com/sun/star/registry/XRegistryKey.hpp>
      34                 :            : 
      35                 :            : #include <cppuhelper/factory.hxx>   // helper for factories
      36                 :            : #include <unotools/localedatawrapper.hxx>
      37                 :            : #include <comphelper/processfactory.hxx>
      38                 :            : #include <tools/debug.hxx>
      39                 :            : #include <svl/lngmisc.hxx>
      40                 :            : #include <osl/mutex.hxx>
      41                 :            : 
      42                 :            : #include <vector>
      43                 :            : 
      44                 :            : #include "spelldsp.hxx"
      45                 :            : #include "linguistic/spelldta.hxx"
      46                 :            : #include "lngsvcmgr.hxx"
      47                 :            : #include "linguistic/lngprops.hxx"
      48                 :            : 
      49                 :            : using namespace osl;
      50                 :            : using namespace com::sun::star;
      51                 :            : using namespace com::sun::star::beans;
      52                 :            : using namespace com::sun::star::lang;
      53                 :            : using namespace com::sun::star::uno;
      54                 :            : using namespace com::sun::star::linguistic2;
      55                 :            : using namespace linguistic;
      56                 :            : 
      57                 :            : using ::rtl::OUString;
      58                 :            : 
      59                 :            : // ProposalList: list of proposals for misspelled words
      60                 :            : //   The order of strings in the array should be left unchanged because the
      61                 :            : // spellchecker should have put the more likely suggestions at the top.
      62                 :            : // New entries will be added to the end but duplicates are to be avoided.
      63                 :            : // Removing entries is done by assigning the empty string.
      64                 :            : // The sequence is constructed from all non empty strings in the original
      65                 :            : // while maintaining the order.
      66                 :          0 : class ProposalList
      67                 :            : {
      68                 :            :     std::vector< OUString > aVec;
      69                 :            : 
      70                 :            :     sal_Bool    HasEntry( const OUString &rText ) const;
      71                 :            : 
      72                 :            :     // make copy c-tor and assignment operator private
      73                 :            :     ProposalList( const ProposalList & );
      74                 :            :     ProposalList & operator = ( const ProposalList & );
      75                 :            : 
      76                 :            : public:
      77                 :          0 :     ProposalList()  {}
      78                 :            : 
      79                 :            :     size_t  Count() const;
      80                 :            :     void    Prepend( const OUString &rText );
      81                 :            :     void    Append( const OUString &rNew );
      82                 :            :     void    Append( const std::vector< OUString > &rNew );
      83                 :            :     void    Append( const Sequence< OUString > &rNew );
      84                 :            :     Sequence< OUString >    GetSequence() const;
      85                 :            : };
      86                 :            : 
      87                 :            : 
      88                 :          0 : sal_Bool ProposalList::HasEntry( const OUString &rText ) const
      89                 :            : {
      90                 :          0 :     sal_Bool bFound = sal_False;
      91                 :          0 :     size_t nCnt = aVec.size();
      92 [ #  # ][ #  # ]:          0 :     for (size_t i = 0;  !bFound && i < nCnt;  ++i)
                 [ #  # ]
      93                 :            :     {
      94         [ #  # ]:          0 :         if (aVec[i] == rText)
      95                 :          0 :             bFound = sal_True;
      96                 :            :     }
      97                 :          0 :     return bFound;
      98                 :            : }
      99                 :            : 
     100                 :          0 : void ProposalList::Prepend( const OUString &rText )
     101                 :            : {
     102         [ #  # ]:          0 :     if (!HasEntry( rText ))
     103                 :          0 :         aVec.insert( aVec.begin(), rText );
     104                 :          0 : }
     105                 :            : 
     106                 :          0 : void ProposalList::Append( const OUString &rText )
     107                 :            : {
     108         [ #  # ]:          0 :     if (!HasEntry( rText ))
     109                 :          0 :         aVec.push_back( rText );
     110                 :          0 : }
     111                 :            : 
     112                 :          0 : void ProposalList::Append( const std::vector< OUString > &rNew )
     113                 :            : {
     114                 :          0 :     size_t nLen = rNew.size();
     115         [ #  # ]:          0 :     for ( size_t i = 0;  i < nLen;  ++i)
     116                 :            :     {
     117                 :          0 :         const OUString &rText = rNew[i];
     118         [ #  # ]:          0 :         if (!HasEntry( rText ))
     119                 :          0 :             Append( rText );
     120                 :            :     }
     121                 :          0 : }
     122                 :            : 
     123                 :          0 : void ProposalList::Append( const Sequence< OUString > &rNew )
     124                 :            : {
     125                 :          0 :     sal_Int32 nLen = rNew.getLength();
     126                 :          0 :     const OUString *pNew = rNew.getConstArray();
     127         [ #  # ]:          0 :     for (sal_Int32 i = 0;  i < nLen;  ++i)
     128                 :            :     {
     129                 :          0 :         const OUString &rText = pNew[i];
     130         [ #  # ]:          0 :         if (!HasEntry( rText ))
     131                 :          0 :             Append( rText );
     132                 :            :     }
     133                 :          0 : }
     134                 :            : 
     135                 :          0 : size_t ProposalList::Count() const
     136                 :            : {
     137                 :            :     // returns the number of non-empty strings in the vector
     138                 :            : 
     139                 :          0 :     size_t nRes = 0;
     140                 :          0 :     size_t nLen = aVec.size();
     141         [ #  # ]:          0 :     for (size_t i = 0;  i < nLen;  ++i)
     142                 :            :     {
     143         [ #  # ]:          0 :         if (!aVec[i].isEmpty())
     144                 :          0 :             ++nRes;
     145                 :            :     }
     146                 :          0 :     return nRes;
     147                 :            : }
     148                 :            : 
     149                 :          0 : Sequence< OUString > ProposalList::GetSequence() const
     150                 :            : {
     151                 :          0 :     sal_Int32 nCount = Count();
     152                 :          0 :     sal_Int32 nIdx = 0;
     153                 :          0 :     Sequence< OUString > aRes( nCount );
     154         [ #  # ]:          0 :     OUString *pRes = aRes.getArray();
     155                 :          0 :     sal_Int32 nLen = aVec.size();
     156         [ #  # ]:          0 :     for (sal_Int32 i = 0;  i < nLen;  ++i)
     157                 :            :     {
     158                 :          0 :         const OUString &rText = aVec[i];
     159                 :            :         DBG_ASSERT( nIdx < nCount, "index our of range" );
     160 [ #  # ][ #  # ]:          0 :         if (nIdx < nCount && !rText.isEmpty())
                 [ #  # ]
     161                 :          0 :             pRes[ nIdx++ ] = rText;
     162                 :            :     }
     163                 :          0 :     return aRes;
     164                 :            : }
     165                 :            : 
     166                 :         40 : sal_Bool SvcListHasLanguage(
     167                 :            :         const LangSvcEntries_Spell &rEntry,
     168                 :            :         LanguageType nLanguage )
     169                 :            : {
     170                 :         40 :     sal_Bool bHasLanguage = sal_False;
     171                 :         40 :     Locale aTmpLocale;
     172                 :            : 
     173                 :         40 :     const Reference< XSpellChecker >  *pRef  = rEntry.aSvcRefs .getConstArray();
     174                 :         40 :     sal_Int32 nLen = rEntry.aSvcRefs.getLength();
     175 [ +  + ][ +  - ]:         80 :     for (sal_Int32 k = 0;  k < nLen  &&  !bHasLanguage;  ++k)
                 [ +  + ]
     176                 :            :     {
     177         [ +  - ]:         40 :         if (pRef[k].is())
     178                 :            :         {
     179         [ +  - ]:         40 :             if (aTmpLocale.Language.isEmpty())
     180         [ +  - ]:         40 :                 aTmpLocale = CreateLocale( nLanguage );
     181 [ +  - ][ +  - ]:         40 :             bHasLanguage = pRef[k]->hasLocale( aTmpLocale );
     182                 :            :         }
     183                 :            :     }
     184                 :            : 
     185                 :         40 :     return bHasLanguage;
     186                 :            : }
     187                 :            : 
     188                 :         46 : SpellCheckerDispatcher::SpellCheckerDispatcher( LngSvcMgr &rLngSvcMgr ) :
     189 [ +  - ][ +  - ]:         46 :     rMgr    (rLngSvcMgr)
     190                 :            : {
     191                 :         46 :     pCache = NULL;
     192                 :         46 : }
     193                 :            : 
     194                 :            : 
     195         [ +  - ]:         44 : SpellCheckerDispatcher::~SpellCheckerDispatcher()
     196                 :            : {
     197         [ +  - ]:         44 :     ClearSvcList();
     198 [ +  + ][ +  - ]:         44 :     delete pCache;
     199         [ -  + ]:         88 : }
     200                 :            : 
     201                 :            : 
     202                 :         44 : void SpellCheckerDispatcher::ClearSvcList()
     203                 :            : {
     204                 :            :     // release memory for each table entry
     205         [ +  - ]:         44 :     SpellSvcByLangMap_t aTmp;
     206         [ +  - ]:         44 :     aSvcMap.swap( aTmp );
     207                 :         44 : }
     208                 :            : 
     209                 :            : 
     210                 :          0 : Sequence< Locale > SAL_CALL SpellCheckerDispatcher::getLocales()
     211                 :            :         throw(RuntimeException)
     212                 :            : {
     213 [ #  # ][ #  # ]:          0 :     MutexGuard  aGuard( GetLinguMutex() );
     214                 :            : 
     215         [ #  # ]:          0 :     Sequence< Locale > aLocales( static_cast< sal_Int32 >(aSvcMap.size()) );
     216         [ #  # ]:          0 :     Locale *pLocales = aLocales.getArray();
     217                 :          0 :     SpellSvcByLangMap_t::const_iterator aIt;
     218         [ #  # ]:          0 :     for (aIt = aSvcMap.begin();  aIt != aSvcMap.end();  ++aIt)
     219                 :            :     {
     220         [ #  # ]:          0 :         *pLocales++ = CreateLocale( aIt->first );
     221                 :            :     }
     222         [ #  # ]:          0 :     return aLocales;
     223                 :            : }
     224                 :            : 
     225                 :            : 
     226                 :      29241 : sal_Bool SAL_CALL SpellCheckerDispatcher::hasLocale( const Locale& rLocale )
     227                 :            :         throw(RuntimeException)
     228                 :            : {
     229 [ +  - ][ +  - ]:      29241 :     MutexGuard  aGuard( GetLinguMutex() );
     230 [ +  - ][ +  - ]:      29241 :     SpellSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LocaleToLanguage( rLocale ) ) );
     231         [ +  - ]:      29241 :     return aIt != aSvcMap.end();
     232                 :            : }
     233                 :            : 
     234                 :            : 
     235                 :            : sal_Bool SAL_CALL
     236                 :      32229 :     SpellCheckerDispatcher::isValid( const OUString& rWord, const Locale& rLocale,
     237                 :            :             const PropertyValues& rProperties )
     238                 :            :         throw(IllegalArgumentException, RuntimeException)
     239                 :            : {
     240 [ +  - ][ +  - ]:      32229 :     MutexGuard  aGuard( GetLinguMutex() );
     241 [ +  - ][ +  - ]:      32229 :     return isValid_Impl( rWord, LocaleToLanguage( rLocale ), rProperties, sal_True );
                 [ +  - ]
     242                 :            : }
     243                 :            : 
     244                 :            : 
     245                 :            : Reference< XSpellAlternatives > SAL_CALL
     246                 :          0 :     SpellCheckerDispatcher::spell( const OUString& rWord, const Locale& rLocale,
     247                 :            :             const PropertyValues& rProperties )
     248                 :            :         throw(IllegalArgumentException, RuntimeException)
     249                 :            : {
     250 [ #  # ][ #  # ]:          0 :     MutexGuard  aGuard( GetLinguMutex() );
     251 [ #  # ][ #  # ]:          0 :     return spell_Impl( rWord, LocaleToLanguage( rLocale ), rProperties, sal_True );
                 [ #  # ]
     252                 :            : }
     253                 :            : 
     254                 :            : 
     255                 :            : // returns the overall result of cross-checking with all user-dictionaries
     256                 :            : // including the IgnoreAll list
     257                 :      32229 : static Reference< XDictionaryEntry > lcl_GetRulingDictionaryEntry(
     258                 :            :     const OUString &rWord,
     259                 :            :     LanguageType nLanguage )
     260                 :            : {
     261                 :      32229 :     Reference< XDictionaryEntry > xRes;
     262                 :            : 
     263                 :            :     // the order of winning from top to bottom is:
     264                 :            :     // 1) IgnoreAll list will always win
     265                 :            :     // 2) Negative dictionaries will win over positive dictionaries
     266         [ +  - ]:      32229 :     Reference< XDictionary > xIgnoreAll( GetIgnoreAllList() );
     267         [ +  - ]:      32229 :     if (xIgnoreAll.is())
     268 [ +  - ][ +  - ]:      32229 :         xRes = xIgnoreAll->getEntry( rWord );
                 [ +  - ]
     269         [ +  - ]:      32229 :     if (!xRes.is())
     270                 :            :     {
     271         [ +  - ]:      32229 :         Reference< XDictionaryList > xDList( GetDictionaryList() );
     272                 :            :         Reference< XDictionaryEntry > xNegEntry( SearchDicList( xDList,
     273         [ +  - ]:      32229 :                 rWord, nLanguage, sal_False, sal_True ) );
     274         [ -  + ]:      32229 :         if (xNegEntry.is())
     275         [ #  # ]:          0 :             xRes = xNegEntry;
     276                 :            :         else
     277                 :            :         {
     278                 :            :             Reference< XDictionaryEntry > xPosEntry( SearchDicList( xDList,
     279         [ +  - ]:      32229 :                     rWord, nLanguage, sal_True, sal_True ) );
     280         [ +  + ]:      32229 :             if (xPosEntry.is())
     281         [ +  - ]:      32229 :                 xRes = xPosEntry;
     282                 :      32229 :         }
     283                 :            :     }
     284                 :            : 
     285                 :      32229 :     return xRes;
     286                 :            : }
     287                 :            : 
     288                 :            : 
     289                 :      32229 : sal_Bool SpellCheckerDispatcher::isValid_Impl(
     290                 :            :             const OUString& rWord,
     291                 :            :             LanguageType nLanguage,
     292                 :            :             const PropertyValues& rProperties,
     293                 :            :             sal_Bool bCheckDics)
     294                 :            :         throw( RuntimeException, IllegalArgumentException )
     295                 :            : {
     296 [ +  - ][ +  - ]:      32229 :     MutexGuard  aGuard( GetLinguMutex() );
     297                 :            : 
     298                 :      32229 :     sal_Bool bRes = sal_True;
     299                 :            : 
     300 [ +  - ][ -  + ]:      32229 :     if (nLanguage == LANGUAGE_NONE || rWord.isEmpty())
                 [ -  + ]
     301                 :          0 :         return bRes;
     302                 :            : 
     303                 :            :     // search for entry with that language
     304         [ +  - ]:      32229 :     SpellSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
     305         [ +  - ]:      32229 :     LangSvcEntries_Spell    *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
     306                 :            : 
     307         [ +  - ]:      32229 :     if (!pEntry)
     308                 :            :     {
     309                 :            : #ifdef LINGU_EXCEPTIONS
     310                 :            :         throw IllegalArgumentException();
     311                 :            : #endif
     312                 :            :     }
     313                 :            :     else
     314                 :            :     {
     315                 :      32229 :         OUString aChkWord( rWord );
     316         [ +  - ]:      32229 :         Locale aLocale( CreateLocale( nLanguage ) );
     317                 :            : 
     318                 :            :         // replace typographical apostroph by ascii apostroph
     319 [ +  - ][ +  - ]:      32229 :         String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
                 [ +  - ]
     320                 :            :         DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
     321         [ +  - ]:      32229 :         if (aSingleQuote.Len())
     322                 :      32229 :             aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
     323                 :            : 
     324         [ +  - ]:      32229 :         RemoveHyphens( aChkWord );
     325 [ +  - ][ +  - ]:      32229 :         if (IsIgnoreControlChars( rProperties, GetPropSet() ))
                 [ +  - ]
     326         [ +  - ]:      32229 :             RemoveControlChars( aChkWord );
     327                 :            : 
     328                 :      32229 :         sal_Int32 nLen = pEntry->aSvcRefs.getLength();
     329                 :            :         DBG_ASSERT( nLen == pEntry->aSvcImplNames.getLength(),
     330                 :            :                 "lng : sequence length mismatch");
     331                 :            :         DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
     332                 :            :                 "lng : index out of range");
     333                 :            : 
     334                 :      32229 :         sal_Int32 i = 0;
     335                 :      32229 :         sal_Bool bTmpRes = sal_True;
     336                 :      32229 :         sal_Bool bTmpResValid = sal_False;
     337                 :            : 
     338                 :            :         // try already instantiated services first
     339                 :            :         {
     340                 :            :             const Reference< XSpellChecker >  *pRef  =
     341                 :      32229 :                     pEntry->aSvcRefs.getConstArray();
     342 [ +  + ][ -  + ]:      64418 :             while (i <= pEntry->nLastTriedSvcIndex
         [ #  # ][ +  + ]
     343                 :            :                    &&  (!bTmpResValid  ||  sal_False == bTmpRes))
     344                 :            :             {
     345                 :      32189 :                 bTmpResValid = sal_True;
     346 [ +  - ][ +  - ]:      32189 :                 if (pRef[i].is()  &&  pRef[i]->hasLocale( aLocale ))
         [ +  - ][ +  - ]
                 [ +  - ]
     347                 :            :                 {
     348 [ +  - ][ +  - ]:      32189 :                     bTmpRes = GetCache().CheckWord( aChkWord, nLanguage );
     349         [ +  + ]:      32189 :                     if (!bTmpRes)
     350                 :            :                     {
     351 [ +  - ][ +  - ]:      14757 :                         bTmpRes = pRef[i]->isValid( aChkWord, aLocale, rProperties );
     352                 :            : 
     353                 :            :                         // Add correct words to the cache.
     354                 :            :                         // But not those that are correct only because of
     355                 :            :                         // the temporary supplied settings.
     356 [ +  + ][ +  - ]:      14757 :                         if (bTmpRes  &&  0 == rProperties.getLength())
                 [ +  + ]
     357 [ +  - ][ +  - ]:      10670 :                             GetCache().AddWord( aChkWord, nLanguage );
     358                 :            :                     }
     359                 :            :                 }
     360                 :            :                 else
     361                 :          0 :                     bTmpResValid = sal_False;
     362                 :            : 
     363         [ +  - ]:      32189 :                 if (bTmpResValid)
     364                 :      32189 :                     bRes = bTmpRes;
     365                 :            : 
     366                 :      32189 :                 ++i;
     367                 :            :             }
     368                 :            :         }
     369                 :            : 
     370                 :            :         // if still no result instantiate new services and try those
     371 [ +  + ][ +  + ]:      32229 :         if ((!bTmpResValid  ||  sal_False == bTmpRes)
                 [ +  + ]
     372                 :            :             &&  pEntry->nLastTriedSvcIndex < nLen - 1)
     373                 :            :         {
     374                 :         40 :             const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
     375         [ +  - ]:         40 :             Reference< XSpellChecker >  *pRef  = pEntry->aSvcRefs .getArray();
     376                 :            : 
     377                 :            :             Reference< XMultiServiceFactory > xMgr(
     378         [ +  - ]:         40 :                 comphelper::getProcessServiceFactory() );
     379         [ +  - ]:         40 :             if (xMgr.is())
     380                 :            :             {
     381                 :            :                 // build service initialization argument
     382         [ +  - ]:         40 :                 Sequence< Any > aArgs(2);
     383 [ +  - ][ +  - ]:         40 :                 aArgs.getArray()[0] <<= GetPropSet();
                 [ +  - ]
     384                 :            : 
     385 [ +  + ][ -  + ]:         80 :                 while (i < nLen  &&  (!bTmpResValid  ||  sal_False == bTmpRes))
         [ #  # ][ +  + ]
     386                 :            :                 {
     387                 :            :                     // create specific service via it's implementation name
     388                 :         40 :                     Reference< XSpellChecker > xSpell;
     389                 :            :                     try
     390                 :            :                     {
     391                 :            :                         xSpell = Reference< XSpellChecker >(
     392         [ +  - ]:         40 :                                 xMgr->createInstanceWithArguments(
     393 [ +  - ][ +  - ]:         40 :                                 pImplNames[i], aArgs ),  UNO_QUERY );
         [ +  - ][ #  # ]
     394                 :            :                     }
     395         [ #  # ]:          0 :                     catch (uno::Exception &)
     396                 :            :                     {
     397                 :            :                         DBG_ASSERT( 0, "createInstanceWithArguments failed" );
     398                 :            :                     }
     399         [ +  - ]:         40 :                     pRef [i] = xSpell;
     400                 :            : 
     401                 :            :                     Reference< XLinguServiceEventBroadcaster >
     402         [ +  - ]:         40 :                             xBroadcaster( xSpell, UNO_QUERY );
     403         [ +  - ]:         40 :                     if (xBroadcaster.is())
     404         [ +  - ]:         40 :                         rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
     405                 :            : 
     406                 :         40 :                     bTmpResValid = sal_True;
     407 [ +  - ][ +  - ]:         40 :                     if (xSpell.is()  &&  xSpell->hasLocale( aLocale ))
         [ +  - ][ +  - ]
                 [ +  - ]
     408                 :            :                     {
     409 [ +  - ][ +  - ]:         40 :                         bTmpRes = GetCache().CheckWord( aChkWord, nLanguage );
     410         [ +  - ]:         40 :                         if (!bTmpRes)
     411                 :            :                         {
     412 [ +  - ][ +  - ]:         40 :                             bTmpRes = xSpell->isValid( aChkWord, aLocale, rProperties );
     413                 :            : 
     414                 :            :                             // Add correct words to the cache.
     415                 :            :                             // But not those that are correct only because of
     416                 :            :                             // the temporary supplied settings.
     417 [ +  + ][ +  - ]:         40 :                             if (bTmpRes  &&  0 == rProperties.getLength())
                 [ +  + ]
     418 [ +  - ][ +  - ]:         31 :                                 GetCache().AddWord( aChkWord, nLanguage );
     419                 :            :                         }
     420                 :            :                     }
     421                 :            :                     else
     422                 :          0 :                         bTmpResValid = sal_False;
     423                 :            : 
     424         [ +  - ]:         40 :                     if (bTmpResValid)
     425                 :         40 :                         bRes = bTmpRes;
     426                 :            : 
     427                 :         40 :                     pEntry->nLastTriedSvcIndex = (sal_Int16) i;
     428                 :         40 :                     ++i;
     429                 :         40 :                 }
     430                 :            : 
     431                 :            :                 // if language is not supported by any of the services
     432                 :            :                 // remove it from the list.
     433         [ +  - ]:         40 :                 if (i == nLen)
     434                 :            :                 {
     435 [ +  - ][ -  + ]:         40 :                     if (!SvcListHasLanguage( *pEntry, nLanguage ))
     436         [ #  # ]:          0 :                         aSvcMap.erase( nLanguage );
     437         [ +  - ]:         40 :                 }
     438                 :         40 :             }
     439                 :            :         }
     440                 :            : 
     441                 :            :         // cross-check against results from dictionaries which have precedence!
     442   [ +  -  +  - ]:     128916 :         if (bCheckDics  &&
         [ +  - ][ +  - ]
     443 [ +  - ][ +  - ]:      96687 :             GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
         [ +  - ][ +  - ]
                 [ +  - ]
           [ #  #  #  # ]
     444                 :            :         {
     445         [ +  - ]:      32229 :             Reference< XDictionaryEntry > xTmp( lcl_GetRulingDictionaryEntry( aChkWord, nLanguage ) );
     446         [ +  + ]:      32229 :             if (xTmp.is())
     447 [ +  - ][ +  - ]:      32229 :                 bRes = !xTmp->isNegative();
     448         [ +  - ]:      32229 :         }
     449                 :            :     }
     450                 :            : 
     451         [ +  - ]:      32229 :     return bRes;
     452                 :            : }
     453                 :            : 
     454                 :            : 
     455                 :          0 : Reference< XSpellAlternatives > SpellCheckerDispatcher::spell_Impl(
     456                 :            :             const OUString& rWord,
     457                 :            :             LanguageType nLanguage,
     458                 :            :             const PropertyValues& rProperties,
     459                 :            :             sal_Bool bCheckDics )
     460                 :            :         throw(IllegalArgumentException, RuntimeException)
     461                 :            : {
     462 [ #  # ][ #  # ]:          0 :     MutexGuard  aGuard( GetLinguMutex() );
     463                 :            : 
     464                 :          0 :     Reference< XSpellAlternatives > xRes;
     465                 :            : 
     466 [ #  # ][ #  # ]:          0 :     if (nLanguage == LANGUAGE_NONE || rWord.isEmpty())
                 [ #  # ]
     467                 :            :         return xRes;
     468                 :            : 
     469                 :            :     // search for entry with that language
     470         [ #  # ]:          0 :     SpellSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
     471         [ #  # ]:          0 :     LangSvcEntries_Spell    *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
     472                 :            : 
     473         [ #  # ]:          0 :     if (!pEntry)
     474                 :            :     {
     475                 :            : #ifdef LINGU_EXCEPTIONS
     476                 :            :         throw IllegalArgumentException();
     477                 :            : #endif
     478                 :            :     }
     479                 :            :     else
     480                 :            :     {
     481                 :          0 :         OUString aChkWord( rWord );
     482         [ #  # ]:          0 :         Locale aLocale( CreateLocale( nLanguage ) );
     483                 :            : 
     484                 :            :         // replace typographical apostroph by ascii apostroph
     485 [ #  # ][ #  # ]:          0 :         String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
                 [ #  # ]
     486                 :            :         DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
     487         [ #  # ]:          0 :         if (aSingleQuote.Len())
     488                 :          0 :             aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
     489                 :            : 
     490         [ #  # ]:          0 :         RemoveHyphens( aChkWord );
     491 [ #  # ][ #  # ]:          0 :         if (IsIgnoreControlChars( rProperties, GetPropSet() ))
                 [ #  # ]
     492         [ #  # ]:          0 :             RemoveControlChars( aChkWord );
     493                 :            : 
     494                 :          0 :         sal_Int32 nLen = pEntry->aSvcRefs.getLength();
     495                 :            :         DBG_ASSERT( nLen == pEntry->aSvcImplNames.getLength(),
     496                 :            :                 "lng : sequence length mismatch");
     497                 :            :         DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
     498                 :            :                 "lng : index out of range");
     499                 :            : 
     500                 :          0 :         sal_Int32 i = 0;
     501                 :          0 :         Reference< XSpellAlternatives > xTmpRes;
     502                 :          0 :         sal_Bool bTmpResValid = sal_False;
     503                 :            : 
     504                 :            :         // try already instantiated services first
     505                 :            :         {
     506                 :          0 :             const Reference< XSpellChecker >  *pRef  = pEntry->aSvcRefs.getConstArray();
     507                 :          0 :             sal_Int32 nNumSugestions = -1;
     508         [ #  # ]:          0 :             while (i <= pEntry->nLastTriedSvcIndex
           [ #  #  #  # ]
                 [ #  # ]
     509                 :          0 :                    &&  (!bTmpResValid || xTmpRes.is()) )
     510                 :            :             {
     511                 :          0 :                 bTmpResValid = sal_True;
     512 [ #  # ][ #  # ]:          0 :                 if (pRef[i].is()  &&  pRef[i]->hasLocale( aLocale ))
         [ #  # ][ #  # ]
                 [ #  # ]
     513                 :            :                 {
     514 [ #  # ][ #  # ]:          0 :                     sal_Bool bOK = GetCache().CheckWord( aChkWord, nLanguage );
     515         [ #  # ]:          0 :                     if (bOK)
     516         [ #  # ]:          0 :                         xTmpRes = NULL;
     517                 :            :                     else
     518                 :            :                     {
     519 [ #  # ][ #  # ]:          0 :                         xTmpRes = pRef[i]->spell( aChkWord, aLocale, rProperties );
                 [ #  # ]
     520                 :            : 
     521                 :            :                         // Add correct words to the cache.
     522                 :            :                         // But not those that are correct only because of
     523                 :            :                         // the temporary supplied settings.
     524 [ #  # ][ #  # ]:          0 :                         if (!xTmpRes.is()  &&  0 == rProperties.getLength())
                 [ #  # ]
     525 [ #  # ][ #  # ]:          0 :                             GetCache().AddWord( aChkWord, nLanguage );
     526                 :            :                     }
     527                 :            :                 }
     528                 :            :                 else
     529                 :          0 :                     bTmpResValid = sal_False;
     530                 :            : 
     531                 :            :                 // return first found result if the word is not known by any checker.
     532                 :            :                 // But if that result has no suggestions use the first one that does
     533                 :            :                 // provide suggestions for the misspelled word.
     534 [ #  # ][ #  # ]:          0 :                 if (!xRes.is() && bTmpResValid)
                 [ #  # ]
     535                 :            :                 {
     536         [ #  # ]:          0 :                     xRes = xTmpRes;
     537                 :          0 :                     nNumSugestions = 0;
     538         [ #  # ]:          0 :                     if (xRes.is())
     539 [ #  # ][ #  # ]:          0 :                         nNumSugestions = xRes->getAlternatives().getLength();
                 [ #  # ]
     540                 :            :                 }
     541                 :          0 :                 sal_Int32 nTmpNumSugestions = 0;
     542 [ #  # ][ #  # ]:          0 :                 if (xTmpRes.is() && bTmpResValid)
                 [ #  # ]
     543 [ #  # ][ #  # ]:          0 :                     nTmpNumSugestions = xTmpRes->getAlternatives().getLength();
                 [ #  # ]
     544 [ #  # ][ #  # ]:          0 :                 if (xRes.is() && nNumSugestions == 0 && nTmpNumSugestions > 0)
         [ #  # ][ #  # ]
     545                 :            :                 {
     546         [ #  # ]:          0 :                     xRes = xTmpRes;
     547                 :          0 :                     nNumSugestions = nTmpNumSugestions;
     548                 :            :                 }
     549                 :            : 
     550                 :          0 :                 ++i;
     551                 :            :             }
     552                 :            :         }
     553                 :            : 
     554                 :            :         // if still no result instantiate new services and try those
     555 [ #  # ][ #  # ]:          0 :         if ((!bTmpResValid || xTmpRes.is())
         [ #  # ][ #  # ]
     556                 :            :             &&  pEntry->nLastTriedSvcIndex < nLen - 1)
     557                 :            :         {
     558                 :          0 :             const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
     559         [ #  # ]:          0 :             Reference< XSpellChecker >  *pRef  = pEntry->aSvcRefs .getArray();
     560                 :            : 
     561                 :            :             Reference< XMultiServiceFactory > xMgr(
     562         [ #  # ]:          0 :                 comphelper::getProcessServiceFactory() );
     563         [ #  # ]:          0 :             if (xMgr.is())
     564                 :            :             {
     565                 :            :                 // build service initialization argument
     566         [ #  # ]:          0 :                 Sequence< Any > aArgs(2);
     567 [ #  # ][ #  # ]:          0 :                 aArgs.getArray()[0] <<= GetPropSet();
                 [ #  # ]
     568                 :            : 
     569                 :          0 :                 sal_Int32 nNumSugestions = -1;
     570 [ #  # ][ #  # ]:          0 :                 while (i < nLen  &&  (!bTmpResValid || xTmpRes.is()))
         [ #  # ][ #  # ]
     571                 :            :                 {
     572                 :            :                     // create specific service via it's implementation name
     573                 :          0 :                     Reference< XSpellChecker > xSpell;
     574                 :            :                     try
     575                 :            :                     {
     576                 :            :                         xSpell = Reference< XSpellChecker >(
     577         [ #  # ]:          0 :                                 xMgr->createInstanceWithArguments(
     578 [ #  # ][ #  # ]:          0 :                                 pImplNames[i], aArgs ), UNO_QUERY );
         [ #  # ][ #  # ]
     579                 :            :                     }
     580         [ #  # ]:          0 :                     catch (uno::Exception &)
     581                 :            :                     {
     582                 :            :                         DBG_ASSERT( 0, "createInstanceWithArguments failed" );
     583                 :            :                     }
     584         [ #  # ]:          0 :                     pRef [i] = xSpell;
     585                 :            : 
     586                 :            :                     Reference< XLinguServiceEventBroadcaster >
     587         [ #  # ]:          0 :                             xBroadcaster( xSpell, UNO_QUERY );
     588         [ #  # ]:          0 :                     if (xBroadcaster.is())
     589         [ #  # ]:          0 :                         rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
     590                 :            : 
     591                 :          0 :                     bTmpResValid = sal_True;
     592 [ #  # ][ #  # ]:          0 :                     if (xSpell.is()  &&  xSpell->hasLocale( aLocale ))
         [ #  # ][ #  # ]
                 [ #  # ]
     593                 :            :                     {
     594 [ #  # ][ #  # ]:          0 :                         sal_Bool bOK = GetCache().CheckWord( aChkWord, nLanguage );
     595         [ #  # ]:          0 :                         if (bOK)
     596         [ #  # ]:          0 :                             xTmpRes = NULL;
     597                 :            :                         else
     598                 :            :                         {
     599 [ #  # ][ #  # ]:          0 :                             xTmpRes = xSpell->spell( aChkWord, aLocale, rProperties );
                 [ #  # ]
     600                 :            : 
     601                 :            :                             // Add correct words to the cache.
     602                 :            :                             // But not those that are correct only because of
     603                 :            :                             // the temporary supplied settings.
     604 [ #  # ][ #  # ]:          0 :                             if (!xTmpRes.is()  &&  0 == rProperties.getLength())
                 [ #  # ]
     605 [ #  # ][ #  # ]:          0 :                                 GetCache().AddWord( aChkWord, nLanguage );
     606                 :            :                         }
     607                 :            :                     }
     608                 :            :                     else
     609                 :          0 :                         bTmpResValid = sal_False;
     610                 :            : 
     611                 :            :                     // return first found result if the word is not known by any checker.
     612                 :            :                     // But if that result has no suggestions use the first one that does
     613                 :            :                     // provide suggestions for the misspelled word.
     614 [ #  # ][ #  # ]:          0 :                     if (!xRes.is() && bTmpResValid)
                 [ #  # ]
     615                 :            :                     {
     616         [ #  # ]:          0 :                         xRes = xTmpRes;
     617                 :          0 :                         nNumSugestions = 0;
     618         [ #  # ]:          0 :                         if (xRes.is())
     619 [ #  # ][ #  # ]:          0 :                             nNumSugestions = xRes->getAlternatives().getLength();
                 [ #  # ]
     620                 :            :                     }
     621                 :          0 :                     sal_Int32 nTmpNumSugestions = 0;
     622 [ #  # ][ #  # ]:          0 :                     if (xTmpRes.is() && bTmpResValid)
                 [ #  # ]
     623 [ #  # ][ #  # ]:          0 :                         nTmpNumSugestions = xTmpRes->getAlternatives().getLength();
                 [ #  # ]
     624 [ #  # ][ #  # ]:          0 :                     if (xRes.is() && nNumSugestions == 0 && nTmpNumSugestions > 0)
         [ #  # ][ #  # ]
     625                 :            :                     {
     626         [ #  # ]:          0 :                         xRes = xTmpRes;
     627                 :          0 :                         nNumSugestions = nTmpNumSugestions;
     628                 :            :                     }
     629                 :            : 
     630                 :          0 :                     pEntry->nLastTriedSvcIndex = (sal_Int16) i;
     631                 :          0 :                     ++i;
     632                 :          0 :                 }
     633                 :            : 
     634                 :            :                 // if language is not supported by any of the services
     635                 :            :                 // remove it from the list.
     636         [ #  # ]:          0 :                 if (i == nLen)
     637                 :            :                 {
     638 [ #  # ][ #  # ]:          0 :                     if (!SvcListHasLanguage( *pEntry, nLanguage ))
     639         [ #  # ]:          0 :                         aSvcMap.erase( nLanguage );
     640         [ #  # ]:          0 :                 }
     641                 :          0 :             }
     642                 :            :         }
     643                 :            : 
     644                 :            :         // if word is finally found to be correct
     645                 :            :         // clear previously remembered alternatives
     646 [ #  # ][ #  # ]:          0 :         if (bTmpResValid  &&  !xTmpRes.is())
                 [ #  # ]
     647         [ #  # ]:          0 :             xRes = NULL;
     648                 :            : 
     649                 :            :         // list of proposals found (to be checked against entries of
     650                 :            :         // neagtive dictionaries)
     651         [ #  # ]:          0 :         ProposalList aProposalList;
     652                 :          0 :         sal_Int16 eFailureType = -1;    // no failure
     653         [ #  # ]:          0 :         if (xRes.is())
     654                 :            :         {
     655 [ #  # ][ #  # ]:          0 :             aProposalList.Append( xRes->getAlternatives() );
         [ #  # ][ #  # ]
     656 [ #  # ][ #  # ]:          0 :             eFailureType = xRes->getFailureType();
     657                 :            :         }
     658                 :          0 :         Reference< XDictionaryList > xDList;
     659 [ #  # ][ #  # ]:          0 :         if (GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  #  
           #  # ][ #  # ]
     660 [ #  # ][ #  # ]:          0 :             xDList = Reference< XDictionaryList >( GetDicList(), UNO_QUERY );
                 [ #  # ]
     661                 :            : 
     662                 :            :         // cross-check against results from user-dictionaries which have precedence!
     663 [ #  # ][ #  # ]:          0 :         if (bCheckDics  &&  xDList.is())
                 [ #  # ]
     664                 :            :         {
     665         [ #  # ]:          0 :             Reference< XDictionaryEntry > xTmp( lcl_GetRulingDictionaryEntry( aChkWord, nLanguage ) );
     666         [ #  # ]:          0 :             if (xTmp.is())
     667                 :            :             {
     668 [ #  # ][ #  # ]:          0 :                 if (xTmp->isNegative())    // positive entry found
                 [ #  # ]
     669                 :            :                 {
     670                 :          0 :                     eFailureType = SpellFailure::IS_NEGATIVE_WORD;
     671                 :            : 
     672                 :            :                     // replacement text to be added to suggestions, if not empty
     673 [ #  # ][ #  # ]:          0 :                     OUString aAddRplcTxt( xTmp->getReplacementText() );
     674                 :            : 
     675                 :            :                     // replacement text must not be in negative dictionary itself
     676   [ #  #  #  # ]:          0 :                     if (!aAddRplcTxt.isEmpty() &&
                 [ #  # ]
     677 [ #  # ][ #  # ]:          0 :                         !SearchDicList( xDList, aAddRplcTxt, nLanguage, sal_False, sal_True ).is())
                 [ #  # ]
     678                 :            :                     {
     679         [ #  # ]:          0 :                         aProposalList.Prepend( aAddRplcTxt );
     680                 :          0 :                     }
     681                 :            :                 }
     682                 :            :                 else    // positive entry found
     683                 :            :                 {
     684         [ #  # ]:          0 :                     xRes = NULL;
     685                 :          0 :                     eFailureType = -1;  // no failure
     686                 :            :                 }
     687                 :          0 :             }
     688                 :            :         }
     689                 :            : 
     690         [ #  # ]:          0 :         if (eFailureType != -1)     // word misspelled or found in negative user-dictionary
     691                 :            :         {
     692                 :            :             // search suitable user-dictionaries for suggestions that are
     693                 :            :             // similar to the misspelled word
     694         [ #  # ]:          0 :             std::vector< OUString > aDicListProps;   // list of proposals from user-dictionaries
     695         [ #  # ]:          0 :             SearchSimilarText( aChkWord, nLanguage, xDList, aDicListProps );
     696         [ #  # ]:          0 :             aProposalList.Append( aDicListProps );
     697         [ #  # ]:          0 :             Sequence< OUString > aProposals = aProposalList.GetSequence();
     698                 :            : 
     699                 :            :             // remove entries listed in negative dictionaries
     700                 :            :             // (we don't want to display suggestions that will be regarded as misspelledlater on)
     701 [ #  # ][ #  # ]:          0 :             if (bCheckDics  &&  xDList.is())
                 [ #  # ]
     702         [ #  # ]:          0 :                 SeqRemoveNegEntries( aProposals, xDList, nLanguage );
     703                 :            : 
     704         [ #  # ]:          0 :             uno::Reference< linguistic2::XSetSpellAlternatives > xSetAlt( xRes, uno::UNO_QUERY );
     705         [ #  # ]:          0 :             if (xSetAlt.is())
     706                 :            :             {
     707 [ #  # ][ #  # ]:          0 :                 xSetAlt->setAlternatives( aProposals );
     708 [ #  # ][ #  # ]:          0 :                 xSetAlt->setFailureType( eFailureType );
     709                 :            :             }
     710                 :            :             else
     711                 :            :             {
     712         [ #  # ]:          0 :                 if (xRes.is())
     713                 :            :                 {
     714                 :            :                     DBG_ASSERT( 0, "XSetSpellAlternatives not implemented!" );
     715                 :            :                 }
     716         [ #  # ]:          0 :                 else if (aProposals.getLength() > 0)
     717                 :            :                 {
     718                 :            :                     // no xRes but Proposals found from the user-dictionaries.
     719                 :            :                     // Thus we need to create an xRes...
     720                 :            :                     xRes = new linguistic::SpellAlternatives( rWord, nLanguage,
     721 [ #  # ][ #  # ]:          0 :                             SpellFailure::IS_NEGATIVE_WORD, aProposals );
                 [ #  # ]
     722                 :            :                 }
     723         [ #  # ]:          0 :             }
     724         [ #  # ]:          0 :         }
     725                 :            :     }
     726                 :            : 
     727         [ #  # ]:          0 :     return xRes;
     728                 :            : }
     729                 :            : 
     730                 :          0 : uno::Sequence< sal_Int16 > SAL_CALL SpellCheckerDispatcher::getLanguages(  )
     731                 :            : throw (uno::RuntimeException)
     732                 :            : {
     733 [ #  # ][ #  # ]:          0 :     MutexGuard  aGuard( GetLinguMutex() );
     734         [ #  # ]:          0 :     uno::Sequence< Locale > aTmp( getLocales() );
     735         [ #  # ]:          0 :     uno::Sequence< sal_Int16 > aRes( LocaleSeqToLangSeq( aTmp ) );
     736 [ #  # ][ #  # ]:          0 :     return aRes;
     737                 :            : }
     738                 :            : 
     739                 :            : 
     740                 :      29241 : sal_Bool SAL_CALL SpellCheckerDispatcher::hasLanguage(
     741                 :            :     sal_Int16 nLanguage )
     742                 :            : throw (uno::RuntimeException)
     743                 :            : {
     744 [ +  - ][ +  - ]:      29241 :     MutexGuard  aGuard( GetLinguMutex() );
     745         [ +  - ]:      29241 :     Locale aLocale( CreateLocale( nLanguage ) );
     746 [ +  - ][ +  - ]:      29241 :     return hasLocale( aLocale );
     747                 :            : }
     748                 :            : 
     749                 :            : 
     750                 :      32229 : sal_Bool SAL_CALL SpellCheckerDispatcher::isValid(
     751                 :            :     const OUString& rWord,
     752                 :            :     sal_Int16 nLanguage,
     753                 :            :     const uno::Sequence< beans::PropertyValue >& rProperties )
     754                 :            : throw (lang::IllegalArgumentException, uno::RuntimeException)
     755                 :            : {
     756 [ +  - ][ +  - ]:      32229 :     MutexGuard  aGuard( GetLinguMutex() );
     757         [ +  - ]:      32229 :     Locale aLocale( CreateLocale( nLanguage ) );
     758 [ +  - ][ +  - ]:      32229 :     return isValid( rWord, aLocale, rProperties);
     759                 :            : }
     760                 :            : 
     761                 :            : 
     762                 :          0 : uno::Reference< linguistic2::XSpellAlternatives > SAL_CALL SpellCheckerDispatcher::spell(
     763                 :            :     const OUString& rWord,
     764                 :            :     sal_Int16 nLanguage,
     765                 :            :     const uno::Sequence< beans::PropertyValue >& rProperties )
     766                 :            : throw (lang::IllegalArgumentException, uno::RuntimeException)
     767                 :            : {
     768 [ #  # ][ #  # ]:          0 :     MutexGuard  aGuard( GetLinguMutex() );
     769         [ #  # ]:          0 :     Locale aLocale( CreateLocale( nLanguage ) );
     770 [ #  # ][ #  # ]:          0 :     return spell( rWord, aLocale, rProperties);
     771                 :            : }
     772                 :            : 
     773                 :            : 
     774                 :       2064 : void SpellCheckerDispatcher::SetServiceList( const Locale &rLocale,
     775                 :            :         const Sequence< OUString > &rSvcImplNames )
     776                 :            : {
     777 [ +  - ][ +  - ]:       2064 :     MutexGuard  aGuard( GetLinguMutex() );
     778                 :            : 
     779         [ +  + ]:       2064 :     if (pCache)
     780         [ +  - ]:         86 :         pCache->Flush();    // new services may spell differently...
     781                 :            : 
     782         [ +  - ]:       2064 :     sal_Int16 nLanguage = LocaleToLanguage( rLocale );
     783                 :            : 
     784                 :       2064 :     sal_Int32 nLen = rSvcImplNames.getLength();
     785         [ -  + ]:       2064 :     if (0 == nLen)
     786                 :            :         // remove entry
     787         [ #  # ]:          0 :         aSvcMap.erase( nLanguage );
     788                 :            :     else
     789                 :            :     {
     790                 :            :         // modify/add entry
     791         [ +  - ]:       2064 :         LangSvcEntries_Spell *pEntry = aSvcMap[ nLanguage ].get();
     792         [ +  + ]:       2064 :         if (pEntry)
     793                 :            :         {
     794         [ +  - ]:         86 :             pEntry->Clear();
     795         [ +  - ]:         86 :             pEntry->aSvcImplNames = rSvcImplNames;
     796 [ +  - ][ +  - ]:         86 :             pEntry->aSvcRefs = Sequence< Reference < XSpellChecker > > ( nLen );
                 [ +  - ]
     797                 :            :         }
     798                 :            :         else
     799                 :            :         {
     800 [ +  - ][ +  - ]:       1978 :             boost::shared_ptr< LangSvcEntries_Spell > pTmpEntry( new LangSvcEntries_Spell( rSvcImplNames ) );
                 [ +  - ]
     801 [ +  - ][ +  - ]:       1978 :             pTmpEntry->aSvcRefs = Sequence< Reference < XSpellChecker > >( nLen );
                 [ +  - ]
     802 [ +  - ][ +  - ]:       1978 :             aSvcMap[ nLanguage ] = pTmpEntry;
                 [ +  - ]
     803                 :            :         }
     804         [ +  - ]:       2064 :     }
     805                 :       2064 : }
     806                 :            : 
     807                 :            : 
     808                 :            : Sequence< OUString >
     809                 :          0 :     SpellCheckerDispatcher::GetServiceList( const Locale &rLocale ) const
     810                 :            : {
     811 [ #  # ][ #  # ]:          0 :     MutexGuard  aGuard( GetLinguMutex() );
     812                 :            : 
     813         [ #  # ]:          0 :     Sequence< OUString > aRes;
     814                 :            : 
     815                 :            :     // search for entry with that language and use data from that
     816         [ #  # ]:          0 :     sal_Int16 nLanguage = LocaleToLanguage( rLocale );
     817                 :          0 :     SpellCheckerDispatcher          *pThis = (SpellCheckerDispatcher *) this;
     818         [ #  # ]:          0 :     const SpellSvcByLangMap_t::iterator aIt( pThis->aSvcMap.find( nLanguage ) );
     819         [ #  # ]:          0 :     const LangSvcEntries_Spell      *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
     820         [ #  # ]:          0 :     if (pEntry)
     821         [ #  # ]:          0 :         aRes = pEntry->aSvcImplNames;
     822                 :            : 
     823         [ #  # ]:          0 :     return aRes;
     824                 :            : }
     825                 :            : 
     826                 :            : 
     827                 :          0 : LinguDispatcher::DspType SpellCheckerDispatcher::GetDspType() const
     828                 :            : {
     829                 :          0 :     return DSP_SPELL;
     830                 :            : }
     831                 :            : 
     832                 :          2 : void SpellCheckerDispatcher::FlushSpellCache()
     833                 :            : {
     834         [ +  - ]:          2 :     if (pCache)
     835                 :          2 :         pCache->Flush();
     836                 :          2 : }
     837                 :            : 
     838                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10