xref: /trunk/main/sw/source/core/crsr/findtxt.cxx (revision 86e1cf34)
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