Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <com/sun/star/util/SearchOptions.hpp>
31 : : #include <com/sun/star/util/SearchFlags.hpp>
32 : :
33 : : #include <comphelper/string.hxx>
34 : :
35 : : #include <vcl/svapp.hxx>
36 : : #include <vcl/window.hxx>
37 : :
38 : : #include <txatritr.hxx>
39 : : #include <fldbas.hxx>
40 : : #include <fmtfld.hxx>
41 : : #include <txtatr.hxx>
42 : : #include <txtfld.hxx>
43 : : #include <swcrsr.hxx>
44 : : #include <doc.hxx>
45 : : #include <IDocumentUndoRedo.hxx>
46 : : #include <pamtyp.hxx>
47 : : #include <ndtxt.hxx>
48 : : #include <swundo.hxx>
49 : : #include <UndoInsert.hxx>
50 : : #include <breakit.hxx>
51 : :
52 : : #include <docsh.hxx>
53 : : #include <PostItMgr.hxx>
54 : : #include <viewsh.hxx>
55 : :
56 : : using namespace ::com::sun::star;
57 : : using namespace util;
58 : :
59 : : String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam );
60 : :
61 : 584 : String& lcl_CleanStr( const SwTxtNode& rNd, xub_StrLen nStart, xub_StrLen& rEnd,
62 : : std::vector<sal_uLong> &rArr, String& rRet,
63 : : bool bRemoveSoftHyphen )
64 : : {
65 [ + - ]: 584 : rRet = rNd.GetTxt();
66 : 584 : rArr.clear();
67 : :
68 : 584 : const SwpHints *pHts = rNd.GetpSwpHints();
69 : :
70 : 584 : sal_uInt16 n = 0;
71 : 584 : xub_StrLen nSoftHyphen = nStart;
72 : 584 : xub_StrLen nHintStart = STRING_LEN;
73 : 584 : bool bNewHint = true;
74 : 584 : bool bNewSoftHyphen = true;
75 : 584 : const xub_StrLen nEnd = rEnd;
76 [ + - ]: 584 : std::vector<sal_uInt16> aReplaced;
77 : :
78 : 16 : do
79 : : {
80 [ + - ]: 600 : if ( bNewHint )
81 : 24 : nHintStart = pHts && n < pHts->Count() ?
82 [ + - ]: 16 : *(*pHts)[n]->GetStart() :
83 [ + + + + ]: 640 : STRING_LEN;
84 : :
85 [ + + ]: 600 : if ( bNewSoftHyphen )
86 : : nSoftHyphen = bRemoveSoftHyphen ?
87 : 584 : rNd.GetTxt().Search( CHAR_SOFTHYPHEN, nSoftHyphen ) :
88 [ + - + - ]: 1168 : STRING_LEN;
89 : :
90 : 600 : bNewHint = false;
91 : 600 : bNewSoftHyphen = false;
92 : :
93 : 600 : xub_StrLen nStt = 0;
94 : :
95 : : // Check if next stop is a hint.
96 [ + + ][ + - ]: 600 : if ( STRING_LEN != nHintStart && nHintStart < nSoftHyphen && nHintStart < nEnd )
[ + - ]
97 : : {
98 : 16 : nStt = nHintStart;
99 : 16 : bNewHint = true;
100 : : }
101 : : // Check if next stop is a soft hyphen.
102 [ - + ][ # # ]: 584 : else if ( STRING_LEN != nSoftHyphen && nSoftHyphen < nHintStart && nSoftHyphen < nEnd )
[ # # ]
103 : : {
104 : 0 : nStt = nSoftHyphen;
105 : 0 : bNewSoftHyphen = true;
106 : : }
107 : : // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
108 [ - + ][ # # ]: 584 : else if ( STRING_LEN != nSoftHyphen && nSoftHyphen == nHintStart )
109 : : {
110 : 0 : nStt = nSoftHyphen;
111 : 0 : bNewHint = true;
112 : 0 : bNewSoftHyphen = true;
113 : : }
114 : : else
115 : : break;
116 : :
117 : 16 : const xub_StrLen nAkt = nStt - rArr.size();
118 : :
119 [ + - ]: 16 : if ( bNewHint )
120 : : {
121 [ + - ]: 16 : const SwTxtAttr* pHt = (*pHts)[n];
122 [ + - ][ + - ]: 16 : if ( pHt->HasDummyChar() && (nStt >= nStart) )
[ + - ]
123 : : {
124 [ + - ][ + - ]: 16 : switch( pHt->Which() )
125 : : {
126 : : case RES_TXTATR_FLYCNT:
127 : : case RES_TXTATR_FTN:
128 : : case RES_TXTATR_FIELD:
129 : : case RES_TXTATR_REFMARK:
130 : : case RES_TXTATR_TOXMARK:
131 : : case RES_TXTATR_META:
132 : : case RES_TXTATR_METAFIELD:
133 : : {
134 : : // (1998) they are desired as separators and
135 : : // belong not any longer to a word.
136 : : // they should also be ignored at a
137 : : // beginning/end of a sentence if blank. Those are
138 : : // simply removed if first. If at the end, we keep the
139 : : // replacement and remove afterwards all at a string's
140 : : // end (might be normal 0x7f).
141 [ + - ]: 16 : sal_Bool bEmpty = RES_TXTATR_FIELD != pHt->Which() ||
142 : : !(static_cast<SwTxtFld const*>(pHt)
143 [ - + ][ # # ]: 16 : ->GetFld().GetFld()->ExpandField(true).Len());
[ # # ][ - + ]
[ # # ][ # # ]
144 [ + - ][ + - ]: 16 : if ( bEmpty && nStart == nAkt )
145 : : {
146 [ + - ]: 16 : rArr.push_back( nAkt );
147 : 16 : --rEnd;
148 [ + - ]: 16 : rRet.Erase( nAkt, 1 );
149 : : }
150 : : else
151 : : {
152 [ # # ]: 0 : if ( bEmpty )
153 [ # # ]: 0 : aReplaced.push_back( nAkt );
154 [ # # ]: 0 : rRet.SetChar( nAkt, '\x7f' );
155 : : }
156 : : }
157 : 16 : break;
158 : : default:
159 : : OSL_FAIL( "unknown case in lcl_CleanStr" );
160 : 16 : break;
161 : : }
162 : : }
163 : 16 : ++n;
164 : : }
165 : :
166 [ - + ]: 16 : if ( bNewSoftHyphen )
167 : : {
168 [ # # ]: 0 : rArr.push_back( nAkt );
169 : 0 : --rEnd;
170 [ # # ]: 0 : rRet.Erase( nAkt, 1 );
171 : 0 : ++nSoftHyphen;
172 : : }
173 : : }
174 : : while ( true );
175 : :
176 [ - + ]: 584 : for( sal_uInt16 i = aReplaced.size(); i; )
177 : : {
178 [ # # ]: 0 : const xub_StrLen nTmp = aReplaced[ --i ];
179 [ # # ]: 0 : if( nTmp == rRet.Len() - 1 )
180 : : {
181 [ # # ]: 0 : rRet.Erase( nTmp );
182 [ # # ]: 0 : rArr.push_back( nTmp );
183 : 0 : --rEnd;
184 : : }
185 : : }
186 : :
187 : 584 : return rRet;
188 : : }
189 : :
190 : : // skip all non SwPostIts inside the array
191 : 0 : xub_StrLen GetPostIt(xub_StrLen aCount,const SwpHints *pHts)
192 : : {
193 : 0 : xub_StrLen aIndex = 0;
194 [ # # ]: 0 : while (aCount)
195 : : {
196 [ # # ]: 0 : for (xub_StrLen i = 0; i <pHts->Count();i++)
197 : : {
198 : 0 : aIndex++;
199 : 0 : const SwTxtAttr* pTxtAttr = (*pHts)[i];
200 [ # # ]: 0 : if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
[ # # # # ]
201 : 0 : (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
202 : : {
203 : 0 : aCount--;
204 [ # # ]: 0 : if (!aCount)
205 : 0 : break;
206 : : }
207 : : }
208 : : }
209 : : // throw away all following non postits
210 [ # # ]: 0 : for (xub_StrLen i = aIndex; i <pHts->Count();i++)
211 : : {
212 : 0 : const SwTxtAttr* pTxtAttr = (*pHts)[i];
213 [ # # ]: 0 : if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
[ # # # # ]
214 : 0 : (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
215 : 0 : break;
216 : : else
217 : 0 : aIndex++;
218 : : }
219 : 0 : return aIndex;
220 : : }
221 : :
222 : 180 : sal_uInt8 SwPaM::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes , utl::TextSearch& rSTxt,
223 : : SwMoveFn fnMove, const SwPaM * pRegion,
224 : : sal_Bool bInReadOnly )
225 : : {
226 [ - + ]: 180 : if( rSearchOpt.searchString.isEmpty() )
227 : 0 : return sal_False;
228 : :
229 [ + - ]: 180 : SwPaM* pPam = MakeRegion( fnMove, pRegion );
230 : 180 : sal_Bool bSrchForward = fnMove == fnMoveForward;
231 : 180 : SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
232 : 180 : SwIndex& rCntntIdx = pPam->GetPoint()->nContent;
233 : :
234 : : // If a beginning/end, from out of node; stop if empty node
235 [ + + + + ]: 384 : if( bSrchForward
[ # # ][ # # ]
[ + + ][ + - ]
236 [ + - ]: 180 : ? ( rCntntIdx.GetIndex() == pPam->GetCntntNode()->Len() &&
237 : 24 : rCntntIdx.GetIndex() )
238 [ # # ]: 0 : : !rCntntIdx.GetIndex() && pPam->GetCntntNode()->Len() )
239 : : {
240 [ + - ][ - + ]: 10 : if( !(*fnMove->fnNds)( &rNdIdx, sal_False ))
241 : : {
242 [ # # ][ # # ]: 0 : delete pPam;
243 : 0 : return sal_False;
244 : : }
245 : 10 : SwCntntNode *pNd = rNdIdx.GetNode().GetCntntNode();
246 [ # # ][ - + ]: 10 : xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
247 [ + - ][ + - ]: 10 : rCntntIdx.Assign( pNd, nTmpPos );
248 : : }
249 : :
250 : : // If bFound is true then the string was found and is between nStart and nEnd
251 : 180 : sal_Bool bFound = sal_False;
252 : : // start position in text or initial position
253 : 180 : sal_Bool bFirst = sal_True;
254 : : SwCntntNode * pNode;
255 : :
256 : : xub_StrLen nStart, nEnd, nTxtLen;
257 : :
258 : 180 : sal_Bool bRegSearch = SearchAlgorithms_REGEXP == rSearchOpt.algorithmType;
259 : 0 : sal_Bool bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() &&
260 : 0 : ( !rSearchOpt.searchString.compareToAscii( "^$" ) ||
261 [ - + # # : 180 : !rSearchOpt.searchString.compareToAscii( "$^" ) );
# # ][ # # ]
262 : 0 : sal_Bool bChkParaEnd = bRegSearch && 1 == rSearchOpt.searchString.getLength() &&
263 [ - + # # ]: 180 : !rSearchOpt.searchString.compareToAscii( "$" );
[ # # ]
264 : :
265 : : // LanguageType eLastLang = 0;
266 [ + - ][ + + ]: 604 : while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
267 : : {
268 [ + + ]: 592 : if( pNode->IsTxtNode() )
269 : : {
270 : 584 : nTxtLen = ((SwTxtNode*)pNode)->GetTxt().Len();
271 [ + + ]: 584 : if( rNdIdx == pPam->GetMark()->nNode )
272 : 2 : nEnd = pPam->GetMark()->nContent.GetIndex();
273 : : else
274 [ + - ]: 582 : nEnd = bSrchForward ? nTxtLen : 0;
275 : 584 : nStart = rCntntIdx.GetIndex();
276 : :
277 : : /* #i80135# */
278 : : // if there are SwPostItFields inside our current node text, we
279 : : // split the text into seperate pieces and search for text inside
280 : : // the pieces as well as inside the fields
281 : 584 : const SwpHints *pHts = ((SwTxtNode*)pNode)->GetpSwpHints();
282 : :
283 : : // count PostItFields by looping over all fields
284 : 584 : xub_StrLen aNumberPostits = 0;
285 : 584 : xub_StrLen aIgnore = 0;
286 [ - + ][ + + ]: 584 : if (pHts && bSearchInNotes)
287 : : {
288 [ # # ]: 0 : if (!bSrchForward)
289 : : {
290 : 0 : xub_StrLen swap = nEnd;
291 : 0 : nEnd = nStart;
292 : 0 : nStart = swap;
293 : : }
294 : :
295 [ # # ]: 0 : for (xub_StrLen i = 0; i <pHts->Count();i++)
296 : : {
297 [ # # ]: 0 : xub_StrLen aPos = *(*pHts)[i]->GetStart();
298 [ # # ]: 0 : const SwTxtAttr* pTxtAttr = (*pHts)[i];
299 [ # # ]: 0 : if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
[ # # # # ]
[ # # ]
300 : 0 : (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
301 : : {
302 [ # # ][ # # ]: 0 : if ( (aPos >= nStart) && (aPos <= nEnd) )
303 : 0 : aNumberPostits++;
304 : : else
305 : : {
306 [ # # ]: 0 : if (bSrchForward)
307 : 0 : aIgnore++;
308 : : }
309 : : }
310 : : }
311 : :
312 [ # # ]: 0 : if (!bSrchForward)
313 : : {
314 : 0 : xub_StrLen swap = nEnd;
315 : 0 : nEnd = nStart;
316 : 0 : nStart = swap;
317 : : }
318 : :
319 : : }
320 : :
321 : 584 : SwDocShell *const pDocShell = pNode->GetDoc()->GetDocShell();
322 [ + - ]: 584 : ViewShell *const pWrtShell = (pDocShell) ? (ViewShell*)(pDocShell->GetWrtShell()) : 0;
323 [ + - ][ + - ]: 584 : SwPostItMgr *const pPostItMgr = (pWrtShell) ? pWrtShell->GetPostItMgr() : 0;
324 : :
325 : 584 : xub_StrLen aStart = 0;
326 : : // do we need to finish a note?
327 [ + - ][ + - ]: 584 : if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
[ - + ][ - + ]
328 : : {
329 [ # # ]: 0 : if (bSearchInNotes)
330 : : {
331 [ # # ]: 0 : if (bSrchForward)
332 : 0 : aStart++;
333 : : else
334 : : {
335 [ # # ]: 0 : if (aNumberPostits)
336 : 0 : --aNumberPostits;
337 : : }
338 : : //search inside and finsih and put focus back into the doc
339 [ # # ][ # # ]: 0 : if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward))
340 : : {
341 : 0 : bFound = true ;
342 : 0 : break;
343 : : }
344 : : }
345 : : else
346 : : {
347 [ # # ]: 0 : pPostItMgr->SetActiveSidebarWin(0);
348 : : }
349 : : }
350 : :
351 [ - + ]: 584 : if (aNumberPostits)
352 : : {
353 : : // now we have to split
354 : 0 : xub_StrLen nStartInside = 0;
355 : 0 : xub_StrLen nEndInside = 0;
356 [ # # ]: 0 : sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits;
357 : :
358 [ # # ][ # # ]: 0 : while ( (aLoop>=0) && (aLoop<=aNumberPostits))
[ # # ]
359 : : {
360 [ # # ]: 0 : if (bSrchForward)
361 : : {
362 [ # # ][ # # ]: 0 : nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
[ # # ]
363 [ # # ][ # # ]: 0 : nEndInside = aLoop==aNumberPostits ? nEnd : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
[ # # ]
364 : 0 : nTxtLen = nEndInside - nStartInside;
365 : : }
366 : : else
367 : : {
368 [ # # ][ # # ]: 0 : nStartInside = aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
[ # # ]
369 [ # # ][ # # ]: 0 : nEndInside = aLoop==0 ? nEnd : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
[ # # ]
370 : 0 : nTxtLen = nStartInside - nEndInside;
371 : : }
372 : : // search inside the text between a note
373 : : bFound = DoSearch( rSearchOpt, rSTxt, fnMove, bSrchForward,
374 : : bRegSearch, bChkEmptyPara, bChkParaEnd,
375 : : nStartInside, nEndInside, nTxtLen, pNode,
376 [ # # ][ # # ]: 0 : pPam );
377 [ # # ]: 0 : if ( bFound )
378 : 0 : break;
379 : : else
380 : : {
381 : : // we should now be right in front of a note, search inside
382 [ # # ][ # # ]: 0 : if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) ))
[ # # ][ # # ]
[ # # ][ # # ]
383 : : {
384 [ # # ][ # # ]: 0 : const SwTxtAttr* pTxtAttr = bSrchForward ? (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)];
[ # # ][ # # ]
[ # # ]
385 [ # # ][ # # ]: 0 : if ( pPostItMgr && pPostItMgr->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFld(),rSearchOpt,bSrchForward) )
[ # # ][ # # ]
386 : : {
387 : 0 : bFound = true ;
388 : 0 : break;
389 : : }
390 : : }
391 : : }
392 [ # # ]: 0 : aLoop = bSrchForward ? aLoop+1 : aLoop-1;
393 : : }
394 : : }
395 : : else
396 : : {
397 : : // if there is no SwPostItField inside or searching inside notes
398 : : // is disabled, we search the whole length just like before
399 : : bFound = DoSearch( rSearchOpt, rSTxt, fnMove, bSrchForward,
400 : : bRegSearch, bChkEmptyPara, bChkParaEnd,
401 [ + - ][ + - ]: 584 : nStart, nEnd, nTxtLen, pNode, pPam );
402 : : }
403 [ + + ]: 584 : if (bFound)
404 : 168 : break;
405 : : }
406 : : }
407 [ + - ][ + - ]: 180 : delete pPam;
408 : 180 : return bFound;
409 : : }
410 : :
411 : 584 : bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt,
412 : : SwMoveFn fnMove, sal_Bool bSrchForward, sal_Bool bRegSearch,
413 : : sal_Bool bChkEmptyPara, sal_Bool bChkParaEnd,
414 : : xub_StrLen &nStart, xub_StrLen &nEnd, xub_StrLen nTxtLen,
415 : : SwNode* pNode, SwPaM* pPam)
416 : : {
417 : 584 : bool bFound = false;
418 : 584 : SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
419 : 584 : const SwNode* pSttNd = &rNdIdx.GetNode();
420 [ + - ]: 584 : String sCleanStr;
421 [ + - ]: 584 : std::vector<sal_uLong> aFltArr;
422 : 584 : LanguageType eLastLang = 0;
423 : : // if the search string contains a soft hypen,
424 : : // we don't strip them from the text:
425 : 584 : bool bRemoveSoftHyphens = true;
426 [ - + ]: 584 : if ( bRegSearch )
427 : : {
428 [ # # ]: 0 : const rtl::OUString a00AD(RTL_CONSTASCII_USTRINGPARAM("\\x00AD"));
429 [ # # ]: 0 : if ( -1 != rSearchOpt.searchString.indexOf( a00AD ) )
430 : 0 : bRemoveSoftHyphens = false;
431 : : }
432 : : else
433 : : {
434 [ - + # # ]: 584 : if ( 1 == rSearchOpt.searchString.getLength() &&
[ - + ]
435 : 0 : CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
436 : 0 : bRemoveSoftHyphens = false;
437 : : }
438 : :
439 [ + - ]: 584 : if( bSrchForward )
440 : : lcl_CleanStr( *(SwTxtNode*)pNode, nStart, nEnd,
441 [ + - ][ + - ]: 584 : aFltArr, sCleanStr, bRemoveSoftHyphens );
442 : : else
443 : : lcl_CleanStr( *(SwTxtNode*)pNode, nEnd, nStart,
444 [ # # ][ # # ]: 0 : aFltArr, sCleanStr, bRemoveSoftHyphens );
445 : :
446 : 584 : SwScriptIterator* pScriptIter = 0;
447 : 584 : sal_uInt16 nSearchScript = 0;
448 : 584 : sal_uInt16 nCurrScript = 0;
449 : :
450 [ - + # # ]: 1168 : if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType &&
[ - + ]
451 [ # # ][ - + ]: 584 : pBreakIt->GetBreakIter().is() )
[ # # ]
452 : : {
453 [ # # ][ # # ]: 0 : pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward );
454 [ # # ]: 0 : nSearchScript = pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
455 : : }
456 : :
457 : 584 : xub_StrLen nStringEnd = nEnd;
458 [ + - ][ + + ]: 688 : while ( (bSrchForward && nStart < nStringEnd) ||
[ - + ][ # # ]
[ + + ]
459 : : (! bSrchForward && nStart > nStringEnd) )
460 : : {
461 : : // SearchAlgorithms_APPROXIMATE works on a per word base so we have to
462 : : // provide the text searcher with the correct locale, because it uses
463 : : // the break-iterator
464 [ - + ]: 272 : if ( pScriptIter )
465 : : {
466 : 0 : nEnd = pScriptIter->GetScriptChgPos();
467 : 0 : nCurrScript = pScriptIter->GetCurrScript();
468 [ # # ]: 0 : if ( nSearchScript == nCurrScript )
469 : : {
470 : : const LanguageType eCurrLang =
471 : : ((SwTxtNode*)pNode)->GetLang( bSrchForward ?
472 : : nStart :
473 [ # # ][ # # ]: 0 : nEnd );
[ # # ]
474 : :
475 [ # # ]: 0 : if ( eCurrLang != eLastLang )
476 : : {
477 : : const lang::Locale aLocale(
478 [ # # ]: 0 : pBreakIt->GetLocale( eCurrLang ) );
479 [ # # ]: 0 : rSTxt.SetLocale( rSearchOpt, aLocale );
480 : 0 : eLastLang = eCurrLang;
481 : : }
482 : : }
483 [ # # ]: 0 : pScriptIter->Next();
484 : : }
485 : :
486 [ + - ][ + + ]: 544 : if( nSearchScript == nCurrScript &&
[ + + ]
487 [ + - ][ + - ]: 272 : (rSTxt.*fnMove->fnSearch)( sCleanStr, &nStart, &nEnd, 0 ))
488 : : {
489 : : // set section correctly
490 [ + - ]: 168 : *GetPoint() = *pPam->GetPoint();
491 [ + - ]: 168 : SetMark();
492 : :
493 : : // adjust start and end
494 [ - + ]: 168 : if( !aFltArr.empty() )
495 : : {
496 : : xub_StrLen n, nNew;
497 : : // if backward search, switch positions temporarily
498 [ # # ]: 0 : if( !bSrchForward ) { n = nStart; nStart = nEnd; nEnd = n; }
499 : :
500 [ # # ][ # # ]: 0 : for( n = 0, nNew = nStart;
[ # # ]
501 [ # # ]: 0 : n < aFltArr.size() && aFltArr[ n ] <= nStart;
502 : : ++n, ++nNew )
503 : : ;
504 : 0 : nStart = nNew;
505 [ # # ][ # # ]: 0 : for( n = 0, nNew = nEnd;
[ # # ]
506 [ # # ]: 0 : n < aFltArr.size() && aFltArr[ n ] < nEnd;
507 : : ++n, ++nNew )
508 : : ;
509 : :
510 : 0 : nEnd = nNew;
511 : : // if backward search, switch positions temporarily
512 [ # # ]: 0 : if( !bSrchForward ) { n = nStart; nStart = nEnd; nEnd = n; }
513 : : }
514 [ + - ]: 168 : GetMark()->nContent = nStart;
515 [ + - ]: 168 : GetPoint()->nContent = nEnd;
516 : :
517 : : // if backward search, switch point and mark
518 [ - + ]: 168 : if( !bSrchForward )
519 : 0 : Exchange();
520 : 168 : bFound = sal_True;
521 : 168 : break;
522 : : }
523 : 104 : nStart = nEnd;
524 : : }
525 : :
526 : 584 : delete pScriptIter;
527 : :
528 [ + + ]: 584 : if ( bFound )
529 : 168 : return true;
530 [ - + ][ # # ]: 416 : else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd )
[ # # ][ - + ]
531 : : {
532 [ # # ]: 0 : *GetPoint() = *pPam->GetPoint();
533 [ # # ][ # # ]: 0 : GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0;
534 [ # # ]: 0 : SetMark();
535 [ # # ][ # # ]: 0 : if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) &&
[ # # ][ # #
# # # # ]
[ # # ]
536 [ # # ]: 0 : Move( fnMoveForward, fnGoCntnt ) &&
537 : 0 : (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) &&
538 : 0 : 1 == Abs( (int)( GetPoint()->nNode.GetIndex() -
539 : 0 : GetMark()->nNode.GetIndex()) ) )
540 : : {
541 : : // if backward search, switch point and mark
542 [ # # ]: 0 : if( !bSrchForward )
543 : 0 : Exchange();
544 : 0 : return true;
545 : : }
546 : : }
547 [ + - ]: 584 : return bFound;
548 : : }
549 : :
550 : : /// parameters for search and replace in text
551 : : struct SwFindParaText : public SwFindParas
552 : : {
553 : : const SearchOptions& rSearchOpt;
554 : : SwCursor& rCursor;
555 : : utl::TextSearch aSTxt;
556 : : sal_Bool bReplace;
557 : : sal_Bool bSearchInNotes;
558 : :
559 : 18 : SwFindParaText( const SearchOptions& rOpt, sal_Bool bSearchNotes, int bRepl, SwCursor& rCrsr )
560 [ + - ]: 18 : : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes )
561 : 18 : {}
562 : : virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
563 : : virtual int IsReplaceMode() const;
564 : : virtual ~SwFindParaText();
565 : : };
566 : :
567 [ + - ]: 18 : SwFindParaText::~SwFindParaText()
568 : : {
569 [ - + ]: 18 : }
570 : :
571 : 180 : int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,
572 : : const SwPaM* pRegion, sal_Bool bInReadOnly )
573 : : {
574 [ + - ][ + + ]: 180 : if( bInReadOnly && bReplace )
575 : 92 : bInReadOnly = sal_False;
576 : :
577 : 180 : sal_Bool bFnd = (sal_Bool)pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly );
578 : :
579 : :
580 [ + + ][ + + ]: 180 : if( bFnd && bReplace ) // replace string
581 : : {
582 : : // use replace method in SwDoc
583 : 88 : const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType);
584 [ + - ]: 88 : SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
585 : 88 : xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
586 : : // add to shell-cursor-ring so that the regions will be moved enventually
587 : 88 : Ring *pPrev(0);
588 [ - + ]: 88 : if( bRegExp )
589 : : {
590 : 0 : pPrev = pRegion->GetPrev();
591 [ # # ]: 0 : ((Ring*)pRegion)->MoveRingTo( &rCursor );
592 : : }
593 : :
594 : : ::std::auto_ptr<String> pRepl( (bRegExp)
595 [ - + ][ # # ]: 88 : ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 );
596 : 88 : rCursor.GetDoc()->ReplaceRange( *pCrsr,
597 : 88 : (pRepl.get()) ? *pRepl : String(rSearchOpt.replaceString),
598 [ + - ][ + - ]: 88 : bRegExp );
[ + - ]
[ - + # # ]
599 [ + - ]: 88 : rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
600 : :
601 [ - + ]: 88 : if( bRegExp )
602 : : {
603 : : // and remove region again
604 : 0 : Ring *p, *pNext = (Ring*)pRegion;
605 [ # # ]: 0 : do {
606 : 0 : p = pNext;
607 : 0 : pNext = p->GetNext();
608 [ # # ]: 0 : p->MoveTo( (Ring*)pRegion );
609 : : } while( p != pPrev );
610 : : }
611 [ + - ][ + - ]: 88 : pCrsr->Start()->nContent = nSttCnt;
612 [ + - ]: 88 : return FIND_NO_RING;
613 : : }
614 [ + + ]: 180 : return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
615 : : }
616 : :
617 : :
618 : 0 : int SwFindParaText::IsReplaceMode() const
619 : : {
620 : 0 : return bReplace;
621 : : }
622 : :
623 : :
624 : 18 : sal_uLong SwCursor::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
625 : : SwDocPositions nStart, SwDocPositions nEnd,
626 : : sal_Bool& bCancel, FindRanges eFndRngs, int bReplace )
627 : : {
628 : : // switch off OLE-notifications
629 : 18 : SwDoc* pDoc = GetDoc();
630 : 18 : Link aLnk( pDoc->GetOle2Link() );
631 [ + - ]: 18 : pDoc->SetOle2Link( Link() );
632 : :
633 [ + - ][ + - ]: 18 : bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
[ + + ][ + - ]
634 [ + + ]: 18 : if (bStartUndo)
635 : : {
636 [ + - ][ + - ]: 4 : pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
637 : : }
638 : :
639 : 18 : sal_Bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
640 [ - + ]: 18 : if( bSearchSel )
641 : 0 : eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL);
642 [ + - ]: 18 : SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this );
643 [ + - ]: 18 : sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnd, eFndRngs, bCancel );
644 : 18 : pDoc->SetOle2Link( aLnk );
645 [ + + ][ + + ]: 18 : if( nRet && bReplace )
646 [ + - ]: 4 : pDoc->SetModified();
647 : :
648 [ + + ]: 18 : if (bStartUndo)
649 : : {
650 : : SwRewriter rewriter(MakeUndoReplaceRewriter(
651 [ + - ]: 4 : nRet, rSearchOpt.searchString, rSearchOpt.replaceString));
652 [ + - ][ + - ]: 4 : pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, & rewriter );
[ + - ]
653 : : }
654 [ + - ]: 18 : return nRet;
655 : : }
656 : :
657 : 0 : String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam )
658 : : {
659 : 0 : String *pRet = 0;
660 [ # # ][ # # ]: 0 : if( pPam && pPam->HasMark() &&
[ # # ][ # # ]
661 : : SearchAlgorithms_REGEXP == rSearchOpt.algorithmType )
662 : : {
663 : 0 : const SwCntntNode* pTxtNode = pPam->GetCntntNode( sal_True );
664 [ # # ][ # # ]: 0 : if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( sal_False ) )
[ # # ][ # # ]
665 : : {
666 [ # # ]: 0 : utl::TextSearch aSTxt( rSearchOpt );
667 [ # # ]: 0 : String aStr( pPam->GetTxt() );
668 [ # # ]: 0 : String aSearchStr( rSearchOpt.searchString );
669 [ # # ]: 0 : String aReplaceStr( rSearchOpt.replaceString );
670 [ # # ][ # # ]: 0 : aStr = comphelper::string::remove(aStr, CH_TXTATR_BREAKWORD);
671 [ # # ][ # # ]: 0 : aStr = comphelper::string::remove(aStr, CH_TXTATR_INWORD);
672 : 0 : xub_StrLen nStart = 0;
673 : 0 : rtl::OUString sX( 'x' );
674 [ # # ][ # # ]: 0 : if( pPam->Start()->nContent > 0 )
675 : : {
676 [ # # ][ # # ]: 0 : aStr.Insert( sX, 0 );
[ # # ]
677 : 0 : ++nStart;
678 : : }
679 : 0 : xub_StrLen nEnd = aStr.Len();
680 : 0 : bool bDeleteLastX = false;
681 [ # # ][ # # ]: 0 : if( pPam->End()->nContent < (static_cast<const SwTxtNode*>(pTxtNode))->GetTxt().Len() )
682 : : {
683 [ # # ][ # # ]: 0 : aStr.Insert( sX );
[ # # ]
684 : 0 : bDeleteLastX = true;
685 : : }
686 [ # # ]: 0 : SearchResult aResult;
687 [ # # ][ # # ]: 0 : if( aSTxt.SearchFrwrd( aStr, &nStart, &nEnd, &aResult ) )
688 : : {
689 [ # # ]: 0 : if( bDeleteLastX )
690 [ # # ]: 0 : aStr.Erase( aStr.Len() - 1 );
691 [ # # ]: 0 : aSTxt.ReplaceBackReferences( aReplaceStr, aStr, aResult );
692 [ # # ][ # # ]: 0 : pRet = new String( aReplaceStr );
693 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ]
694 : : }
695 : : }
696 : 0 : return pRet;
697 : : }
698 : :
699 : :
700 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|