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

Generated by: LCOV version 1.10