1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_linguistic.hxx" 30*cdf0e10cSrcweir #include <tools/string.hxx> 31*cdf0e10cSrcweir #include <tools/fsys.hxx> 32*cdf0e10cSrcweir #include <tools/debug.hxx> 33*cdf0e10cSrcweir #include <unotools/pathoptions.hxx> 34*cdf0e10cSrcweir #include <svl/lngmisc.hxx> 35*cdf0e10cSrcweir #include <ucbhelper/content.hxx> 36*cdf0e10cSrcweir #include <i18npool/mslangid.hxx> 37*cdf0e10cSrcweir #include <com/sun/star/ucb/XCommandEnvironment.hpp> 38*cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 39*cdf0e10cSrcweir #include <com/sun/star/beans/XFastPropertySet.hpp> 40*cdf0e10cSrcweir #include <com/sun/star/beans/XPropertyChangeListener.hpp> 41*cdf0e10cSrcweir #include <com/sun/star/frame/XTerminateListener.hpp> 42*cdf0e10cSrcweir #include <com/sun/star/frame/XDesktop.hpp> 43*cdf0e10cSrcweir #include <com/sun/star/frame/XStorable.hpp> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValues.hpp> 46*cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.hxx> 47*cdf0e10cSrcweir #include <com/sun/star/uno/Reference.h> 48*cdf0e10cSrcweir #include <com/sun/star/linguistic2/DictionaryType.hpp> 49*cdf0e10cSrcweir #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp> 50*cdf0e10cSrcweir #include <unotools/processfactory.hxx> 51*cdf0e10cSrcweir #include <unotools/localedatawrapper.hxx> 52*cdf0e10cSrcweir #include <unotools/syslocale.hxx> 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir #include <rtl/instance.hxx> 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir #include "linguistic/misc.hxx" 57*cdf0e10cSrcweir #include "defs.hxx" 58*cdf0e10cSrcweir #include "linguistic/lngprops.hxx" 59*cdf0e10cSrcweir #include "linguistic/hyphdta.hxx" 60*cdf0e10cSrcweir #include <i18npool/mslangid.hxx> 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir using namespace utl; 63*cdf0e10cSrcweir using namespace osl; 64*cdf0e10cSrcweir using namespace rtl; 65*cdf0e10cSrcweir using namespace com::sun::star; 66*cdf0e10cSrcweir using namespace com::sun::star::beans; 67*cdf0e10cSrcweir using namespace com::sun::star::lang; 68*cdf0e10cSrcweir using namespace com::sun::star::uno; 69*cdf0e10cSrcweir using namespace com::sun::star::i18n; 70*cdf0e10cSrcweir using namespace com::sun::star::linguistic2; 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir namespace linguistic 73*cdf0e10cSrcweir { 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 76*cdf0e10cSrcweir 77*cdf0e10cSrcweir //!! multi-thread safe mutex for all platforms !! 78*cdf0e10cSrcweir struct LinguMutex : public rtl::Static< osl::Mutex, LinguMutex > 79*cdf0e10cSrcweir { 80*cdf0e10cSrcweir }; 81*cdf0e10cSrcweir 82*cdf0e10cSrcweir osl::Mutex & GetLinguMutex() 83*cdf0e10cSrcweir { 84*cdf0e10cSrcweir return LinguMutex::get(); 85*cdf0e10cSrcweir } 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 88*cdf0e10cSrcweir 89*cdf0e10cSrcweir LocaleDataWrapper & GetLocaleDataWrapper( sal_Int16 nLang ) 90*cdf0e10cSrcweir { 91*cdf0e10cSrcweir static LocaleDataWrapper aLclDtaWrp( 92*cdf0e10cSrcweir getProcessServiceFactory(), 93*cdf0e10cSrcweir CreateLocale( SvtSysLocale().GetUILanguage() ) ); 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir const Locale &rLcl = aLclDtaWrp.getLoadedLocale(); 96*cdf0e10cSrcweir Locale aLcl( CreateLocale( nLang ) ); 97*cdf0e10cSrcweir if (aLcl.Language != rLcl.Language || 98*cdf0e10cSrcweir aLcl.Country != rLcl.Country || 99*cdf0e10cSrcweir aLcl.Variant != rLcl.Variant) 100*cdf0e10cSrcweir aLclDtaWrp.setLocale( aLcl ); 101*cdf0e10cSrcweir return aLclDtaWrp; 102*cdf0e10cSrcweir } 103*cdf0e10cSrcweir 104*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir /** 107*cdf0e10cSrcweir returns text-encoding used for ByteString unicode String conversion 108*cdf0e10cSrcweir */ 109*cdf0e10cSrcweir rtl_TextEncoding GetTextEncoding( sal_Int16 nLanguage ) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir DBG_ASSERT( nLanguage != LANGUAGE_NONE, "invalid language argument" ); 112*cdf0e10cSrcweir static sal_Int16 nLastLanguage = LANGUAGE_NONE; 113*cdf0e10cSrcweir 114*cdf0e10cSrcweir // set default value for unknown languages 115*cdf0e10cSrcweir static rtl_TextEncoding nEncoding = RTL_TEXTENCODING_DONTKNOW; 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir if (nLastLanguage != nLanguage) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir //!! IPR uses textencodings Latin-1, Latin-2, Latin-5 and Latin-7 !! 120*cdf0e10cSrcweir 121*cdf0e10cSrcweir nLastLanguage = nLanguage; 122*cdf0e10cSrcweir switch (nLanguage) 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir case LANGUAGE_GERMAN : 125*cdf0e10cSrcweir case LANGUAGE_GERMAN_SWISS : 126*cdf0e10cSrcweir case LANGUAGE_ENGLISH_US : 127*cdf0e10cSrcweir case LANGUAGE_ENGLISH_UK : 128*cdf0e10cSrcweir case LANGUAGE_FRENCH : 129*cdf0e10cSrcweir case LANGUAGE_ITALIAN : 130*cdf0e10cSrcweir case LANGUAGE_SPANISH : 131*cdf0e10cSrcweir case LANGUAGE_CATALAN : 132*cdf0e10cSrcweir case LANGUAGE_PORTUGUESE : 133*cdf0e10cSrcweir case LANGUAGE_PORTUGUESE_BRAZILIAN : 134*cdf0e10cSrcweir case LANGUAGE_DANISH : 135*cdf0e10cSrcweir case LANGUAGE_DUTCH : 136*cdf0e10cSrcweir case LANGUAGE_SWEDISH : 137*cdf0e10cSrcweir case LANGUAGE_FINNISH : 138*cdf0e10cSrcweir case LANGUAGE_NORWEGIAN_BOKMAL : 139*cdf0e10cSrcweir case LANGUAGE_NORWEGIAN_NYNORSK : 140*cdf0e10cSrcweir case LANGUAGE_AFRIKAANS : 141*cdf0e10cSrcweir case LANGUAGE_ENGLISH_EIRE : 142*cdf0e10cSrcweir case LANGUAGE_ENGLISH_AUS : 143*cdf0e10cSrcweir #ifdef WNT 144*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_MS_1252; break; 145*cdf0e10cSrcweir #else 146*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_ISO_8859_1; break; 147*cdf0e10cSrcweir #endif 148*cdf0e10cSrcweir case LANGUAGE_CZECH : 149*cdf0e10cSrcweir case LANGUAGE_HUNGARIAN : 150*cdf0e10cSrcweir case LANGUAGE_POLISH : 151*cdf0e10cSrcweir #ifdef WNT 152*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_MS_1250; break; 153*cdf0e10cSrcweir #else 154*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_ISO_8859_2; break; 155*cdf0e10cSrcweir #endif 156*cdf0e10cSrcweir case LANGUAGE_RUSSIAN : 157*cdf0e10cSrcweir #ifdef WNT 158*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_MS_1251; break; 159*cdf0e10cSrcweir #else 160*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_ISO_8859_5; break; 161*cdf0e10cSrcweir #endif 162*cdf0e10cSrcweir case LANGUAGE_GREEK : 163*cdf0e10cSrcweir #ifdef WNT 164*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_MS_1253; break; 165*cdf0e10cSrcweir #else 166*cdf0e10cSrcweir nEncoding = RTL_TEXTENCODING_ISO_8859_7; break; 167*cdf0e10cSrcweir #endif 168*cdf0e10cSrcweir default: 169*cdf0e10cSrcweir DBG_ASSERT( 0, "unexpected language" ); 170*cdf0e10cSrcweir } 171*cdf0e10cSrcweir } 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir return nEncoding; 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir static inline sal_Int32 Minimum( sal_Int32 n1, sal_Int32 n2, sal_Int32 n3 ) 179*cdf0e10cSrcweir { 180*cdf0e10cSrcweir sal_Int32 nMin = n1 < n2 ? n1 : n2; 181*cdf0e10cSrcweir return nMin < n3 ? nMin : n3; 182*cdf0e10cSrcweir } 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir class IntArray2D 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir private: 189*cdf0e10cSrcweir sal_Int32 *pData; 190*cdf0e10cSrcweir int n1, n2; 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir public: 193*cdf0e10cSrcweir IntArray2D( int nDim1, int nDim2 ); 194*cdf0e10cSrcweir ~IntArray2D(); 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir sal_Int32 & Value( int i, int k ); 197*cdf0e10cSrcweir }; 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir IntArray2D::IntArray2D( int nDim1, int nDim2 ) 200*cdf0e10cSrcweir { 201*cdf0e10cSrcweir n1 = nDim1; 202*cdf0e10cSrcweir n2 = nDim2; 203*cdf0e10cSrcweir pData = new sal_Int32[n1 * n2]; 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir IntArray2D::~IntArray2D() 207*cdf0e10cSrcweir { 208*cdf0e10cSrcweir delete[] pData; 209*cdf0e10cSrcweir } 210*cdf0e10cSrcweir 211*cdf0e10cSrcweir sal_Int32 & IntArray2D::Value( int i, int k ) 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir DBG_ASSERT( 0 <= i && i < n1, "first index out of range" ); 214*cdf0e10cSrcweir DBG_ASSERT( 0 <= k && k < n2, "first index out of range" ); 215*cdf0e10cSrcweir DBG_ASSERT( i * n2 + k < n1 * n2, "index out of range" ); 216*cdf0e10cSrcweir return pData[ i * n2 + k ]; 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir 220*cdf0e10cSrcweir sal_Int32 LevDistance( const OUString &rTxt1, const OUString &rTxt2 ) 221*cdf0e10cSrcweir { 222*cdf0e10cSrcweir sal_Int32 nLen1 = rTxt1.getLength(); 223*cdf0e10cSrcweir sal_Int32 nLen2 = rTxt2.getLength(); 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir if (nLen1 == 0) 226*cdf0e10cSrcweir return nLen2; 227*cdf0e10cSrcweir if (nLen2 == 0) 228*cdf0e10cSrcweir return nLen1; 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir IntArray2D aData( nLen1 + 1, nLen2 + 1 ); 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir sal_Int32 i, k; 233*cdf0e10cSrcweir for (i = 0; i <= nLen1; ++i) 234*cdf0e10cSrcweir aData.Value(i, 0) = i; 235*cdf0e10cSrcweir for (k = 0; k <= nLen2; ++k) 236*cdf0e10cSrcweir aData.Value(0, k) = k; 237*cdf0e10cSrcweir for (i = 1; i <= nLen1; ++i) 238*cdf0e10cSrcweir { 239*cdf0e10cSrcweir for (k = 1; k <= nLen2; ++k) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir sal_Unicode c1i = rTxt1.getStr()[i - 1]; 242*cdf0e10cSrcweir sal_Unicode c2k = rTxt2.getStr()[k - 1]; 243*cdf0e10cSrcweir sal_Int32 nCost = c1i == c2k ? 0 : 1; 244*cdf0e10cSrcweir sal_Int32 nNew = Minimum( aData.Value(i-1, k ) + 1, 245*cdf0e10cSrcweir aData.Value(i , k-1) + 1, 246*cdf0e10cSrcweir aData.Value(i-1, k-1) + nCost ); 247*cdf0e10cSrcweir // take transposition (exchange with left or right char) in account 248*cdf0e10cSrcweir if (2 < i && 2 < k) 249*cdf0e10cSrcweir { 250*cdf0e10cSrcweir int nT = aData.Value(i-2, k-2) + 1; 251*cdf0e10cSrcweir if (rTxt1.getStr()[i - 2] != c1i) 252*cdf0e10cSrcweir ++nT; 253*cdf0e10cSrcweir if (rTxt2.getStr()[k - 2] != c2k) 254*cdf0e10cSrcweir ++nT; 255*cdf0e10cSrcweir if (nT < nNew) 256*cdf0e10cSrcweir nNew = nT; 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir aData.Value(i, k) = nNew; 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir } 262*cdf0e10cSrcweir sal_Int32 nDist = aData.Value(nLen1, nLen2); 263*cdf0e10cSrcweir return nDist; 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir sal_Bool IsUseDicList( const PropertyValues &rProperties, 269*cdf0e10cSrcweir const uno::Reference< XPropertySet > &rxProp ) 270*cdf0e10cSrcweir { 271*cdf0e10cSrcweir sal_Bool bRes = sal_True; 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir sal_Int32 nLen = rProperties.getLength(); 274*cdf0e10cSrcweir const PropertyValue *pVal = rProperties.getConstArray(); 275*cdf0e10cSrcweir sal_Int32 i; 276*cdf0e10cSrcweir 277*cdf0e10cSrcweir for ( i = 0; i < nLen; ++i) 278*cdf0e10cSrcweir { 279*cdf0e10cSrcweir if (UPH_IS_USE_DICTIONARY_LIST == pVal[i].Handle) 280*cdf0e10cSrcweir { 281*cdf0e10cSrcweir pVal[i].Value >>= bRes; 282*cdf0e10cSrcweir break; 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir if (i >= nLen) // no temporary value found in 'rProperties' 286*cdf0e10cSrcweir { 287*cdf0e10cSrcweir uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY ); 288*cdf0e10cSrcweir if (xFast.is()) 289*cdf0e10cSrcweir xFast->getFastPropertyValue( UPH_IS_USE_DICTIONARY_LIST ) >>= bRes; 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir return bRes; 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir sal_Bool IsIgnoreControlChars( const PropertyValues &rProperties, 297*cdf0e10cSrcweir const uno::Reference< XPropertySet > &rxProp ) 298*cdf0e10cSrcweir { 299*cdf0e10cSrcweir sal_Bool bRes = sal_True; 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir sal_Int32 nLen = rProperties.getLength(); 302*cdf0e10cSrcweir const PropertyValue *pVal = rProperties.getConstArray(); 303*cdf0e10cSrcweir sal_Int32 i; 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir for ( i = 0; i < nLen; ++i) 306*cdf0e10cSrcweir { 307*cdf0e10cSrcweir if (UPH_IS_IGNORE_CONTROL_CHARACTERS == pVal[i].Handle) 308*cdf0e10cSrcweir { 309*cdf0e10cSrcweir pVal[i].Value >>= bRes; 310*cdf0e10cSrcweir break; 311*cdf0e10cSrcweir } 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir if (i >= nLen) // no temporary value found in 'rProperties' 314*cdf0e10cSrcweir { 315*cdf0e10cSrcweir uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY ); 316*cdf0e10cSrcweir if (xFast.is()) 317*cdf0e10cSrcweir xFast->getFastPropertyValue( UPH_IS_IGNORE_CONTROL_CHARACTERS ) >>= bRes; 318*cdf0e10cSrcweir } 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir return bRes; 321*cdf0e10cSrcweir } 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir 324*cdf0e10cSrcweir static sal_Bool lcl_HasHyphInfo( const uno::Reference<XDictionaryEntry> &xEntry ) 325*cdf0e10cSrcweir { 326*cdf0e10cSrcweir sal_Bool bRes = sal_False; 327*cdf0e10cSrcweir if (xEntry.is()) 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir // there has to be (at least one) '=' denoting a hyphenation position 330*cdf0e10cSrcweir // and it must not be before any character of the word 331*cdf0e10cSrcweir sal_Int32 nIdx = xEntry->getDictionaryWord().indexOf( '=' ); 332*cdf0e10cSrcweir bRes = nIdx != -1 && nIdx != 0; 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir return bRes; 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir uno::Reference< XDictionaryEntry > SearchDicList( 339*cdf0e10cSrcweir const uno::Reference< XDictionaryList > &xDicList, 340*cdf0e10cSrcweir const OUString &rWord, sal_Int16 nLanguage, 341*cdf0e10cSrcweir sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry ) 342*cdf0e10cSrcweir { 343*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir uno::Reference< XDictionaryEntry > xEntry; 346*cdf0e10cSrcweir 347*cdf0e10cSrcweir if (!xDicList.is()) 348*cdf0e10cSrcweir return xEntry; 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir const uno::Sequence< uno::Reference< XDictionary > > 351*cdf0e10cSrcweir aDics( xDicList->getDictionaries() ); 352*cdf0e10cSrcweir const uno::Reference< XDictionary > 353*cdf0e10cSrcweir *pDic = aDics.getConstArray(); 354*cdf0e10cSrcweir sal_Int32 nDics = xDicList->getCount(); 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir sal_Int32 i; 357*cdf0e10cSrcweir for (i = 0; i < nDics; i++) 358*cdf0e10cSrcweir { 359*cdf0e10cSrcweir uno::Reference< XDictionary > axDic( pDic[i], UNO_QUERY ); 360*cdf0e10cSrcweir 361*cdf0e10cSrcweir DictionaryType eType = axDic->getDictionaryType(); 362*cdf0e10cSrcweir sal_Int16 nLang = LocaleToLanguage( axDic->getLocale() ); 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir if ( axDic.is() && axDic->isActive() 365*cdf0e10cSrcweir && (nLang == nLanguage || nLang == LANGUAGE_NONE) ) 366*cdf0e10cSrcweir { 367*cdf0e10cSrcweir DBG_ASSERT( eType != DictionaryType_MIXED, 368*cdf0e10cSrcweir "lng : unexpected dictionary type" ); 369*cdf0e10cSrcweir 370*cdf0e10cSrcweir if ( (!bSearchPosDics && eType == DictionaryType_NEGATIVE) 371*cdf0e10cSrcweir || ( bSearchPosDics && eType == DictionaryType_POSITIVE)) 372*cdf0e10cSrcweir { 373*cdf0e10cSrcweir if ( (xEntry = axDic->getEntry( rWord )).is() ) 374*cdf0e10cSrcweir { 375*cdf0e10cSrcweir if (bSearchSpellEntry || lcl_HasHyphInfo( xEntry )) 376*cdf0e10cSrcweir break; 377*cdf0e10cSrcweir } 378*cdf0e10cSrcweir xEntry = 0; 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir } 381*cdf0e10cSrcweir } 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir return xEntry; 384*cdf0e10cSrcweir } 385*cdf0e10cSrcweir 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir sal_Bool SaveDictionaries( const uno::Reference< XDictionaryList > &xDicList ) 388*cdf0e10cSrcweir { 389*cdf0e10cSrcweir if (!xDicList.is()) 390*cdf0e10cSrcweir return sal_True; 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir sal_Bool bRet = sal_True; 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir Sequence< uno::Reference< XDictionary > > aDics( xDicList->getDictionaries() ); 395*cdf0e10cSrcweir const uno::Reference< XDictionary > *pDic = aDics.getConstArray(); 396*cdf0e10cSrcweir sal_Int32 nCount = aDics.getLength(); 397*cdf0e10cSrcweir for (sal_Int32 i = 0; i < nCount; i++) 398*cdf0e10cSrcweir { 399*cdf0e10cSrcweir try 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir uno::Reference< frame::XStorable > xStor( pDic[i], UNO_QUERY ); 402*cdf0e10cSrcweir if (xStor.is()) 403*cdf0e10cSrcweir { 404*cdf0e10cSrcweir if (!xStor->isReadonly() && xStor->hasLocation()) 405*cdf0e10cSrcweir xStor->store(); 406*cdf0e10cSrcweir } 407*cdf0e10cSrcweir } 408*cdf0e10cSrcweir catch(uno::Exception &) 409*cdf0e10cSrcweir { 410*cdf0e10cSrcweir bRet = sal_False; 411*cdf0e10cSrcweir } 412*cdf0e10cSrcweir } 413*cdf0e10cSrcweir 414*cdf0e10cSrcweir return bRet; 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir sal_uInt8 AddEntryToDic( 419*cdf0e10cSrcweir uno::Reference< XDictionary > &rxDic, 420*cdf0e10cSrcweir const OUString &rWord, sal_Bool bIsNeg, 421*cdf0e10cSrcweir const OUString &rRplcTxt, sal_Int16 /* nRplcLang */, 422*cdf0e10cSrcweir sal_Bool bStripDot ) 423*cdf0e10cSrcweir { 424*cdf0e10cSrcweir if (!rxDic.is()) 425*cdf0e10cSrcweir return DIC_ERR_NOT_EXISTS; 426*cdf0e10cSrcweir 427*cdf0e10cSrcweir OUString aTmp( rWord ); 428*cdf0e10cSrcweir if (bStripDot) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir sal_Int32 nLen = rWord.getLength(); 431*cdf0e10cSrcweir if (nLen > 0 && '.' == rWord[ nLen - 1]) 432*cdf0e10cSrcweir { 433*cdf0e10cSrcweir // remove trailing '.' 434*cdf0e10cSrcweir // (this is the official way to do this :-( ) 435*cdf0e10cSrcweir aTmp = aTmp.copy( 0, nLen - 1 ); 436*cdf0e10cSrcweir } 437*cdf0e10cSrcweir } 438*cdf0e10cSrcweir sal_Bool bAddOk = rxDic->add( aTmp, bIsNeg, rRplcTxt ); 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir sal_uInt8 nRes = DIC_ERR_NONE; 441*cdf0e10cSrcweir if (!bAddOk) 442*cdf0e10cSrcweir { 443*cdf0e10cSrcweir if (rxDic->isFull()) 444*cdf0e10cSrcweir nRes = DIC_ERR_FULL; 445*cdf0e10cSrcweir else 446*cdf0e10cSrcweir { 447*cdf0e10cSrcweir uno::Reference< frame::XStorable > xStor( rxDic, UNO_QUERY ); 448*cdf0e10cSrcweir if (xStor.is() && xStor->isReadonly()) 449*cdf0e10cSrcweir nRes = DIC_ERR_READONLY; 450*cdf0e10cSrcweir else 451*cdf0e10cSrcweir nRes = DIC_ERR_UNKNOWN; 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir } 454*cdf0e10cSrcweir 455*cdf0e10cSrcweir return nRes; 456*cdf0e10cSrcweir } 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir 459*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 460*cdf0e10cSrcweir 461*cdf0e10cSrcweir LanguageType LocaleToLanguage( const Locale& rLocale ) 462*cdf0e10cSrcweir { 463*cdf0e10cSrcweir // empty Locale -> LANGUAGE_NONE 464*cdf0e10cSrcweir if ( rLocale.Language.getLength() == 0 ) 465*cdf0e10cSrcweir return LANGUAGE_NONE; 466*cdf0e10cSrcweir 467*cdf0e10cSrcweir return MsLangId::convertLocaleToLanguage( rLocale ); 468*cdf0e10cSrcweir } 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir Locale& LanguageToLocale( Locale& rLocale, LanguageType eLang ) 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir if ( eLang != LANGUAGE_NONE /* && eLang != LANGUAGE_SYSTEM */) 474*cdf0e10cSrcweir MsLangId::convertLanguageToLocale( eLang, rLocale ); 475*cdf0e10cSrcweir 476*cdf0e10cSrcweir return rLocale; 477*cdf0e10cSrcweir } 478*cdf0e10cSrcweir 479*cdf0e10cSrcweir Locale CreateLocale( LanguageType eLang ) 480*cdf0e10cSrcweir { 481*cdf0e10cSrcweir Locale aLocale; 482*cdf0e10cSrcweir if ( eLang != LANGUAGE_NONE /* && eLang != LANGUAGE_SYSTEM */) 483*cdf0e10cSrcweir return MsLangId::convertLanguageToLocale( eLang ); 484*cdf0e10cSrcweir 485*cdf0e10cSrcweir return aLocale; 486*cdf0e10cSrcweir } 487*cdf0e10cSrcweir 488*cdf0e10cSrcweir uno::Sequence< Locale > LangSeqToLocaleSeq( const uno::Sequence< sal_Int16 > &rLangSeq ) 489*cdf0e10cSrcweir { 490*cdf0e10cSrcweir const sal_Int16 *pLang = rLangSeq.getConstArray(); 491*cdf0e10cSrcweir sal_Int32 nCount = rLangSeq.getLength(); 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir uno::Sequence< Locale > aLocales( nCount ); 494*cdf0e10cSrcweir Locale *pLocale = aLocales.getArray(); 495*cdf0e10cSrcweir for (sal_Int32 i = 0; i < nCount; ++i) 496*cdf0e10cSrcweir { 497*cdf0e10cSrcweir LanguageToLocale( pLocale[i], pLang[ i ] ); 498*cdf0e10cSrcweir } 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir return aLocales; 501*cdf0e10cSrcweir } 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir uno::Sequence< sal_Int16 > 504*cdf0e10cSrcweir LocaleSeqToLangSeq( uno::Sequence< Locale > &rLocaleSeq ) 505*cdf0e10cSrcweir { 506*cdf0e10cSrcweir const Locale *pLocale = rLocaleSeq.getConstArray(); 507*cdf0e10cSrcweir sal_Int32 nCount = rLocaleSeq.getLength(); 508*cdf0e10cSrcweir 509*cdf0e10cSrcweir uno::Sequence< sal_Int16 > aLangs( nCount ); 510*cdf0e10cSrcweir sal_Int16 *pLang = aLangs.getArray(); 511*cdf0e10cSrcweir for (sal_Int32 i = 0; i < nCount; ++i) 512*cdf0e10cSrcweir { 513*cdf0e10cSrcweir pLang[i] = LocaleToLanguage( pLocale[i] ); 514*cdf0e10cSrcweir } 515*cdf0e10cSrcweir 516*cdf0e10cSrcweir return aLangs; 517*cdf0e10cSrcweir } 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 520*cdf0e10cSrcweir 521*cdf0e10cSrcweir sal_Bool IsReadOnly( const String &rURL, sal_Bool *pbExist ) 522*cdf0e10cSrcweir { 523*cdf0e10cSrcweir sal_Bool bRes = sal_False; 524*cdf0e10cSrcweir sal_Bool bExists = sal_False; 525*cdf0e10cSrcweir 526*cdf0e10cSrcweir if (rURL.Len() > 0) 527*cdf0e10cSrcweir { 528*cdf0e10cSrcweir try 529*cdf0e10cSrcweir { 530*cdf0e10cSrcweir uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv; 531*cdf0e10cSrcweir ::ucbhelper::Content aContent( rURL, xCmdEnv ); 532*cdf0e10cSrcweir 533*cdf0e10cSrcweir bExists = aContent.isDocument(); 534*cdf0e10cSrcweir if (bExists) 535*cdf0e10cSrcweir { 536*cdf0e10cSrcweir Any aAny( aContent.getPropertyValue( A2OU( "IsReadOnly" ) ) ); 537*cdf0e10cSrcweir aAny >>= bRes; 538*cdf0e10cSrcweir } 539*cdf0e10cSrcweir } 540*cdf0e10cSrcweir catch (Exception &) 541*cdf0e10cSrcweir { 542*cdf0e10cSrcweir bRes = sal_True; 543*cdf0e10cSrcweir } 544*cdf0e10cSrcweir } 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir if (pbExist) 547*cdf0e10cSrcweir *pbExist = bExists; 548*cdf0e10cSrcweir return bRes; 549*cdf0e10cSrcweir } 550*cdf0e10cSrcweir 551*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 552*cdf0e10cSrcweir 553*cdf0e10cSrcweir 554*cdf0e10cSrcweir static sal_Bool GetAltSpelling( sal_Int16 &rnChgPos, sal_Int16 &rnChgLen, OUString &rRplc, 555*cdf0e10cSrcweir uno::Reference< XHyphenatedWord > &rxHyphWord ) 556*cdf0e10cSrcweir { 557*cdf0e10cSrcweir sal_Bool bRes = rxHyphWord->isAlternativeSpelling(); 558*cdf0e10cSrcweir if (bRes) 559*cdf0e10cSrcweir { 560*cdf0e10cSrcweir OUString aWord( rxHyphWord->getWord() ), 561*cdf0e10cSrcweir aHyphenatedWord( rxHyphWord->getHyphenatedWord() ); 562*cdf0e10cSrcweir sal_Int16 nHyphenationPos = rxHyphWord->getHyphenationPos(); 563*cdf0e10cSrcweir /*sal_Int16 nHyphenPos = rxHyphWord->getHyphenPos()*/; 564*cdf0e10cSrcweir const sal_Unicode *pWord = aWord.getStr(), 565*cdf0e10cSrcweir *pAltWord = aHyphenatedWord.getStr(); 566*cdf0e10cSrcweir 567*cdf0e10cSrcweir // at least char changes directly left or right to the hyphen 568*cdf0e10cSrcweir // should(!) be handled properly... 569*cdf0e10cSrcweir //! nHyphenationPos and nHyphenPos differ at most by 1 (see above) 570*cdf0e10cSrcweir //! Beware: eg "Schiffahrt" in German (pre spelling reform) 571*cdf0e10cSrcweir //! proves to be a bit nasty (nChgPosLeft and nChgPosRight overlap 572*cdf0e10cSrcweir //! to an extend.) 573*cdf0e10cSrcweir 574*cdf0e10cSrcweir // find first different char from left 575*cdf0e10cSrcweir sal_Int32 nPosL = 0, 576*cdf0e10cSrcweir nAltPosL = 0; 577*cdf0e10cSrcweir for (sal_Int16 i = 0 ; pWord[ nPosL ] == pAltWord[ nAltPosL ]; nPosL++, nAltPosL++, i++) 578*cdf0e10cSrcweir { 579*cdf0e10cSrcweir // restrict changes area beginning to the right to 580*cdf0e10cSrcweir // the char immediately following the hyphen. 581*cdf0e10cSrcweir //! serves to insert the additional "f" in "Schiffahrt" at 582*cdf0e10cSrcweir //! position 5 rather than position 6. 583*cdf0e10cSrcweir if (i >= nHyphenationPos + 1) 584*cdf0e10cSrcweir break; 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir 587*cdf0e10cSrcweir // find first different char from right 588*cdf0e10cSrcweir sal_Int32 nPosR = aWord.getLength() - 1, 589*cdf0e10cSrcweir nAltPosR = aHyphenatedWord.getLength() - 1; 590*cdf0e10cSrcweir for ( ; nPosR >= nPosL && nAltPosR >= nAltPosL 591*cdf0e10cSrcweir && pWord[ nPosR ] == pAltWord[ nAltPosR ]; 592*cdf0e10cSrcweir nPosR--, nAltPosR--) 593*cdf0e10cSrcweir ; 594*cdf0e10cSrcweir 595*cdf0e10cSrcweir rnChgPos = sal::static_int_cast< sal_Int16 >(nPosL); 596*cdf0e10cSrcweir rnChgLen = sal::static_int_cast< sal_Int16 >(nPosR - nPosL + 1); 597*cdf0e10cSrcweir DBG_ASSERT( rnChgLen >= 0, "nChgLen < 0"); 598*cdf0e10cSrcweir 599*cdf0e10cSrcweir sal_Int32 nTxtStart = nPosL; 600*cdf0e10cSrcweir sal_Int32 nTxtLen = nAltPosL - nPosL + 1; 601*cdf0e10cSrcweir rRplc = aHyphenatedWord.copy( nTxtStart, nTxtLen ); 602*cdf0e10cSrcweir } 603*cdf0e10cSrcweir return bRes; 604*cdf0e10cSrcweir } 605*cdf0e10cSrcweir 606*cdf0e10cSrcweir 607*cdf0e10cSrcweir static sal_Int16 GetOrigWordPos( const OUString &rOrigWord, sal_Int16 nPos ) 608*cdf0e10cSrcweir { 609*cdf0e10cSrcweir sal_Int32 nLen = rOrigWord.getLength(); 610*cdf0e10cSrcweir sal_Int32 i = -1; 611*cdf0e10cSrcweir while (nPos >= 0 && i++ < nLen) 612*cdf0e10cSrcweir { 613*cdf0e10cSrcweir sal_Unicode cChar = rOrigWord[i]; 614*cdf0e10cSrcweir sal_Bool bSkip = IsHyphen( cChar ) || IsControlChar( cChar ); 615*cdf0e10cSrcweir if (!bSkip) 616*cdf0e10cSrcweir --nPos; 617*cdf0e10cSrcweir } 618*cdf0e10cSrcweir return sal::static_int_cast< sal_Int16 >((0 <= i && i < nLen) ? i : -1); 619*cdf0e10cSrcweir } 620*cdf0e10cSrcweir 621*cdf0e10cSrcweir 622*cdf0e10cSrcweir sal_Int32 GetPosInWordToCheck( const OUString &rTxt, sal_Int32 nPos ) 623*cdf0e10cSrcweir { 624*cdf0e10cSrcweir sal_Int32 nRes = -1; 625*cdf0e10cSrcweir sal_Int32 nLen = rTxt.getLength(); 626*cdf0e10cSrcweir if (0 <= nPos && nPos < nLen) 627*cdf0e10cSrcweir { 628*cdf0e10cSrcweir nRes = 0; 629*cdf0e10cSrcweir for (sal_Int32 i = 0; i < nPos; ++i) 630*cdf0e10cSrcweir { 631*cdf0e10cSrcweir sal_Unicode cChar = rTxt[i]; 632*cdf0e10cSrcweir sal_Bool bSkip = IsHyphen( cChar ) || IsControlChar( cChar ); 633*cdf0e10cSrcweir if (!bSkip) 634*cdf0e10cSrcweir ++nRes; 635*cdf0e10cSrcweir } 636*cdf0e10cSrcweir } 637*cdf0e10cSrcweir return nRes; 638*cdf0e10cSrcweir } 639*cdf0e10cSrcweir 640*cdf0e10cSrcweir 641*cdf0e10cSrcweir uno::Reference< XHyphenatedWord > RebuildHyphensAndControlChars( 642*cdf0e10cSrcweir const OUString &rOrigWord, 643*cdf0e10cSrcweir uno::Reference< XHyphenatedWord > &rxHyphWord ) 644*cdf0e10cSrcweir { 645*cdf0e10cSrcweir uno::Reference< XHyphenatedWord > xRes; 646*cdf0e10cSrcweir if (rOrigWord.getLength() && rxHyphWord.is()) 647*cdf0e10cSrcweir { 648*cdf0e10cSrcweir sal_Int16 nChgPos = 0, 649*cdf0e10cSrcweir nChgLen = 0; 650*cdf0e10cSrcweir OUString aRplc; 651*cdf0e10cSrcweir sal_Bool bAltSpelling = GetAltSpelling( nChgPos, nChgLen, aRplc, rxHyphWord ); 652*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 653*cdf0e10cSrcweir OUString aWord( rxHyphWord->getWord() ); 654*cdf0e10cSrcweir #endif 655*cdf0e10cSrcweir 656*cdf0e10cSrcweir OUString aOrigHyphenatedWord; 657*cdf0e10cSrcweir sal_Int16 nOrigHyphenPos = -1; 658*cdf0e10cSrcweir sal_Int16 nOrigHyphenationPos = -1; 659*cdf0e10cSrcweir if (!bAltSpelling) 660*cdf0e10cSrcweir { 661*cdf0e10cSrcweir aOrigHyphenatedWord = rOrigWord; 662*cdf0e10cSrcweir nOrigHyphenPos = GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenPos() ); 663*cdf0e10cSrcweir nOrigHyphenationPos = GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenationPos() ); 664*cdf0e10cSrcweir } 665*cdf0e10cSrcweir else 666*cdf0e10cSrcweir { 667*cdf0e10cSrcweir //! should at least work with the German words 668*cdf0e10cSrcweir //! B�-c-k-er and Sc-hif-fah-rt 669*cdf0e10cSrcweir 670*cdf0e10cSrcweir OUString aLeft, aRight; 671*cdf0e10cSrcweir sal_Int16 nPos = GetOrigWordPos( rOrigWord, nChgPos ); 672*cdf0e10cSrcweir 673*cdf0e10cSrcweir // get words like Sc-hif-fah-rt to work correct 674*cdf0e10cSrcweir sal_Int16 nHyphenationPos = rxHyphWord->getHyphenationPos(); 675*cdf0e10cSrcweir if (nChgPos > nHyphenationPos) 676*cdf0e10cSrcweir --nPos; 677*cdf0e10cSrcweir 678*cdf0e10cSrcweir aLeft = rOrigWord.copy( 0, nPos ); 679*cdf0e10cSrcweir aRight = rOrigWord.copy( nPos + nChgLen ); 680*cdf0e10cSrcweir 681*cdf0e10cSrcweir aOrigHyphenatedWord = aLeft; 682*cdf0e10cSrcweir aOrigHyphenatedWord += aRplc; 683*cdf0e10cSrcweir aOrigHyphenatedWord += aRight; 684*cdf0e10cSrcweir 685*cdf0e10cSrcweir nOrigHyphenPos = sal::static_int_cast< sal_Int16 >(aLeft.getLength() + 686*cdf0e10cSrcweir rxHyphWord->getHyphenPos() - nChgPos); 687*cdf0e10cSrcweir nOrigHyphenationPos = GetOrigWordPos( rOrigWord, nHyphenationPos ); 688*cdf0e10cSrcweir } 689*cdf0e10cSrcweir 690*cdf0e10cSrcweir if (nOrigHyphenPos == -1 || nOrigHyphenationPos == -1) 691*cdf0e10cSrcweir { 692*cdf0e10cSrcweir DBG_ASSERT( 0, "failed to get nOrigHyphenPos or nOrigHyphenationPos" ); 693*cdf0e10cSrcweir } 694*cdf0e10cSrcweir else 695*cdf0e10cSrcweir { 696*cdf0e10cSrcweir sal_Int16 nLang = LocaleToLanguage( rxHyphWord->getLocale() ); 697*cdf0e10cSrcweir xRes = new HyphenatedWord( 698*cdf0e10cSrcweir rOrigWord, nLang, nOrigHyphenationPos, 699*cdf0e10cSrcweir aOrigHyphenatedWord, nOrigHyphenPos ); 700*cdf0e10cSrcweir } 701*cdf0e10cSrcweir 702*cdf0e10cSrcweir } 703*cdf0e10cSrcweir return xRes; 704*cdf0e10cSrcweir } 705*cdf0e10cSrcweir 706*cdf0e10cSrcweir 707*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 708*cdf0e10cSrcweir 709*cdf0e10cSrcweir 710*cdf0e10cSrcweir static CharClass & lcl_GetCharClass() 711*cdf0e10cSrcweir { 712*cdf0e10cSrcweir static CharClass aCC( CreateLocale( LANGUAGE_ENGLISH_US ) ); 713*cdf0e10cSrcweir return aCC; 714*cdf0e10cSrcweir } 715*cdf0e10cSrcweir 716*cdf0e10cSrcweir 717*cdf0e10cSrcweir osl::Mutex & lcl_GetCharClassMutex() 718*cdf0e10cSrcweir { 719*cdf0e10cSrcweir static osl::Mutex aMutex; 720*cdf0e10cSrcweir return aMutex; 721*cdf0e10cSrcweir } 722*cdf0e10cSrcweir 723*cdf0e10cSrcweir 724*cdf0e10cSrcweir sal_Bool IsUpper( const String &rText, xub_StrLen nPos, xub_StrLen nLen, sal_Int16 nLanguage ) 725*cdf0e10cSrcweir { 726*cdf0e10cSrcweir MutexGuard aGuard( lcl_GetCharClassMutex() ); 727*cdf0e10cSrcweir 728*cdf0e10cSrcweir CharClass &rCC = lcl_GetCharClass(); 729*cdf0e10cSrcweir rCC.setLocale( CreateLocale( nLanguage ) ); 730*cdf0e10cSrcweir sal_Int32 nFlags = rCC.getStringType( rText, nPos, nLen ); 731*cdf0e10cSrcweir return (nFlags & KCharacterType::UPPER) 732*cdf0e10cSrcweir && !(nFlags & KCharacterType::LOWER); 733*cdf0e10cSrcweir } 734*cdf0e10cSrcweir 735*cdf0e10cSrcweir 736*cdf0e10cSrcweir sal_Bool IsLower( const String &rText, xub_StrLen nPos, xub_StrLen nLen, sal_Int16 nLanguage ) 737*cdf0e10cSrcweir { 738*cdf0e10cSrcweir MutexGuard aGuard( lcl_GetCharClassMutex() ); 739*cdf0e10cSrcweir 740*cdf0e10cSrcweir CharClass &rCC = lcl_GetCharClass(); 741*cdf0e10cSrcweir rCC.setLocale( CreateLocale( nLanguage ) ); 742*cdf0e10cSrcweir sal_Int32 nFlags = rCC.getStringType( rText, nPos, nLen ); 743*cdf0e10cSrcweir return (nFlags & KCharacterType::LOWER) 744*cdf0e10cSrcweir && !(nFlags & KCharacterType::UPPER); 745*cdf0e10cSrcweir } 746*cdf0e10cSrcweir 747*cdf0e10cSrcweir 748*cdf0e10cSrcweir String ToLower( const String &rText, sal_Int16 nLanguage ) 749*cdf0e10cSrcweir { 750*cdf0e10cSrcweir MutexGuard aGuard( lcl_GetCharClassMutex() ); 751*cdf0e10cSrcweir 752*cdf0e10cSrcweir CharClass &rCC = lcl_GetCharClass(); 753*cdf0e10cSrcweir rCC.setLocale( CreateLocale( nLanguage ) ); 754*cdf0e10cSrcweir return rCC.lower( rText ); 755*cdf0e10cSrcweir } 756*cdf0e10cSrcweir 757*cdf0e10cSrcweir 758*cdf0e10cSrcweir String ToUpper( const String &rText, sal_Int16 nLanguage ) 759*cdf0e10cSrcweir { 760*cdf0e10cSrcweir MutexGuard aGuard( lcl_GetCharClassMutex() ); 761*cdf0e10cSrcweir 762*cdf0e10cSrcweir CharClass &rCC = lcl_GetCharClass(); 763*cdf0e10cSrcweir rCC.setLocale( CreateLocale( nLanguage ) ); 764*cdf0e10cSrcweir return rCC.upper( rText ); 765*cdf0e10cSrcweir } 766*cdf0e10cSrcweir 767*cdf0e10cSrcweir 768*cdf0e10cSrcweir String ToTitle( const String &rText, sal_Int16 nLanguage ) 769*cdf0e10cSrcweir { 770*cdf0e10cSrcweir MutexGuard aGuard( lcl_GetCharClassMutex() ); 771*cdf0e10cSrcweir 772*cdf0e10cSrcweir CharClass &rCC = lcl_GetCharClass(); 773*cdf0e10cSrcweir rCC.setLocale( CreateLocale( nLanguage ) ); 774*cdf0e10cSrcweir return rCC.toTitle( rText, 0, rText.Len() ); 775*cdf0e10cSrcweir } 776*cdf0e10cSrcweir 777*cdf0e10cSrcweir 778*cdf0e10cSrcweir sal_Unicode ToLower( const sal_Unicode cChar, sal_Int16 nLanguage ) 779*cdf0e10cSrcweir { 780*cdf0e10cSrcweir MutexGuard aGuard( lcl_GetCharClassMutex() ); 781*cdf0e10cSrcweir 782*cdf0e10cSrcweir CharClass &rCC = lcl_GetCharClass(); 783*cdf0e10cSrcweir rCC.setLocale( CreateLocale( nLanguage ) ); 784*cdf0e10cSrcweir return rCC.lower( cChar ).GetChar(0); 785*cdf0e10cSrcweir } 786*cdf0e10cSrcweir 787*cdf0e10cSrcweir 788*cdf0e10cSrcweir sal_Unicode ToUpper( const sal_Unicode cChar, sal_Int16 nLanguage ) 789*cdf0e10cSrcweir { 790*cdf0e10cSrcweir MutexGuard aGuard( lcl_GetCharClassMutex() ); 791*cdf0e10cSrcweir 792*cdf0e10cSrcweir CharClass &rCC = lcl_GetCharClass(); 793*cdf0e10cSrcweir rCC.setLocale( CreateLocale( nLanguage ) ); 794*cdf0e10cSrcweir return rCC.upper( cChar ).GetChar(0); 795*cdf0e10cSrcweir } 796*cdf0e10cSrcweir 797*cdf0e10cSrcweir // sorted(!) array of unicode ranges for code points that are exclusively(!) used as numbers 798*cdf0e10cSrcweir // and thus may NOT not be part of names or words like the Chinese/Japanese number characters 799*cdf0e10cSrcweir static const sal_uInt32 the_aDigitZeroes [] = 800*cdf0e10cSrcweir { 801*cdf0e10cSrcweir 0x00000030, //0039 ; Decimal # Nd [10] DIGIT ZERO..DIGIT NINE 802*cdf0e10cSrcweir 0x00000660, //0669 ; Decimal # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE 803*cdf0e10cSrcweir 0x000006F0, //06F9 ; Decimal # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE 804*cdf0e10cSrcweir 0x000007C0, //07C9 ; Decimal # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE 805*cdf0e10cSrcweir 0x00000966, //096F ; Decimal # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE 806*cdf0e10cSrcweir 0x000009E6, //09EF ; Decimal # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE 807*cdf0e10cSrcweir 0x00000A66, //0A6F ; Decimal # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE 808*cdf0e10cSrcweir 0x00000AE6, //0AEF ; Decimal # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE 809*cdf0e10cSrcweir 0x00000B66, //0B6F ; Decimal # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE 810*cdf0e10cSrcweir 0x00000BE6, //0BEF ; Decimal # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE 811*cdf0e10cSrcweir 0x00000C66, //0C6F ; Decimal # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE 812*cdf0e10cSrcweir 0x00000CE6, //0CEF ; Decimal # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE 813*cdf0e10cSrcweir 0x00000D66, //0D6F ; Decimal # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE 814*cdf0e10cSrcweir 0x00000E50, //0E59 ; Decimal # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE 815*cdf0e10cSrcweir 0x00000ED0, //0ED9 ; Decimal # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE 816*cdf0e10cSrcweir 0x00000F20, //0F29 ; Decimal # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE 817*cdf0e10cSrcweir 0x00001040, //1049 ; Decimal # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE 818*cdf0e10cSrcweir 0x00001090, //1099 ; Decimal # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE 819*cdf0e10cSrcweir 0x000017E0, //17E9 ; Decimal # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE 820*cdf0e10cSrcweir 0x00001810, //1819 ; Decimal # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE 821*cdf0e10cSrcweir 0x00001946, //194F ; Decimal # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE 822*cdf0e10cSrcweir 0x000019D0, //19D9 ; Decimal # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE 823*cdf0e10cSrcweir 0x00001B50, //1B59 ; Decimal # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE 824*cdf0e10cSrcweir 0x00001BB0, //1BB9 ; Decimal # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE 825*cdf0e10cSrcweir 0x00001C40, //1C49 ; Decimal # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE 826*cdf0e10cSrcweir 0x00001C50, //1C59 ; Decimal # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE 827*cdf0e10cSrcweir 0x0000A620, //A629 ; Decimal # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE 828*cdf0e10cSrcweir 0x0000A8D0, //A8D9 ; Decimal # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE 829*cdf0e10cSrcweir 0x0000A900, //A909 ; Decimal # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE 830*cdf0e10cSrcweir 0x0000AA50, //AA59 ; Decimal # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE 831*cdf0e10cSrcweir 0x0000FF10, //FF19 ; Decimal # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE 832*cdf0e10cSrcweir 0x000104A0, //104A9 ; Decimal # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE 833*cdf0e10cSrcweir 0x0001D7CE //1D7FF ; Decimal # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE 834*cdf0e10cSrcweir }; 835*cdf0e10cSrcweir 836*cdf0e10cSrcweir sal_Bool HasDigits( const OUString &rText ) 837*cdf0e10cSrcweir { 838*cdf0e10cSrcweir static const int nNumDigitZeroes = sizeof(the_aDigitZeroes) / sizeof(the_aDigitZeroes[0]); 839*cdf0e10cSrcweir const sal_Int32 nLen = rText.getLength(); 840*cdf0e10cSrcweir 841*cdf0e10cSrcweir sal_Int32 i = 0; 842*cdf0e10cSrcweir while (i < nLen) // for all characters ... 843*cdf0e10cSrcweir { 844*cdf0e10cSrcweir const sal_uInt32 nCodePoint = rText.iterateCodePoints( &i ); // handle unicode surrogates correctly... 845*cdf0e10cSrcweir for (int j = 0; j < nNumDigitZeroes; ++j) // ... check in all 0..9 ranges 846*cdf0e10cSrcweir { 847*cdf0e10cSrcweir sal_uInt32 nDigitZero = the_aDigitZeroes[ j ]; 848*cdf0e10cSrcweir if (nDigitZero > nCodePoint) 849*cdf0e10cSrcweir break; 850*cdf0e10cSrcweir if (/*nDigitZero <= nCodePoint &&*/ nCodePoint <= nDigitZero + 9) 851*cdf0e10cSrcweir return sal_True; 852*cdf0e10cSrcweir } 853*cdf0e10cSrcweir } 854*cdf0e10cSrcweir return sal_False; 855*cdf0e10cSrcweir } 856*cdf0e10cSrcweir 857*cdf0e10cSrcweir 858*cdf0e10cSrcweir sal_Bool IsNumeric( const String &rText ) 859*cdf0e10cSrcweir { 860*cdf0e10cSrcweir sal_Bool bRes = sal_False; 861*cdf0e10cSrcweir xub_StrLen nLen = rText.Len(); 862*cdf0e10cSrcweir if (nLen) 863*cdf0e10cSrcweir { 864*cdf0e10cSrcweir bRes = sal_True; 865*cdf0e10cSrcweir xub_StrLen i = 0; 866*cdf0e10cSrcweir while (i < nLen) 867*cdf0e10cSrcweir { 868*cdf0e10cSrcweir sal_Unicode cChar = rText.GetChar( i++ ); 869*cdf0e10cSrcweir if ( !((sal_Unicode)'0' <= cChar && cChar <= (sal_Unicode)'9') ) 870*cdf0e10cSrcweir { 871*cdf0e10cSrcweir bRes = sal_False; 872*cdf0e10cSrcweir break; 873*cdf0e10cSrcweir } 874*cdf0e10cSrcweir } 875*cdf0e10cSrcweir } 876*cdf0e10cSrcweir return bRes; 877*cdf0e10cSrcweir } 878*cdf0e10cSrcweir 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 881*cdf0e10cSrcweir 882*cdf0e10cSrcweir uno::Reference< XInterface > GetOneInstanceService( const char *pServiceName ) 883*cdf0e10cSrcweir { 884*cdf0e10cSrcweir uno::Reference< XInterface > xRef; 885*cdf0e10cSrcweir 886*cdf0e10cSrcweir if (pServiceName) 887*cdf0e10cSrcweir { 888*cdf0e10cSrcweir uno::Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() ); 889*cdf0e10cSrcweir if (xMgr.is()) 890*cdf0e10cSrcweir { 891*cdf0e10cSrcweir try 892*cdf0e10cSrcweir { 893*cdf0e10cSrcweir xRef = xMgr->createInstance( A2OU( pServiceName ) ); 894*cdf0e10cSrcweir } 895*cdf0e10cSrcweir catch (uno::Exception &) 896*cdf0e10cSrcweir { 897*cdf0e10cSrcweir DBG_ASSERT( 0, "createInstance failed" ); 898*cdf0e10cSrcweir } 899*cdf0e10cSrcweir } 900*cdf0e10cSrcweir } 901*cdf0e10cSrcweir 902*cdf0e10cSrcweir return xRef; 903*cdf0e10cSrcweir } 904*cdf0e10cSrcweir 905*cdf0e10cSrcweir uno::Reference< XPropertySet > GetLinguProperties() 906*cdf0e10cSrcweir { 907*cdf0e10cSrcweir return uno::Reference< XPropertySet > ( 908*cdf0e10cSrcweir GetOneInstanceService( SN_LINGU_PROPERTIES ), UNO_QUERY ); 909*cdf0e10cSrcweir } 910*cdf0e10cSrcweir 911*cdf0e10cSrcweir uno::Reference< XSearchableDictionaryList > GetSearchableDictionaryList() 912*cdf0e10cSrcweir { 913*cdf0e10cSrcweir return uno::Reference< XSearchableDictionaryList > ( 914*cdf0e10cSrcweir GetOneInstanceService( SN_DICTIONARY_LIST ), UNO_QUERY ); 915*cdf0e10cSrcweir } 916*cdf0e10cSrcweir 917*cdf0e10cSrcweir uno::Reference< XDictionaryList > GetDictionaryList() 918*cdf0e10cSrcweir { 919*cdf0e10cSrcweir return uno::Reference< XDictionaryList > ( 920*cdf0e10cSrcweir GetOneInstanceService( SN_DICTIONARY_LIST ), UNO_QUERY ); 921*cdf0e10cSrcweir } 922*cdf0e10cSrcweir 923*cdf0e10cSrcweir uno::Reference< XDictionary > GetIgnoreAllList() 924*cdf0e10cSrcweir { 925*cdf0e10cSrcweir uno::Reference< XDictionary > xRes; 926*cdf0e10cSrcweir uno::Reference< XDictionaryList > xDL( GetDictionaryList() ); 927*cdf0e10cSrcweir if (xDL.is()) 928*cdf0e10cSrcweir xRes = xDL->getDictionaryByName( A2OU("IgnoreAllList") ); 929*cdf0e10cSrcweir return xRes; 930*cdf0e10cSrcweir } 931*cdf0e10cSrcweir 932*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 933*cdf0e10cSrcweir 934*cdf0e10cSrcweir AppExitListener::AppExitListener() 935*cdf0e10cSrcweir { 936*cdf0e10cSrcweir // add object to Desktop EventListeners in order to properly call 937*cdf0e10cSrcweir // the AtExit function at appliction exit. 938*cdf0e10cSrcweir uno::Reference< XMultiServiceFactory > xMgr = getProcessServiceFactory(); 939*cdf0e10cSrcweir 940*cdf0e10cSrcweir if (xMgr.is()) 941*cdf0e10cSrcweir { 942*cdf0e10cSrcweir try 943*cdf0e10cSrcweir { 944*cdf0e10cSrcweir xDesktop = uno::Reference< frame::XDesktop >( 945*cdf0e10cSrcweir xMgr->createInstance( A2OU( SN_DESKTOP ) ), UNO_QUERY ); 946*cdf0e10cSrcweir } 947*cdf0e10cSrcweir catch (uno::Exception &) 948*cdf0e10cSrcweir { 949*cdf0e10cSrcweir DBG_ASSERT( 0, "createInstance failed" ); 950*cdf0e10cSrcweir } 951*cdf0e10cSrcweir } 952*cdf0e10cSrcweir } 953*cdf0e10cSrcweir 954*cdf0e10cSrcweir AppExitListener::~AppExitListener() 955*cdf0e10cSrcweir { 956*cdf0e10cSrcweir } 957*cdf0e10cSrcweir 958*cdf0e10cSrcweir 959*cdf0e10cSrcweir void AppExitListener::Activate() 960*cdf0e10cSrcweir { 961*cdf0e10cSrcweir if (xDesktop.is()) 962*cdf0e10cSrcweir xDesktop->addTerminateListener( this ); 963*cdf0e10cSrcweir } 964*cdf0e10cSrcweir 965*cdf0e10cSrcweir 966*cdf0e10cSrcweir void AppExitListener::Deactivate() 967*cdf0e10cSrcweir { 968*cdf0e10cSrcweir if (xDesktop.is()) 969*cdf0e10cSrcweir xDesktop->removeTerminateListener( this ); 970*cdf0e10cSrcweir } 971*cdf0e10cSrcweir 972*cdf0e10cSrcweir 973*cdf0e10cSrcweir void SAL_CALL 974*cdf0e10cSrcweir AppExitListener::disposing( const EventObject& rEvtSource ) 975*cdf0e10cSrcweir throw(RuntimeException) 976*cdf0e10cSrcweir { 977*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 978*cdf0e10cSrcweir 979*cdf0e10cSrcweir if (xDesktop.is() && rEvtSource.Source == xDesktop) 980*cdf0e10cSrcweir { 981*cdf0e10cSrcweir xDesktop = NULL; //! release reference to desktop 982*cdf0e10cSrcweir } 983*cdf0e10cSrcweir } 984*cdf0e10cSrcweir 985*cdf0e10cSrcweir 986*cdf0e10cSrcweir void SAL_CALL 987*cdf0e10cSrcweir AppExitListener::queryTermination( const EventObject& /*rEvtSource*/ ) 988*cdf0e10cSrcweir throw(frame::TerminationVetoException, RuntimeException) 989*cdf0e10cSrcweir { 990*cdf0e10cSrcweir //MutexGuard aGuard( GetLinguMutex() ); 991*cdf0e10cSrcweir } 992*cdf0e10cSrcweir 993*cdf0e10cSrcweir 994*cdf0e10cSrcweir void SAL_CALL 995*cdf0e10cSrcweir AppExitListener::notifyTermination( const EventObject& rEvtSource ) 996*cdf0e10cSrcweir throw(RuntimeException) 997*cdf0e10cSrcweir { 998*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 999*cdf0e10cSrcweir 1000*cdf0e10cSrcweir if (xDesktop.is() && rEvtSource.Source == xDesktop) 1001*cdf0e10cSrcweir { 1002*cdf0e10cSrcweir AtExit(); 1003*cdf0e10cSrcweir } 1004*cdf0e10cSrcweir } 1005*cdf0e10cSrcweir 1006*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 1007*cdf0e10cSrcweir 1008*cdf0e10cSrcweir } // namespace linguistic 1009*cdf0e10cSrcweir 1010