1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 #include <com/sun/star/util/SearchOptions.hpp> 28 #include <com/sun/star/util/SearchFlags.hpp> 29 30 #define _SVSTDARR_USHORTS 31 #define _SVSTDARR_ULONGS 32 #include <svl/svstdarr.hxx> 33 34 #include <vcl/svapp.hxx> 35 #include <vcl/window.hxx> 36 37 #include <txatritr.hxx> 38 #include <fldbas.hxx> 39 #include <fmtfld.hxx> 40 #include <txtatr.hxx> 41 #include <txtfld.hxx> 42 #include <swcrsr.hxx> 43 #include <doc.hxx> 44 #include <IDocumentUndoRedo.hxx> 45 #include <pamtyp.hxx> 46 #include <ndtxt.hxx> 47 #include <swundo.hxx> 48 #include <UndoInsert.hxx> 49 #include <breakit.hxx> 50 51 #include <docsh.hxx> 52 #include <PostItMgr.hxx> 53 #include <viewsh.hxx> 54 55 using namespace ::com::sun::star; 56 using namespace util; 57 58 String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam ); 59 60 String& lcl_CleanStr( 61 const SwTxtNode& rNd, 62 xub_StrLen nStart, 63 xub_StrLen& rEnde, 64 SvULongs& rArr, 65 String& rRet, 66 const bool bRemoveSoftHyphen ) 67 { 68 rRet = rNd.GetTxt(); 69 if( rArr.Count() ) 70 rArr.Remove( 0, rArr.Count() ); 71 72 const SwpHints *pHts = rNd.GetpSwpHints(); 73 74 sal_uInt16 n = 0; 75 xub_StrLen nSoftHyphen = nStart; 76 xub_StrLen nHintStart = STRING_LEN; 77 bool bNewHint = true; 78 bool bNewSoftHyphen = true; 79 const xub_StrLen nEnd = rEnde; 80 SvUShorts aReplaced; 81 82 do 83 { 84 if ( bNewHint ) 85 nHintStart = pHts && n < pHts->Count() ? 86 *(*pHts)[n]->GetStart() : 87 STRING_LEN; 88 89 if ( bNewSoftHyphen ) 90 nSoftHyphen = bRemoveSoftHyphen ? 91 rNd.GetTxt().Search( CHAR_SOFTHYPHEN, nSoftHyphen ) : 92 STRING_LEN; 93 94 bNewHint = false; 95 bNewSoftHyphen = false; 96 97 xub_StrLen nStt = 0; 98 99 // Check if next stop is a hint. 100 if ( STRING_LEN != nHintStart && nHintStart < nSoftHyphen && nHintStart < nEnd ) 101 { 102 nStt = nHintStart; 103 bNewHint = true; 104 } 105 // Check if next stop is a soft hyphen. 106 else if ( STRING_LEN != nSoftHyphen && nSoftHyphen < nHintStart && nSoftHyphen < nEnd ) 107 { 108 nStt = nSoftHyphen; 109 bNewSoftHyphen = true; 110 } 111 // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end. 112 else if ( STRING_LEN != nSoftHyphen && nSoftHyphen == nHintStart ) 113 { 114 nStt = nSoftHyphen; 115 bNewHint = true; 116 bNewSoftHyphen = true; 117 } 118 else 119 break; 120 121 const xub_StrLen nAkt = nStt - rArr.Count(); 122 123 if ( bNewHint ) 124 { 125 const SwTxtAttr* pHt = (*pHts)[n]; 126 if ( pHt->HasDummyChar() && (nStt >= nStart) ) 127 { 128 //JP 17.05.00: Task 75806 ask for ">=" and not for ">" 129 switch( pHt->Which() ) 130 { 131 case RES_TXTATR_FLYCNT: 132 case RES_TXTATR_FTN: 133 case RES_TXTATR_FIELD: 134 case RES_TXTATR_REFMARK: 135 case RES_TXTATR_TOXMARK: 136 case RES_TXTATR_META: 137 case RES_TXTATR_METAFIELD: 138 { 139 // JP 06.05.98: mit Bug 50100 werden sie als Trenner erwuenscht und nicht 140 // mehr zum Wort dazu gehoerend. 141 // MA 23.06.98: mit Bug 51215 sollen sie konsequenterweise auch am 142 // Satzanfang und -ende ignoriert werden wenn sie Leer sind. 143 // Dazu werden sie schlicht entfernt. Fuer den Anfang entfernen 144 // wir sie einfach. 145 // Fuer das Ende merken wir uns die Ersetzungen und entferenen 146 // hinterher alle am Stringende (koenten ja 'normale' 0x7f drinstehen 147 sal_Bool bEmpty = RES_TXTATR_FIELD != pHt->Which() || 148 !(static_cast<SwTxtFld const*>(pHt) 149 ->GetFmtFld().GetField()->ExpandField(true).Len()); 150 if ( bEmpty && nStart == nAkt ) 151 { 152 rArr.Insert( nAkt, rArr.Count() ); 153 --rEnde; 154 rRet.Erase( nAkt, 1 ); 155 } 156 else 157 { 158 if ( bEmpty ) 159 aReplaced.Insert( nAkt, aReplaced.Count() ); 160 rRet.SetChar( nAkt, '\x7f' ); 161 } 162 } 163 break; 164 default: 165 ASSERT( false, "unknown case in lcl_CleanStr" ) 166 break; 167 } 168 } 169 ++n; 170 } 171 172 if ( bNewSoftHyphen ) 173 { 174 rArr.Insert( nAkt, rArr.Count() ); 175 --rEnde; 176 rRet.Erase( nAkt, 1 ); 177 ++nSoftHyphen; 178 } 179 } 180 while ( true ); 181 182 for( sal_uInt16 i = aReplaced.Count(); i; ) 183 { 184 const xub_StrLen nTmp = aReplaced[ --i ]; 185 if( nTmp == rRet.Len() - 1 ) 186 { 187 rRet.Erase( nTmp ); 188 rArr.Insert( nTmp, rArr.Count() ); 189 --rEnde; 190 } 191 } 192 193 return rRet; 194 } 195 196 // skip all non SwPostIts inside the array 197 xub_StrLen GetPostIt(xub_StrLen aCount,const SwpHints *pHts) 198 { 199 xub_StrLen aIndex = 0; 200 while (aCount) 201 { 202 for (xub_StrLen i = 0; i <pHts->Count();i++) 203 { 204 aIndex++; 205 const SwTxtAttr* pTxtAttr = (*pHts)[i]; 206 if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) && 207 (pTxtAttr->GetFmtFld().GetField()->Which()==RES_POSTITFLD)) 208 { 209 aCount--; 210 if (!aCount) 211 break; 212 } 213 } 214 } 215 // throw away all following non postits 216 for (xub_StrLen i = aIndex; i <pHts->Count();i++) 217 { 218 const SwTxtAttr* pTxtAttr = (*pHts)[i]; 219 if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) && 220 (pTxtAttr->GetFmtFld().GetField()->Which()==RES_POSTITFLD)) 221 break; 222 else 223 aIndex++; 224 } 225 return aIndex; 226 } 227 228 sal_uInt8 SwPaM::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes , utl::TextSearch& rSTxt, 229 SwMoveFn fnMove, const SwPaM * pRegion, 230 sal_Bool bInReadOnly ) 231 { 232 if( !rSearchOpt.searchString.getLength() ) 233 return sal_False; 234 235 SwPaM* pPam = MakeRegion( fnMove, pRegion ); 236 sal_Bool bSrchForward = fnMove == fnMoveForward; 237 SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode; 238 SwIndex& rCntntIdx = pPam->GetPoint()->nContent; 239 240 // Wenn am Anfang/Ende, aus dem Node moven 241 // beim leeren Node nicht weiter 242 if( bSrchForward 243 ? ( rCntntIdx.GetIndex() == pPam->GetCntntNode()->Len() && 244 rCntntIdx.GetIndex() ) 245 : !rCntntIdx.GetIndex() && pPam->GetCntntNode()->Len() ) 246 { 247 if( !(*fnMove->fnNds)( &rNdIdx, sal_False )) 248 { 249 delete pPam; 250 return sal_False; 251 } 252 SwCntntNode *pNd = rNdIdx.GetNode().GetCntntNode(); 253 xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len(); 254 rCntntIdx.Assign( pNd, nTmpPos ); 255 } 256 257 /* 258 * Ist bFound == sal_True, dann wurde der String gefunden und in 259 * nStart und nEnde steht der gefundenen String 260 */ 261 sal_Bool bFound = sal_False; 262 /* 263 * StartPostion im Text oder Anfangsposition 264 */ 265 sal_Bool bFirst = sal_True; 266 SwCntntNode * pNode; 267 //testarea 268 //String sCleanStr; 269 //SvULongs aFltArr; 270 //const SwNode* pSttNd = &rNdIdx.GetNode(); 271 272 xub_StrLen nStart, nEnde, nTxtLen; 273 274 sal_Bool bRegSearch = SearchAlgorithms_REGEXP == rSearchOpt.algorithmType; 275 sal_Bool bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() && 276 ( !rSearchOpt.searchString.compareToAscii( "^$" ) || 277 !rSearchOpt.searchString.compareToAscii( "$^" ) ); 278 sal_Bool bChkParaEnd = bRegSearch && 1 == rSearchOpt.searchString.getLength() && 279 !rSearchOpt.searchString.compareToAscii( "$" ); 280 281 // LanguageType eLastLang = 0; 282 while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) )) 283 { 284 if( pNode->IsTxtNode() ) 285 { 286 nTxtLen = ((SwTxtNode*)pNode)->GetTxt().Len(); 287 if( rNdIdx == pPam->GetMark()->nNode ) 288 nEnde = pPam->GetMark()->nContent.GetIndex(); 289 else 290 nEnde = bSrchForward ? nTxtLen : 0; 291 nStart = rCntntIdx.GetIndex(); 292 293 /* #i80135# */ 294 // if there are SwPostItFields inside our current node text, we split the text into seperate pieces 295 // and search for text inside the pieces as well as inside the fields 296 const SwpHints *pHts = ((SwTxtNode*)pNode)->GetpSwpHints(); 297 298 // count postitfields by looping over all fields 299 xub_StrLen aNumberPostits = 0; 300 xub_StrLen aIgnore = 0; 301 if (pHts && bSearchInNotes) 302 { 303 if (!bSrchForward) 304 { 305 xub_StrLen swap = nEnde; 306 nEnde = nStart; 307 nStart = swap; 308 } 309 310 for (xub_StrLen i = 0; i <pHts->Count();i++) 311 { 312 xub_StrLen aPos = *(*pHts)[i]->GetStart(); 313 const SwTxtAttr* pTxtAttr = (*pHts)[i]; 314 if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) && 315 (pTxtAttr->GetFmtFld().GetField()->Which()==RES_POSTITFLD)) 316 { 317 if ( (aPos >= nStart) && (aPos <= nEnde) ) 318 aNumberPostits++; 319 else 320 { 321 if (bSrchForward) 322 aIgnore++; 323 } 324 } 325 } 326 327 if (!bSrchForward) 328 { 329 xub_StrLen swap = nEnde; 330 nEnde = nStart; 331 nStart = swap; 332 } 333 334 } 335 336 SwDocShell *const pDocShell = pNode->GetDoc()->GetDocShell(); 337 ViewShell *const pWrtShell = (pDocShell) ? (ViewShell*)(pDocShell->GetWrtShell()) : 0; 338 SwPostItMgr *const pPostItMgr = (pWrtShell) ? pWrtShell->GetPostItMgr() : 0; 339 340 xub_StrLen aStart = 0; 341 // do we need to finish a note? 342 if (pPostItMgr && pPostItMgr->HasActiveSidebarWin()) 343 { 344 if (bSearchInNotes) 345 { 346 if (bSrchForward) 347 aStart++; 348 else 349 { 350 if (aNumberPostits) 351 --aNumberPostits; 352 } 353 //search inside and finsih and put focus back into the doc 354 if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward)) 355 { 356 bFound = true ; 357 break; 358 } 359 } 360 else 361 { 362 pPostItMgr->SetActiveSidebarWin(0); 363 } 364 } 365 366 if (aNumberPostits) 367 { 368 // now we have to split 369 xub_StrLen nStartInside = 0; 370 xub_StrLen nEndeInside = 0; 371 sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits; 372 373 while ( (aLoop>=0) && (aLoop<=aNumberPostits)) 374 { 375 if (bSrchForward) 376 { 377 nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1; 378 nEndeInside = aLoop==aNumberPostits? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart(); 379 nTxtLen = nEndeInside-nStartInside; 380 } 381 else 382 { 383 nStartInside = aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart(); 384 nEndeInside = aLoop==0 ? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1; 385 nTxtLen = nStartInside-nEndeInside; 386 } 387 // search inside the text between a note 388 bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd, 389 nStartInside,nEndeInside,nTxtLen, pNode,pPam); 390 if (bFound) 391 break; 392 else 393 { 394 // we should now be right in front of a note, search inside 395 if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) )) 396 { 397 const SwTxtAttr* pTxtAttr = bSrchForward ? (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]; 398 if ( pPostItMgr && pPostItMgr->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFmtFld(),rSearchOpt,bSrchForward) ) 399 { 400 bFound = true ; 401 break; 402 } 403 } 404 } 405 aLoop = bSrchForward ? aLoop+1 : aLoop-1; 406 } 407 } 408 else 409 { 410 // if there is no SwPostItField inside or searching inside notes is disabled, we search the whole length just like before 411 bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd, 412 nStart,nEnde,nTxtLen, pNode,pPam); 413 } 414 if (bFound) 415 break; 416 } 417 } 418 delete pPam; 419 return bFound; 420 } 421 422 bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt, 423 SwMoveFn fnMove, 424 sal_Bool bSrchForward, sal_Bool bRegSearch, sal_Bool bChkEmptyPara, sal_Bool bChkParaEnd, 425 xub_StrLen &nStart, xub_StrLen &nEnde, xub_StrLen nTxtLen,SwNode* pNode, SwPaM* pPam) 426 { 427 bool bFound = false; 428 SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode; 429 const SwNode* pSttNd = &rNdIdx.GetNode(); 430 String sCleanStr; 431 SvULongs aFltArr; 432 LanguageType eLastLang = 0; 433 // if the search string contains a soft hypen, we don't strip them from the text: 434 bool bRemoveSoftHyphens = true; 435 if ( bRegSearch ) 436 { 437 const rtl::OUString a00AD( rtl::OUString::createFromAscii( "\\x00AD" ) ); 438 if ( -1 != rSearchOpt.searchString.indexOf( a00AD ) ) 439 bRemoveSoftHyphens = false; 440 } 441 else 442 { 443 if ( 1 == rSearchOpt.searchString.getLength() && 444 CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() ) 445 bRemoveSoftHyphens = false; 446 } 447 448 if( bSrchForward ) 449 lcl_CleanStr( *(SwTxtNode*)pNode, nStart, nEnde, 450 aFltArr, sCleanStr, bRemoveSoftHyphens ); 451 else 452 lcl_CleanStr( *(SwTxtNode*)pNode, nEnde, nStart, 453 aFltArr, sCleanStr, bRemoveSoftHyphens ); 454 455 SwScriptIterator* pScriptIter = 0; 456 sal_uInt16 nSearchScript = 0; 457 sal_uInt16 nCurrScript = 0; 458 459 if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType && 460 pBreakIt->GetBreakIter().is() ) 461 { 462 pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward ); 463 nSearchScript = pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 ); 464 } 465 466 xub_StrLen nStringEnd = nEnde; 467 while ( (bSrchForward && nStart < nStringEnd) || 468 (! bSrchForward && nStart > nStringEnd) ) 469 { 470 // SearchAlgorithms_APPROXIMATE works on a per word base 471 // so we have to provide the text searcher with the correct 472 // locale, because it uses the breakiterator 473 if ( pScriptIter ) 474 { 475 nEnde = pScriptIter->GetScriptChgPos(); 476 nCurrScript = pScriptIter->GetCurrScript(); 477 if ( nSearchScript == nCurrScript ) 478 { 479 const LanguageType eCurrLang = 480 ((SwTxtNode*)pNode)->GetLang( bSrchForward ? 481 nStart : 482 nEnde ); 483 484 if ( eCurrLang != eLastLang ) 485 { 486 const lang::Locale aLocale( 487 pBreakIt->GetLocale( eCurrLang ) ); 488 rSTxt.SetLocale( rSearchOpt, aLocale ); 489 eLastLang = eCurrLang; 490 } 491 } 492 pScriptIter->Next(); 493 } 494 495 if( nSearchScript == nCurrScript && 496 (rSTxt.*fnMove->fnSearch)( sCleanStr, &nStart, &nEnde, 0 )) 497 { 498 // setze den Bereich richtig 499 *GetPoint() = *pPam->GetPoint(); 500 SetMark(); 501 502 // Start und Ende wieder korrigieren !! 503 if( aFltArr.Count() ) 504 { 505 xub_StrLen n, nNew; 506 // bei Rueckwaertssuche die Positionen temp. vertauschen 507 if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; } 508 509 for( n = 0, nNew = nStart; 510 n < aFltArr.Count() && aFltArr[ n ] <= nStart; 511 ++n, ++nNew ) 512 ; 513 nStart = nNew; 514 for( n = 0, nNew = nEnde; 515 n < aFltArr.Count() && aFltArr[ n ] < nEnde; 516 ++n, ++nNew ) 517 ; 518 nEnde = nNew; 519 520 // bei Rueckwaertssuche die Positionen temp. vertauschen 521 if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; } 522 } 523 GetMark()->nContent = nStart; // Startposition setzen 524 GetPoint()->nContent = nEnde; 525 526 if( !bSrchForward ) // rueckwaerts Suche? 527 Exchange(); // Point und Mark tauschen 528 bFound = sal_True; 529 break; 530 } 531 532 nStart = nEnde; 533 } // end of script while 534 535 delete pScriptIter; 536 537 if ( bFound ) 538 return true; 539 else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd ) 540 { 541 *GetPoint() = *pPam->GetPoint(); 542 GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0; 543 SetMark(); 544 if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) && 545 Move( fnMoveForward, fnGoCntnt ) && 546 (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) && 547 1 == Abs( (int)( GetPoint()->nNode.GetIndex() - 548 GetMark()->nNode.GetIndex()) ) ) 549 { 550 if( !bSrchForward ) // rueckwaerts Suche? 551 Exchange(); // Point und Mark tauschen 552 //bFound = sal_True; 553 //break; 554 return true; 555 } 556 } 557 return bFound; 558 } 559 560 // Parameter fuers Suchen und Ersetzen von Text 561 struct SwFindParaText : public SwFindParas 562 { 563 const SearchOptions& rSearchOpt; 564 SwCursor& rCursor; 565 utl::TextSearch aSTxt; 566 sal_Bool bReplace; 567 sal_Bool bSearchInNotes; 568 569 SwFindParaText( const SearchOptions& rOpt, sal_Bool bSearchNotes, int bRepl, SwCursor& rCrsr ) 570 : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes ) 571 {} 572 virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly ); 573 virtual int IsReplaceMode() const; 574 virtual ~SwFindParaText(); 575 }; 576 577 SwFindParaText::~SwFindParaText() 578 { 579 } 580 581 int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove, 582 const SwPaM* pRegion, sal_Bool bInReadOnly ) 583 { 584 if( bInReadOnly && bReplace ) 585 bInReadOnly = sal_False; 586 587 sal_Bool bFnd = (sal_Bool)pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly ); 588 589 /* #i80135# if we found something in a note, Mark and Point is the same 590 if( bFnd && *pCrsr->GetMark() == *pCrsr->GetPoint() ) 591 return FIND_NOT_FOUND; 592 */ 593 594 if( bFnd && bReplace ) // String ersetzen ?? 595 { 596 // Replace-Methode vom SwDoc benutzen 597 const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType); 598 SwIndex& rSttCntIdx = pCrsr->Start()->nContent; 599 xub_StrLen nSttCnt = rSttCntIdx.GetIndex(); 600 // damit die Region auch verschoben wird, in den Shell-Cursr-Ring 601 // mit aufnehmen !! 602 Ring *pPrev(0); 603 if( bRegExp ) 604 { 605 pPrev = pRegion->GetPrev(); 606 ((Ring*)pRegion)->MoveRingTo( &rCursor ); 607 } 608 609 ::std::auto_ptr<String> pRepl( (bRegExp) 610 ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 ); 611 rCursor.GetDoc()->ReplaceRange( *pCrsr, 612 (pRepl.get()) ? *pRepl : String(rSearchOpt.replaceString), 613 bRegExp ); 614 rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() ); 615 616 if( bRegExp ) 617 { 618 // und die Region wieder herausnehmen: 619 Ring *p, *pNext = (Ring*)pRegion; 620 do { 621 p = pNext; 622 pNext = p->GetNext(); 623 p->MoveTo( (Ring*)pRegion ); 624 } while( p != pPrev ); 625 } 626 pCrsr->Start()->nContent = nSttCnt; 627 return FIND_NO_RING; 628 } 629 return bFnd ? FIND_FOUND : FIND_NOT_FOUND; 630 } 631 632 633 int SwFindParaText::IsReplaceMode() const 634 { 635 return bReplace; 636 } 637 638 639 sal_uLong SwCursor::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes, 640 SwDocPositions nStart, SwDocPositions nEnde, 641 sal_Bool& bCancel, 642 FindRanges eFndRngs, int bReplace ) 643 { 644 // OLE-Benachrichtigung abschalten !! 645 SwDoc* pDoc = GetDoc(); 646 Link aLnk( pDoc->GetOle2Link() ); 647 pDoc->SetOle2Link( Link() ); 648 649 bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace; 650 if (bStartUndo) 651 { 652 pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL ); 653 } 654 655 sal_Bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE); 656 if( bSearchSel ) 657 eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL); 658 SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this ); 659 sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnde, eFndRngs, bCancel ); 660 pDoc->SetOle2Link( aLnk ); 661 if( nRet && bReplace ) 662 pDoc->SetModified(); 663 664 if (bStartUndo) 665 { 666 SwRewriter rewriter(MakeUndoReplaceRewriter( 667 nRet, rSearchOpt.searchString, rSearchOpt.replaceString)); 668 pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, & rewriter ); 669 } 670 return nRet; 671 } 672 673 String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam ) 674 { 675 String *pRet = 0; 676 if( pPam && pPam->HasMark() && 677 SearchAlgorithms_REGEXP == rSearchOpt.algorithmType ) 678 { 679 const SwCntntNode* pTxtNode = pPam->GetCntntNode( sal_True ); 680 if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( sal_False ) ) 681 { 682 utl::TextSearch aSTxt( rSearchOpt ); 683 const String& rStr = static_cast<const SwTxtNode*>(pTxtNode)->GetTxt(); 684 xub_StrLen nStart = pPam->Start()->nContent.GetIndex(); 685 xub_StrLen nEnd = pPam->End()->nContent.GetIndex(); 686 SearchResult aResult; 687 if( aSTxt.SearchFrwrd( rStr, &nStart, &nEnd, &aResult ) ) 688 { 689 String aReplaceStr( rSearchOpt.replaceString ); 690 aSTxt.ReplaceBackReferences( aReplaceStr, rStr, aResult ); 691 pRet = new String( aReplaceStr ); 692 } 693 } 694 } 695 return pRet; 696 } 697