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_unotools.hxx" 30*cdf0e10cSrcweir #include <i18npool/mslangid.hxx> 31*cdf0e10cSrcweir #include <tools/debug.hxx> 32*cdf0e10cSrcweir #ifndef _INTN_HXX //autogen 33*cdf0e10cSrcweir //#include <tools/intn.hxx> 34*cdf0e10cSrcweir #endif 35*cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp> 36*cdf0e10cSrcweir #ifndef _COM_SUN_STAR_UTIL_SEARCHFLAGS_HDL_ 37*cdf0e10cSrcweir #include <com/sun/star/util/SearchFlags.hdl> 38*cdf0e10cSrcweir #endif 39*cdf0e10cSrcweir #include <com/sun/star/i18n/TransliterationModules.hpp> 40*cdf0e10cSrcweir #include <unotools/charclass.hxx> 41*cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 42*cdf0e10cSrcweir #include <unotools/textsearch.hxx> 43*cdf0e10cSrcweir #include <rtl/instance.hxx> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir using namespace ::com::sun::star::util; 46*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 47*cdf0e10cSrcweir using namespace ::com::sun::star::lang; 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir // ............................................................................ 50*cdf0e10cSrcweir namespace utl 51*cdf0e10cSrcweir { 52*cdf0e10cSrcweir // ............................................................................ 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir SearchParam::SearchParam( const String &rText, 55*cdf0e10cSrcweir SearchType eType, 56*cdf0e10cSrcweir sal_Bool bCaseSensitive, 57*cdf0e10cSrcweir sal_Bool bWrdOnly, 58*cdf0e10cSrcweir sal_Bool bSearchInSel ) 59*cdf0e10cSrcweir { 60*cdf0e10cSrcweir sSrchStr = rText; 61*cdf0e10cSrcweir eSrchType = eType; 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir bWordOnly = bWrdOnly; 64*cdf0e10cSrcweir bSrchInSel = bSearchInSel; 65*cdf0e10cSrcweir bCaseSense = bCaseSensitive; 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir nTransliterationFlags = 0; 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir // Werte fuer "Gewichtete Levenshtein-Distanz" 70*cdf0e10cSrcweir bLEV_Relaxed = sal_True; 71*cdf0e10cSrcweir nLEV_OtherX = 2; 72*cdf0e10cSrcweir nLEV_ShorterY = 1; 73*cdf0e10cSrcweir nLEV_LongerZ = 3; 74*cdf0e10cSrcweir } 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir SearchParam::SearchParam( const SearchParam& rParam ) 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir sSrchStr = rParam.sSrchStr; 79*cdf0e10cSrcweir sReplaceStr = rParam.sReplaceStr; 80*cdf0e10cSrcweir eSrchType = rParam.eSrchType; 81*cdf0e10cSrcweir 82*cdf0e10cSrcweir bWordOnly = rParam.bWordOnly; 83*cdf0e10cSrcweir bSrchInSel = rParam.bSrchInSel; 84*cdf0e10cSrcweir bCaseSense = rParam.bCaseSense; 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir bLEV_Relaxed = rParam.bLEV_Relaxed; 87*cdf0e10cSrcweir nLEV_OtherX = rParam.nLEV_OtherX; 88*cdf0e10cSrcweir nLEV_ShorterY = rParam.nLEV_ShorterY; 89*cdf0e10cSrcweir nLEV_LongerZ = rParam.nLEV_LongerZ; 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir nTransliterationFlags = rParam.nTransliterationFlags; 92*cdf0e10cSrcweir } 93*cdf0e10cSrcweir 94*cdf0e10cSrcweir static bool lcl_Equals( const SearchOptions& rSO1, const SearchOptions& rSO2 ) 95*cdf0e10cSrcweir { 96*cdf0e10cSrcweir return rSO1.algorithmType == rSO2.algorithmType && 97*cdf0e10cSrcweir rSO1.searchFlag == rSO2.searchFlag && 98*cdf0e10cSrcweir rSO1.searchString.equals(rSO2.searchString) && 99*cdf0e10cSrcweir rSO1.replaceString.equals(rSO2.replaceString) && 100*cdf0e10cSrcweir rSO1.changedChars == rSO2.changedChars && 101*cdf0e10cSrcweir rSO1.deletedChars == rSO2.deletedChars && 102*cdf0e10cSrcweir rSO1.insertedChars == rSO2.insertedChars && 103*cdf0e10cSrcweir rSO1.Locale.Language == rSO2.Locale.Language && 104*cdf0e10cSrcweir rSO1.Locale.Country == rSO2.Locale.Country && 105*cdf0e10cSrcweir rSO1.Locale.Variant == rSO2.Locale.Variant && 106*cdf0e10cSrcweir rSO1.transliterateFlags == rSO2.transliterateFlags; 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir namespace 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir struct CachedTextSearch 112*cdf0e10cSrcweir { 113*cdf0e10cSrcweir ::osl::Mutex mutex; 114*cdf0e10cSrcweir ::com::sun::star::util::SearchOptions Options; 115*cdf0e10cSrcweir ::com::sun::star::uno::Reference< ::com::sun::star::util::XTextSearch > xTextSearch; 116*cdf0e10cSrcweir }; 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir struct theCachedTextSearch 119*cdf0e10cSrcweir : public rtl::Static< CachedTextSearch, theCachedTextSearch > {}; 120*cdf0e10cSrcweir } 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir Reference<XTextSearch> TextSearch::getXTextSearch( const SearchOptions& rPara ) 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir CachedTextSearch &rCache = theCachedTextSearch::get(); 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir osl::MutexGuard aGuard(rCache.mutex); 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir if ( lcl_Equals(rCache.Options, rPara) ) 129*cdf0e10cSrcweir return rCache.xTextSearch; 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir try 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); 134*cdf0e10cSrcweir rCache.xTextSearch.set( xMSF->createInstance( 135*cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 136*cdf0e10cSrcweir "com.sun.star.util.TextSearch" ) ) ), UNO_QUERY_THROW ); 137*cdf0e10cSrcweir rCache.xTextSearch->setOptions( rPara ); 138*cdf0e10cSrcweir rCache.Options = rPara; 139*cdf0e10cSrcweir } 140*cdf0e10cSrcweir catch ( Exception& ) 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir DBG_ERRORFILE( "TextSearch ctor: Exception caught!" ); 143*cdf0e10cSrcweir } 144*cdf0e10cSrcweir return rCache.xTextSearch; 145*cdf0e10cSrcweir } 146*cdf0e10cSrcweir 147*cdf0e10cSrcweir TextSearch::TextSearch(const SearchParam & rParam, LanguageType eLang ) 148*cdf0e10cSrcweir { 149*cdf0e10cSrcweir if( LANGUAGE_NONE == eLang ) 150*cdf0e10cSrcweir eLang = LANGUAGE_SYSTEM; 151*cdf0e10cSrcweir ::com::sun::star::lang::Locale aLocale( 152*cdf0e10cSrcweir MsLangId::convertLanguageToLocale( LanguageType(eLang))); 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir Init( rParam, aLocale); 155*cdf0e10cSrcweir } 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir TextSearch::TextSearch(const SearchParam & rParam, const CharClass& rCClass ) 158*cdf0e10cSrcweir { 159*cdf0e10cSrcweir Init( rParam, rCClass.getLocale() ); 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir TextSearch::TextSearch( const SearchOptions& rPara ) 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir xTextSearch = getXTextSearch( rPara ); 165*cdf0e10cSrcweir } 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir void TextSearch::Init( const SearchParam & rParam, 168*cdf0e10cSrcweir const ::com::sun::star::lang::Locale& rLocale ) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir // convert SearchParam to the UNO SearchOptions 171*cdf0e10cSrcweir SearchOptions aSOpt; 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir switch( rParam.GetSrchType() ) 174*cdf0e10cSrcweir { 175*cdf0e10cSrcweir case SearchParam::SRCH_REGEXP: 176*cdf0e10cSrcweir aSOpt.algorithmType = SearchAlgorithms_REGEXP; 177*cdf0e10cSrcweir if( rParam.IsSrchInSelection() ) 178*cdf0e10cSrcweir aSOpt.searchFlag |= SearchFlags::REG_NOT_BEGINOFLINE | 179*cdf0e10cSrcweir SearchFlags::REG_NOT_ENDOFLINE; 180*cdf0e10cSrcweir break; 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir case SearchParam::SRCH_LEVDIST: 183*cdf0e10cSrcweir aSOpt.algorithmType = SearchAlgorithms_APPROXIMATE; 184*cdf0e10cSrcweir aSOpt.changedChars = rParam.GetLEVOther(); 185*cdf0e10cSrcweir aSOpt.deletedChars = rParam.GetLEVLonger(); 186*cdf0e10cSrcweir aSOpt.insertedChars = rParam.GetLEVShorter(); 187*cdf0e10cSrcweir if( rParam.IsSrchRelaxed() ) 188*cdf0e10cSrcweir aSOpt.searchFlag |= SearchFlags::LEV_RELAXED; 189*cdf0e10cSrcweir break; 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir // case SearchParam::SRCH_NORMAL: 192*cdf0e10cSrcweir default: 193*cdf0e10cSrcweir aSOpt.algorithmType = SearchAlgorithms_ABSOLUTE; 194*cdf0e10cSrcweir if( rParam.IsSrchWordOnly() ) 195*cdf0e10cSrcweir aSOpt.searchFlag |= SearchFlags::NORM_WORD_ONLY; 196*cdf0e10cSrcweir break; 197*cdf0e10cSrcweir } 198*cdf0e10cSrcweir aSOpt.searchString = rParam.GetSrchStr(); 199*cdf0e10cSrcweir aSOpt.replaceString = rParam.GetReplaceStr(); 200*cdf0e10cSrcweir aSOpt.Locale = rLocale; 201*cdf0e10cSrcweir aSOpt.transliterateFlags = rParam.GetTransliterationFlags(); 202*cdf0e10cSrcweir if( !rParam.IsCaseSensitive() ) 203*cdf0e10cSrcweir { 204*cdf0e10cSrcweir aSOpt.searchFlag |= SearchFlags::ALL_IGNORE_CASE; 205*cdf0e10cSrcweir aSOpt.transliterateFlags |= ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE; 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir xTextSearch = getXTextSearch( aSOpt ); 209*cdf0e10cSrcweir } 210*cdf0e10cSrcweir 211*cdf0e10cSrcweir void TextSearch::SetLocale( const ::com::sun::star::util::SearchOptions& rOptions, 212*cdf0e10cSrcweir const ::com::sun::star::lang::Locale& rLocale ) 213*cdf0e10cSrcweir { 214*cdf0e10cSrcweir // convert SearchParam to the UNO SearchOptions 215*cdf0e10cSrcweir SearchOptions aSOpt( rOptions ); 216*cdf0e10cSrcweir aSOpt.Locale = rLocale; 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir xTextSearch = getXTextSearch( aSOpt ); 219*cdf0e10cSrcweir } 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir TextSearch::~TextSearch() 223*cdf0e10cSrcweir { 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir /* 227*cdf0e10cSrcweir * Die allgemeinen Methoden zu Suchen. Diese rufen dann die entpsrecheden 228*cdf0e10cSrcweir * Methoden fuer die normale Suche oder der Suche nach Regular-Expressions 229*cdf0e10cSrcweir * ueber die MethodenPointer auf. 230*cdf0e10cSrcweir */ 231*cdf0e10cSrcweir #if defined _MSC_VER 232*cdf0e10cSrcweir #pragma optimize("", off) 233*cdf0e10cSrcweir #pragma warning(push) 234*cdf0e10cSrcweir #pragma warning(disable: 4748) 235*cdf0e10cSrcweir #endif 236*cdf0e10cSrcweir int TextSearch::SearchFrwrd( const String & rStr, xub_StrLen* pStart, 237*cdf0e10cSrcweir xub_StrLen* pEnde, SearchResult* pRes ) 238*cdf0e10cSrcweir { 239*cdf0e10cSrcweir int nRet = 0; 240*cdf0e10cSrcweir try 241*cdf0e10cSrcweir { 242*cdf0e10cSrcweir if( xTextSearch.is() ) 243*cdf0e10cSrcweir { 244*cdf0e10cSrcweir SearchResult aRet( xTextSearch->searchForward( 245*cdf0e10cSrcweir rStr, *pStart, *pEnde )); 246*cdf0e10cSrcweir if( aRet.subRegExpressions > 0 ) 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir nRet = 1; 249*cdf0e10cSrcweir // the XTextsearch returns in startOffset the higher position 250*cdf0e10cSrcweir // and the endposition is allways exclusive. 251*cdf0e10cSrcweir // The caller of this function will have in startPos the 252*cdf0e10cSrcweir // lower pos. and end 253*cdf0e10cSrcweir *pStart = (xub_StrLen)aRet.startOffset[ 0 ]; 254*cdf0e10cSrcweir *pEnde = (xub_StrLen)aRet.endOffset[ 0 ]; 255*cdf0e10cSrcweir if( pRes ) 256*cdf0e10cSrcweir *pRes = aRet; 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir } 260*cdf0e10cSrcweir catch ( Exception& ) 261*cdf0e10cSrcweir { 262*cdf0e10cSrcweir DBG_ERRORFILE( "SearchForward: Exception caught!" ); 263*cdf0e10cSrcweir } 264*cdf0e10cSrcweir return nRet; 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir 267*cdf0e10cSrcweir int TextSearch::SearchBkwrd( const String & rStr, xub_StrLen* pStart, 268*cdf0e10cSrcweir xub_StrLen* pEnde, SearchResult* pRes ) 269*cdf0e10cSrcweir { 270*cdf0e10cSrcweir int nRet = 0; 271*cdf0e10cSrcweir try 272*cdf0e10cSrcweir { 273*cdf0e10cSrcweir if( xTextSearch.is() ) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir SearchResult aRet( xTextSearch->searchBackward( 276*cdf0e10cSrcweir rStr, *pStart, *pEnde )); 277*cdf0e10cSrcweir if( aRet.subRegExpressions ) 278*cdf0e10cSrcweir { 279*cdf0e10cSrcweir nRet = 1; 280*cdf0e10cSrcweir // the XTextsearch returns in startOffset the higher position 281*cdf0e10cSrcweir // and the endposition is allways exclusive. 282*cdf0e10cSrcweir // The caller of this function will have in startPos the 283*cdf0e10cSrcweir // lower pos. and end 284*cdf0e10cSrcweir *pEnde = (xub_StrLen)aRet.startOffset[ 0 ]; 285*cdf0e10cSrcweir *pStart = (xub_StrLen)aRet.endOffset[ 0 ]; 286*cdf0e10cSrcweir if( pRes ) 287*cdf0e10cSrcweir *pRes = aRet; 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir } 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir catch ( Exception& ) 292*cdf0e10cSrcweir { 293*cdf0e10cSrcweir DBG_ERRORFILE( "SearchBackward: Exception caught!" ); 294*cdf0e10cSrcweir } 295*cdf0e10cSrcweir return nRet; 296*cdf0e10cSrcweir } 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir void TextSearch::ReplaceBackReferences( String& rReplaceStr, const String &rStr, const SearchResult& rResult ) 299*cdf0e10cSrcweir { 300*cdf0e10cSrcweir if( rResult.subRegExpressions > 0 ) 301*cdf0e10cSrcweir { 302*cdf0e10cSrcweir String sTab( '\t' ); 303*cdf0e10cSrcweir sal_Unicode sSrchChrs[] = {'\\', '&', '$', 0}; 304*cdf0e10cSrcweir String sTmp; 305*cdf0e10cSrcweir xub_StrLen nPos = 0; 306*cdf0e10cSrcweir sal_Unicode sFndChar; 307*cdf0e10cSrcweir while( STRING_NOTFOUND != ( nPos = rReplaceStr.SearchChar( sSrchChrs, nPos )) ) 308*cdf0e10cSrcweir { 309*cdf0e10cSrcweir if( rReplaceStr.GetChar( nPos ) == '&') 310*cdf0e10cSrcweir { 311*cdf0e10cSrcweir sal_uInt16 nStart = (sal_uInt16)(rResult.startOffset[0]); 312*cdf0e10cSrcweir sal_uInt16 nLength = (sal_uInt16)(rResult.endOffset[0] - rResult.startOffset[0]); 313*cdf0e10cSrcweir rReplaceStr.Erase( nPos, 1 ); // delete ampersand 314*cdf0e10cSrcweir // replace by found string 315*cdf0e10cSrcweir rReplaceStr.Insert( rStr, nStart, nLength, nPos ); 316*cdf0e10cSrcweir // jump over 317*cdf0e10cSrcweir nPos = nPos + nLength; 318*cdf0e10cSrcweir } 319*cdf0e10cSrcweir else if( rReplaceStr.GetChar( nPos ) == '$') 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir if( nPos + 1 < rReplaceStr.Len()) 322*cdf0e10cSrcweir { 323*cdf0e10cSrcweir sFndChar = rReplaceStr.GetChar( nPos + 1 ); 324*cdf0e10cSrcweir switch(sFndChar) 325*cdf0e10cSrcweir { // placeholder for a backward reference? 326*cdf0e10cSrcweir case '0': 327*cdf0e10cSrcweir case '1': 328*cdf0e10cSrcweir case '2': 329*cdf0e10cSrcweir case '3': 330*cdf0e10cSrcweir case '4': 331*cdf0e10cSrcweir case '5': 332*cdf0e10cSrcweir case '6': 333*cdf0e10cSrcweir case '7': 334*cdf0e10cSrcweir case '8': 335*cdf0e10cSrcweir case '9': 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir rReplaceStr.Erase( nPos, 2 ); // delete both 338*cdf0e10cSrcweir int i = sFndChar - '0'; // index 339*cdf0e10cSrcweir if(i < rResult.subRegExpressions) 340*cdf0e10cSrcweir { 341*cdf0e10cSrcweir sal_uInt16 nSttReg = (sal_uInt16)(rResult.startOffset[i]); 342*cdf0e10cSrcweir sal_uInt16 nRegLen = (sal_uInt16)(rResult.endOffset[i]); 343*cdf0e10cSrcweir if( nRegLen > nSttReg ) 344*cdf0e10cSrcweir nRegLen = nRegLen - nSttReg; 345*cdf0e10cSrcweir else 346*cdf0e10cSrcweir { 347*cdf0e10cSrcweir nRegLen = nSttReg - nRegLen; 348*cdf0e10cSrcweir nSttReg = (sal_uInt16)(rResult.endOffset[i]); 349*cdf0e10cSrcweir } 350*cdf0e10cSrcweir // Copy reference from found string 351*cdf0e10cSrcweir sTmp = rStr.Copy((sal_uInt16)nSttReg, (sal_uInt16)nRegLen); 352*cdf0e10cSrcweir // insert 353*cdf0e10cSrcweir rReplaceStr.Insert( sTmp, nPos ); 354*cdf0e10cSrcweir // and step over 355*cdf0e10cSrcweir nPos = nPos + sTmp.Len(); 356*cdf0e10cSrcweir } 357*cdf0e10cSrcweir } 358*cdf0e10cSrcweir break; 359*cdf0e10cSrcweir default: 360*cdf0e10cSrcweir nPos += 2; // leave both chars unchanged 361*cdf0e10cSrcweir break; 362*cdf0e10cSrcweir } 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir else 365*cdf0e10cSrcweir ++nPos; 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir else 368*cdf0e10cSrcweir { 369*cdf0e10cSrcweir // at least another character? 370*cdf0e10cSrcweir if( nPos + 1 < rReplaceStr.Len()) 371*cdf0e10cSrcweir { 372*cdf0e10cSrcweir sFndChar = rReplaceStr.GetChar( nPos + 1 ); 373*cdf0e10cSrcweir switch(sFndChar) 374*cdf0e10cSrcweir { 375*cdf0e10cSrcweir case '\\': 376*cdf0e10cSrcweir case '&': 377*cdf0e10cSrcweir case '$': 378*cdf0e10cSrcweir rReplaceStr.Erase( nPos, 1 ); 379*cdf0e10cSrcweir nPos++; 380*cdf0e10cSrcweir break; 381*cdf0e10cSrcweir case 't': 382*cdf0e10cSrcweir rReplaceStr.Erase( nPos, 2 ); // delete both 383*cdf0e10cSrcweir rReplaceStr.Insert( sTab, nPos ); // insert tabulator 384*cdf0e10cSrcweir nPos++; // step over 385*cdf0e10cSrcweir break; 386*cdf0e10cSrcweir default: 387*cdf0e10cSrcweir nPos += 2; // ignore both characters 388*cdf0e10cSrcweir break; 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir } 391*cdf0e10cSrcweir else 392*cdf0e10cSrcweir ++nPos; 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir } 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir } 397*cdf0e10cSrcweir 398*cdf0e10cSrcweir 399*cdf0e10cSrcweir #if defined _MSC_VER 400*cdf0e10cSrcweir #pragma optimize("", on) 401*cdf0e10cSrcweir #pragma warning(pop) 402*cdf0e10cSrcweir #endif 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir // ............................................................................ 405*cdf0e10cSrcweir } // namespace utl 406*cdf0e10cSrcweir // ............................................................................ 407*cdf0e10cSrcweir 408