LCOV - code coverage report
Current view: top level - libreoffice/lingucomponent/source/spellcheck/spell - sspellimp.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 291 0.0 %
Date: 2012-12-27 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <com/sun/star/uno/Reference.h>
      22             : #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
      23             : 
      24             : #include <com/sun/star/linguistic2/SpellFailure.hpp>
      25             : #include <cppuhelper/factory.hxx>   // helper for factories
      26             : #include <com/sun/star/registry/XRegistryKey.hpp>
      27             : #include <tools/debug.hxx>
      28             : #include <osl/mutex.hxx>
      29             : 
      30             : #include <lingutil.hxx>
      31             : #include <hunspell.hxx>
      32             : #include <dictmgr.hxx>
      33             : #include <sspellimp.hxx>
      34             : 
      35             : #include <linguistic/lngprops.hxx>
      36             : #include <linguistic/spelldta.hxx>
      37             : #include <i18npool/languagetag.hxx>
      38             : #include <unotools/pathoptions.hxx>
      39             : #include <unotools/lingucfg.hxx>
      40             : #include <unotools/useroptions.hxx>
      41             : #include <osl/file.hxx>
      42             : #include <rtl/ustrbuf.hxx>
      43             : #include <rtl/textenc.h>
      44             : 
      45             : #include <list>
      46             : #include <set>
      47             : #include <string.h>
      48             : 
      49             : using namespace utl;
      50             : using namespace osl;
      51             : using namespace com::sun::star;
      52             : using namespace com::sun::star::beans;
      53             : using namespace com::sun::star::lang;
      54             : using namespace com::sun::star::uno;
      55             : using namespace com::sun::star::linguistic2;
      56             : using namespace linguistic;
      57             : 
      58             : using ::rtl::OUString;
      59             : using ::rtl::OUStringBuffer;
      60             : using ::rtl::OString;
      61             : 
      62             : // XML-header of SPELLML queries
      63             : #define SPELLML_HEADER "<?xml?>"
      64             : 
      65             : ///////////////////////////////////////////////////////////////////////////
      66             : 
      67           0 : SpellChecker::SpellChecker() :
      68             :     aDicts(NULL),
      69             :     aDEncs(NULL),
      70             :     aDLocs(NULL),
      71             :     aDNames(NULL),
      72             :     numdict(0),
      73           0 :     aEvtListeners(GetLinguMutex()),
      74             :     pPropHelper(NULL),
      75           0 :     bDisposing(false)
      76             : {
      77           0 : }
      78             : 
      79           0 : SpellChecker::~SpellChecker()
      80             : {
      81           0 :     if (aDicts)
      82             :     {
      83           0 :        for (int i = 0; i < numdict; ++i)
      84             :        {
      85           0 :             delete aDicts[i];
      86             :        }
      87           0 :        delete[] aDicts;
      88             :     }
      89           0 :     delete[] aDEncs;
      90           0 :     delete[] aDLocs;
      91           0 :     delete[] aDNames;
      92           0 :     if (pPropHelper)
      93             :     {
      94           0 :         pPropHelper->RemoveAsPropListener();
      95           0 :         delete pPropHelper;
      96             :     }
      97           0 : }
      98             : 
      99           0 : PropertyHelper_Spelling & SpellChecker::GetPropHelper_Impl()
     100             : {
     101           0 :     if (!pPropHelper)
     102             :     {
     103           0 :         Reference< XPropertySet >   xPropSet( GetLinguProperties(), UNO_QUERY );
     104             : 
     105           0 :         pPropHelper = new PropertyHelper_Spelling( (XSpellChecker *) this, xPropSet );
     106           0 :         pPropHelper->AddAsPropListener();   //! after a reference is established
     107             :     }
     108           0 :     return *pPropHelper;
     109             : }
     110             : 
     111             : 
     112           0 : Sequence< Locale > SAL_CALL SpellChecker::getLocales()
     113             :         throw(RuntimeException)
     114             : {
     115           0 :     MutexGuard  aGuard( GetLinguMutex() );
     116             : 
     117             :     // this routine should return the locales supported by the installed
     118             :     // dictionaries.
     119             : 
     120           0 :     if (!numdict)
     121             :     {
     122           0 :         SvtLinguConfig aLinguCfg;
     123             : 
     124             :         // get list of extension dictionaries-to-use
     125             :         // (or better speaking: the list of dictionaries using the
     126             :         // new configuration entries).
     127           0 :         std::list< SvtLinguConfigDictionaryEntry > aDics;
     128           0 :         uno::Sequence< rtl::OUString > aFormatList;
     129             :         aLinguCfg.GetSupportedDictionaryFormatsFor( A2OU("SpellCheckers"),
     130           0 :                 A2OU("org.openoffice.lingu.MySpellSpellChecker"), aFormatList );
     131           0 :         sal_Int32 nLen = aFormatList.getLength();
     132           0 :         for (sal_Int32 i = 0;  i < nLen;  ++i)
     133             :         {
     134             :             std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
     135           0 :                     aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) );
     136           0 :             aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
     137           0 :         }
     138             : 
     139             :         //!! for compatibility with old dictionaries (the ones not using extensions
     140             :         //!! or new configuration entries, but still using the dictionary.lst file)
     141             :         //!! Get the list of old style spell checking dictionaries to use...
     142             :         std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
     143           0 :                 GetOldStyleDics( "DICT" ) );
     144             : 
     145             :         // to prefer dictionaries with configuration entries we will only
     146             :         // use those old style dictionaries that add a language that
     147             :         // is not yet supported by the list od new style dictionaries
     148           0 :         MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
     149             : 
     150           0 :         if (!aDics.empty())
     151             :         {
     152             :             // get supported locales from the dictionaries-to-use...
     153           0 :             sal_Int32 k = 0;
     154           0 :             std::set< rtl::OUString, lt_rtl_OUString > aLocaleNamesSet;
     155           0 :             std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt;
     156           0 :             for (aDictIt = aDics.begin();  aDictIt != aDics.end();  ++aDictIt)
     157             :             {
     158           0 :                 uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
     159           0 :                 sal_Int32 nLen2 = aLocaleNames.getLength();
     160           0 :                 for (k = 0;  k < nLen2;  ++k)
     161             :                 {
     162           0 :                     aLocaleNamesSet.insert( aLocaleNames[k] );
     163             :                 }
     164           0 :             }
     165             :             // ... and add them to the resulting sequence
     166           0 :             aSuppLocales.realloc( aLocaleNamesSet.size() );
     167           0 :             std::set< rtl::OUString, lt_rtl_OUString >::const_iterator aItB;
     168           0 :             k = 0;
     169           0 :             for (aItB = aLocaleNamesSet.begin();  aItB != aLocaleNamesSet.end();  ++aItB)
     170             :             {
     171           0 :                 Locale aTmp( LanguageTag( *aItB ).getLocale());
     172           0 :                 aSuppLocales[k++] = aTmp;
     173           0 :             }
     174             : 
     175             :             //! For each dictionary and each locale we need a seperate entry.
     176             :             //! If this results in more than one dictionary per locale than (for now)
     177             :             //! it is undefined which dictionary gets used.
     178             :             //! In the future the implementation should support using several dictionaries
     179             :             //! for one locale.
     180           0 :             numdict = 0;
     181           0 :             for (aDictIt = aDics.begin();  aDictIt != aDics.end();  ++aDictIt)
     182           0 :                 numdict = numdict + aDictIt->aLocaleNames.getLength();
     183             : 
     184             :             // add dictionary information
     185           0 :             aDicts  = new Hunspell* [numdict];
     186           0 :             aDEncs  = new rtl_TextEncoding [numdict];
     187           0 :             aDLocs  = new Locale [numdict];
     188           0 :             aDNames = new OUString [numdict];
     189           0 :             k = 0;
     190           0 :             for (aDictIt = aDics.begin();  aDictIt != aDics.end();  ++aDictIt)
     191             :             {
     192           0 :                 if (aDictIt->aLocaleNames.getLength() > 0 &&
     193           0 :                     aDictIt->aLocations.getLength() > 0)
     194             :                 {
     195           0 :                     uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
     196           0 :                     sal_Int32 nLocales = aLocaleNames.getLength();
     197             : 
     198             :                     // currently only one language per dictionary is supported in the actual implementation...
     199             :                     // Thus here we work-around this by adding the same dictionary several times.
     200             :                     // Once for each of it's supported locales.
     201           0 :                     for (sal_Int32 i = 0;  i < nLocales;  ++i)
     202             :                     {
     203           0 :                         aDicts[k]  = NULL;
     204           0 :                         aDEncs[k]  = RTL_TEXTENCODING_DONTKNOW;
     205           0 :                         aDLocs[k]  = LanguageTag( aLocaleNames[i] ).getLocale();
     206             :                         // also both files have to be in the same directory and the
     207             :                         // file names must only differ in the extension (.aff/.dic).
     208             :                         // Thus we use the first location only and strip the extension part.
     209           0 :                         rtl::OUString aLocation = aDictIt->aLocations[0];
     210           0 :                         sal_Int32 nPos = aLocation.lastIndexOf( '.' );
     211           0 :                         aLocation = aLocation.copy( 0, nPos );
     212           0 :                         aDNames[k] = aLocation;
     213             : 
     214           0 :                         ++k;
     215           0 :                     }
     216             :                 }
     217             :             }
     218           0 :             DBG_ASSERT( k == numdict, "index mismatch?" );
     219             :         }
     220             :         else
     221             :         {
     222             :             /* no dictionary found so register no dictionaries */
     223           0 :             numdict = 0;
     224           0 :             delete[] aDicts;
     225           0 :             aDicts  = NULL;
     226           0 :             delete[] aDEncs;
     227           0 :             aDEncs = NULL;
     228           0 :             delete[] aDLocs;
     229           0 :             aDLocs  = NULL;
     230           0 :             delete[] aDNames;
     231           0 :             aDNames = NULL;
     232           0 :             aSuppLocales.realloc(0);
     233           0 :         }
     234             :     }
     235             : 
     236           0 :     return aSuppLocales;
     237             : }
     238             : 
     239             : 
     240           0 : sal_Bool SAL_CALL SpellChecker::hasLocale(const Locale& rLocale)
     241             :         throw(RuntimeException)
     242             : {
     243           0 :     MutexGuard  aGuard( GetLinguMutex() );
     244             : 
     245           0 :     sal_Bool bRes = sal_False;
     246           0 :     if (!aSuppLocales.getLength())
     247           0 :         getLocales();
     248             : 
     249           0 :     sal_Int32 nLen = aSuppLocales.getLength();
     250           0 :     for (sal_Int32 i = 0;  i < nLen;  ++i)
     251             :     {
     252           0 :         const Locale *pLocale = aSuppLocales.getConstArray();
     253           0 :         if (rLocale == pLocale[i])
     254             :         {
     255           0 :             bRes = sal_True;
     256           0 :             break;
     257             :         }
     258             :     }
     259           0 :     return bRes;
     260             : }
     261             : 
     262             : 
     263           0 : sal_Int16 SpellChecker::GetSpellFailure( const OUString &rWord, const Locale &rLocale )
     264             : {
     265           0 :     Hunspell * pMS = NULL;
     266           0 :     rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
     267             : 
     268             :     // initialize a myspell object for each dictionary once
     269             :     // (note: mutex is held higher up in isValid)
     270             : 
     271           0 :     sal_Int16 nRes = -1;
     272             : 
     273             :     // first handle smart quotes both single and double
     274           0 :     OUStringBuffer rBuf(rWord);
     275           0 :     sal_Int32 n = rBuf.getLength();
     276             :     sal_Unicode c;
     277           0 :     for (sal_Int32 ix=0; ix < n; ix++)
     278             :     {
     279           0 :         c = rBuf[ix];
     280           0 :         if ((c == 0x201C) || (c == 0x201D))
     281           0 :             rBuf[ix] = (sal_Unicode)0x0022;
     282           0 :         if ((c == 0x2018) || (c == 0x2019))
     283           0 :             rBuf[ix] = (sal_Unicode)0x0027;
     284             :     }
     285           0 :     OUString nWord(rBuf.makeStringAndClear());
     286             : 
     287           0 :     if (n)
     288             :     {
     289           0 :         for (sal_Int32 i = 0; i < numdict; ++i)
     290             :         {
     291           0 :             pMS = NULL;
     292           0 :             eEnc = RTL_TEXTENCODING_DONTKNOW;
     293             : 
     294           0 :             if (rLocale == aDLocs[i])
     295             :             {
     296           0 :                 if (!aDicts[i])
     297             :                 {
     298           0 :                     OUString dicpath = aDNames[i] + A2OU(".dic");
     299           0 :                     OUString affpath = aDNames[i] + A2OU(".aff");
     300           0 :                     OUString dict;
     301           0 :                     OUString aff;
     302           0 :                     osl::FileBase::getSystemPathFromFileURL(dicpath,dict);
     303           0 :                     osl::FileBase::getSystemPathFromFileURL(affpath,aff);
     304           0 :                     OString aTmpaff(OU2ENC(aff,osl_getThreadTextEncoding()));
     305           0 :                     OString aTmpdict(OU2ENC(dict,osl_getThreadTextEncoding()));
     306             : 
     307             : #if defined(WNT)
     308             :                     // workaround for Windows specifc problem that the
     309             :                     // path length in calls to 'fopen' is limted to somewhat
     310             :                     // about 120+ characters which will usually be exceed when
     311             :                     // using dictionaries as extensions.
     312             :                     aTmpaff = Win_GetShortPathName( aff );
     313             :                     aTmpdict = Win_GetShortPathName( dict );
     314             : #endif
     315             : 
     316           0 :                     aDicts[i] = new Hunspell(aTmpaff.getStr(),aTmpdict.getStr());
     317           0 :                     aDEncs[i] = RTL_TEXTENCODING_DONTKNOW;
     318           0 :                     if (aDicts[i])
     319           0 :                         aDEncs[i] = getTextEncodingFromCharset(aDicts[i]->get_dic_encoding());
     320             :                 }
     321           0 :                 pMS = aDicts[i];
     322           0 :                 eEnc = aDEncs[i];
     323             :             }
     324             : 
     325           0 :             if (pMS)
     326             :             {
     327             :                 // we don't want to work with a default text encoding since following incorrect
     328             :                 // results may occur only for specific text and thus may be hard to notice.
     329             :                 // Thus better always make a clean exit here if the text encoding is in question.
     330             :                 // Hopefully something not working at all will raise proper attention quickly. ;-)
     331             :                 DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
     332           0 :                 if (eEnc == RTL_TEXTENCODING_DONTKNOW)
     333           0 :                     return -1;
     334             : 
     335           0 :                 OString aWrd(OU2ENC(nWord,eEnc));
     336           0 :                 int rVal = pMS->spell((char*)aWrd.getStr());
     337           0 :                 if (rVal != 1)
     338           0 :                     nRes = SpellFailure::SPELLING_ERROR;
     339             :                 else
     340           0 :                     return -1;
     341           0 :                 pMS = NULL;
     342             :             }
     343             :         }
     344             :     }
     345             : 
     346           0 :     return nRes;
     347             : }
     348             : 
     349             : 
     350           0 : sal_Bool SAL_CALL SpellChecker::isValid( const OUString& rWord, const Locale& rLocale,
     351             :             const PropertyValues& rProperties )
     352             :         throw(IllegalArgumentException, RuntimeException)
     353             : {
     354           0 :     MutexGuard  aGuard( GetLinguMutex() );
     355             : 
     356           0 :      if (rLocale == Locale()  ||  rWord.isEmpty())
     357           0 :         return sal_True;
     358             : 
     359           0 :     if (!hasLocale( rLocale ))
     360           0 :         return sal_True;
     361             : 
     362             :     // return sal_False to process SPELLML requests (they are longer than the header)
     363           0 :     if (rWord.match(A2OU(SPELLML_HEADER), 0) && (rWord.getLength() > 10)) return sal_False;
     364             : 
     365             :     // Get property values to be used.
     366             :     // These are be the default values set in the SN_LINGU_PROPERTIES
     367             :     // PropertySet which are overridden by the supplied ones from the
     368             :     // last argument.
     369             :     // You'll probably like to use a simplier solution than the provided
     370             :     // one using the PropertyHelper_Spell.
     371             : 
     372           0 :     PropertyHelper_Spelling& rHelper = GetPropHelper();
     373           0 :     rHelper.SetTmpPropVals( rProperties );
     374             : 
     375           0 :     sal_Int16 nFailure = GetSpellFailure( rWord, rLocale );
     376           0 :     if (nFailure != -1 && !rWord.match(A2OU(SPELLML_HEADER), 0))
     377             :     {
     378           0 :         sal_Int16 nLang = LanguageTag( rLocale ).getLanguageType();
     379             :         // postprocess result for errors that should be ignored
     380             :         const bool bIgnoreError =
     381           0 :                 (!rHelper.IsSpellUpperCase()  && IsUpper( rWord, nLang )) ||
     382           0 :                 (!rHelper.IsSpellWithDigits() && HasDigits( rWord )) ||
     383           0 :                 (!rHelper.IsSpellCapitalization()  &&  nFailure == SpellFailure::CAPTION_ERROR);
     384           0 :         if (bIgnoreError)
     385           0 :             nFailure = -1;
     386             :     }
     387             : 
     388           0 :     return (nFailure == -1);
     389             : }
     390             : 
     391             : 
     392             : Reference< XSpellAlternatives >
     393           0 :     SpellChecker::GetProposals( const OUString &rWord, const Locale &rLocale )
     394             : {
     395             :     // Retrieves the return values for the 'spell' function call in case
     396             :     // of a misspelled word.
     397             :     // Especially it may give a list of suggested (correct) words:
     398             : 
     399           0 :     Reference< XSpellAlternatives > xRes;
     400             :     // note: mutex is held by higher up by spell which covers both
     401             : 
     402           0 :     Hunspell* pMS = NULL;
     403           0 :     rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
     404             : 
     405             :     // first handle smart quotes (single and double)
     406           0 :     OUStringBuffer rBuf(rWord);
     407           0 :     sal_Int32 n = rBuf.getLength();
     408             :     sal_Unicode c;
     409           0 :     for (sal_Int32 ix=0; ix < n; ix++)
     410             :     {
     411           0 :         c = rBuf[ix];
     412           0 :         if ((c == 0x201C) || (c == 0x201D))
     413           0 :             rBuf[ix] = (sal_Unicode)0x0022;
     414           0 :         if ((c == 0x2018) || (c == 0x2019))
     415           0 :             rBuf[ix] = (sal_Unicode)0x0027;
     416             :     }
     417           0 :     OUString nWord(rBuf.makeStringAndClear());
     418             : 
     419           0 :     if (n)
     420             :     {
     421           0 :         sal_Int16 nLang = LanguageTag( rLocale ).getLanguageType();
     422           0 :         int numsug = 0;
     423             : 
     424           0 :         Sequence< OUString > aStr( 0 );
     425           0 :         for (int i = 0; i < numdict; i++)
     426             :         {
     427           0 :             pMS = NULL;
     428           0 :             eEnc = RTL_TEXTENCODING_DONTKNOW;
     429             : 
     430           0 :             if (rLocale == aDLocs[i])
     431             :             {
     432           0 :                 pMS = aDicts[i];
     433           0 :                 eEnc = aDEncs[i];
     434             :             }
     435             : 
     436           0 :             if (pMS)
     437             :             {
     438           0 :                 char ** suglst = NULL;
     439           0 :                 OString aWrd(OU2ENC(nWord,eEnc));
     440           0 :                 int count = pMS->suggest(&suglst, (const char *) aWrd.getStr());
     441             : 
     442           0 :                 if (count)
     443             :                 {
     444           0 :                     aStr.realloc( numsug + count );
     445           0 :                     OUString *pStr = aStr.getArray();
     446           0 :                     for (int ii=0; ii < count; ++ii)
     447             :                     {
     448           0 :                         OUString cvtwrd(suglst[ii],strlen(suglst[ii]),eEnc);
     449           0 :                         pStr[numsug + ii] = cvtwrd;
     450           0 :                     }
     451           0 :                     pMS->free_list(&suglst, count);
     452           0 :                     numsug += count;
     453           0 :                 }
     454             :             }
     455             :         }
     456             : 
     457             :         // now return an empty alternative for no suggestions or the list of alternatives if some found
     458           0 :         String aTmp(rWord);
     459           0 :         xRes = SpellAlternatives::CreateSpellAlternatives( aTmp, nLang, SpellFailure::SPELLING_ERROR, aStr );
     460           0 :         return xRes;
     461             :     }
     462           0 :     return xRes;
     463             : }
     464             : 
     465             : 
     466           0 : Reference< XSpellAlternatives > SAL_CALL SpellChecker::spell(
     467             :         const OUString& rWord, const Locale& rLocale,
     468             :         const PropertyValues& rProperties )
     469             :         throw(IllegalArgumentException, RuntimeException)
     470             : {
     471           0 :     MutexGuard  aGuard( GetLinguMutex() );
     472             : 
     473           0 :      if (rLocale == Locale()  ||  rWord.isEmpty())
     474           0 :         return NULL;
     475             : 
     476           0 :     if (!hasLocale( rLocale ))
     477           0 :         return NULL;
     478             : 
     479           0 :     Reference< XSpellAlternatives > xAlt;
     480           0 :     if (!isValid( rWord, rLocale, rProperties ))
     481             :     {
     482           0 :         xAlt =  GetProposals( rWord, rLocale );
     483             :     }
     484           0 :     return xAlt;
     485             : }
     486             : 
     487             : 
     488           0 : Reference< XInterface > SAL_CALL SpellChecker_CreateInstance(
     489             :         const Reference< XMultiServiceFactory > & /*rSMgr*/ )
     490             :         throw(Exception)
     491             : {
     492             : 
     493           0 :     Reference< XInterface > xService = (cppu::OWeakObject*) new SpellChecker;
     494           0 :     return xService;
     495             : }
     496             : 
     497             : 
     498           0 : sal_Bool SAL_CALL SpellChecker::addLinguServiceEventListener(
     499             :         const Reference< XLinguServiceEventListener >& rxLstnr )
     500             :         throw(RuntimeException)
     501             : {
     502           0 :     MutexGuard  aGuard( GetLinguMutex() );
     503             : 
     504           0 :     sal_Bool bRes = sal_False;
     505           0 :     if (!bDisposing && rxLstnr.is())
     506             :     {
     507           0 :         bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr );
     508             :     }
     509           0 :     return bRes;
     510             : }
     511             : 
     512             : 
     513           0 : sal_Bool SAL_CALL SpellChecker::removeLinguServiceEventListener(
     514             :         const Reference< XLinguServiceEventListener >& rxLstnr )
     515             :         throw(RuntimeException)
     516             : {
     517           0 :     MutexGuard  aGuard( GetLinguMutex() );
     518             : 
     519           0 :     sal_Bool bRes = sal_False;
     520           0 :     if (!bDisposing && rxLstnr.is())
     521             :     {
     522           0 :         bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr );
     523             :     }
     524           0 :     return bRes;
     525             : }
     526             : 
     527             : 
     528           0 : OUString SAL_CALL SpellChecker::getServiceDisplayName( const Locale& /*rLocale*/ )
     529             :         throw(RuntimeException)
     530             : {
     531           0 :     MutexGuard  aGuard( GetLinguMutex() );
     532           0 :     return A2OU( "Hunspell SpellChecker" );
     533             : }
     534             : 
     535             : 
     536           0 : void SAL_CALL SpellChecker::initialize( const Sequence< Any >& rArguments )
     537             :         throw(Exception, RuntimeException)
     538             : {
     539           0 :     MutexGuard  aGuard( GetLinguMutex() );
     540             : 
     541           0 :     if (!pPropHelper)
     542             :     {
     543           0 :         sal_Int32 nLen = rArguments.getLength();
     544           0 :         if (2 == nLen)
     545             :         {
     546           0 :             Reference< XPropertySet >   xPropSet;
     547           0 :             rArguments.getConstArray()[0] >>= xPropSet;
     548             :             //rArguments.getConstArray()[1] >>= xDicList;
     549             : 
     550             :             //! Pointer allows for access of the non-UNO functions.
     551             :             //! And the reference to the UNO-functions while increasing
     552             :             //! the ref-count and will implicitly free the memory
     553             :             //! when the object is not longer used.
     554           0 :             pPropHelper = new PropertyHelper_Spelling( (XSpellChecker *) this, xPropSet );
     555           0 :             pPropHelper->AddAsPropListener();   //! after a reference is established
     556             :         }
     557             :         else {
     558             :             OSL_FAIL( "wrong number of arguments in sequence" );
     559             :         }
     560           0 :     }
     561           0 : }
     562             : 
     563             : 
     564           0 : void SAL_CALL SpellChecker::dispose()
     565             :         throw(RuntimeException)
     566             : {
     567           0 :     MutexGuard  aGuard( GetLinguMutex() );
     568             : 
     569           0 :     if (!bDisposing)
     570             :     {
     571           0 :         bDisposing = true;
     572           0 :         EventObject aEvtObj( (XSpellChecker *) this );
     573           0 :         aEvtListeners.disposeAndClear( aEvtObj );
     574           0 :         if (pPropHelper)
     575             :         {
     576           0 :             pPropHelper->RemoveAsPropListener();
     577           0 :             delete pPropHelper;
     578           0 :             pPropHelper = NULL;
     579           0 :         }
     580           0 :     }
     581           0 : }
     582             : 
     583             : 
     584           0 : void SAL_CALL SpellChecker::addEventListener( const Reference< XEventListener >& rxListener )
     585             :         throw(RuntimeException)
     586             : {
     587           0 :     MutexGuard  aGuard( GetLinguMutex() );
     588             : 
     589           0 :     if (!bDisposing && rxListener.is())
     590           0 :         aEvtListeners.addInterface( rxListener );
     591           0 : }
     592             : 
     593             : 
     594           0 : void SAL_CALL SpellChecker::removeEventListener( const Reference< XEventListener >& rxListener )
     595             :         throw(RuntimeException)
     596             : {
     597           0 :     MutexGuard  aGuard( GetLinguMutex() );
     598             : 
     599           0 :     if (!bDisposing && rxListener.is())
     600           0 :         aEvtListeners.removeInterface( rxListener );
     601           0 : }
     602             : 
     603             : 
     604             : ///////////////////////////////////////////////////////////////////////////
     605             : // Service specific part
     606             : //
     607             : 
     608           0 : OUString SAL_CALL SpellChecker::getImplementationName()
     609             :         throw(RuntimeException)
     610             : {
     611           0 :     MutexGuard  aGuard( GetLinguMutex() );
     612             : 
     613           0 :     return getImplementationName_Static();
     614             : }
     615             : 
     616             : 
     617           0 : sal_Bool SAL_CALL SpellChecker::supportsService( const OUString& ServiceName )
     618             :         throw(RuntimeException)
     619             : {
     620           0 :     MutexGuard  aGuard( GetLinguMutex() );
     621             : 
     622           0 :     Sequence< OUString > aSNL = getSupportedServiceNames();
     623           0 :     const OUString * pArray = aSNL.getConstArray();
     624           0 :     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
     625           0 :         if( pArray[i] == ServiceName )
     626           0 :             return sal_True;
     627           0 :     return sal_False;
     628             : }
     629             : 
     630             : 
     631           0 : Sequence< OUString > SAL_CALL SpellChecker::getSupportedServiceNames()
     632             :         throw(RuntimeException)
     633             : {
     634           0 :     MutexGuard  aGuard( GetLinguMutex() );
     635             : 
     636           0 :     return getSupportedServiceNames_Static();
     637             : }
     638             : 
     639             : 
     640           0 : Sequence< OUString > SpellChecker::getSupportedServiceNames_Static()
     641             :         throw()
     642             : {
     643           0 :     MutexGuard  aGuard( GetLinguMutex() );
     644             : 
     645           0 :     Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich
     646           0 :     aSNS.getArray()[0] = A2OU( SN_SPELLCHECKER );
     647           0 :     return aSNS;
     648             : }
     649             : 
     650           0 : void * SAL_CALL SpellChecker_getFactory( const sal_Char * pImplName,
     651             :             XMultiServiceFactory * pServiceManager, void *  )
     652             : {
     653           0 :     void * pRet = 0;
     654           0 :     if ( !SpellChecker::getImplementationName_Static().compareToAscii( pImplName ) )
     655             :     {
     656             :         Reference< XSingleServiceFactory > xFactory =
     657             :             cppu::createOneInstanceFactory(
     658             :                 pServiceManager,
     659             :                 SpellChecker::getImplementationName_Static(),
     660             :                 SpellChecker_CreateInstance,
     661           0 :                 SpellChecker::getSupportedServiceNames_Static());
     662             :         // acquire, because we return an interface pointer instead of a reference
     663           0 :         xFactory->acquire();
     664           0 :         pRet = xFactory.get();
     665             :     }
     666           0 :     return pRet;
     667             : }
     668             : 
     669             : 
     670             : ///////////////////////////////////////////////////////////////////////////
     671             : 
     672             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10