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
lcl_CleanStr(const SwTxtNode & rNd,const xub_StrLen nStart,xub_StrLen & rEnde,SvULongs & rArr,String & rRet,const bool bRemoveSoftHyphen)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
GetPostIt(xub_StrLen aCount,const SwpHints * pHts)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
Find(const SearchOptions & rSearchOpt,sal_Bool bSearchInNotes,utl::TextSearch & rSTxt,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)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 separate 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
DoSearch(const SearchOptions & rSearchOpt,utl::TextSearch & rSTxt,SwMoveFn fnMove,sal_Bool bSrchForward,sal_Bool bRegSearch,sal_Bool bChkEmptyPara,sal_Bool bChkParaEnd,xub_StrLen & nStart,xub_StrLen & nEnde,xub_StrLen nTxtLen,SwNode * pNode,SwPaM * pPam)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
SwFindParaTextSwFindParaText560 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
~SwFindParaText()568 SwFindParaText::~SwFindParaText()
569 {
570 }
571
Find(SwPaM * pCrsr,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)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
IsReplaceMode() const624 int SwFindParaText::IsReplaceMode() const
625 {
626 return bReplace;
627 }
628
629
Find(const SearchOptions & rSearchOpt,sal_Bool bSearchInNotes,SwDocPositions nStart,SwDocPositions nEnde,sal_Bool & bCancel,FindRanges eFndRngs,int bReplace)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
ReplaceBackReferences(const SearchOptions & rSearchOpt,SwPaM * pPam)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