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