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_REFMARK: 135 case RES_TXTATR_TOXMARK: 136 case RES_TXTATR_META: 137 case RES_TXTATR_METAFIELD: 138 { 139 sal_Bool bEmpty = RES_TXTATR_FIELD != pHt->Which() || 140 !(static_cast<SwTxtFld const*>(pHt) 141 ->GetFmtFld().GetField()->ExpandField(true).Len()); 142 if ( bEmpty && nStart == nAkt ) 143 { 144 rArr.Insert( nAkt, rArr.Count() ); 145 --rEnde; 146 rRet.Erase( nAkt, 1 ); 147 } 148 else 149 { 150 if ( bEmpty ) 151 aReplaced.Insert( nAkt, aReplaced.Count() ); 152 rRet.SetChar( nAkt, '\x7f' ); 153 } 154 } 155 break; 156 default: 157 ASSERT( false, "unknown case in lcl_CleanStr" ) 158 break; 159 } 160 } 161 ++n; 162 } 163 164 if ( bNewSoftHyphen ) 165 { 166 rArr.Insert( nAkt, rArr.Count() ); 167 --rEnde; 168 rRet.Erase( nAkt, 1 ); 169 ++nSoftHyphen; 170 } 171 } 172 while ( true ); 173 174 for( sal_uInt16 i = aReplaced.Count(); i; ) 175 { 176 const xub_StrLen nTmp = aReplaced[ --i ]; 177 if( nTmp == rRet.Len() - 1 ) 178 { 179 rRet.Erase( nTmp ); 180 rArr.Insert( nTmp, rArr.Count() ); 181 --rEnde; 182 } 183 } 184 185 return rRet; 186 } 187 188 // skip all non SwPostIts inside the array 189 xub_StrLen GetPostIt(xub_StrLen aCount,const SwpHints *pHts) 190 { 191 xub_StrLen aIndex = 0; 192 while (aCount) 193 { 194 for (xub_StrLen i = 0; i <pHts->Count();i++) 195 { 196 aIndex++; 197 const SwTxtAttr* pTxtAttr = (*pHts)[i]; 198 if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) 199 && (pTxtAttr->GetFmtFld().GetField()->Which()==RES_POSTITFLD)) 200 { 201 aCount--; 202 if (!aCount) 203 break; 204 } 205 } 206 } 207 // throw away all following non postits 208 for (xub_StrLen i = aIndex; i <pHts->Count();i++) 209 { 210 const SwTxtAttr* pTxtAttr = (*pHts)[i]; 211 if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) 212 && (pTxtAttr->GetFmtFld().GetField()->Which()==RES_POSTITFLD)) 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_FIELD) 307 && (pTxtAttr->GetFmtFld().GetField()->Which()==RES_POSTITFLD)) 308 { 309 if ( (aPos >= nStart) && (aPos <= nEnde) ) 310 aNumberPostits++; 311 else 312 { 313 if (bSrchForward) 314 aIgnore++; 315 } 316 } 317 } 318 319 if (!bSrchForward) 320 { 321 xub_StrLen swap = nEnde; 322 nEnde = nStart; 323 nStart = swap; 324 } 325 326 } 327 328 SwDocShell *const pDocShell = pNode->GetDoc()->GetDocShell(); 329 ViewShell *const pWrtShell = (pDocShell) ? (ViewShell*)(pDocShell->GetWrtShell()) : 0; 330 SwPostItMgr *const pPostItMgr = (pWrtShell) ? pWrtShell->GetPostItMgr() : 0; 331 332 xub_StrLen aStart = 0; 333 // do we need to finish a note? 334 if (pPostItMgr && pPostItMgr->HasActiveSidebarWin()) 335 { 336 if (bSearchInNotes) 337 { 338 if (bSrchForward) 339 aStart++; 340 else 341 { 342 if (aNumberPostits) 343 --aNumberPostits; 344 } 345 //search inside and finsih and put focus back into the doc 346 if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward)) 347 { 348 bFound = true ; 349 break; 350 } 351 } 352 else 353 { 354 pPostItMgr->SetActiveSidebarWin(0); 355 } 356 } 357 358 if (aNumberPostits) 359 { 360 // now we have to split 361 xub_StrLen nStartInside = 0; 362 xub_StrLen nEndeInside = 0; 363 sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits; 364 365 while ( (aLoop>=0) && (aLoop<=aNumberPostits)) 366 { 367 if (bSrchForward) 368 { 369 nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1; 370 nEndeInside = aLoop==aNumberPostits? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart(); 371 nTxtLen = nEndeInside-nStartInside; 372 } 373 else 374 { 375 nStartInside = aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart(); 376 nEndeInside = aLoop==0 ? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1; 377 nTxtLen = nStartInside-nEndeInside; 378 } 379 // search inside the text between a note 380 bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd, 381 nStartInside,nEndeInside,nTxtLen, pNode,pPam); 382 if (bFound) 383 break; 384 else 385 { 386 // we should now be right in front of a note, search inside 387 if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) )) 388 { 389 const SwTxtAttr* pTxtAttr = bSrchForward ? (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]; 390 if ( pPostItMgr && pPostItMgr->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFmtFld(),rSearchOpt,bSrchForward) ) 391 { 392 bFound = true ; 393 break; 394 } 395 } 396 } 397 aLoop = bSrchForward ? aLoop+1 : aLoop-1; 398 } 399 } 400 else 401 { 402 // if there is no SwPostItField inside or searching inside notes is disabled, we search the whole length just like before 403 bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd, 404 nStart,nEnde,nTxtLen, pNode,pPam); 405 } 406 if (bFound) 407 break; 408 } 409 } 410 delete pPam; 411 return bFound; 412 } 413 414 bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt, 415 SwMoveFn fnMove, 416 sal_Bool bSrchForward, sal_Bool bRegSearch, sal_Bool bChkEmptyPara, sal_Bool bChkParaEnd, 417 xub_StrLen &nStart, xub_StrLen &nEnde, xub_StrLen nTxtLen,SwNode* pNode, SwPaM* pPam) 418 { 419 bool bFound = false; 420 SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode; 421 const SwNode* pSttNd = &rNdIdx.GetNode(); 422 String sCleanStr; 423 SvULongs aFltArr; 424 LanguageType eLastLang = 0; 425 // if the search string contains a soft hypen, we don't strip them from the text: 426 bool bRemoveSoftHyphens = true; 427 if ( bRegSearch ) 428 { 429 const rtl::OUString a00AD( rtl::OUString::createFromAscii( "\\x00AD" ) ); 430 if ( -1 != rSearchOpt.searchString.indexOf( a00AD ) ) 431 bRemoveSoftHyphens = false; 432 } 433 else 434 { 435 if ( 1 == rSearchOpt.searchString.getLength() && 436 CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() ) 437 bRemoveSoftHyphens = false; 438 } 439 440 if( bSrchForward ) 441 lcl_CleanStr( *(SwTxtNode*)pNode, nStart, nEnde, 442 aFltArr, sCleanStr, bRemoveSoftHyphens ); 443 else 444 lcl_CleanStr( *(SwTxtNode*)pNode, nEnde, nStart, 445 aFltArr, sCleanStr, bRemoveSoftHyphens ); 446 447 SwScriptIterator* pScriptIter = 0; 448 sal_uInt16 nSearchScript = 0; 449 sal_uInt16 nCurrScript = 0; 450 451 if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType && 452 pBreakIt->GetBreakIter().is() ) 453 { 454 pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward ); 455 nSearchScript = pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 ); 456 } 457 458 xub_StrLen nStringEnd = nEnde; 459 while ( (bSrchForward && nStart < nStringEnd) || 460 (! bSrchForward && nStart > nStringEnd) ) 461 { 462 // SearchAlgorithms_APPROXIMATE works on a per word base 463 // so we have to provide the text searcher with the correct 464 // locale, because it uses the breakiterator 465 if ( pScriptIter ) 466 { 467 nEnde = pScriptIter->GetScriptChgPos(); 468 nCurrScript = pScriptIter->GetCurrScript(); 469 if ( nSearchScript == nCurrScript ) 470 { 471 const LanguageType eCurrLang = 472 ((SwTxtNode*)pNode)->GetLang( bSrchForward ? 473 nStart : 474 nEnde ); 475 476 if ( eCurrLang != eLastLang ) 477 { 478 const lang::Locale aLocale( 479 pBreakIt->GetLocale( eCurrLang ) ); 480 rSTxt.SetLocale( rSearchOpt, aLocale ); 481 eLastLang = eCurrLang; 482 } 483 } 484 pScriptIter->Next(); 485 } 486 487 if( nSearchScript == nCurrScript && 488 (rSTxt.*fnMove->fnSearch)( sCleanStr, &nStart, &nEnde, 0 )) 489 { 490 // setze den Bereich richtig 491 *GetPoint() = *pPam->GetPoint(); 492 SetMark(); 493 494 // Start und Ende wieder korrigieren !! 495 if( aFltArr.Count() ) 496 { 497 xub_StrLen n, nNew; 498 // bei Rueckwaertssuche die Positionen temp. vertauschen 499 if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; } 500 501 for( n = 0, nNew = nStart; 502 n < aFltArr.Count() && aFltArr[ n ] <= nStart; 503 ++n, ++nNew ) 504 ; 505 nStart = nNew; 506 for( n = 0, nNew = nEnde; 507 n < aFltArr.Count() && aFltArr[ n ] < nEnde; 508 ++n, ++nNew ) 509 ; 510 nEnde = nNew; 511 512 // bei Rueckwaertssuche die Positionen temp. vertauschen 513 if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; } 514 } 515 GetMark()->nContent = nStart; // Startposition setzen 516 GetPoint()->nContent = nEnde; 517 518 if( !bSrchForward ) // rueckwaerts Suche? 519 Exchange(); // Point und Mark tauschen 520 bFound = sal_True; 521 break; 522 } 523 524 nStart = nEnde; 525 } // end of script while 526 527 delete pScriptIter; 528 529 if ( bFound ) 530 return true; 531 else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd ) 532 { 533 *GetPoint() = *pPam->GetPoint(); 534 GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0; 535 SetMark(); 536 if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) && 537 Move( fnMoveForward, fnGoCntnt ) && 538 (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) && 539 1 == Abs( (int)( GetPoint()->nNode.GetIndex() - 540 GetMark()->nNode.GetIndex()) ) ) 541 { 542 if( !bSrchForward ) // rueckwaerts Suche? 543 Exchange(); // Point und Mark tauschen 544 //bFound = sal_True; 545 //break; 546 return true; 547 } 548 } 549 return bFound; 550 } 551 552 // Parameter fuers Suchen und Ersetzen von Text 553 struct SwFindParaText : public SwFindParas 554 { 555 const SearchOptions& rSearchOpt; 556 SwCursor& rCursor; 557 utl::TextSearch aSTxt; 558 sal_Bool bReplace; 559 sal_Bool bSearchInNotes; 560 561 SwFindParaText( const SearchOptions& rOpt, sal_Bool bSearchNotes, int bRepl, SwCursor& rCrsr ) 562 : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes ) 563 {} 564 virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly ); 565 virtual int IsReplaceMode() const; 566 virtual ~SwFindParaText(); 567 }; 568 569 SwFindParaText::~SwFindParaText() 570 { 571 } 572 573 int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove, 574 const SwPaM* pRegion, sal_Bool bInReadOnly ) 575 { 576 if( bInReadOnly && bReplace ) 577 bInReadOnly = sal_False; 578 579 sal_Bool bFnd = (sal_Bool)pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly ); 580 581 /* #i80135# if we found something in a note, Mark and Point is the same 582 if( bFnd && *pCrsr->GetMark() == *pCrsr->GetPoint() ) 583 return FIND_NOT_FOUND; 584 */ 585 586 if( bFnd && bReplace ) // String ersetzen ?? 587 { 588 // Replace-Methode vom SwDoc benutzen 589 const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType); 590 SwIndex& rSttCntIdx = pCrsr->Start()->nContent; 591 xub_StrLen nSttCnt = rSttCntIdx.GetIndex(); 592 // damit die Region auch verschoben wird, in den Shell-Cursr-Ring 593 // mit aufnehmen !! 594 Ring *pPrev(0); 595 if( bRegExp ) 596 { 597 pPrev = pRegion->GetPrev(); 598 ((Ring*)pRegion)->MoveRingTo( &rCursor ); 599 } 600 601 ::std::auto_ptr<String> pRepl( (bRegExp) 602 ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 ); 603 rCursor.GetDoc()->ReplaceRange( *pCrsr, 604 (pRepl.get()) ? *pRepl : String(rSearchOpt.replaceString), 605 bRegExp ); 606 rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() ); 607 608 if( bRegExp ) 609 { 610 // und die Region wieder herausnehmen: 611 Ring *p, *pNext = (Ring*)pRegion; 612 do { 613 p = pNext; 614 pNext = p->GetNext(); 615 p->MoveTo( (Ring*)pRegion ); 616 } while( p != pPrev ); 617 } 618 pCrsr->Start()->nContent = nSttCnt; 619 return FIND_NO_RING; 620 } 621 return bFnd ? FIND_FOUND : FIND_NOT_FOUND; 622 } 623 624 625 int SwFindParaText::IsReplaceMode() const 626 { 627 return bReplace; 628 } 629 630 631 sal_uLong SwCursor::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes, 632 SwDocPositions nStart, SwDocPositions nEnde, 633 sal_Bool& bCancel, 634 FindRanges eFndRngs, int bReplace ) 635 { 636 // OLE-Benachrichtigung abschalten !! 637 SwDoc* pDoc = GetDoc(); 638 Link aLnk( pDoc->GetOle2Link() ); 639 pDoc->SetOle2Link( Link() ); 640 641 bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace; 642 if (bStartUndo) 643 { 644 pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL ); 645 } 646 647 sal_Bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE); 648 if( bSearchSel ) 649 eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL); 650 SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this ); 651 sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnde, eFndRngs, bCancel ); 652 pDoc->SetOle2Link( aLnk ); 653 if( nRet && bReplace ) 654 pDoc->SetModified(); 655 656 if (bStartUndo) 657 { 658 SwRewriter rewriter(MakeUndoReplaceRewriter( 659 nRet, rSearchOpt.searchString, rSearchOpt.replaceString)); 660 pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, & rewriter ); 661 } 662 return nRet; 663 } 664 665 String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam ) 666 { 667 String *pRet = 0; 668 if( pPam && pPam->HasMark() && 669 SearchAlgorithms_REGEXP == rSearchOpt.algorithmType ) 670 { 671 const SwCntntNode* pTxtNode = pPam->GetCntntNode( sal_True ); 672 if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( sal_False ) ) 673 { 674 utl::TextSearch aSTxt( rSearchOpt ); 675 const String& rStr = static_cast<const SwTxtNode*>(pTxtNode)->GetTxt(); 676 xub_StrLen nStart = pPam->Start()->nContent.GetIndex(); 677 xub_StrLen nEnd = pPam->End()->nContent.GetIndex(); 678 SearchResult aResult; 679 if( aSTxt.SearchFrwrd( rStr, &nStart, &nEnd, &aResult ) ) 680 { 681 String aReplaceStr( rSearchOpt.replaceString ); 682 aSTxt.ReplaceBackReferences( aReplaceStr, rStr, aResult ); 683 pRet = new String( aReplaceStr ); 684 } 685 } 686 } 687 return pRet; 688 } 689