diff options
Diffstat (limited to 'linguistic/source/misc.cxx')
-rw-r--r-- | linguistic/source/misc.cxx | 911 |
1 files changed, 911 insertions, 0 deletions
diff --git a/linguistic/source/misc.cxx b/linguistic/source/misc.cxx new file mode 100644 index 000000000000..0bc393605752 --- /dev/null +++ b/linguistic/source/misc.cxx @@ -0,0 +1,911 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_linguistic.hxx" +#include <sal/macros.h> +#include <tools/string.hxx> +#include <tools/fsys.hxx> +#include <tools/debug.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/lngmisc.hxx> +#include <ucbhelper/content.hxx> +#include <i18npool/mslangid.hxx> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XStorable.hpp> + +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/linguistic2/DictionaryType.hpp> +#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp> +#include <unotools/processfactory.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/syslocale.hxx> + +#include <rtl/instance.hxx> + +#include "linguistic/misc.hxx" +#include "defs.hxx" +#include "linguistic/lngprops.hxx" +#include "linguistic/hyphdta.hxx" +#include <i18npool/mslangid.hxx> + +using namespace utl; +using namespace osl; +using namespace com::sun::star; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace com::sun::star::i18n; +using namespace com::sun::star::linguistic2; + +using ::rtl::OUString; + +namespace linguistic +{ + + +//!! multi-thread safe mutex for all platforms !! +struct LinguMutex : public rtl::Static< osl::Mutex, LinguMutex > +{ +}; + +osl::Mutex & GetLinguMutex() +{ + return LinguMutex::get(); +} + + +LocaleDataWrapper & GetLocaleDataWrapper( sal_Int16 nLang ) +{ + static LocaleDataWrapper aLclDtaWrp( + getProcessServiceFactory(), + CreateLocale( SvtSysLocale().GetUILanguage() ) ); + + const Locale &rLcl = aLclDtaWrp.getLoadedLocale(); + Locale aLcl( CreateLocale( nLang ) ); + if (aLcl.Language != rLcl.Language || + aLcl.Country != rLcl.Country || + aLcl.Variant != rLcl.Variant) + aLclDtaWrp.setLocale( aLcl ); + return aLclDtaWrp; +} + +static inline sal_Int32 Minimum( sal_Int32 n1, sal_Int32 n2, sal_Int32 n3 ) +{ + sal_Int32 nMin = n1 < n2 ? n1 : n2; + return nMin < n3 ? nMin : n3; +} + +class IntArray2D +{ +private: + sal_Int32 *pData; + int n1, n2; + +public: + IntArray2D( int nDim1, int nDim2 ); + ~IntArray2D(); + + sal_Int32 & Value( int i, int k ); +}; + +IntArray2D::IntArray2D( int nDim1, int nDim2 ) +{ + n1 = nDim1; + n2 = nDim2; + pData = new sal_Int32[n1 * n2]; +} + +IntArray2D::~IntArray2D() +{ + delete[] pData; +} + +sal_Int32 & IntArray2D::Value( int i, int k ) +{ + DBG_ASSERT( 0 <= i && i < n1, "first index out of range" ); + DBG_ASSERT( 0 <= k && k < n2, "first index out of range" ); + DBG_ASSERT( i * n2 + k < n1 * n2, "index out of range" ); + return pData[ i * n2 + k ]; +} + + +sal_Int32 LevDistance( const OUString &rTxt1, const OUString &rTxt2 ) +{ + sal_Int32 nLen1 = rTxt1.getLength(); + sal_Int32 nLen2 = rTxt2.getLength(); + + if (nLen1 == 0) + return nLen2; + if (nLen2 == 0) + return nLen1; + + IntArray2D aData( nLen1 + 1, nLen2 + 1 ); + + sal_Int32 i, k; + for (i = 0; i <= nLen1; ++i) + aData.Value(i, 0) = i; + for (k = 0; k <= nLen2; ++k) + aData.Value(0, k) = k; + for (i = 1; i <= nLen1; ++i) + { + for (k = 1; k <= nLen2; ++k) + { + sal_Unicode c1i = rTxt1.getStr()[i - 1]; + sal_Unicode c2k = rTxt2.getStr()[k - 1]; + sal_Int32 nCost = c1i == c2k ? 0 : 1; + sal_Int32 nNew = Minimum( aData.Value(i-1, k ) + 1, + aData.Value(i , k-1) + 1, + aData.Value(i-1, k-1) + nCost ); + // take transposition (exchange with left or right char) in account + if (2 < i && 2 < k) + { + int nT = aData.Value(i-2, k-2) + 1; + if (rTxt1.getStr()[i - 2] != c1i) + ++nT; + if (rTxt2.getStr()[k - 2] != c2k) + ++nT; + if (nT < nNew) + nNew = nT; + } + + aData.Value(i, k) = nNew; + } + } + sal_Int32 nDist = aData.Value(nLen1, nLen2); + return nDist; + } + + +sal_Bool IsUseDicList( const PropertyValues &rProperties, + const uno::Reference< XPropertySet > &rxProp ) +{ + sal_Bool bRes = sal_True; + + sal_Int32 nLen = rProperties.getLength(); + const PropertyValue *pVal = rProperties.getConstArray(); + sal_Int32 i; + + for ( i = 0; i < nLen; ++i) + { + if (UPH_IS_USE_DICTIONARY_LIST == pVal[i].Handle) + { + pVal[i].Value >>= bRes; + break; + } + } + if (i >= nLen) // no temporary value found in 'rProperties' + { + uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY ); + if (xFast.is()) + xFast->getFastPropertyValue( UPH_IS_USE_DICTIONARY_LIST ) >>= bRes; + } + + return bRes; +} + + +sal_Bool IsIgnoreControlChars( const PropertyValues &rProperties, + const uno::Reference< XPropertySet > &rxProp ) +{ + sal_Bool bRes = sal_True; + + sal_Int32 nLen = rProperties.getLength(); + const PropertyValue *pVal = rProperties.getConstArray(); + sal_Int32 i; + + for ( i = 0; i < nLen; ++i) + { + if (UPH_IS_IGNORE_CONTROL_CHARACTERS == pVal[i].Handle) + { + pVal[i].Value >>= bRes; + break; + } + } + if (i >= nLen) // no temporary value found in 'rProperties' + { + uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY ); + if (xFast.is()) + xFast->getFastPropertyValue( UPH_IS_IGNORE_CONTROL_CHARACTERS ) >>= bRes; + } + + return bRes; +} + + +static sal_Bool lcl_HasHyphInfo( const uno::Reference<XDictionaryEntry> &xEntry ) +{ + sal_Bool bRes = sal_False; + if (xEntry.is()) + { + // there has to be (at least one) '=' denoting a hyphenation position + // and it must not be before any character of the word + sal_Int32 nIdx = xEntry->getDictionaryWord().indexOf( '=' ); + bRes = nIdx != -1 && nIdx != 0; + } + return bRes; +} + + +uno::Reference< XDictionaryEntry > SearchDicList( + const uno::Reference< XDictionaryList > &xDicList, + const OUString &rWord, sal_Int16 nLanguage, + sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry ) +{ + MutexGuard aGuard( GetLinguMutex() ); + + uno::Reference< XDictionaryEntry > xEntry; + + if (!xDicList.is()) + return xEntry; + + const uno::Sequence< uno::Reference< XDictionary > > + aDics( xDicList->getDictionaries() ); + const uno::Reference< XDictionary > + *pDic = aDics.getConstArray(); + sal_Int32 nDics = xDicList->getCount(); + + sal_Int32 i; + for (i = 0; i < nDics; i++) + { + uno::Reference< XDictionary > axDic( pDic[i], UNO_QUERY ); + + DictionaryType eType = axDic->getDictionaryType(); + sal_Int16 nLang = LocaleToLanguage( axDic->getLocale() ); + + if ( axDic.is() && axDic->isActive() + && (nLang == nLanguage || nLang == LANGUAGE_NONE) ) + { + DBG_ASSERT( eType != DictionaryType_MIXED, + "lng : unexpected dictionary type" ); + + if ( (!bSearchPosDics && eType == DictionaryType_NEGATIVE) + || ( bSearchPosDics && eType == DictionaryType_POSITIVE)) + { + if ( (xEntry = axDic->getEntry( rWord )).is() ) + { + if (bSearchSpellEntry || lcl_HasHyphInfo( xEntry )) + break; + } + xEntry = 0; + } + } + } + + return xEntry; +} + + +sal_Bool SaveDictionaries( const uno::Reference< XDictionaryList > &xDicList ) +{ + if (!xDicList.is()) + return sal_True; + + sal_Bool bRet = sal_True; + + Sequence< uno::Reference< XDictionary > > aDics( xDicList->getDictionaries() ); + const uno::Reference< XDictionary > *pDic = aDics.getConstArray(); + sal_Int32 nCount = aDics.getLength(); + for (sal_Int32 i = 0; i < nCount; i++) + { + try + { + uno::Reference< frame::XStorable > xStor( pDic[i], UNO_QUERY ); + if (xStor.is()) + { + if (!xStor->isReadonly() && xStor->hasLocation()) + xStor->store(); + } + } + catch(uno::Exception &) + { + bRet = sal_False; + } + } + + return bRet; +} + + +sal_uInt8 AddEntryToDic( + uno::Reference< XDictionary > &rxDic, + const OUString &rWord, sal_Bool bIsNeg, + const OUString &rRplcTxt, sal_Int16 /* nRplcLang */, + sal_Bool bStripDot ) +{ + if (!rxDic.is()) + return DIC_ERR_NOT_EXISTS; + + OUString aTmp( rWord ); + if (bStripDot) + { + sal_Int32 nLen = rWord.getLength(); + if (nLen > 0 && '.' == rWord[ nLen - 1]) + { + // remove trailing '.' + // (this is the official way to do this :-( ) + aTmp = aTmp.copy( 0, nLen - 1 ); + } + } + sal_Bool bAddOk = rxDic->add( aTmp, bIsNeg, rRplcTxt ); + + sal_uInt8 nRes = DIC_ERR_NONE; + if (!bAddOk) + { + if (rxDic->isFull()) + nRes = DIC_ERR_FULL; + else + { + uno::Reference< frame::XStorable > xStor( rxDic, UNO_QUERY ); + if (xStor.is() && xStor->isReadonly()) + nRes = DIC_ERR_READONLY; + else + nRes = DIC_ERR_UNKNOWN; + } + } + + return nRes; +} + + + +LanguageType LocaleToLanguage( const Locale& rLocale ) +{ + // empty Locale -> LANGUAGE_NONE + if ( rLocale.Language.getLength() == 0 ) + return LANGUAGE_NONE; + + return MsLangId::convertLocaleToLanguage( rLocale ); +} + + +Locale& LanguageToLocale( Locale& rLocale, LanguageType eLang ) +{ + if ( eLang != LANGUAGE_NONE /* && eLang != LANGUAGE_SYSTEM */) + MsLangId::convertLanguageToLocale( eLang, rLocale ); + + return rLocale; +} + +Locale CreateLocale( LanguageType eLang ) +{ + Locale aLocale; + if ( eLang != LANGUAGE_NONE /* && eLang != LANGUAGE_SYSTEM */) + return MsLangId::convertLanguageToLocale( eLang ); + + return aLocale; +} + +uno::Sequence< sal_Int16 > + LocaleSeqToLangSeq( uno::Sequence< Locale > &rLocaleSeq ) +{ + const Locale *pLocale = rLocaleSeq.getConstArray(); + sal_Int32 nCount = rLocaleSeq.getLength(); + + uno::Sequence< sal_Int16 > aLangs( nCount ); + sal_Int16 *pLang = aLangs.getArray(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + pLang[i] = LocaleToLanguage( pLocale[i] ); + } + + return aLangs; +} + + +sal_Bool IsReadOnly( const String &rURL, sal_Bool *pbExist ) +{ + sal_Bool bRes = sal_False; + sal_Bool bExists = sal_False; + + if (rURL.Len() > 0) + { + try + { + uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv; + ::ucbhelper::Content aContent( rURL, xCmdEnv ); + + bExists = aContent.isDocument(); + if (bExists) + { + Any aAny( aContent.getPropertyValue( A2OU( "IsReadOnly" ) ) ); + aAny >>= bRes; + } + } + catch (Exception &) + { + bRes = sal_True; + } + } + + if (pbExist) + *pbExist = bExists; + return bRes; +} + + + +static sal_Bool GetAltSpelling( sal_Int16 &rnChgPos, sal_Int16 &rnChgLen, OUString &rRplc, + uno::Reference< XHyphenatedWord > &rxHyphWord ) +{ + sal_Bool bRes = rxHyphWord->isAlternativeSpelling(); + if (bRes) + { + OUString aWord( rxHyphWord->getWord() ), + aHyphenatedWord( rxHyphWord->getHyphenatedWord() ); + sal_Int16 nHyphenationPos = rxHyphWord->getHyphenationPos(); + /*sal_Int16 nHyphenPos = rxHyphWord->getHyphenPos()*/; + const sal_Unicode *pWord = aWord.getStr(), + *pAltWord = aHyphenatedWord.getStr(); + + // at least char changes directly left or right to the hyphen + // should(!) be handled properly... + //! nHyphenationPos and nHyphenPos differ at most by 1 (see above) + //! Beware: eg "Schiffahrt" in German (pre spelling reform) + //! proves to be a bit nasty (nChgPosLeft and nChgPosRight overlap + //! to an extend.) + + // find first different char from left + sal_Int32 nPosL = 0, + nAltPosL = 0; + for (sal_Int16 i = 0 ; pWord[ nPosL ] == pAltWord[ nAltPosL ]; nPosL++, nAltPosL++, i++) + { + // restrict changes area beginning to the right to + // the char immediately following the hyphen. + //! serves to insert the additional "f" in "Schiffahrt" at + //! position 5 rather than position 6. + if (i >= nHyphenationPos + 1) + break; + } + + // find first different char from right + sal_Int32 nPosR = aWord.getLength() - 1, + nAltPosR = aHyphenatedWord.getLength() - 1; + for ( ; nPosR >= nPosL && nAltPosR >= nAltPosL + && pWord[ nPosR ] == pAltWord[ nAltPosR ]; + nPosR--, nAltPosR--) + ; + + rnChgPos = sal::static_int_cast< sal_Int16 >(nPosL); + rnChgLen = sal::static_int_cast< sal_Int16 >(nPosR - nPosL + 1); + DBG_ASSERT( rnChgLen >= 0, "nChgLen < 0"); + + sal_Int32 nTxtStart = nPosL; + sal_Int32 nTxtLen = nAltPosL - nPosL + 1; + rRplc = aHyphenatedWord.copy( nTxtStart, nTxtLen ); + } + return bRes; +} + + +static sal_Int16 GetOrigWordPos( const OUString &rOrigWord, sal_Int16 nPos ) +{ + sal_Int32 nLen = rOrigWord.getLength(); + sal_Int32 i = -1; + while (nPos >= 0 && i++ < nLen) + { + sal_Unicode cChar = rOrigWord[i]; + sal_Bool bSkip = IsHyphen( cChar ) || IsControlChar( cChar ); + if (!bSkip) + --nPos; + } + return sal::static_int_cast< sal_Int16 >((0 <= i && i < nLen) ? i : -1); +} + + +sal_Int32 GetPosInWordToCheck( const OUString &rTxt, sal_Int32 nPos ) +{ + sal_Int32 nRes = -1; + sal_Int32 nLen = rTxt.getLength(); + if (0 <= nPos && nPos < nLen) + { + nRes = 0; + for (sal_Int32 i = 0; i < nPos; ++i) + { + sal_Unicode cChar = rTxt[i]; + sal_Bool bSkip = IsHyphen( cChar ) || IsControlChar( cChar ); + if (!bSkip) + ++nRes; + } + } + return nRes; +} + + +uno::Reference< XHyphenatedWord > RebuildHyphensAndControlChars( + const OUString &rOrigWord, + uno::Reference< XHyphenatedWord > &rxHyphWord ) +{ + uno::Reference< XHyphenatedWord > xRes; + if (rOrigWord.getLength() && rxHyphWord.is()) + { + sal_Int16 nChgPos = 0, + nChgLen = 0; + OUString aRplc; + sal_Bool bAltSpelling = GetAltSpelling( nChgPos, nChgLen, aRplc, rxHyphWord ); +#if OSL_DEBUG_LEVEL > 1 + OUString aWord( rxHyphWord->getWord() ); +#endif + + OUString aOrigHyphenatedWord; + sal_Int16 nOrigHyphenPos = -1; + sal_Int16 nOrigHyphenationPos = -1; + if (!bAltSpelling) + { + aOrigHyphenatedWord = rOrigWord; + nOrigHyphenPos = GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenPos() ); + nOrigHyphenationPos = GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenationPos() ); + } + else + { + //! should at least work with the German words + //! B�-c-k-er and Sc-hif-fah-rt + + OUString aLeft, aRight; + sal_Int16 nPos = GetOrigWordPos( rOrigWord, nChgPos ); + + // get words like Sc-hif-fah-rt to work correct + sal_Int16 nHyphenationPos = rxHyphWord->getHyphenationPos(); + if (nChgPos > nHyphenationPos) + --nPos; + + aLeft = rOrigWord.copy( 0, nPos ); + aRight = rOrigWord.copy( nPos + nChgLen ); + + aOrigHyphenatedWord = aLeft; + aOrigHyphenatedWord += aRplc; + aOrigHyphenatedWord += aRight; + + nOrigHyphenPos = sal::static_int_cast< sal_Int16 >(aLeft.getLength() + + rxHyphWord->getHyphenPos() - nChgPos); + nOrigHyphenationPos = GetOrigWordPos( rOrigWord, nHyphenationPos ); + } + + if (nOrigHyphenPos == -1 || nOrigHyphenationPos == -1) + { + DBG_ASSERT( 0, "failed to get nOrigHyphenPos or nOrigHyphenationPos" ); + } + else + { + sal_Int16 nLang = LocaleToLanguage( rxHyphWord->getLocale() ); + xRes = new HyphenatedWord( + rOrigWord, nLang, nOrigHyphenationPos, + aOrigHyphenatedWord, nOrigHyphenPos ); + } + + } + return xRes; +} + + + + +static CharClass & lcl_GetCharClass() +{ + static CharClass aCC( CreateLocale( LANGUAGE_ENGLISH_US ) ); + return aCC; +} + + +osl::Mutex & lcl_GetCharClassMutex() +{ + static osl::Mutex aMutex; + return aMutex; +} + + +sal_Bool IsUpper( const String &rText, xub_StrLen nPos, xub_StrLen nLen, sal_Int16 nLanguage ) +{ + MutexGuard aGuard( lcl_GetCharClassMutex() ); + + CharClass &rCC = lcl_GetCharClass(); + rCC.setLocale( CreateLocale( nLanguage ) ); + sal_Int32 nFlags = rCC.getStringType( rText, nPos, nLen ); + return (nFlags & KCharacterType::UPPER) + && !(nFlags & KCharacterType::LOWER); +} + + +sal_Bool IsLower( const String &rText, xub_StrLen nPos, xub_StrLen nLen, sal_Int16 nLanguage ) +{ + MutexGuard aGuard( lcl_GetCharClassMutex() ); + + CharClass &rCC = lcl_GetCharClass(); + rCC.setLocale( CreateLocale( nLanguage ) ); + sal_Int32 nFlags = rCC.getStringType( rText, nPos, nLen ); + return (nFlags & KCharacterType::LOWER) + && !(nFlags & KCharacterType::UPPER); +} + + +String ToLower( const String &rText, sal_Int16 nLanguage ) +{ + MutexGuard aGuard( lcl_GetCharClassMutex() ); + + CharClass &rCC = lcl_GetCharClass(); + rCC.setLocale( CreateLocale( nLanguage ) ); + return rCC.lower( rText ); +} + + +String ToUpper( const String &rText, sal_Int16 nLanguage ) +{ + MutexGuard aGuard( lcl_GetCharClassMutex() ); + + CharClass &rCC = lcl_GetCharClass(); + rCC.setLocale( CreateLocale( nLanguage ) ); + return rCC.upper( rText ); +} + + +String ToTitle( const String &rText, sal_Int16 nLanguage ) +{ + MutexGuard aGuard( lcl_GetCharClassMutex() ); + + CharClass &rCC = lcl_GetCharClass(); + rCC.setLocale( CreateLocale( nLanguage ) ); + return rCC.toTitle( rText, 0, rText.Len() ); +} + + +sal_Unicode ToLower( const sal_Unicode cChar, sal_Int16 nLanguage ) +{ + MutexGuard aGuard( lcl_GetCharClassMutex() ); + + CharClass &rCC = lcl_GetCharClass(); + rCC.setLocale( CreateLocale( nLanguage ) ); + return rCC.lower( cChar ).GetChar(0); +} + + +sal_Unicode ToUpper( const sal_Unicode cChar, sal_Int16 nLanguage ) +{ + MutexGuard aGuard( lcl_GetCharClassMutex() ); + + CharClass &rCC = lcl_GetCharClass(); + rCC.setLocale( CreateLocale( nLanguage ) ); + return rCC.upper( cChar ).GetChar(0); +} + +// sorted(!) array of unicode ranges for code points that are exclusively(!) used as numbers +// and thus may NOT not be part of names or words like the Chinese/Japanese number characters +static const sal_uInt32 the_aDigitZeroes [] = +{ + 0x00000030, //0039 ; Decimal # Nd [10] DIGIT ZERO..DIGIT NINE + 0x00000660, //0669 ; Decimal # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE + 0x000006F0, //06F9 ; Decimal # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE + 0x000007C0, //07C9 ; Decimal # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE + 0x00000966, //096F ; Decimal # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE + 0x000009E6, //09EF ; Decimal # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE + 0x00000A66, //0A6F ; Decimal # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE + 0x00000AE6, //0AEF ; Decimal # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE + 0x00000B66, //0B6F ; Decimal # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE + 0x00000BE6, //0BEF ; Decimal # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE + 0x00000C66, //0C6F ; Decimal # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE + 0x00000CE6, //0CEF ; Decimal # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE + 0x00000D66, //0D6F ; Decimal # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE + 0x00000E50, //0E59 ; Decimal # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE + 0x00000ED0, //0ED9 ; Decimal # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE + 0x00000F20, //0F29 ; Decimal # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE + 0x00001040, //1049 ; Decimal # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE + 0x00001090, //1099 ; Decimal # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE + 0x000017E0, //17E9 ; Decimal # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE + 0x00001810, //1819 ; Decimal # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE + 0x00001946, //194F ; Decimal # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE + 0x000019D0, //19D9 ; Decimal # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE + 0x00001B50, //1B59 ; Decimal # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE + 0x00001BB0, //1BB9 ; Decimal # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE + 0x00001C40, //1C49 ; Decimal # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE + 0x00001C50, //1C59 ; Decimal # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE + 0x0000A620, //A629 ; Decimal # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE + 0x0000A8D0, //A8D9 ; Decimal # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE + 0x0000A900, //A909 ; Decimal # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE + 0x0000AA50, //AA59 ; Decimal # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE + 0x0000FF10, //FF19 ; Decimal # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE + 0x000104A0, //104A9 ; Decimal # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE + 0x0001D7CE //1D7FF ; Decimal # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE +}; + +sal_Bool HasDigits( const OUString &rText ) +{ + static const int nNumDigitZeroes = SAL_N_ELEMENTS(the_aDigitZeroes); + const sal_Int32 nLen = rText.getLength(); + + sal_Int32 i = 0; + while (i < nLen) // for all characters ... + { + const sal_uInt32 nCodePoint = rText.iterateCodePoints( &i ); // handle unicode surrogates correctly... + for (int j = 0; j < nNumDigitZeroes; ++j) // ... check in all 0..9 ranges + { + sal_uInt32 nDigitZero = the_aDigitZeroes[ j ]; + if (nDigitZero > nCodePoint) + break; + if (/*nDigitZero <= nCodePoint &&*/ nCodePoint <= nDigitZero + 9) + return sal_True; + } + } + return sal_False; +} + + +sal_Bool IsNumeric( const String &rText ) +{ + sal_Bool bRes = sal_False; + xub_StrLen nLen = rText.Len(); + if (nLen) + { + bRes = sal_True; + xub_StrLen i = 0; + while (i < nLen) + { + sal_Unicode cChar = rText.GetChar( i++ ); + if ( !((sal_Unicode)'0' <= cChar && cChar <= (sal_Unicode)'9') ) + { + bRes = sal_False; + break; + } + } + } + return bRes; +} + + + +uno::Reference< XInterface > GetOneInstanceService( const char *pServiceName ) +{ + uno::Reference< XInterface > xRef; + + if (pServiceName) + { + uno::Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() ); + if (xMgr.is()) + { + try + { + xRef = xMgr->createInstance( ::rtl::OUString::createFromAscii( pServiceName ) ); + } + catch (uno::Exception &) + { + DBG_ASSERT( 0, "createInstance failed" ); + } + } + } + + return xRef; +} + +uno::Reference< XPropertySet > GetLinguProperties() +{ + return uno::Reference< XPropertySet > ( + GetOneInstanceService( SN_LINGU_PROPERTIES ), UNO_QUERY ); +} + +uno::Reference< XSearchableDictionaryList > GetSearchableDictionaryList() +{ + return uno::Reference< XSearchableDictionaryList > ( + GetOneInstanceService( SN_DICTIONARY_LIST ), UNO_QUERY ); +} + +uno::Reference< XDictionaryList > GetDictionaryList() +{ + return uno::Reference< XDictionaryList > ( + GetOneInstanceService( SN_DICTIONARY_LIST ), UNO_QUERY ); +} + +uno::Reference< XDictionary > GetIgnoreAllList() +{ + uno::Reference< XDictionary > xRes; + uno::Reference< XDictionaryList > xDL( GetDictionaryList() ); + if (xDL.is()) + xRes = xDL->getDictionaryByName( A2OU("IgnoreAllList") ); + return xRes; +} + + +AppExitListener::AppExitListener() +{ + // add object to Desktop EventListeners in order to properly call + // the AtExit function at appliction exit. + uno::Reference< XMultiServiceFactory > xMgr = getProcessServiceFactory(); + + if (xMgr.is()) + { + try + { + xDesktop = uno::Reference< frame::XDesktop >( + xMgr->createInstance( A2OU( SN_DESKTOP ) ), UNO_QUERY ); + } + catch (uno::Exception &) + { + DBG_ASSERT( 0, "createInstance failed" ); + } + } +} + +AppExitListener::~AppExitListener() +{ +} + + +void AppExitListener::Activate() +{ + if (xDesktop.is()) + xDesktop->addTerminateListener( this ); +} + + +void AppExitListener::Deactivate() +{ + if (xDesktop.is()) + xDesktop->removeTerminateListener( this ); +} + + +void SAL_CALL + AppExitListener::disposing( const EventObject& rEvtSource ) + throw(RuntimeException) +{ + MutexGuard aGuard( GetLinguMutex() ); + + if (xDesktop.is() && rEvtSource.Source == xDesktop) + { + xDesktop = NULL; //! release reference to desktop + } +} + + +void SAL_CALL + AppExitListener::queryTermination( const EventObject& /*rEvtSource*/ ) + throw(frame::TerminationVetoException, RuntimeException) +{ +} + + +void SAL_CALL + AppExitListener::notifyTermination( const EventObject& rEvtSource ) + throw(RuntimeException) +{ + MutexGuard aGuard( GetLinguMutex() ); + + if (xDesktop.is() && rEvtSource.Source == xDesktop) + { + AtExit(); + } +} + + +} // namespace linguistic + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |