LCOV - code coverage report
Current view: top level - linguistic/source - hyphdsp.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 87 331 26.3 %
Date: 2015-06-13 12:38:46 Functions: 7 14 50.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             : #include <cppuhelper/factory.hxx>
      21             : #include <com/sun/star/registry/XRegistryKey.hpp>
      22             : #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
      23             : #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
      24             : #include <rtl/ustrbuf.hxx>
      25             : #include <i18nlangtag/lang.h>
      26             : #include <unotools/localedatawrapper.hxx>
      27             : #include <tools/debug.hxx>
      28             : #include <svl/lngmisc.hxx>
      29             : #include <comphelper/processfactory.hxx>
      30             : #include <osl/mutex.hxx>
      31             : 
      32             : #include "hyphdsp.hxx"
      33             : #include "linguistic/hyphdta.hxx"
      34             : #include "linguistic/lngprops.hxx"
      35             : #include "lngsvcmgr.hxx"
      36             : 
      37             : using namespace osl;
      38             : using namespace com::sun::star;
      39             : using namespace com::sun::star::beans;
      40             : using namespace com::sun::star::lang;
      41             : using namespace com::sun::star::uno;
      42             : using namespace com::sun::star::linguistic2;
      43             : using namespace linguistic;
      44             : 
      45             : 
      46             : 
      47          74 : HyphenatorDispatcher::HyphenatorDispatcher( LngSvcMgr &rLngSvcMgr ) :
      48          74 :     rMgr    (rLngSvcMgr)
      49             : {
      50          74 : }
      51             : 
      52             : 
      53         207 : HyphenatorDispatcher::~HyphenatorDispatcher()
      54             : {
      55          69 :     ClearSvcList();
      56         138 : }
      57             : 
      58             : 
      59          69 : void HyphenatorDispatcher::ClearSvcList()
      60             : {
      61             :     // release memory for each table entry
      62          69 :     HyphSvcByLangMap_t aTmp;
      63          69 :     aSvcMap.swap( aTmp );
      64          69 : }
      65             : 
      66             : 
      67           0 : Reference<XHyphenatedWord>  HyphenatorDispatcher::buildHyphWord(
      68             :             const OUString& rOrigWord,
      69             :             const Reference<XDictionaryEntry> &xEntry,
      70             :             sal_Int16 nLang, sal_Int16 nMaxLeading )
      71             : {
      72           0 :     MutexGuard  aGuard( GetLinguMutex() );
      73             : 
      74           0 :     Reference< XHyphenatedWord > xRes;
      75             : 
      76           0 :     if (xEntry.is())
      77             :     {
      78           0 :         OUString aText( xEntry->getDictionaryWord() );
      79           0 :         sal_Int32 nTextLen = aText.getLength();
      80             : 
      81             :         // trailing '=' means "hyphenation should not be possible"
      82           0 :         if (nTextLen > 0  &&  aText[ nTextLen - 1 ] != '=' && aText[ nTextLen - 1 ] != '[')
      83             :         {
      84           0 :             sal_Int16 nHyphenationPos = -1;
      85           0 :             sal_Int32 nHyphenPos = -1;
      86           0 :             sal_Int16 nOrigHyphPos = -1;
      87             : 
      88           0 :             OUStringBuffer aTmp( nTextLen );
      89           0 :             bool  bSkip = false;
      90           0 :             bool  bSkip2 = false;
      91           0 :             sal_Int32 nHyphIdx = -1;
      92           0 :             sal_Int32 nLeading = 0;
      93           0 :             for (sal_Int32 i = 0;  i < nTextLen;  i++)
      94             :             {
      95           0 :                 sal_Unicode cTmp = aText[i];
      96           0 :                 if (cTmp == '[' || cTmp == ']')
      97           0 :                     bSkip2 = !bSkip2;
      98           0 :                 if (cTmp != '=' && !bSkip2 && cTmp != ']')
      99             :                 {
     100           0 :                     aTmp.append( cTmp );
     101           0 :                     nLeading++;
     102           0 :                     bSkip = false;
     103           0 :                     nHyphIdx++;
     104             :                 }
     105             :                 else
     106             :                 {
     107           0 :                     if (!bSkip  &&  nHyphIdx >= 0)
     108             :                     {
     109           0 :                         if (nLeading <= nMaxLeading) {
     110           0 :                             nHyphenationPos = (sal_Int16) nHyphIdx;
     111           0 :                             nOrigHyphPos = i;
     112             :                         }
     113             :                     }
     114           0 :                     bSkip = true;   //! multiple '=' should count as one only
     115             :                 }
     116             :             }
     117             : 
     118           0 :             if (nHyphenationPos > 0)
     119             :             {
     120             : 
     121             : #if OSL_DEBUG_LEVEL > 1
     122             :                 {
     123             :                     if (aTmp.toString() != rOrigWord)
     124             :                     {
     125             :                         // both words should only differ by a having a trailing '.'
     126             :                         // character or not...
     127             :                         OUString aShorter, aLonger;
     128             :                         if (aTmp.getLength() <= rOrigWord.getLength())
     129             :                         {
     130             :                             aShorter = aTmp.toString();
     131             :                             aLonger  = rOrigWord;
     132             :                         }
     133             :                         else
     134             :                         {
     135             :                             aShorter = rOrigWord;
     136             :                             aLonger  = aTmp.toString();
     137             :                         }
     138             :                         sal_Int32 nS = aShorter.getLength();
     139             :                         sal_Int32 nL = aLonger.getLength();
     140             :                         if (nS > 0 && nL > 0)
     141             :                         {
     142             :                             DBG_ASSERT( (nS + 1 == nL) && aLonger[nL-1] == '.',
     143             :                                 "HyphenatorDispatcher::buildHyphWord: unexpected difference between words!" );
     144             :                         }
     145             :                     }
     146             :                 }
     147             : #endif
     148           0 :                 if (aText[ nOrigHyphPos ] == '[')  // alternative hyphenation
     149             :                 {
     150           0 :                     sal_Int16 split = 0;
     151           0 :                     sal_Unicode c = aText [ nOrigHyphPos + 1 ];
     152           0 :                     sal_Int32 endhyphpat = aText.indexOf( ']', nOrigHyphPos );
     153           0 :                     if ('0' <= c && c <= '9')
     154             :                     {
     155           0 :                         split = c - '0';
     156           0 :                         nOrigHyphPos++;
     157             :                     }
     158           0 :                     if (endhyphpat > -1)
     159             :                     {
     160           0 :                         OUStringBuffer aTmp2 ( aTmp.copy(0, std::max (nHyphenationPos + 1 - split, 0) ) );
     161           0 :                         aTmp2.append( aText.copy( nOrigHyphPos + 1, endhyphpat - nOrigHyphPos - 1) );
     162           0 :                         nHyphenPos = aTmp2.getLength();
     163           0 :                         aTmp2.append( aTmp.copy( nHyphenationPos + 1 ) );
     164             :                         //! take care of #i22591#
     165           0 :                         if (rOrigWord[ rOrigWord.getLength() - 1 ] == '.')
     166           0 :                             aTmp2.append( '.' );
     167           0 :                         aText = aTmp2.makeStringAndClear();
     168             :                     }
     169             :                 }
     170           0 :                 if (nHyphenPos == -1)
     171           0 :                     aText = rOrigWord;
     172             : 
     173           0 :                 xRes = new HyphenatedWord( rOrigWord, nLang, nHyphenationPos,
     174           0 :                                 aText, (nHyphenPos > -1) ? nHyphenPos - 1 : nHyphenationPos);
     175           0 :             }
     176           0 :         }
     177             :     }
     178             : 
     179           0 :     return xRes;
     180             : }
     181             : 
     182             : 
     183           0 : Reference< XPossibleHyphens > HyphenatorDispatcher::buildPossHyphens(
     184             :             const Reference< XDictionaryEntry > &xEntry, sal_Int16 nLanguage )
     185             : {
     186           0 :     MutexGuard  aGuard( GetLinguMutex() );
     187             : 
     188           0 :     Reference<XPossibleHyphens> xRes;
     189             : 
     190           0 :     if (xEntry.is())
     191             :     {
     192             :         // text with hyphenation info
     193           0 :         OUString aText( xEntry->getDictionaryWord() );
     194           0 :         sal_Int32 nTextLen = aText.getLength();
     195             : 
     196             :         // trailing '=' means "hyphenation should not be possible"
     197           0 :         if (nTextLen > 0  &&  aText[ nTextLen - 1 ] != '=' && aText[ nTextLen - 1 ] != '[')
     198             :         {
     199             :             // sequence to hold hyphenation positions
     200           0 :             Sequence< sal_Int16 > aHyphPos( nTextLen );
     201           0 :             sal_Int16 *pPos = aHyphPos.getArray();
     202           0 :             sal_Int32 nHyphCount = 0;
     203             : 
     204           0 :             OUStringBuffer aTmp( nTextLen );
     205           0 :             bool  bSkip = false;
     206           0 :             bool  bSkip2 = false;
     207           0 :             sal_Int32 nHyphIdx = -1;
     208           0 :             for (sal_Int32 i = 0;  i < nTextLen;  i++)
     209             :             {
     210           0 :                 sal_Unicode cTmp = aText[i];
     211           0 :                 if (cTmp == '[' || cTmp == ']')
     212           0 :                     bSkip2 = !bSkip2;
     213           0 :                 if (cTmp != '=' && !bSkip2 && cTmp != ']')
     214             :                 {
     215           0 :                     aTmp.append( cTmp );
     216           0 :                     bSkip = false;
     217           0 :                     nHyphIdx++;
     218             :                 }
     219             :                 else
     220             :                 {
     221           0 :                     if (!bSkip  &&  nHyphIdx >= 0)
     222           0 :                         pPos[ nHyphCount++ ] = (sal_Int16) nHyphIdx;
     223           0 :                     bSkip = true;   //! multiple '=' should count as one only
     224             :                 }
     225             :             }
     226             : 
     227             :             // ignore (multiple) trailing '='
     228           0 :             if (bSkip  &&  nHyphIdx >= 0)
     229             :             {
     230           0 :                 nHyphCount--;
     231             :             }
     232             :             DBG_ASSERT( nHyphCount >= 0, "lng : invalid hyphenation count");
     233             : 
     234           0 :             if (nHyphCount > 0)
     235             :             {
     236           0 :                 aHyphPos.realloc( nHyphCount );
     237           0 :                 xRes = new PossibleHyphens( aTmp.makeStringAndClear(), nLanguage,
     238           0 :                                 aText, aHyphPos );
     239           0 :             }
     240           0 :         }
     241             :     }
     242             : 
     243           0 :     return xRes;
     244             : }
     245             : 
     246             : 
     247           0 : Sequence< Locale > SAL_CALL HyphenatorDispatcher::getLocales()
     248             :         throw(RuntimeException, std::exception)
     249             : {
     250           0 :     MutexGuard  aGuard( GetLinguMutex() );
     251             : 
     252           0 :     Sequence< Locale > aLocales( static_cast< sal_Int32 >(aSvcMap.size()) );
     253           0 :     Locale *pLocales = aLocales.getArray();
     254           0 :     HyphSvcByLangMap_t::const_iterator aIt;
     255           0 :     for (aIt = aSvcMap.begin();  aIt != aSvcMap.end();  ++aIt)
     256             :     {
     257           0 :         *pLocales++ = LanguageTag::convertToLocale( aIt->first );
     258             :     }
     259           0 :     return aLocales;
     260             : }
     261             : 
     262             : 
     263          12 : sal_Bool SAL_CALL HyphenatorDispatcher::hasLocale(const Locale& rLocale)
     264             :         throw(RuntimeException, std::exception)
     265             : {
     266          12 :     MutexGuard  aGuard( GetLinguMutex() );
     267          12 :     HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LinguLocaleToLanguage( rLocale ) ) );
     268          12 :     return aIt != aSvcMap.end();
     269             : }
     270             : 
     271             : 
     272             : Reference< XHyphenatedWord > SAL_CALL
     273       25654 :     HyphenatorDispatcher::hyphenate(
     274             :             const OUString& rWord, const Locale& rLocale, sal_Int16 nMaxLeading,
     275             :             const PropertyValues& rProperties )
     276             :         throw(IllegalArgumentException, RuntimeException, std::exception)
     277             : {
     278       25654 :     MutexGuard  aGuard( GetLinguMutex() );
     279             : 
     280       51308 :     Reference< XHyphenatedWord >    xRes;
     281             : 
     282       25654 :     sal_Int32 nWordLen = rWord.getLength();
     283       25654 :     sal_Int16 nLanguage = LinguLocaleToLanguage( rLocale );
     284       76962 :     if (LinguIsUnspecified(nLanguage) || !nWordLen ||
     285       49057 :         nMaxLeading == 0 || nMaxLeading == nWordLen)
     286        2251 :         return xRes;
     287             : 
     288             :     // search for entry with that language
     289       23403 :     HyphSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
     290       23403 :     LangSvcEntries_Hyph     *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
     291             : 
     292       23403 :     bool bWordModified = false;
     293       23403 :     if (!pEntry || (nMaxLeading < 0 || nMaxLeading > nWordLen))
     294             :     {
     295       18168 :         return NULL;
     296             :     }
     297             :     else
     298             :     {
     299        5235 :         OUString aChkWord( rWord );
     300             : 
     301             :         // replace typographical apostroph by ascii apostroph
     302       10470 :         OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
     303             :         DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpectend length of quotation mark" );
     304        5235 :         if (!aSingleQuote.isEmpty())
     305        5235 :             aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
     306             : 
     307        5235 :         bWordModified |= RemoveHyphens( aChkWord );
     308        5235 :         if (IsIgnoreControlChars( rProperties, GetPropSet() ))
     309        5235 :             bWordModified |= RemoveControlChars( aChkWord );
     310        5235 :         sal_Int16 nChkMaxLeading = (sal_Int16) GetPosInWordToCheck( rWord, nMaxLeading );
     311             : 
     312             :         // check for results from (positive) dictionaries which have precedence!
     313       10470 :         Reference< XDictionaryEntry > xEntry;
     314             : 
     315        5235 :         if (GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
     316             :         {
     317       15705 :             xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
     318       10470 :                         sal_True, sal_False );
     319             :         }
     320             : 
     321        5235 :         if (xEntry.is())
     322             :         {
     323             :             //! because queryDictionaryEntry (in the end DictionaryNeo::getEntry)
     324             :             //! does not distinguish betwee "XYZ" and "XYZ." in order to avoid
     325             :             //! to require them as different entry we have to supply the
     326             :             //! original word here as well so it can be used in th result
     327             :             //! otherwise a strange effect may occur (see #i22591#)
     328           0 :             xRes = buildHyphWord( rWord, xEntry, nLanguage, nChkMaxLeading );
     329             :         }
     330             :         else
     331             :         {
     332        5235 :             sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
     333             :             DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
     334             :                     "lng : index out of range");
     335             : 
     336        5235 :             sal_Int32 i = 0;
     337        5235 :             Reference< XHyphenator > xHyph;
     338        5235 :             if (pEntry->aSvcRefs.getLength() > 0)
     339        5235 :                 xHyph = pEntry->aSvcRefs[0];
     340             : 
     341             :             // try already instantiated service
     342        5235 :             if (i <= pEntry->nLastTriedSvcIndex)
     343             :             {
     344        5230 :                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
     345       15690 :                     xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
     346       10460 :                                             rProperties );
     347        5230 :                 ++i;
     348             :             }
     349           5 :             else if (pEntry->nLastTriedSvcIndex < nLen - 1)
     350             :             // instantiate services and try it
     351             :             {
     352           5 :                 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
     353             : 
     354             :                 Reference< XComponentContext > xContext(
     355           5 :                     comphelper::getProcessComponentContext() );
     356             : 
     357             :                 // build service initialization argument
     358          10 :                 Sequence< Any > aArgs(2);
     359           5 :                 aArgs.getArray()[0] <<= GetPropSet();
     360             : 
     361             :                 // create specific service via it's implementation name
     362             :                 try
     363             :                 {
     364          10 :                     xHyph = Reference< XHyphenator >(
     365          10 :                                 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
     366           5 :                                     pEntry->aSvcImplNames[0], aArgs, xContext ),
     367           5 :                                 UNO_QUERY );
     368             :                 }
     369           0 :                 catch (uno::Exception &)
     370             :                 {
     371             :                     DBG_ASSERT( false, "createInstanceWithArguments failed" );
     372             :                 }
     373           5 :                 pRef [i] = xHyph;
     374             : 
     375             :                 Reference< XLinguServiceEventBroadcaster >
     376          10 :                         xBroadcaster( xHyph, UNO_QUERY );
     377           5 :                 if (xBroadcaster.is())
     378           5 :                     rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
     379             : 
     380           5 :                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
     381          15 :                     xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
     382          10 :                                             rProperties );
     383             : 
     384           5 :                 pEntry->nLastTriedSvcIndex = (sal_Int16) i;
     385           5 :                 ++i;
     386             : 
     387             :                 // if language is not supported by the services
     388             :                 // remove it from the list.
     389           5 :                 if (xHyph.is()  &&  !xHyph->hasLocale( rLocale ))
     390           5 :                     aSvcMap.erase( nLanguage );
     391        5235 :             }
     392        5235 :         }   // if (xEntry.is())
     393             :     }
     394             : 
     395        5235 :     if (bWordModified  &&  xRes.is())
     396           0 :         xRes = RebuildHyphensAndControlChars( rWord, xRes );
     397             : 
     398        5235 :     if (xRes.is()  &&  xRes->getWord() != rWord)
     399             :     {
     400           0 :         xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
     401           0 :                                    xRes->getHyphenatedWord(),
     402           0 :                                    xRes->getHyphenPos() );
     403             :     }
     404             : 
     405       30889 :     return xRes;
     406             : }
     407             : 
     408             : 
     409             : Reference< XHyphenatedWord > SAL_CALL
     410           0 :     HyphenatorDispatcher::queryAlternativeSpelling(
     411             :             const OUString& rWord, const Locale& rLocale, sal_Int16 nIndex,
     412             :             const PropertyValues& rProperties )
     413             :         throw(IllegalArgumentException, RuntimeException, std::exception)
     414             : {
     415           0 :     MutexGuard  aGuard( GetLinguMutex() );
     416             : 
     417           0 :     Reference< XHyphenatedWord >    xRes;
     418             : 
     419           0 :     sal_Int32 nWordLen = rWord.getLength();
     420           0 :     sal_Int16 nLanguage = LinguLocaleToLanguage( rLocale );
     421           0 :     if (LinguIsUnspecified(nLanguage) || !nWordLen)
     422           0 :         return xRes;
     423             : 
     424             :     // search for entry with that language
     425           0 :     HyphSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
     426           0 :     LangSvcEntries_Hyph     *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
     427             : 
     428           0 :     bool bWordModified = false;
     429           0 :     if (!pEntry || !(0 <= nIndex && nIndex <= nWordLen - 2))
     430             :     {
     431           0 :         return NULL;
     432             :     }
     433             :     else
     434             :     {
     435           0 :         OUString aChkWord( rWord );
     436             : 
     437             :         // replace typographical apostroph by ascii apostroph
     438           0 :         OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
     439             :         DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpectend length of quotation mark" );
     440           0 :         if (!aSingleQuote.isEmpty())
     441           0 :             aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
     442             : 
     443           0 :         bWordModified |= RemoveHyphens( aChkWord );
     444           0 :         if (IsIgnoreControlChars( rProperties, GetPropSet() ))
     445           0 :             bWordModified |= RemoveControlChars( aChkWord );
     446           0 :         sal_Int16 nChkIndex = (sal_Int16) GetPosInWordToCheck( rWord, nIndex );
     447             : 
     448             :         // check for results from (positive) dictionaries which have precedence!
     449           0 :         Reference< XDictionaryEntry > xEntry;
     450             : 
     451           0 :         if (GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
     452             :         {
     453           0 :             xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
     454           0 :                         sal_True, sal_False );
     455             :         }
     456             : 
     457           0 :         if (xEntry.is())
     458             :         {
     459           0 :             xRes = buildHyphWord(aChkWord, xEntry, nLanguage, nIndex + 1);
     460           0 :             if (xRes.is() && xRes->isAlternativeSpelling() && xRes->getHyphenationPos() == nIndex)
     461           0 :                     return xRes;
     462             :         }
     463             :         else
     464             :         {
     465           0 :             sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
     466             :             DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
     467             :                     "lng : index out of range");
     468             : 
     469           0 :             sal_Int32 i = 0;
     470           0 :             Reference< XHyphenator > xHyph;
     471           0 :             if (pEntry->aSvcRefs.getLength() > 0)
     472           0 :                 xHyph = pEntry->aSvcRefs[0];
     473             : 
     474             :             // try already instantiated service
     475           0 :             if (i <= pEntry->nLastTriedSvcIndex)
     476             :             {
     477           0 :                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
     478           0 :                     xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
     479           0 :                                 nChkIndex, rProperties );
     480           0 :                 ++i;
     481             :             }
     482           0 :             else if (pEntry->nLastTriedSvcIndex < nLen - 1)
     483             :             // instantiate services and try it
     484             :             {
     485           0 :                 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
     486             : 
     487             :                 Reference< XComponentContext > xContext(
     488           0 :                     comphelper::getProcessComponentContext() );
     489             : 
     490             :                 // build service initialization argument
     491           0 :                 Sequence< Any > aArgs(2);
     492           0 :                 aArgs.getArray()[0] <<= GetPropSet();
     493             : 
     494             :                 // create specific service via it's implementation name
     495             :                 try
     496             :                 {
     497           0 :                     xHyph = Reference< XHyphenator >(
     498           0 :                                 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
     499           0 :                                     pEntry->aSvcImplNames[0], aArgs, xContext ), UNO_QUERY );
     500             :                 }
     501           0 :                 catch (uno::Exception &)
     502             :                 {
     503             :                     DBG_ASSERT( false, "createInstanceWithArguments failed" );
     504             :                 }
     505           0 :                 pRef [i] = xHyph;
     506             : 
     507             :                 Reference< XLinguServiceEventBroadcaster >
     508           0 :                         xBroadcaster( xHyph, UNO_QUERY );
     509           0 :                 if (xBroadcaster.is())
     510           0 :                     rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
     511             : 
     512           0 :                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
     513           0 :                     xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
     514           0 :                                 nChkIndex, rProperties );
     515             : 
     516           0 :                 pEntry->nLastTriedSvcIndex = (sal_Int16) i;
     517           0 :                 ++i;
     518             : 
     519             :                 // if language is not supported by the services
     520             :                 // remove it from the list.
     521           0 :                 if (xHyph.is()  &&  !xHyph->hasLocale( rLocale ))
     522           0 :                     aSvcMap.erase( nLanguage );
     523           0 :             }
     524           0 :         }   // if (xEntry.is())
     525             :     }
     526             : 
     527           0 :     if (bWordModified  &&  xRes.is())
     528           0 :         xRes = RebuildHyphensAndControlChars( rWord, xRes );
     529             : 
     530           0 :     if (xRes.is()  &&  xRes->getWord() != rWord)
     531             :     {
     532           0 :         xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
     533           0 :                                    xRes->getHyphenatedWord(),
     534           0 :                                    xRes->getHyphenPos() );
     535             :     }
     536             : 
     537           0 :     return xRes;
     538             : }
     539             : 
     540             : 
     541             : Reference< XPossibleHyphens > SAL_CALL
     542           0 :     HyphenatorDispatcher::createPossibleHyphens(
     543             :             const OUString& rWord, const Locale& rLocale,
     544             :             const PropertyValues& rProperties )
     545             :         throw(IllegalArgumentException, RuntimeException, std::exception)
     546             : {
     547           0 :     MutexGuard  aGuard( GetLinguMutex() );
     548             : 
     549           0 :     Reference< XPossibleHyphens >   xRes;
     550             : 
     551           0 :     sal_Int16 nLanguage = LinguLocaleToLanguage( rLocale );
     552           0 :     if (LinguIsUnspecified(nLanguage) || rWord.isEmpty())
     553           0 :         return xRes;
     554             : 
     555             :     // search for entry with that language
     556           0 :     HyphSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
     557           0 :     LangSvcEntries_Hyph     *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
     558             : 
     559           0 :     if (pEntry)
     560             :     {
     561           0 :         OUString aChkWord( rWord );
     562             : 
     563             :         // replace typographical apostroph by ascii apostroph
     564           0 :         OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
     565             :         DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpectend length of quotation mark" );
     566           0 :         if (!aSingleQuote.isEmpty())
     567           0 :             aChkWord = aChkWord.replace( aSingleQuote[0], '\'' );
     568             : 
     569           0 :         RemoveHyphens( aChkWord );
     570           0 :         if (IsIgnoreControlChars( rProperties, GetPropSet() ))
     571           0 :             RemoveControlChars( aChkWord );
     572             : 
     573             :         // check for results from (positive) dictionaries which have precedence!
     574           0 :         Reference< XDictionaryEntry > xEntry;
     575             : 
     576           0 :         if (GetDicList().is()  &&  IsUseDicList( rProperties, GetPropSet() ))
     577             :         {
     578           0 :             xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
     579           0 :                         sal_True, sal_False );
     580             :         }
     581             : 
     582           0 :         if (xEntry.is())
     583             :         {
     584           0 :             xRes = buildPossHyphens( xEntry, nLanguage );
     585             :         }
     586             :         else
     587             :         {
     588           0 :             sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
     589             :             DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
     590             :                     "lng : index out of range");
     591             : 
     592           0 :             sal_Int32 i = 0;
     593           0 :             Reference< XHyphenator > xHyph;
     594           0 :             if (pEntry->aSvcRefs.getLength() > 0)
     595           0 :                 xHyph = pEntry->aSvcRefs[0];
     596             : 
     597             :             // try already instantiated service
     598           0 :             if (i <= pEntry->nLastTriedSvcIndex)
     599             :             {
     600           0 :                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
     601           0 :                     xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
     602           0 :                                 rProperties );
     603           0 :                 ++i;
     604             :             }
     605           0 :             else if (pEntry->nLastTriedSvcIndex < nLen - 1)
     606             :             // instantiate services and try it
     607             :             {
     608           0 :                 Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
     609             : 
     610             :                 Reference< XComponentContext > xContext(
     611           0 :                     comphelper::getProcessComponentContext() );
     612             : 
     613             :                 // build service initialization argument
     614           0 :                 Sequence< Any > aArgs(2);
     615           0 :                 aArgs.getArray()[0] <<= GetPropSet();
     616             : 
     617             :                 // create specific service via it's implementation name
     618             :                 try
     619             :                 {
     620           0 :                     xHyph = Reference< XHyphenator >(
     621           0 :                                 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
     622           0 :                                     pEntry->aSvcImplNames[0], aArgs, xContext ),
     623           0 :                                 UNO_QUERY );
     624             :                 }
     625           0 :                 catch (uno::Exception &)
     626             :                 {
     627             :                     DBG_ASSERT( false, "createWithArguments failed" );
     628             :                 }
     629           0 :                 pRef [i] = xHyph;
     630             : 
     631             :                 Reference< XLinguServiceEventBroadcaster >
     632           0 :                         xBroadcaster( xHyph, UNO_QUERY );
     633           0 :                 if (xBroadcaster.is())
     634           0 :                     rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
     635             : 
     636           0 :                 if (xHyph.is()  &&  xHyph->hasLocale( rLocale ))
     637           0 :                     xRes = xHyph->createPossibleHyphens( aChkWord, rLocale, rProperties );
     638             : 
     639           0 :                 pEntry->nLastTriedSvcIndex = (sal_Int16) i;
     640           0 :                 ++i;
     641             : 
     642             :                 // if language is not supported by the services
     643             :                 // remove it from the list.
     644           0 :                 if (xHyph.is()  &&  !xHyph->hasLocale( rLocale ))
     645           0 :                     aSvcMap.erase( nLanguage );
     646           0 :             }
     647           0 :         }   // if (xEntry.is())
     648             :     }
     649             : 
     650           0 :     if (xRes.is()  &&  xRes->getWord() != rWord)
     651             :     {
     652           0 :         xRes = new PossibleHyphens( rWord, nLanguage,
     653           0 :                                     xRes->getPossibleHyphens(),
     654           0 :                                     xRes->getHyphenationPositions() );
     655             :     }
     656             : 
     657           0 :     return xRes;
     658             : }
     659             : 
     660             : 
     661          43 : void HyphenatorDispatcher::SetServiceList( const Locale &rLocale,
     662             :         const Sequence< OUString > &rSvcImplNames )
     663             : {
     664          43 :     MutexGuard  aGuard( GetLinguMutex() );
     665             : 
     666          43 :     sal_Int16 nLanguage = LinguLocaleToLanguage( rLocale );
     667             : 
     668          43 :     sal_Int32 nLen = rSvcImplNames.getLength();
     669          43 :     if (0 == nLen)
     670             :         // remove entry
     671           0 :         aSvcMap.erase( nLanguage );
     672             :     else
     673             :     {
     674             :         // modify/add entry
     675          43 :         LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
     676          43 :         if (pEntry)
     677             :         {
     678           0 :             pEntry->Clear();
     679           0 :             pEntry->aSvcImplNames = rSvcImplNames;
     680           0 :             pEntry->aSvcImplNames.realloc(1);
     681           0 :             pEntry->aSvcRefs  = Sequence< Reference < XHyphenator > > ( 1 );
     682             :         }
     683             :         else
     684             :         {
     685          43 :             boost::shared_ptr< LangSvcEntries_Hyph > pTmpEntry( new LangSvcEntries_Hyph( rSvcImplNames[0] ) );
     686          43 :             pTmpEntry->aSvcRefs = Sequence< Reference < XHyphenator > >( 1 );
     687          43 :             aSvcMap[ nLanguage ] = pTmpEntry;
     688             :         }
     689          43 :     }
     690          43 : }
     691             : 
     692             : 
     693             : Sequence< OUString >
     694           0 :     HyphenatorDispatcher::GetServiceList( const Locale &rLocale ) const
     695             : {
     696           0 :     MutexGuard  aGuard( GetLinguMutex() );
     697             : 
     698           0 :     Sequence< OUString > aRes;
     699             : 
     700             :     // search for entry with that language and use data from that
     701           0 :     sal_Int16 nLanguage = LinguLocaleToLanguage( rLocale );
     702           0 :     const HyphSvcByLangMap_t::const_iterator  aIt( aSvcMap.find( nLanguage ) );
     703           0 :     const LangSvcEntries_Hyph       *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
     704           0 :     if (pEntry)
     705             :     {
     706           0 :         aRes = pEntry->aSvcImplNames;
     707           0 :         if (aRes.getLength() > 0)
     708           0 :             aRes.realloc(1);
     709             :     }
     710             : 
     711           0 :     return aRes;
     712             : }
     713             : 
     714             : 
     715           0 : LinguDispatcher::DspType HyphenatorDispatcher::GetDspType() const
     716             : {
     717           0 :     return DSP_HYPH;
     718             : }
     719             : 
     720             : 
     721             : 
     722             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11