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