1efeef26fSAndrew Rist /**************************************************************
2efeef26fSAndrew Rist *
3efeef26fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist * or more contributor license agreements. See the NOTICE file
5efeef26fSAndrew Rist * distributed with this work for additional information
6efeef26fSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7efeef26fSAndrew Rist * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist * with the License. You may obtain a copy of the License at
10efeef26fSAndrew Rist *
11efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist *
13efeef26fSAndrew Rist * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist * software distributed under the License is distributed on an
15efeef26fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist * KIND, either express or implied. See the License for the
17efeef26fSAndrew Rist * specific language governing permissions and limitations
18efeef26fSAndrew Rist * under the License.
19efeef26fSAndrew Rist *
20efeef26fSAndrew Rist *************************************************************/
21efeef26fSAndrew Rist
22efeef26fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <com/sun/star/util/SearchOptions.hpp>
28cdf0e10cSrcweir #include <com/sun/star/util/SearchFlags.hpp>
29cdf0e10cSrcweir
30cdf0e10cSrcweir #define _SVSTDARR_USHORTS
31cdf0e10cSrcweir #define _SVSTDARR_ULONGS
32cdf0e10cSrcweir #include <svl/svstdarr.hxx>
33cdf0e10cSrcweir
34cdf0e10cSrcweir #include <vcl/svapp.hxx>
35cdf0e10cSrcweir #include <vcl/window.hxx>
36cdf0e10cSrcweir
37cdf0e10cSrcweir #include <txatritr.hxx>
38cdf0e10cSrcweir #include <fldbas.hxx>
39cdf0e10cSrcweir #include <fmtfld.hxx>
40cdf0e10cSrcweir #include <txtatr.hxx>
41cdf0e10cSrcweir #include <txtfld.hxx>
42cdf0e10cSrcweir #include <swcrsr.hxx>
43cdf0e10cSrcweir #include <doc.hxx>
44cdf0e10cSrcweir #include <IDocumentUndoRedo.hxx>
45cdf0e10cSrcweir #include <pamtyp.hxx>
46cdf0e10cSrcweir #include <ndtxt.hxx>
47cdf0e10cSrcweir #include <swundo.hxx>
48cdf0e10cSrcweir #include <UndoInsert.hxx>
49cdf0e10cSrcweir #include <breakit.hxx>
50cdf0e10cSrcweir
51cdf0e10cSrcweir #include <docsh.hxx>
52cdf0e10cSrcweir #include <PostItMgr.hxx>
53cdf0e10cSrcweir #include <viewsh.hxx>
54cdf0e10cSrcweir
55cdf0e10cSrcweir using namespace ::com::sun::star;
56cdf0e10cSrcweir using namespace util;
57cdf0e10cSrcweir
58cdf0e10cSrcweir String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam );
59cdf0e10cSrcweir
6069a74367SOliver-Rainer Wittmann
lcl_CleanStr(const SwTxtNode & rNd,const xub_StrLen nStart,xub_StrLen & rEnde,SvULongs & rArr,String & rRet,const bool bRemoveSoftHyphen)61c0286415SOliver-Rainer Wittmann String& lcl_CleanStr(
62c0286415SOliver-Rainer Wittmann const SwTxtNode& rNd,
6369a74367SOliver-Rainer Wittmann const xub_StrLen nStart,
64c0286415SOliver-Rainer Wittmann xub_StrLen& rEnde,
65c0286415SOliver-Rainer Wittmann SvULongs& rArr,
66c0286415SOliver-Rainer Wittmann String& rRet,
67c0286415SOliver-Rainer Wittmann const bool bRemoveSoftHyphen )
68cdf0e10cSrcweir {
6969a74367SOliver-Rainer Wittmann rRet = rNd.GetTxt();
7069a74367SOliver-Rainer Wittmann if( rArr.Count() )
7169a74367SOliver-Rainer Wittmann rArr.Remove( 0, rArr.Count() );
72cdf0e10cSrcweir
7369a74367SOliver-Rainer Wittmann const SwpHints *pHts = rNd.GetpSwpHints();
74cdf0e10cSrcweir
75cdf0e10cSrcweir sal_uInt16 n = 0;
76cdf0e10cSrcweir xub_StrLen nSoftHyphen = nStart;
77cdf0e10cSrcweir xub_StrLen nHintStart = STRING_LEN;
78cdf0e10cSrcweir bool bNewHint = true;
79cdf0e10cSrcweir bool bNewSoftHyphen = true;
80cdf0e10cSrcweir const xub_StrLen nEnd = rEnde;
81cdf0e10cSrcweir SvUShorts aReplaced;
82cdf0e10cSrcweir
83cdf0e10cSrcweir do
84cdf0e10cSrcweir {
85cdf0e10cSrcweir if ( bNewHint )
86cdf0e10cSrcweir nHintStart = pHts && n < pHts->Count() ?
87cdf0e10cSrcweir *(*pHts)[n]->GetStart() :
88cdf0e10cSrcweir STRING_LEN;
89cdf0e10cSrcweir
90cdf0e10cSrcweir if ( bNewSoftHyphen )
91cdf0e10cSrcweir nSoftHyphen = bRemoveSoftHyphen ?
92cdf0e10cSrcweir rNd.GetTxt().Search( CHAR_SOFTHYPHEN, nSoftHyphen ) :
93cdf0e10cSrcweir STRING_LEN;
94cdf0e10cSrcweir
95cdf0e10cSrcweir bNewHint = false;
96cdf0e10cSrcweir bNewSoftHyphen = false;
97cdf0e10cSrcweir
98cdf0e10cSrcweir xub_StrLen nStt = 0;
99cdf0e10cSrcweir
100cdf0e10cSrcweir // Check if next stop is a hint.
101cdf0e10cSrcweir if ( STRING_LEN != nHintStart && nHintStart < nSoftHyphen && nHintStart < nEnd )
102cdf0e10cSrcweir {
103cdf0e10cSrcweir nStt = nHintStart;
104cdf0e10cSrcweir bNewHint = true;
105cdf0e10cSrcweir }
106cdf0e10cSrcweir // Check if next stop is a soft hyphen.
107cdf0e10cSrcweir else if ( STRING_LEN != nSoftHyphen && nSoftHyphen < nHintStart && nSoftHyphen < nEnd )
108cdf0e10cSrcweir {
109cdf0e10cSrcweir nStt = nSoftHyphen;
110cdf0e10cSrcweir bNewSoftHyphen = true;
111cdf0e10cSrcweir }
112cdf0e10cSrcweir // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
113cdf0e10cSrcweir else if ( STRING_LEN != nSoftHyphen && nSoftHyphen == nHintStart )
114cdf0e10cSrcweir {
115cdf0e10cSrcweir nStt = nSoftHyphen;
116cdf0e10cSrcweir bNewHint = true;
117cdf0e10cSrcweir bNewSoftHyphen = true;
118cdf0e10cSrcweir }
119cdf0e10cSrcweir else
120cdf0e10cSrcweir break;
121cdf0e10cSrcweir
122cdf0e10cSrcweir const xub_StrLen nAkt = nStt - rArr.Count();
123cdf0e10cSrcweir
124cdf0e10cSrcweir if ( bNewHint )
125cdf0e10cSrcweir {
126cdf0e10cSrcweir const SwTxtAttr* pHt = (*pHts)[n];
127cdf0e10cSrcweir if ( pHt->HasDummyChar() && (nStt >= nStart) )
128cdf0e10cSrcweir {
129c0286415SOliver-Rainer Wittmann switch( pHt->Which() )
130c0286415SOliver-Rainer Wittmann {
131c0286415SOliver-Rainer Wittmann case RES_TXTATR_FLYCNT:
132c0286415SOliver-Rainer Wittmann case RES_TXTATR_FTN:
133c0286415SOliver-Rainer Wittmann case RES_TXTATR_FIELD:
134dec99bbdSOliver-Rainer Wittmann case RES_TXTATR_ANNOTATION:
135c0286415SOliver-Rainer Wittmann case RES_TXTATR_REFMARK:
136c0286415SOliver-Rainer Wittmann case RES_TXTATR_TOXMARK:
137cdf0e10cSrcweir case RES_TXTATR_META:
138cdf0e10cSrcweir case RES_TXTATR_METAFIELD:
139cdf0e10cSrcweir {
140dec99bbdSOliver-Rainer Wittmann const bool bEmpty =
141dec99bbdSOliver-Rainer Wittmann ( pHt->Which() != RES_TXTATR_FIELD
142dec99bbdSOliver-Rainer Wittmann && pHt->Which() != RES_TXTATR_ANNOTATION )
143dec99bbdSOliver-Rainer Wittmann || !(static_cast<SwTxtFld const*>(pHt)->GetFmtFld().GetField()->ExpandField(true).Len());
144c0286415SOliver-Rainer Wittmann if ( bEmpty && nStart == nAkt )
145c0286415SOliver-Rainer Wittmann {
146c0286415SOliver-Rainer Wittmann rArr.Insert( nAkt, rArr.Count() );
147c0286415SOliver-Rainer Wittmann --rEnde;
148c0286415SOliver-Rainer Wittmann rRet.Erase( nAkt, 1 );
149c0286415SOliver-Rainer Wittmann }
150c0286415SOliver-Rainer Wittmann else
151c0286415SOliver-Rainer Wittmann {
152c0286415SOliver-Rainer Wittmann if ( bEmpty )
153c0286415SOliver-Rainer Wittmann aReplaced.Insert( nAkt, aReplaced.Count() );
154c0286415SOliver-Rainer Wittmann rRet.SetChar( nAkt, '\x7f' );
155c0286415SOliver-Rainer Wittmann }
156c0286415SOliver-Rainer Wittmann }
157c0286415SOliver-Rainer Wittmann break;
158c0286415SOliver-Rainer Wittmann default:
159cdf0e10cSrcweir ASSERT( false, "unknown case in lcl_CleanStr" )
160c0286415SOliver-Rainer Wittmann break;
161c0286415SOliver-Rainer Wittmann }
162c0286415SOliver-Rainer Wittmann }
163cdf0e10cSrcweir ++n;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir
166cdf0e10cSrcweir if ( bNewSoftHyphen )
167cdf0e10cSrcweir {
16869a74367SOliver-Rainer Wittmann rArr.Insert( nAkt, rArr.Count() );
16969a74367SOliver-Rainer Wittmann --rEnde;
17069a74367SOliver-Rainer Wittmann rRet.Erase( nAkt, 1 );
171cdf0e10cSrcweir ++nSoftHyphen;
172cdf0e10cSrcweir }
173cdf0e10cSrcweir }
174cdf0e10cSrcweir while ( true );
175cdf0e10cSrcweir
176cdf0e10cSrcweir for( sal_uInt16 i = aReplaced.Count(); i; )
17769a74367SOliver-Rainer Wittmann {
17869a74367SOliver-Rainer Wittmann const xub_StrLen nTmp = aReplaced[ --i ];
179cdf0e10cSrcweir if( nTmp == rRet.Len() - 1 )
18069a74367SOliver-Rainer Wittmann {
18169a74367SOliver-Rainer Wittmann rRet.Erase( nTmp );
18269a74367SOliver-Rainer Wittmann rArr.Insert( nTmp, rArr.Count() );
18369a74367SOliver-Rainer Wittmann --rEnde;
18469a74367SOliver-Rainer Wittmann }
18569a74367SOliver-Rainer Wittmann }
186cdf0e10cSrcweir
18769a74367SOliver-Rainer Wittmann return rRet;
188cdf0e10cSrcweir }
189cdf0e10cSrcweir
190cdf0e10cSrcweir // skip all non SwPostIts inside the array
GetPostIt(xub_StrLen aCount,const SwpHints * pHts)191cdf0e10cSrcweir xub_StrLen GetPostIt(xub_StrLen aCount,const SwpHints *pHts)
192cdf0e10cSrcweir {
19369a74367SOliver-Rainer Wittmann xub_StrLen aIndex = 0;
19469a74367SOliver-Rainer Wittmann while (aCount)
19569a74367SOliver-Rainer Wittmann {
19669a74367SOliver-Rainer Wittmann for (xub_StrLen i = 0; i <pHts->Count();i++)
19769a74367SOliver-Rainer Wittmann {
19869a74367SOliver-Rainer Wittmann aIndex++;
19969a74367SOliver-Rainer Wittmann const SwTxtAttr* pTxtAttr = (*pHts)[i];
200dec99bbdSOliver-Rainer Wittmann if ( pTxtAttr->Which() == RES_TXTATR_ANNOTATION )
20169a74367SOliver-Rainer Wittmann {
20269a74367SOliver-Rainer Wittmann aCount--;
20369a74367SOliver-Rainer Wittmann if (!aCount)
20469a74367SOliver-Rainer Wittmann break;
20569a74367SOliver-Rainer Wittmann }
20669a74367SOliver-Rainer Wittmann }
20769a74367SOliver-Rainer Wittmann }
20869a74367SOliver-Rainer Wittmann // throw away all following non postits
20969a74367SOliver-Rainer Wittmann for (xub_StrLen i = aIndex; i <pHts->Count();i++)
21069a74367SOliver-Rainer Wittmann {
21169a74367SOliver-Rainer Wittmann const SwTxtAttr* pTxtAttr = (*pHts)[i];
212dec99bbdSOliver-Rainer Wittmann if ( pTxtAttr->Which() == RES_TXTATR_ANNOTATION )
21369a74367SOliver-Rainer Wittmann break;
21469a74367SOliver-Rainer Wittmann else
21569a74367SOliver-Rainer Wittmann aIndex++;
21669a74367SOliver-Rainer Wittmann }
21769a74367SOliver-Rainer Wittmann return aIndex;
218cdf0e10cSrcweir }
219cdf0e10cSrcweir
Find(const SearchOptions & rSearchOpt,sal_Bool bSearchInNotes,utl::TextSearch & rSTxt,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)220cdf0e10cSrcweir sal_uInt8 SwPaM::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes , utl::TextSearch& rSTxt,
221cdf0e10cSrcweir SwMoveFn fnMove, const SwPaM * pRegion,
222cdf0e10cSrcweir sal_Bool bInReadOnly )
223cdf0e10cSrcweir {
224cdf0e10cSrcweir if( !rSearchOpt.searchString.getLength() )
225cdf0e10cSrcweir return sal_False;
226cdf0e10cSrcweir
227cdf0e10cSrcweir SwPaM* pPam = MakeRegion( fnMove, pRegion );
228cdf0e10cSrcweir sal_Bool bSrchForward = fnMove == fnMoveForward;
229cdf0e10cSrcweir SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
230cdf0e10cSrcweir SwIndex& rCntntIdx = pPam->GetPoint()->nContent;
231cdf0e10cSrcweir
232cdf0e10cSrcweir // Wenn am Anfang/Ende, aus dem Node moven
233cdf0e10cSrcweir // beim leeren Node nicht weiter
234cdf0e10cSrcweir if( bSrchForward
235cdf0e10cSrcweir ? ( rCntntIdx.GetIndex() == pPam->GetCntntNode()->Len() &&
236cdf0e10cSrcweir rCntntIdx.GetIndex() )
237cdf0e10cSrcweir : !rCntntIdx.GetIndex() && pPam->GetCntntNode()->Len() )
238cdf0e10cSrcweir {
239cdf0e10cSrcweir if( !(*fnMove->fnNds)( &rNdIdx, sal_False ))
240cdf0e10cSrcweir {
241cdf0e10cSrcweir delete pPam;
242cdf0e10cSrcweir return sal_False;
243cdf0e10cSrcweir }
244cdf0e10cSrcweir SwCntntNode *pNd = rNdIdx.GetNode().GetCntntNode();
245cdf0e10cSrcweir xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
246cdf0e10cSrcweir rCntntIdx.Assign( pNd, nTmpPos );
247cdf0e10cSrcweir }
248cdf0e10cSrcweir
249cdf0e10cSrcweir /*
250cdf0e10cSrcweir * Ist bFound == sal_True, dann wurde der String gefunden und in
251cdf0e10cSrcweir * nStart und nEnde steht der gefundenen String
252cdf0e10cSrcweir */
253cdf0e10cSrcweir sal_Bool bFound = sal_False;
254cdf0e10cSrcweir /*
255cdf0e10cSrcweir * StartPostion im Text oder Anfangsposition
256cdf0e10cSrcweir */
257cdf0e10cSrcweir sal_Bool bFirst = sal_True;
258cdf0e10cSrcweir SwCntntNode * pNode;
259cdf0e10cSrcweir //testarea
260cdf0e10cSrcweir //String sCleanStr;
261cdf0e10cSrcweir //SvULongs aFltArr;
262cdf0e10cSrcweir //const SwNode* pSttNd = &rNdIdx.GetNode();
263cdf0e10cSrcweir
264cdf0e10cSrcweir xub_StrLen nStart, nEnde, nTxtLen;
265cdf0e10cSrcweir
266cdf0e10cSrcweir sal_Bool bRegSearch = SearchAlgorithms_REGEXP == rSearchOpt.algorithmType;
267cdf0e10cSrcweir sal_Bool bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() &&
268cdf0e10cSrcweir ( !rSearchOpt.searchString.compareToAscii( "^$" ) ||
269cdf0e10cSrcweir !rSearchOpt.searchString.compareToAscii( "$^" ) );
270cdf0e10cSrcweir sal_Bool bChkParaEnd = bRegSearch && 1 == rSearchOpt.searchString.getLength() &&
271cdf0e10cSrcweir !rSearchOpt.searchString.compareToAscii( "$" );
272cdf0e10cSrcweir
273cdf0e10cSrcweir // LanguageType eLastLang = 0;
274cdf0e10cSrcweir while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
275cdf0e10cSrcweir {
276cdf0e10cSrcweir if( pNode->IsTxtNode() )
277cdf0e10cSrcweir {
278cdf0e10cSrcweir nTxtLen = ((SwTxtNode*)pNode)->GetTxt().Len();
279cdf0e10cSrcweir if( rNdIdx == pPam->GetMark()->nNode )
280cdf0e10cSrcweir nEnde = pPam->GetMark()->nContent.GetIndex();
281cdf0e10cSrcweir else
282cdf0e10cSrcweir nEnde = bSrchForward ? nTxtLen : 0;
283cdf0e10cSrcweir nStart = rCntntIdx.GetIndex();
284cdf0e10cSrcweir
285cdf0e10cSrcweir /* #i80135# */
286*86e1cf34SPedro Giffuni // if there are SwPostItFields inside our current node text, we split the text into separate pieces
287cdf0e10cSrcweir // and search for text inside the pieces as well as inside the fields
288cdf0e10cSrcweir const SwpHints *pHts = ((SwTxtNode*)pNode)->GetpSwpHints();
289cdf0e10cSrcweir
290cdf0e10cSrcweir // count postitfields by looping over all fields
291cdf0e10cSrcweir xub_StrLen aNumberPostits = 0;
292cdf0e10cSrcweir xub_StrLen aIgnore = 0;
293cdf0e10cSrcweir if (pHts && bSearchInNotes)
294cdf0e10cSrcweir {
295cdf0e10cSrcweir if (!bSrchForward)
296cdf0e10cSrcweir {
297cdf0e10cSrcweir xub_StrLen swap = nEnde;
298cdf0e10cSrcweir nEnde = nStart;
299cdf0e10cSrcweir nStart = swap;
300cdf0e10cSrcweir }
301cdf0e10cSrcweir
30269a74367SOliver-Rainer Wittmann for (xub_StrLen i = 0; i <pHts->Count();i++)
30369a74367SOliver-Rainer Wittmann {
30469a74367SOliver-Rainer Wittmann const xub_StrLen aPos = *(*pHts)[i]->GetStart();
30569a74367SOliver-Rainer Wittmann const SwTxtAttr* pTxtAttr = (*pHts)[i];
306dec99bbdSOliver-Rainer Wittmann if ( pTxtAttr->Which()==RES_TXTATR_ANNOTATION )
30769a74367SOliver-Rainer Wittmann {
30869a74367SOliver-Rainer Wittmann if ( (aPos >= nStart) && (aPos <= nEnde) )
30969a74367SOliver-Rainer Wittmann aNumberPostits++;
31069a74367SOliver-Rainer Wittmann else
31169a74367SOliver-Rainer Wittmann {
31269a74367SOliver-Rainer Wittmann if (bSrchForward)
31369a74367SOliver-Rainer Wittmann aIgnore++;
31469a74367SOliver-Rainer Wittmann }
31569a74367SOliver-Rainer Wittmann }
31669a74367SOliver-Rainer Wittmann }
317cdf0e10cSrcweir
318cdf0e10cSrcweir if (!bSrchForward)
319cdf0e10cSrcweir {
320cdf0e10cSrcweir xub_StrLen swap = nEnde;
321cdf0e10cSrcweir nEnde = nStart;
322cdf0e10cSrcweir nStart = swap;
323cdf0e10cSrcweir }
324cdf0e10cSrcweir
325cdf0e10cSrcweir }
326cdf0e10cSrcweir
327cdf0e10cSrcweir SwDocShell *const pDocShell = pNode->GetDoc()->GetDocShell();
328cdf0e10cSrcweir ViewShell *const pWrtShell = (pDocShell) ? (ViewShell*)(pDocShell->GetWrtShell()) : 0;
329cdf0e10cSrcweir SwPostItMgr *const pPostItMgr = (pWrtShell) ? pWrtShell->GetPostItMgr() : 0;
330cdf0e10cSrcweir
331cdf0e10cSrcweir xub_StrLen aStart = 0;
332cdf0e10cSrcweir // do we need to finish a note?
333cdf0e10cSrcweir if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
334cdf0e10cSrcweir {
335cdf0e10cSrcweir if (bSearchInNotes)
336cdf0e10cSrcweir {
337cdf0e10cSrcweir if (bSrchForward)
338cdf0e10cSrcweir aStart++;
339cdf0e10cSrcweir else
340cdf0e10cSrcweir {
341cdf0e10cSrcweir if (aNumberPostits)
342cdf0e10cSrcweir --aNumberPostits;
343cdf0e10cSrcweir }
344cdf0e10cSrcweir //search inside and finsih and put focus back into the doc
345cdf0e10cSrcweir if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward))
346cdf0e10cSrcweir {
347cdf0e10cSrcweir bFound = true ;
348cdf0e10cSrcweir break;
349cdf0e10cSrcweir }
350cdf0e10cSrcweir }
351cdf0e10cSrcweir else
352cdf0e10cSrcweir {
353cdf0e10cSrcweir pPostItMgr->SetActiveSidebarWin(0);
354cdf0e10cSrcweir }
355cdf0e10cSrcweir }
356cdf0e10cSrcweir
357cdf0e10cSrcweir if (aNumberPostits)
358cdf0e10cSrcweir {
359cdf0e10cSrcweir // now we have to split
360cdf0e10cSrcweir xub_StrLen nStartInside = 0;
361cdf0e10cSrcweir xub_StrLen nEndeInside = 0;
362cdf0e10cSrcweir sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits;
363cdf0e10cSrcweir
364cdf0e10cSrcweir while ( (aLoop>=0) && (aLoop<=aNumberPostits))
365cdf0e10cSrcweir {
366cdf0e10cSrcweir if (bSrchForward)
367cdf0e10cSrcweir {
368cdf0e10cSrcweir nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
369cdf0e10cSrcweir nEndeInside = aLoop==aNumberPostits? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
370cdf0e10cSrcweir nTxtLen = nEndeInside-nStartInside;
371cdf0e10cSrcweir }
372cdf0e10cSrcweir else
373cdf0e10cSrcweir {
374cdf0e10cSrcweir nStartInside = aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
375cdf0e10cSrcweir nEndeInside = aLoop==0 ? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
376cdf0e10cSrcweir nTxtLen = nStartInside-nEndeInside;
377cdf0e10cSrcweir }
378cdf0e10cSrcweir // search inside the text between a note
379cdf0e10cSrcweir bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
380cdf0e10cSrcweir nStartInside,nEndeInside,nTxtLen, pNode,pPam);
381cdf0e10cSrcweir if (bFound)
382cdf0e10cSrcweir break;
383cdf0e10cSrcweir else
384cdf0e10cSrcweir {
385cdf0e10cSrcweir // we should now be right in front of a note, search inside
386cdf0e10cSrcweir if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) ))
387cdf0e10cSrcweir {
388cdf0e10cSrcweir const SwTxtAttr* pTxtAttr = bSrchForward ? (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)];
389c0286415SOliver-Rainer Wittmann if ( pPostItMgr && pPostItMgr->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFmtFld(),rSearchOpt,bSrchForward) )
390cdf0e10cSrcweir {
391cdf0e10cSrcweir bFound = true ;
392cdf0e10cSrcweir break;
393cdf0e10cSrcweir }
394cdf0e10cSrcweir }
395cdf0e10cSrcweir }
396cdf0e10cSrcweir aLoop = bSrchForward ? aLoop+1 : aLoop-1;
397cdf0e10cSrcweir }
398cdf0e10cSrcweir }
399cdf0e10cSrcweir else
400cdf0e10cSrcweir {
401cdf0e10cSrcweir // if there is no SwPostItField inside or searching inside notes is disabled, we search the whole length just like before
402cdf0e10cSrcweir bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
403cdf0e10cSrcweir nStart,nEnde,nTxtLen, pNode,pPam);
404cdf0e10cSrcweir }
405cdf0e10cSrcweir if (bFound)
406cdf0e10cSrcweir break;
407cdf0e10cSrcweir }
408cdf0e10cSrcweir }
409cdf0e10cSrcweir delete pPam;
410cdf0e10cSrcweir return bFound;
411cdf0e10cSrcweir }
412cdf0e10cSrcweir
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)413cdf0e10cSrcweir bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt,
414cdf0e10cSrcweir SwMoveFn fnMove,
415cdf0e10cSrcweir sal_Bool bSrchForward, sal_Bool bRegSearch, sal_Bool bChkEmptyPara, sal_Bool bChkParaEnd,
416cdf0e10cSrcweir xub_StrLen &nStart, xub_StrLen &nEnde, xub_StrLen nTxtLen,SwNode* pNode, SwPaM* pPam)
417cdf0e10cSrcweir {
418cdf0e10cSrcweir bool bFound = false;
419cdf0e10cSrcweir SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
420cdf0e10cSrcweir const SwNode* pSttNd = &rNdIdx.GetNode();
421cdf0e10cSrcweir String sCleanStr;
422cdf0e10cSrcweir SvULongs aFltArr;
423cdf0e10cSrcweir LanguageType eLastLang = 0;
424cdf0e10cSrcweir // if the search string contains a soft hypen, we don't strip them from the text:
425cdf0e10cSrcweir bool bRemoveSoftHyphens = true;
426cdf0e10cSrcweir if ( bRegSearch )
427cdf0e10cSrcweir {
428cdf0e10cSrcweir const rtl::OUString a00AD( rtl::OUString::createFromAscii( "\\x00AD" ) );
429cdf0e10cSrcweir if ( -1 != rSearchOpt.searchString.indexOf( a00AD ) )
430cdf0e10cSrcweir bRemoveSoftHyphens = false;
431cdf0e10cSrcweir }
432cdf0e10cSrcweir else
433cdf0e10cSrcweir {
434cdf0e10cSrcweir if ( 1 == rSearchOpt.searchString.getLength() &&
435cdf0e10cSrcweir CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
436cdf0e10cSrcweir bRemoveSoftHyphens = false;
437cdf0e10cSrcweir }
438cdf0e10cSrcweir
439cdf0e10cSrcweir if( bSrchForward )
440cdf0e10cSrcweir lcl_CleanStr( *(SwTxtNode*)pNode, nStart, nEnde,
441cdf0e10cSrcweir aFltArr, sCleanStr, bRemoveSoftHyphens );
442cdf0e10cSrcweir else
443cdf0e10cSrcweir lcl_CleanStr( *(SwTxtNode*)pNode, nEnde, nStart,
444cdf0e10cSrcweir aFltArr, sCleanStr, bRemoveSoftHyphens );
445cdf0e10cSrcweir
446cdf0e10cSrcweir SwScriptIterator* pScriptIter = 0;
447cdf0e10cSrcweir sal_uInt16 nSearchScript = 0;
448cdf0e10cSrcweir sal_uInt16 nCurrScript = 0;
449cdf0e10cSrcweir
450cdf0e10cSrcweir if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType &&
451cdf0e10cSrcweir pBreakIt->GetBreakIter().is() )
452cdf0e10cSrcweir {
453cdf0e10cSrcweir pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward );
454cdf0e10cSrcweir nSearchScript = pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
455cdf0e10cSrcweir }
456cdf0e10cSrcweir
457cdf0e10cSrcweir xub_StrLen nStringEnd = nEnde;
458cdf0e10cSrcweir while ( (bSrchForward && nStart < nStringEnd) ||
459cdf0e10cSrcweir (! bSrchForward && nStart > nStringEnd) )
460cdf0e10cSrcweir {
461cdf0e10cSrcweir // SearchAlgorithms_APPROXIMATE works on a per word base
462cdf0e10cSrcweir // so we have to provide the text searcher with the correct
463cdf0e10cSrcweir // locale, because it uses the breakiterator
464cdf0e10cSrcweir if ( pScriptIter )
465cdf0e10cSrcweir {
466cdf0e10cSrcweir nEnde = pScriptIter->GetScriptChgPos();
467cdf0e10cSrcweir nCurrScript = pScriptIter->GetCurrScript();
468cdf0e10cSrcweir if ( nSearchScript == nCurrScript )
469cdf0e10cSrcweir {
470cdf0e10cSrcweir const LanguageType eCurrLang =
471cdf0e10cSrcweir ((SwTxtNode*)pNode)->GetLang( bSrchForward ?
472cdf0e10cSrcweir nStart :
473cdf0e10cSrcweir nEnde );
474cdf0e10cSrcweir
475cdf0e10cSrcweir if ( eCurrLang != eLastLang )
476cdf0e10cSrcweir {
477cdf0e10cSrcweir const lang::Locale aLocale(
478cdf0e10cSrcweir pBreakIt->GetLocale( eCurrLang ) );
479cdf0e10cSrcweir rSTxt.SetLocale( rSearchOpt, aLocale );
480cdf0e10cSrcweir eLastLang = eCurrLang;
481cdf0e10cSrcweir }
482cdf0e10cSrcweir }
483cdf0e10cSrcweir pScriptIter->Next();
484cdf0e10cSrcweir }
485cdf0e10cSrcweir
486cdf0e10cSrcweir if( nSearchScript == nCurrScript &&
487cdf0e10cSrcweir (rSTxt.*fnMove->fnSearch)( sCleanStr, &nStart, &nEnde, 0 ))
488cdf0e10cSrcweir {
489cdf0e10cSrcweir // setze den Bereich richtig
490cdf0e10cSrcweir *GetPoint() = *pPam->GetPoint();
491cdf0e10cSrcweir SetMark();
492cdf0e10cSrcweir
493cdf0e10cSrcweir // Start und Ende wieder korrigieren !!
494cdf0e10cSrcweir if( aFltArr.Count() )
495cdf0e10cSrcweir {
496cdf0e10cSrcweir xub_StrLen n, nNew;
497cdf0e10cSrcweir // bei Rueckwaertssuche die Positionen temp. vertauschen
498cdf0e10cSrcweir if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
499cdf0e10cSrcweir
500cdf0e10cSrcweir for( n = 0, nNew = nStart;
501cdf0e10cSrcweir n < aFltArr.Count() && aFltArr[ n ] <= nStart;
502cdf0e10cSrcweir ++n, ++nNew )
503cdf0e10cSrcweir ;
504cdf0e10cSrcweir nStart = nNew;
505cdf0e10cSrcweir for( n = 0, nNew = nEnde;
506cdf0e10cSrcweir n < aFltArr.Count() && aFltArr[ n ] < nEnde;
507cdf0e10cSrcweir ++n, ++nNew )
508cdf0e10cSrcweir ;
509cdf0e10cSrcweir nEnde = nNew;
510cdf0e10cSrcweir
511cdf0e10cSrcweir // bei Rueckwaertssuche die Positionen temp. vertauschen
512cdf0e10cSrcweir if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
513cdf0e10cSrcweir }
514cdf0e10cSrcweir GetMark()->nContent = nStart; // Startposition setzen
515cdf0e10cSrcweir GetPoint()->nContent = nEnde;
516cdf0e10cSrcweir
517cdf0e10cSrcweir if( !bSrchForward ) // rueckwaerts Suche?
518cdf0e10cSrcweir Exchange(); // Point und Mark tauschen
519cdf0e10cSrcweir bFound = sal_True;
520cdf0e10cSrcweir break;
521cdf0e10cSrcweir }
522cdf0e10cSrcweir
523cdf0e10cSrcweir nStart = nEnde;
524cdf0e10cSrcweir } // end of script while
525cdf0e10cSrcweir
526cdf0e10cSrcweir delete pScriptIter;
527cdf0e10cSrcweir
528cdf0e10cSrcweir if ( bFound )
529cdf0e10cSrcweir return true;
530cdf0e10cSrcweir else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd )
531cdf0e10cSrcweir {
532cdf0e10cSrcweir *GetPoint() = *pPam->GetPoint();
533cdf0e10cSrcweir GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0;
534cdf0e10cSrcweir SetMark();
535cdf0e10cSrcweir if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) &&
536cdf0e10cSrcweir Move( fnMoveForward, fnGoCntnt ) &&
537cdf0e10cSrcweir (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) &&
538cdf0e10cSrcweir 1 == Abs( (int)( GetPoint()->nNode.GetIndex() -
539cdf0e10cSrcweir GetMark()->nNode.GetIndex()) ) )
540cdf0e10cSrcweir {
541cdf0e10cSrcweir if( !bSrchForward ) // rueckwaerts Suche?
542cdf0e10cSrcweir Exchange(); // Point und Mark tauschen
543cdf0e10cSrcweir //bFound = sal_True;
544cdf0e10cSrcweir //break;
545cdf0e10cSrcweir return true;
546cdf0e10cSrcweir }
547cdf0e10cSrcweir }
548cdf0e10cSrcweir return bFound;
549cdf0e10cSrcweir }
550cdf0e10cSrcweir
551cdf0e10cSrcweir // Parameter fuers Suchen und Ersetzen von Text
552cdf0e10cSrcweir struct SwFindParaText : public SwFindParas
553cdf0e10cSrcweir {
554cdf0e10cSrcweir const SearchOptions& rSearchOpt;
555cdf0e10cSrcweir SwCursor& rCursor;
556cdf0e10cSrcweir utl::TextSearch aSTxt;
557cdf0e10cSrcweir sal_Bool bReplace;
558cdf0e10cSrcweir sal_Bool bSearchInNotes;
559cdf0e10cSrcweir
SwFindParaTextSwFindParaText560cdf0e10cSrcweir SwFindParaText( const SearchOptions& rOpt, sal_Bool bSearchNotes, int bRepl, SwCursor& rCrsr )
561cdf0e10cSrcweir : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes )
562cdf0e10cSrcweir {}
563cdf0e10cSrcweir virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
564cdf0e10cSrcweir virtual int IsReplaceMode() const;
565cdf0e10cSrcweir virtual ~SwFindParaText();
566cdf0e10cSrcweir };
567cdf0e10cSrcweir
~SwFindParaText()568cdf0e10cSrcweir SwFindParaText::~SwFindParaText()
569cdf0e10cSrcweir {
570cdf0e10cSrcweir }
571cdf0e10cSrcweir
Find(SwPaM * pCrsr,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)572cdf0e10cSrcweir int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,
573cdf0e10cSrcweir const SwPaM* pRegion, sal_Bool bInReadOnly )
574cdf0e10cSrcweir {
575cdf0e10cSrcweir if( bInReadOnly && bReplace )
576cdf0e10cSrcweir bInReadOnly = sal_False;
577cdf0e10cSrcweir
578cdf0e10cSrcweir sal_Bool bFnd = (sal_Bool)pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly );
579cdf0e10cSrcweir
580cdf0e10cSrcweir /* #i80135# if we found something in a note, Mark and Point is the same
581cdf0e10cSrcweir if( bFnd && *pCrsr->GetMark() == *pCrsr->GetPoint() )
582cdf0e10cSrcweir return FIND_NOT_FOUND;
583cdf0e10cSrcweir */
584cdf0e10cSrcweir
585cdf0e10cSrcweir if( bFnd && bReplace ) // String ersetzen ??
586cdf0e10cSrcweir {
587cdf0e10cSrcweir // Replace-Methode vom SwDoc benutzen
588cdf0e10cSrcweir const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType);
589cdf0e10cSrcweir SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
590cdf0e10cSrcweir xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
591cdf0e10cSrcweir // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
592cdf0e10cSrcweir // mit aufnehmen !!
593cdf0e10cSrcweir Ring *pPrev(0);
594cdf0e10cSrcweir if( bRegExp )
595cdf0e10cSrcweir {
596cdf0e10cSrcweir pPrev = pRegion->GetPrev();
597cdf0e10cSrcweir ((Ring*)pRegion)->MoveRingTo( &rCursor );
598cdf0e10cSrcweir }
599cdf0e10cSrcweir
600cdf0e10cSrcweir ::std::auto_ptr<String> pRepl( (bRegExp)
601cdf0e10cSrcweir ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 );
602cdf0e10cSrcweir rCursor.GetDoc()->ReplaceRange( *pCrsr,
603cdf0e10cSrcweir (pRepl.get()) ? *pRepl : String(rSearchOpt.replaceString),
604cdf0e10cSrcweir bRegExp );
605cdf0e10cSrcweir rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
606cdf0e10cSrcweir
607cdf0e10cSrcweir if( bRegExp )
608cdf0e10cSrcweir {
609cdf0e10cSrcweir // und die Region wieder herausnehmen:
610cdf0e10cSrcweir Ring *p, *pNext = (Ring*)pRegion;
611cdf0e10cSrcweir do {
612cdf0e10cSrcweir p = pNext;
613cdf0e10cSrcweir pNext = p->GetNext();
614cdf0e10cSrcweir p->MoveTo( (Ring*)pRegion );
615cdf0e10cSrcweir } while( p != pPrev );
616cdf0e10cSrcweir }
617cdf0e10cSrcweir pCrsr->Start()->nContent = nSttCnt;
618cdf0e10cSrcweir return FIND_NO_RING;
619cdf0e10cSrcweir }
620cdf0e10cSrcweir return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
621cdf0e10cSrcweir }
622cdf0e10cSrcweir
623cdf0e10cSrcweir
IsReplaceMode() const624cdf0e10cSrcweir int SwFindParaText::IsReplaceMode() const
625cdf0e10cSrcweir {
626cdf0e10cSrcweir return bReplace;
627cdf0e10cSrcweir }
628cdf0e10cSrcweir
629cdf0e10cSrcweir
Find(const SearchOptions & rSearchOpt,sal_Bool bSearchInNotes,SwDocPositions nStart,SwDocPositions nEnde,sal_Bool & bCancel,FindRanges eFndRngs,int bReplace)630cdf0e10cSrcweir sal_uLong SwCursor::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
631cdf0e10cSrcweir SwDocPositions nStart, SwDocPositions nEnde,
632cdf0e10cSrcweir sal_Bool& bCancel,
633cdf0e10cSrcweir FindRanges eFndRngs, int bReplace )
634cdf0e10cSrcweir {
635cdf0e10cSrcweir // OLE-Benachrichtigung abschalten !!
636cdf0e10cSrcweir SwDoc* pDoc = GetDoc();
637cdf0e10cSrcweir Link aLnk( pDoc->GetOle2Link() );
638cdf0e10cSrcweir pDoc->SetOle2Link( Link() );
639cdf0e10cSrcweir
640cdf0e10cSrcweir bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
641cdf0e10cSrcweir if (bStartUndo)
642cdf0e10cSrcweir {
643cdf0e10cSrcweir pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
644cdf0e10cSrcweir }
645cdf0e10cSrcweir
646cdf0e10cSrcweir sal_Bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
647cdf0e10cSrcweir if( bSearchSel )
648cdf0e10cSrcweir eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL);
649cdf0e10cSrcweir SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this );
650cdf0e10cSrcweir sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnde, eFndRngs, bCancel );
651cdf0e10cSrcweir pDoc->SetOle2Link( aLnk );
652cdf0e10cSrcweir if( nRet && bReplace )
653cdf0e10cSrcweir pDoc->SetModified();
654cdf0e10cSrcweir
655cdf0e10cSrcweir if (bStartUndo)
656cdf0e10cSrcweir {
657cdf0e10cSrcweir SwRewriter rewriter(MakeUndoReplaceRewriter(
658cdf0e10cSrcweir nRet, rSearchOpt.searchString, rSearchOpt.replaceString));
659cdf0e10cSrcweir pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, & rewriter );
660cdf0e10cSrcweir }
661cdf0e10cSrcweir return nRet;
662cdf0e10cSrcweir }
663cdf0e10cSrcweir
ReplaceBackReferences(const SearchOptions & rSearchOpt,SwPaM * pPam)664cdf0e10cSrcweir String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam )
665cdf0e10cSrcweir {
666cdf0e10cSrcweir String *pRet = 0;
667cdf0e10cSrcweir if( pPam && pPam->HasMark() &&
668cdf0e10cSrcweir SearchAlgorithms_REGEXP == rSearchOpt.algorithmType )
669cdf0e10cSrcweir {
670cdf0e10cSrcweir const SwCntntNode* pTxtNode = pPam->GetCntntNode( sal_True );
671cdf0e10cSrcweir if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( sal_False ) )
672cdf0e10cSrcweir {
673cdf0e10cSrcweir utl::TextSearch aSTxt( rSearchOpt );
674e926d11bSHerbert Dürr const String& rStr = static_cast<const SwTxtNode*>(pTxtNode)->GetTxt();
675e926d11bSHerbert Dürr xub_StrLen nStart = pPam->Start()->nContent.GetIndex();
676e926d11bSHerbert Dürr xub_StrLen nEnd = pPam->End()->nContent.GetIndex();
677cdf0e10cSrcweir SearchResult aResult;
678e926d11bSHerbert Dürr if( aSTxt.SearchFrwrd( rStr, &nStart, &nEnd, &aResult ) )
679cdf0e10cSrcweir {
680e926d11bSHerbert Dürr String aReplaceStr( rSearchOpt.replaceString );
681e926d11bSHerbert Dürr aSTxt.ReplaceBackReferences( aReplaceStr, rStr, aResult );
682cdf0e10cSrcweir pRet = new String( aReplaceStr );
683cdf0e10cSrcweir }
684cdf0e10cSrcweir }
685cdf0e10cSrcweir }
686cdf0e10cSrcweir return pRet;
687cdf0e10cSrcweir }
688