LCOV - code coverage report
Current view: top level - linguistic/source - misc.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 168 362 46.4 %
Date: 2014-11-03 Functions: 27 41 65.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 file754
      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 <sal/macros.h>
      21             : #include <tools/debug.hxx>
      22             : #include <unotools/pathoptions.hxx>
      23             : #include <svl/lngmisc.hxx>
      24             : #include <ucbhelper/content.hxx>
      25             : #include <i18nlangtag/languagetag.hxx>
      26             : #include <com/sun/star/beans/XPropertySet.hpp>
      27             : #include <com/sun/star/beans/XFastPropertySet.hpp>
      28             : #include <com/sun/star/beans/XPropertyChangeListener.hpp>
      29             : #include <com/sun/star/beans/PropertyValues.hpp>
      30             : #include <com/sun/star/frame/XTerminateListener.hpp>
      31             : #include <com/sun/star/frame/Desktop.hpp>
      32             : #include <com/sun/star/frame/XStorable.hpp>
      33             : #include <com/sun/star/linguistic2/DictionaryType.hpp>
      34             : #include <com/sun/star/linguistic2/DictionaryList.hpp>
      35             : #include <com/sun/star/linguistic2/LinguProperties.hpp>
      36             : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
      37             : #include <com/sun/star/uno/Sequence.hxx>
      38             : #include <com/sun/star/uno/Reference.h>
      39             : #include <comphelper/processfactory.hxx>
      40             : #include <unotools/localedatawrapper.hxx>
      41             : #include <unotools/syslocale.hxx>
      42             : 
      43             : #include <rtl/instance.hxx>
      44             : 
      45             : #include "linguistic/misc.hxx"
      46             : #include "defs.hxx"
      47             : #include "linguistic/lngprops.hxx"
      48             : #include "linguistic/hyphdta.hxx"
      49             : 
      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::i18n;
      56             : using namespace com::sun::star::linguistic2;
      57             : 
      58             : namespace linguistic
      59             : {
      60             : 
      61             : //!! multi-thread safe mutex for all platforms !!
      62             : struct LinguMutex : public rtl::Static< osl::Mutex, LinguMutex >
      63             : {
      64             : };
      65             : 
      66     2980419 : osl::Mutex &    GetLinguMutex()
      67             : {
      68     2980419 :     return LinguMutex::get();
      69             : }
      70             : 
      71       32560 : LocaleDataWrapper & GetLocaleDataWrapper( sal_Int16 nLang )
      72             : {
      73       32560 :     static LocaleDataWrapper aLclDtaWrp( SvtSysLocale().GetLanguageTag() );
      74             : 
      75       32560 :     const LanguageTag &rLcl = aLclDtaWrp.getLoadedLanguageTag();
      76       65120 :     LanguageTag aLcl( nLang );
      77       32560 :     if (aLcl != rLcl)
      78           0 :         aLclDtaWrp.setLanguageTag( aLcl );
      79       65120 :     return aLclDtaWrp;
      80             : }
      81             : 
      82      403863 : LanguageType LinguLocaleToLanguage( const ::com::sun::star::lang::Locale& rLocale )
      83             : {
      84      403863 :     if ( rLocale.Language.isEmpty() )
      85         478 :         return LANGUAGE_NONE;
      86      403385 :     return LanguageTag::convertToLanguageType( rLocale );
      87             : }
      88             : 
      89          38 : ::com::sun::star::lang::Locale LinguLanguageToLocale( LanguageType nLanguage )
      90             : {
      91          38 :     if (nLanguage == LANGUAGE_NONE)
      92          38 :         return ::com::sun::star::lang::Locale();
      93           0 :     return LanguageTag::convertToLocale( nLanguage);
      94             : }
      95             : 
      96      301032 : bool LinguIsUnspecified( LanguageType nLanguage )
      97             : {
      98      301032 :     switch (nLanguage)
      99             :     {
     100             :         case LANGUAGE_NONE:
     101             :         case LANGUAGE_UNDETERMINED:
     102             :         case LANGUAGE_MULTIPLE:
     103      109687 :             return true;
     104             :     }
     105      191345 :     return false;
     106             : }
     107             : 
     108             : // When adding anything keep both LinguIsUnspecified() methods in sync!
     109             : // For mappings between language code string and LanguageType see
     110             : // i18nlangtag/source/isolang/isolang.cxx
     111             : 
     112        3080 : bool LinguIsUnspecified( const OUString & rBcp47 )
     113             : {
     114        3080 :     if (rBcp47.getLength() != 3)
     115        3080 :         return false;
     116           0 :     if (rBcp47 == "zxx" || rBcp47 == "und" || rBcp47 == "mul")
     117           0 :         return true;
     118           0 :     return false;
     119             : }
     120             : 
     121           0 : static inline sal_Int32 Minimum( sal_Int32 n1, sal_Int32 n2, sal_Int32 n3 )
     122             : {
     123           0 :     sal_Int32 nMin = n1 < n2 ? n1 : n2;
     124           0 :     return nMin < n3 ? nMin : n3;
     125             : }
     126             : 
     127             : class IntArray2D
     128             : {
     129             : private:
     130             :     sal_Int32  *pData;
     131             :     int         n1, n2;
     132             : 
     133             : public:
     134             :     IntArray2D( int nDim1, int nDim2 );
     135             :     ~IntArray2D();
     136             : 
     137             :     sal_Int32 & Value( int i, int k  );
     138             : };
     139             : 
     140           0 : IntArray2D::IntArray2D( int nDim1, int nDim2 )
     141             : {
     142           0 :     n1 = nDim1;
     143           0 :     n2 = nDim2;
     144           0 :     pData = new sal_Int32[n1 * n2];
     145           0 : }
     146             : 
     147           0 : IntArray2D::~IntArray2D()
     148             : {
     149           0 :     delete[] pData;
     150           0 : }
     151             : 
     152           0 : sal_Int32 & IntArray2D::Value( int i, int k  )
     153             : {
     154             :     DBG_ASSERT( 0 <= i && i < n1, "first index out of range" );
     155             :     DBG_ASSERT( 0 <= k && k < n2, "first index out of range" );
     156             :     DBG_ASSERT( i * n2 + k < n1 * n2, "index out of range" );
     157           0 :     return pData[ i * n2 + k ];
     158             : }
     159             : 
     160           0 : sal_Int32 LevDistance( const OUString &rTxt1, const OUString &rTxt2 )
     161             : {
     162           0 :     sal_Int32 nLen1 = rTxt1.getLength();
     163           0 :     sal_Int32 nLen2 = rTxt2.getLength();
     164             : 
     165           0 :     if (nLen1 == 0)
     166           0 :         return nLen2;
     167           0 :     if (nLen2 == 0)
     168           0 :         return nLen1;
     169             : 
     170           0 :     IntArray2D aData( nLen1 + 1, nLen2 + 1 );
     171             : 
     172             :     sal_Int32 i, k;
     173           0 :     for (i = 0;  i <= nLen1;  ++i)
     174           0 :         aData.Value(i, 0) = i;
     175           0 :     for (k = 0;  k <= nLen2;  ++k)
     176           0 :         aData.Value(0, k) = k;
     177           0 :     for (i = 1;  i <= nLen1;  ++i)
     178             :     {
     179           0 :         for (k = 1;  k <= nLen2;  ++k)
     180             :         {
     181           0 :             sal_Unicode c1i = rTxt1[i - 1];
     182           0 :             sal_Unicode c2k = rTxt2[k - 1];
     183           0 :             sal_Int32 nCost = c1i == c2k ? 0 : 1;
     184           0 :             sal_Int32 nNew = Minimum( aData.Value(i-1, k  ) + 1,
     185           0 :                                        aData.Value(i  , k-1) + 1,
     186           0 :                                        aData.Value(i-1, k-1) + nCost );
     187             :             // take transposition (exchange with left or right char) in account
     188           0 :             if (2 < i && 2 < k)
     189             :             {
     190           0 :                 int nT = aData.Value(i-2, k-2) + 1;
     191           0 :                 if (rTxt1[i - 2] != c1i)
     192           0 :                     ++nT;
     193           0 :                 if (rTxt2[k - 2] != c2k)
     194           0 :                     ++nT;
     195           0 :                 if (nT < nNew)
     196           0 :                     nNew = nT;
     197             :             }
     198             : 
     199           0 :             aData.Value(i, k) = nNew;
     200             :         }
     201             :     }
     202           0 :     sal_Int32 nDist = aData.Value(nLen1, nLen2);
     203           0 :     return nDist;
     204             : }
     205             : 
     206       31967 : bool IsUseDicList( const PropertyValues &rProperties,
     207             :         const uno::Reference< XPropertySet > &rxProp )
     208             : {
     209       31967 :     bool bRes = true;
     210             : 
     211       31967 :     sal_Int32 nLen = rProperties.getLength();
     212       31967 :     const PropertyValue *pVal = rProperties.getConstArray();
     213             :     sal_Int32 i;
     214             : 
     215       31967 :     for ( i = 0;  i < nLen;  ++i)
     216             :     {
     217           0 :         if (UPH_IS_USE_DICTIONARY_LIST == pVal[i].Handle)
     218             :         {
     219           0 :             pVal[i].Value >>= bRes;
     220           0 :             break;
     221             :         }
     222             :     }
     223       31967 :     if (i >= nLen)  // no temporary value found in 'rProperties'
     224             :     {
     225       31967 :         uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY );
     226       31967 :         if (xFast.is())
     227       31967 :             xFast->getFastPropertyValue( UPH_IS_USE_DICTIONARY_LIST ) >>= bRes;
     228             :     }
     229             : 
     230       31967 :     return bRes;
     231             : }
     232             : 
     233       31967 : bool IsIgnoreControlChars( const PropertyValues &rProperties,
     234             :         const uno::Reference< XPropertySet > &rxProp )
     235             : {
     236       31967 :     bool bRes = true;
     237             : 
     238       31967 :     sal_Int32 nLen = rProperties.getLength();
     239       31967 :     const PropertyValue *pVal = rProperties.getConstArray();
     240             :     sal_Int32 i;
     241             : 
     242       31967 :     for ( i = 0;  i < nLen;  ++i)
     243             :     {
     244           0 :         if (UPH_IS_IGNORE_CONTROL_CHARACTERS == pVal[i].Handle)
     245             :         {
     246           0 :             pVal[i].Value >>= bRes;
     247           0 :             break;
     248             :         }
     249             :     }
     250       31967 :     if (i >= nLen)  // no temporary value found in 'rProperties'
     251             :     {
     252       31967 :         uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY );
     253       31967 :         if (xFast.is())
     254       31967 :             xFast->getFastPropertyValue( UPH_IS_IGNORE_CONTROL_CHARACTERS ) >>= bRes;
     255             :     }
     256             : 
     257       31967 :     return bRes;
     258             : }
     259             : 
     260           0 : static bool lcl_HasHyphInfo( const uno::Reference<XDictionaryEntry> &xEntry )
     261             : {
     262           0 :     bool bRes = false;
     263           0 :     if (xEntry.is())
     264             :     {
     265             :         // there has to be (at least one) '=' or '[' denoting a hyphenation position
     266             :         // and it must not be before any character of the word
     267           0 :         sal_Int32 nIdx = xEntry->getDictionaryWord().indexOf( '=' );
     268           0 :         if (nIdx == -1)
     269           0 :             nIdx = xEntry->getDictionaryWord().indexOf( '[' );
     270           0 :         bRes = nIdx != -1  &&  nIdx != 0;
     271             :     }
     272           0 :     return bRes;
     273             : }
     274             : 
     275       54766 : uno::Reference< XDictionaryEntry > SearchDicList(
     276             :         const uno::Reference< XSearchableDictionaryList > &xDicList,
     277             :         const OUString &rWord, sal_Int16 nLanguage,
     278             :         bool bSearchPosDics, bool bSearchSpellEntry )
     279             : {
     280       54766 :     MutexGuard  aGuard( GetLinguMutex() );
     281             : 
     282       54766 :     uno::Reference< XDictionaryEntry > xEntry;
     283             : 
     284       54766 :     if (!xDicList.is())
     285           0 :         return xEntry;
     286             : 
     287             :     const uno::Sequence< uno::Reference< XDictionary > >
     288      109532 :             aDics( xDicList->getDictionaries() );
     289             :     const uno::Reference< XDictionary >
     290       54766 :             *pDic = aDics.getConstArray();
     291       54766 :     sal_Int32 nDics = xDicList->getCount();
     292             : 
     293             :     sal_Int32 i;
     294      328582 :     for (i = 0;  i < nDics;  i++)
     295             :     {
     296      273828 :         uno::Reference< XDictionary > axDic( pDic[i], UNO_QUERY );
     297             : 
     298      273828 :         DictionaryType  eType = axDic->getDictionaryType();
     299      273828 :         sal_Int16           nLang = LinguLocaleToLanguage( axDic->getLocale() );
     300             : 
     301      821484 :         if ( axDic.is() && axDic->isActive()
     302      547656 :             && (nLang == nLanguage  ||  LinguIsUnspecified( nLang)) )
     303             :         {
     304             :             DBG_ASSERT( eType != DictionaryType_MIXED,
     305             :                 "lng : unexpected dictionary type" );
     306             : 
     307      164308 :             if (   (!bSearchPosDics  &&  eType == DictionaryType_NEGATIVE)
     308      164308 :                 || ( bSearchPosDics  &&  eType == DictionaryType_POSITIVE))
     309             :             {
     310      114544 :                 if ( (xEntry = axDic->getEntry( rWord )).is() )
     311             :                 {
     312          12 :                     if (bSearchSpellEntry || lcl_HasHyphInfo( xEntry ))
     313          12 :                         break;
     314             :                 }
     315      114532 :                 xEntry = 0;
     316             :             }
     317             :         }
     318      273816 :     }
     319             : 
     320      109532 :     return xEntry;
     321             : }
     322             : 
     323           0 : bool SaveDictionaries( const uno::Reference< XSearchableDictionaryList > &xDicList )
     324             : {
     325           0 :     if (!xDicList.is())
     326           0 :         return true;
     327             : 
     328           0 :     bool bRet = true;
     329             : 
     330           0 :     Sequence< uno::Reference< XDictionary >  > aDics( xDicList->getDictionaries() );
     331           0 :     const uno::Reference< XDictionary >  *pDic = aDics.getConstArray();
     332           0 :     sal_Int32 nCount = aDics.getLength();
     333           0 :     for (sal_Int32 i = 0;  i < nCount;  i++)
     334             :     {
     335             :         try
     336             :         {
     337           0 :             uno::Reference< frame::XStorable >  xStor( pDic[i], UNO_QUERY );
     338           0 :             if (xStor.is())
     339             :             {
     340           0 :                 if (!xStor->isReadonly() && xStor->hasLocation())
     341           0 :                     xStor->store();
     342           0 :             }
     343             :         }
     344           0 :         catch(uno::Exception &)
     345             :         {
     346           0 :             bRet = false;
     347             :         }
     348             :     }
     349             : 
     350           0 :     return bRet;
     351             : }
     352             : 
     353           0 : sal_uInt8 AddEntryToDic(
     354             :         uno::Reference< XDictionary >  &rxDic,
     355             :         const OUString &rWord, bool bIsNeg,
     356             :         const OUString &rRplcTxt, sal_Int16 /* nRplcLang */,
     357             :         bool bStripDot )
     358             : {
     359           0 :     if (!rxDic.is())
     360           0 :         return DIC_ERR_NOT_EXISTS;
     361             : 
     362           0 :     OUString aTmp( rWord );
     363           0 :     if (bStripDot)
     364             :     {
     365           0 :         sal_Int32 nLen = rWord.getLength();
     366           0 :         if (nLen > 0  &&  '.' == rWord[ nLen - 1])
     367             :         {
     368             :             // remove trailing '.'
     369             :             // (this is the official way to do this :-( )
     370           0 :             aTmp = aTmp.copy( 0, nLen - 1 );
     371             :         }
     372             :     }
     373           0 :     bool bAddOk = rxDic->add( aTmp, bIsNeg, rRplcTxt );
     374             : 
     375           0 :     sal_uInt8 nRes = DIC_ERR_NONE;
     376           0 :     if (!bAddOk)
     377             :     {
     378           0 :         if (rxDic->isFull())
     379           0 :             nRes = DIC_ERR_FULL;
     380             :         else
     381             :         {
     382           0 :             uno::Reference< frame::XStorable >  xStor( rxDic, UNO_QUERY );
     383           0 :             if (xStor.is() && xStor->isReadonly())
     384           0 :                 nRes = DIC_ERR_READONLY;
     385             :             else
     386           0 :                 nRes = DIC_ERR_UNKNOWN;
     387             :         }
     388             :     }
     389             : 
     390           0 :     return nRes;
     391             : }
     392             : 
     393             : uno::Sequence< sal_Int16 >
     394         132 :     LocaleSeqToLangSeq( uno::Sequence< Locale > &rLocaleSeq )
     395             : {
     396         132 :     const Locale *pLocale = rLocaleSeq.getConstArray();
     397         132 :     sal_Int32 nCount = rLocaleSeq.getLength();
     398             : 
     399         132 :     uno::Sequence< sal_Int16 >   aLangs( nCount );
     400         132 :     sal_Int16 *pLang = aLangs.getArray();
     401        3212 :     for (sal_Int32 i = 0;  i < nCount;  ++i)
     402             :     {
     403        3080 :         pLang[i] = LinguLocaleToLanguage( pLocale[i] );
     404             :     }
     405             : 
     406         132 :     return aLangs;
     407             : }
     408             : 
     409           0 : bool    IsReadOnly( const OUString &rURL, bool *pbExist )
     410             : {
     411           0 :     bool bRes = false;
     412           0 :     bool bExists = false;
     413             : 
     414           0 :     if (!rURL.isEmpty())
     415             :     {
     416             :         try
     417             :         {
     418           0 :             uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv;
     419           0 :             ::ucbhelper::Content aContent( rURL, xCmdEnv, comphelper::getProcessComponentContext() );
     420             : 
     421           0 :             bExists = aContent.isDocument();
     422           0 :             if (bExists)
     423             :             {
     424           0 :                 Any aAny( aContent.getPropertyValue( "IsReadOnly" ) );
     425           0 :                 aAny >>= bRes;
     426           0 :             }
     427             :         }
     428           0 :         catch (Exception &)
     429             :         {
     430           0 :             bRes = true;
     431             :         }
     432             :     }
     433             : 
     434           0 :     if (pbExist)
     435           0 :         *pbExist = bExists;
     436           0 :     return bRes;
     437             : }
     438             : 
     439           0 : static bool GetAltSpelling( sal_Int16 &rnChgPos, sal_Int16 &rnChgLen, OUString &rRplc,
     440             :         uno::Reference< XHyphenatedWord > &rxHyphWord )
     441             : {
     442           0 :     bool bRes = rxHyphWord->isAlternativeSpelling();
     443           0 :     if (bRes)
     444             :     {
     445           0 :         OUString aWord( rxHyphWord->getWord() ),
     446           0 :                  aHyphenatedWord( rxHyphWord->getHyphenatedWord() );
     447           0 :         sal_Int16   nHyphenationPos     = rxHyphWord->getHyphenationPos();
     448             :         /*sal_Int16   nHyphenPos          = rxHyphWord->getHyphenPos()*/;
     449           0 :         const sal_Unicode *pWord    = aWord.getStr(),
     450           0 :                           *pAltWord = aHyphenatedWord.getStr();
     451             : 
     452             :         // at least char changes directly left or right to the hyphen
     453             :         // should(!) be handled properly...
     454             :         //! nHyphenationPos and nHyphenPos differ at most by 1 (see above)
     455             :         //! Beware: eg "Schiffahrt" in German (pre spelling reform)
     456             :         //! proves to be a bit nasty (nChgPosLeft and nChgPosRight overlap
     457             :         //! to an extend.)
     458             : 
     459             :         // find first different char from left
     460           0 :         sal_Int32   nPosL    = 0,
     461           0 :                     nAltPosL = 0;
     462           0 :         for (sal_Int16 i = 0 ;  pWord[ nPosL ] == pAltWord[ nAltPosL ];  nPosL++, nAltPosL++, i++)
     463             :         {
     464             :             // restrict changes area beginning to the right to
     465             :             // the char immediately following the hyphen.
     466             :             //! serves to insert the additional "f" in "Schiffahrt" at
     467             :             //! position 5 rather than position 6.
     468           0 :             if (i >= nHyphenationPos + 1)
     469           0 :                 break;
     470             :         }
     471             : 
     472             :         // find first different char from right
     473           0 :         sal_Int32   nPosR    = aWord.getLength() - 1,
     474           0 :                     nAltPosR = aHyphenatedWord.getLength() - 1;
     475           0 :         for ( ;  nPosR >= nPosL  &&  nAltPosR >= nAltPosL
     476           0 :                     &&  pWord[ nPosR ] == pAltWord[ nAltPosR ];
     477             :                 nPosR--, nAltPosR--)
     478             :             ;
     479             : 
     480           0 :         rnChgPos = sal::static_int_cast< sal_Int16 >(nPosL);
     481           0 :         rnChgLen = sal::static_int_cast< sal_Int16 >(nAltPosR - nPosL);
     482             :         DBG_ASSERT( rnChgLen >= 0, "nChgLen < 0");
     483             : 
     484           0 :         sal_Int32 nTxtStart = nPosL;
     485           0 :         sal_Int32 nTxtLen   = nAltPosR - nPosL + 1;
     486           0 :         rRplc = aHyphenatedWord.copy( nTxtStart, nTxtLen );
     487             :     }
     488           0 :     return bRes;
     489             : }
     490             : 
     491           0 : static sal_Int16 GetOrigWordPos( const OUString &rOrigWord, sal_Int16 nPos )
     492             : {
     493           0 :     sal_Int32 nLen = rOrigWord.getLength();
     494           0 :     sal_Int32 i = -1;
     495           0 :     while (nPos >= 0  &&  i++ < nLen)
     496             :     {
     497           0 :         sal_Unicode cChar = rOrigWord[i];
     498           0 :         bool bSkip = IsHyphen( cChar ) || IsControlChar( cChar );
     499           0 :         if (!bSkip)
     500           0 :             --nPos;
     501             :     }
     502           0 :     return sal::static_int_cast< sal_Int16 >((0 <= i  &&  i < nLen) ? i : -1);
     503             : }
     504             : 
     505       43204 : sal_Int32 GetPosInWordToCheck( const OUString &rTxt, sal_Int32 nPos )
     506             : {
     507       43204 :     sal_Int32 nRes = -1;
     508       43204 :     sal_Int32 nLen = rTxt.getLength();
     509       43204 :     if (0 <= nPos  &&  nPos < nLen)
     510             :     {
     511       43204 :         nRes = 0;
     512       92260 :         for (sal_Int32 i = 0;  i < nPos;  ++i)
     513             :         {
     514       49056 :             sal_Unicode cChar = rTxt[i];
     515       49056 :             bool bSkip = IsHyphen( cChar ) || IsControlChar( cChar );
     516       49056 :             if (!bSkip)
     517       49056 :                 ++nRes;
     518             :         }
     519             :     }
     520       43204 :     return nRes;
     521             : }
     522             : 
     523           0 : uno::Reference< XHyphenatedWord > RebuildHyphensAndControlChars(
     524             :         const OUString &rOrigWord,
     525             :         uno::Reference< XHyphenatedWord > &rxHyphWord )
     526             : {
     527           0 :     uno::Reference< XHyphenatedWord > xRes;
     528           0 :     if (!rOrigWord.isEmpty() && rxHyphWord.is())
     529             :     {
     530           0 :         sal_Int16    nChgPos = 0,
     531           0 :                  nChgLen = 0;
     532           0 :         OUString aRplc;
     533           0 :         bool bAltSpelling = GetAltSpelling( nChgPos, nChgLen, aRplc, rxHyphWord );
     534             : #if OSL_DEBUG_LEVEL > 1
     535             :         OUString aWord( rxHyphWord->getWord() );
     536             : #endif
     537             : 
     538           0 :         OUString aOrigHyphenatedWord;
     539           0 :         sal_Int16 nOrigHyphenPos        = -1;
     540           0 :         sal_Int16 nOrigHyphenationPos   = -1;
     541           0 :         if (!bAltSpelling)
     542             :         {
     543           0 :             aOrigHyphenatedWord = rOrigWord;
     544           0 :             nOrigHyphenPos      = GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenPos() );
     545           0 :             nOrigHyphenationPos = GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenationPos() );
     546             :         }
     547             :         else
     548             :         {
     549             :             //! should at least work with the German words
     550             :             //! B-"u-c-k-er and Sc-hif-fah-rt
     551             : 
     552           0 :             OUString aLeft, aRight;
     553           0 :             sal_Int16 nPos = GetOrigWordPos( rOrigWord, nChgPos );
     554             : 
     555             :             // get words like Sc-hif-fah-rt to work correct
     556           0 :             sal_Int16 nHyphenationPos = rxHyphWord->getHyphenationPos();
     557           0 :             if (nChgPos > nHyphenationPos)
     558           0 :                 --nPos;
     559             : 
     560           0 :             aLeft = rOrigWord.copy( 0, nPos );
     561           0 :             aRight = rOrigWord.copy( nPos ); // FIXME: changes at the right side
     562             : 
     563           0 :             aOrigHyphenatedWord =  aLeft;
     564           0 :             aOrigHyphenatedWord += aRplc;
     565           0 :             aOrigHyphenatedWord += aRight;
     566             : 
     567           0 :             nOrigHyphenPos      = sal::static_int_cast< sal_Int16 >(aLeft.getLength() +
     568           0 :                                   rxHyphWord->getHyphenPos() - nChgPos);
     569           0 :             nOrigHyphenationPos = GetOrigWordPos( rOrigWord, nHyphenationPos );
     570             :         }
     571             : 
     572           0 :         if (nOrigHyphenPos == -1  ||  nOrigHyphenationPos == -1)
     573             :         {
     574             :             DBG_ASSERT( false, "failed to get nOrigHyphenPos or nOrigHyphenationPos" );
     575             :         }
     576             :         else
     577             :         {
     578           0 :             sal_Int16 nLang = LinguLocaleToLanguage( rxHyphWord->getLocale() );
     579           0 :             xRes = new HyphenatedWord(
     580             :                         rOrigWord, nLang, nOrigHyphenationPos,
     581           0 :                         aOrigHyphenatedWord, nOrigHyphenPos );
     582           0 :         }
     583             : 
     584             :     }
     585           0 :     return xRes;
     586             : }
     587             : 
     588        7297 : static CharClass & lcl_GetCharClass()
     589             : {
     590        7297 :     static CharClass aCC( LanguageTag( LANGUAGE_ENGLISH_US ));
     591        7297 :     return aCC;
     592             : }
     593             : 
     594        7297 : osl::Mutex & lcl_GetCharClassMutex()
     595             : {
     596        7297 :     static osl::Mutex   aMutex;
     597        7297 :     return aMutex;
     598             : }
     599             : 
     600        6805 : bool IsUpper( const OUString &rText, sal_Int32 nPos, sal_Int32 nLen, sal_Int16 nLanguage )
     601             : {
     602        6805 :     MutexGuard  aGuard( lcl_GetCharClassMutex() );
     603             : 
     604        6805 :     CharClass &rCC = lcl_GetCharClass();
     605        6805 :     rCC.setLanguageTag( LanguageTag( nLanguage ));
     606        6805 :     sal_Int32 nFlags = rCC.getStringType( rText, nPos, nLen );
     607        6805 :     return      (nFlags & KCharacterType::UPPER)
     608        6805 :             && !(nFlags & KCharacterType::LOWER);
     609             : }
     610             : 
     611       31955 : CapType SAL_CALL capitalType(const OUString& aTerm, CharClass * pCC)
     612             : {
     613       31955 :         sal_Int32 tlen = aTerm.getLength();
     614       31955 :         if ((pCC) && (tlen))
     615             :         {
     616       31955 :             OUString aStr(aTerm);
     617       31955 :             sal_Int32 nc = 0;
     618      241428 :             for (sal_Int32 tindex = 0; tindex < tlen; ++tindex)
     619             :             {
     620      209473 :                 if (pCC->getCharacterType(aStr,tindex) &
     621       37577 :                    ::com::sun::star::i18n::KCharacterType::UPPER) nc++;
     622             :             }
     623             : 
     624       31955 :             if (nc == 0)
     625        7522 :                 return CAPTYPE_NOCAP;
     626       24433 :             if (nc == tlen)
     627        5733 :                 return CAPTYPE_ALLCAP;
     628       18700 :             if ((nc == 1) && (pCC->getCharacterType(aStr,0) &
     629             :                   ::com::sun::star::i18n::KCharacterType::UPPER))
     630       17591 :                 return CAPTYPE_INITCAP;
     631             : 
     632        1109 :             return CAPTYPE_MIXED;
     633             :         }
     634           0 :         return CAPTYPE_UNKNOWN;
     635             : }
     636             : 
     637         492 : OUString ToLower( const OUString &rText, sal_Int16 nLanguage )
     638             : {
     639         492 :     MutexGuard  aGuard( lcl_GetCharClassMutex() );
     640             : 
     641         492 :     CharClass &rCC = lcl_GetCharClass();
     642         492 :     rCC.setLanguageTag( LanguageTag( nLanguage ));
     643         492 :     return rCC.lowercase( rText );
     644             : }
     645             : 
     646             : // sorted(!) array of unicode ranges for code points that are exclusively(!) used as numbers
     647             : // and thus may NOT not be part of names or words like the Chinese/Japanese number characters
     648             : static const sal_uInt32 the_aDigitZeroes [] =
     649             : {
     650             :     0x00000030, //0039    ; Decimal # Nd  [10] DIGIT ZERO..DIGIT NINE
     651             :     0x00000660, //0669    ; Decimal # Nd  [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
     652             :     0x000006F0, //06F9    ; Decimal # Nd  [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
     653             :     0x000007C0, //07C9    ; Decimal # Nd  [10] NKO DIGIT ZERO..NKO DIGIT NINE
     654             :     0x00000966, //096F    ; Decimal # Nd  [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
     655             :     0x000009E6, //09EF    ; Decimal # Nd  [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE
     656             :     0x00000A66, //0A6F    ; Decimal # Nd  [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE
     657             :     0x00000AE6, //0AEF    ; Decimal # Nd  [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
     658             :     0x00000B66, //0B6F    ; Decimal # Nd  [10] ODIA DIGIT ZERO..ODIA DIGIT NINE
     659             :     0x00000BE6, //0BEF    ; Decimal # Nd  [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE
     660             :     0x00000C66, //0C6F    ; Decimal # Nd  [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
     661             :     0x00000CE6, //0CEF    ; Decimal # Nd  [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE
     662             :     0x00000D66, //0D6F    ; Decimal # Nd  [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
     663             :     0x00000E50, //0E59    ; Decimal # Nd  [10] THAI DIGIT ZERO..THAI DIGIT NINE
     664             :     0x00000ED0, //0ED9    ; Decimal # Nd  [10] LAO DIGIT ZERO..LAO DIGIT NINE
     665             :     0x00000F20, //0F29    ; Decimal # Nd  [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
     666             :     0x00001040, //1049    ; Decimal # Nd  [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
     667             :     0x00001090, //1099    ; Decimal # Nd  [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE
     668             :     0x000017E0, //17E9    ; Decimal # Nd  [10] KHMER DIGIT ZERO..KHMER DIGIT NINE
     669             :     0x00001810, //1819    ; Decimal # Nd  [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
     670             :     0x00001946, //194F    ; Decimal # Nd  [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE
     671             :     0x000019D0, //19D9    ; Decimal # Nd  [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
     672             :     0x00001B50, //1B59    ; Decimal # Nd  [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE
     673             :     0x00001BB0, //1BB9    ; Decimal # Nd  [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE
     674             :     0x00001C40, //1C49    ; Decimal # Nd  [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
     675             :     0x00001C50, //1C59    ; Decimal # Nd  [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE
     676             :     0x0000A620, //A629    ; Decimal # Nd  [10] VAI DIGIT ZERO..VAI DIGIT NINE
     677             :     0x0000A8D0, //A8D9    ; Decimal # Nd  [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
     678             :     0x0000A900, //A909    ; Decimal # Nd  [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE
     679             :     0x0000AA50, //AA59    ; Decimal # Nd  [10] CHAM DIGIT ZERO..CHAM DIGIT NINE
     680             :     0x0000FF10, //FF19    ; Decimal # Nd  [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
     681             :     0x000104A0, //104A9   ; Decimal # Nd  [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
     682             :     0x0001D7CE  //1D7FF   ; Decimal # Nd  [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE
     683             : };
     684             : 
     685        6677 : bool HasDigits( const OUString &rText )
     686             : {
     687             :     static const int nNumDigitZeroes = sizeof(the_aDigitZeroes) / sizeof(the_aDigitZeroes[0]);
     688        6677 :     const sal_Int32 nLen = rText.getLength();
     689             : 
     690        6677 :     sal_Int32 i = 0;
     691       30796 :     while (i < nLen) // for all characters ...
     692             :     {
     693       23254 :         const sal_uInt32 nCodePoint = rText.iterateCodePoints( &i );    // handle unicode surrogates correctly...
     694       40696 :         for (int j = 0; j < nNumDigitZeroes; ++j)   // ... check in all 0..9 ranges
     695             :         {
     696       40696 :             sal_uInt32 nDigitZero = the_aDigitZeroes[ j ];
     697       40696 :             if (nDigitZero > nCodePoint)
     698       17442 :                 break;
     699       23254 :             if (/*nDigitZero <= nCodePoint &&*/ nCodePoint <= nDigitZero + 9)
     700        5812 :                 return true;
     701             :         }
     702             :     }
     703         865 :     return false;
     704             : }
     705             : 
     706           0 : bool IsNumeric( const OUString &rText )
     707             : {
     708           0 :     bool bRes = false;
     709           0 :     if (!rText.isEmpty())
     710             :     {
     711           0 :         sal_Int32 nLen = rText.getLength();
     712           0 :         bRes = true;
     713           0 :         for(sal_Int32 i = 0; i < nLen; ++i)
     714             :         {
     715           0 :             sal_Unicode cChar = rText[ i ];
     716           0 :             if ( !((sal_Unicode)'0' <= cChar  &&  cChar <= (sal_Unicode)'9') )
     717             :             {
     718           0 :                 bRes = false;
     719           0 :                 break;
     720             :             }
     721             :         }
     722             :     }
     723           0 :     return bRes;
     724             : }
     725             : 
     726         248 : uno::Reference< XLinguProperties > GetLinguProperties()
     727             : {
     728         248 :     return LinguProperties::create( comphelper::getProcessComponentContext() );
     729             : }
     730             : 
     731       33308 : uno::Reference< XSearchableDictionaryList > GetDictionaryList()
     732             : {
     733       33308 :     uno::Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
     734       33308 :     uno::Reference< XSearchableDictionaryList > xRef;
     735             :     try
     736             :     {
     737       33308 :         xRef = DictionaryList::create(xContext);
     738             :     }
     739           0 :     catch (const uno::Exception &)
     740             :     {
     741             :         DBG_ASSERT( false, "createInstance failed" );
     742             :     }
     743             : 
     744       33308 :     return xRef;
     745             : }
     746             : 
     747       16582 : uno::Reference< XDictionary > GetIgnoreAllList()
     748             : {
     749       16582 :     uno::Reference< XDictionary > xRes;
     750       33164 :     uno::Reference< XSearchableDictionaryList > xDL( GetDictionaryList() );
     751       16582 :     if (xDL.is())
     752       16582 :         xRes = xDL->getDictionaryByName( "IgnoreAllList" );
     753       33164 :     return xRes;
     754             : }
     755             : 
     756          80 : AppExitListener::AppExitListener()
     757             : {
     758             :     // add object to Desktop EventListeners in order to properly call
     759             :     // the AtExit function at appliction exit.
     760          80 :     uno::Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
     761             : 
     762             :     try
     763             :     {
     764          80 :         xDesktop = frame::Desktop::create(xContext);
     765             :     }
     766           0 :     catch (const uno::Exception &)
     767             :     {
     768             :         DBG_ASSERT( false, "createInstance failed" );
     769          80 :     }
     770          80 : }
     771             : 
     772          77 : AppExitListener::~AppExitListener()
     773             : {
     774          77 : }
     775             : 
     776          80 : void AppExitListener::Activate()
     777             : {
     778          80 :     if (xDesktop.is())
     779          80 :         xDesktop->addTerminateListener( this );
     780          80 : }
     781             : 
     782          77 : void AppExitListener::Deactivate()
     783             : {
     784          77 :     if (xDesktop.is())
     785           0 :         xDesktop->removeTerminateListener( this );
     786          77 : }
     787             : 
     788             : void SAL_CALL
     789          80 :     AppExitListener::disposing( const EventObject& rEvtSource )
     790             :         throw(RuntimeException, std::exception)
     791             : {
     792          80 :     MutexGuard  aGuard( GetLinguMutex() );
     793             : 
     794          80 :     if (xDesktop.is()  &&  rEvtSource.Source == xDesktop)
     795             :     {
     796          80 :         xDesktop = NULL;    //! release reference to desktop
     797          80 :     }
     798          80 : }
     799             : 
     800             : void SAL_CALL
     801          36 :     AppExitListener::queryTermination( const EventObject& /*rEvtSource*/ )
     802             :         throw(frame::TerminationVetoException, RuntimeException, std::exception)
     803             : {
     804          36 : }
     805             : 
     806             : void SAL_CALL
     807          36 :     AppExitListener::notifyTermination( const EventObject& rEvtSource )
     808             :         throw(RuntimeException, std::exception)
     809             : {
     810          36 :     MutexGuard  aGuard( GetLinguMutex() );
     811             : 
     812          36 :     if (xDesktop.is()  &&  rEvtSource.Source == xDesktop)
     813             :     {
     814          36 :         AtExit();
     815          36 :     }
     816          36 : }
     817             : 
     818             : }   // namespace linguistic
     819             : 
     820             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10