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 : : #include <com/sun/star/i18n/TransliterationModules.hpp>
30 : :
31 : : #include <unotools/textsearch.hxx>
32 : : #include <svl/srchitem.hxx>
33 : : #include <editeng/editobj.hxx>
34 : :
35 : : #include "table.hxx"
36 : : #include "cell.hxx"
37 : : #include "document.hxx"
38 : : #include "stlpool.hxx"
39 : : #include "markdata.hxx"
40 : : #include "editutil.hxx"
41 : : #include "detfunc.hxx"
42 : : #include "postit.hxx"
43 : :
44 : : //--------------------------------------------------------------------------
45 : :
46 : :
47 : : using ::com::sun::star::util::SearchOptions;
48 : :
49 : : namespace {
50 : :
51 : 8 : bool lcl_GetTextWithBreaks( const ScEditCell& rCell, ScDocument* pDoc, rtl::OUString& rVal )
52 : : {
53 : : // true = more than 1 paragraph
54 : :
55 : 8 : const EditTextObject* pData = NULL;
56 [ + - ]: 8 : rCell.GetData( pData );
57 [ + - ]: 8 : EditEngine& rEngine = pDoc->GetEditEngine();
58 [ + - ]: 8 : rEngine.SetText( *pData );
59 [ + - ][ + - ]: 8 : rVal = rEngine.GetText( LINEEND_LF );
[ + - ]
60 [ + - ]: 8 : return ( rEngine.GetParagraphCount() > 1 );
61 : : }
62 : :
63 : : }
64 : :
65 : 985 : bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRow,
66 : : const ScMarkData& rMark, rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
67 : : {
68 : 985 : bool bFound = false;
69 : 985 : bool bDoSearch = true;
70 : 985 : bool bDoBack = rSearchItem.GetBackward();
71 : :
72 : 985 : rtl::OUString aString;
73 : : ScBaseCell* pCell;
74 [ + + ]: 985 : if (rSearchItem.GetSelection())
75 [ + - ]: 765 : bDoSearch = rMark.IsCellMarked(nCol, nRow);
76 [ + + ][ + - ]: 985 : if ( bDoSearch && ((pCell = aCol[nCol].GetCell( nRow )) != NULL) )
[ + + ][ + + ]
77 : : {
78 : 376 : bool bMultiLine = false;
79 : 376 : CellType eCellType = pCell->GetCellType();
80 [ + - - - ]: 376 : switch (rSearchItem.GetCellType())
81 : : {
82 : : case SVX_SEARCHIN_FORMULA:
83 : : {
84 [ + + ]: 376 : if ( eCellType == CELLTYPE_FORMULA )
85 [ + - ][ + - ]: 24 : static_cast<ScFormulaCell*>(pCell)->GetFormula(aString, pDocument->GetGrammar());
[ + - ]
86 [ + + ]: 352 : else if ( eCellType == CELLTYPE_EDIT )
87 : : bMultiLine = lcl_GetTextWithBreaks(
88 [ + - ]: 8 : *(const ScEditCell*)pCell, pDocument, aString );
89 : : else
90 : : {
91 [ + - ]: 344 : aCol[nCol].GetInputString( nRow, aString );
92 : : }
93 : : }
94 : 376 : break;
95 : : case SVX_SEARCHIN_VALUE:
96 [ # # ]: 0 : if ( eCellType == CELLTYPE_EDIT )
97 : : bMultiLine = lcl_GetTextWithBreaks(
98 [ # # ]: 0 : *(const ScEditCell*)pCell, pDocument, aString );
99 : : else
100 : : {
101 [ # # ]: 0 : aCol[nCol].GetInputString( nRow, aString );
102 : : }
103 : 0 : break;
104 : : case SVX_SEARCHIN_NOTE:
105 : 0 : break; // don't search this case here
106 : : default:
107 : 0 : break;
108 : : }
109 : 376 : xub_StrLen nStart = 0;
110 : 376 : xub_StrLen nEnd = aString.getLength();
111 [ + - ]: 376 : ::com::sun::star::util::SearchResult aSearchResult;
112 [ + - ]: 376 : if (pSearchText)
113 : : {
114 [ - + ]: 376 : if ( bDoBack )
115 : : {
116 : 0 : xub_StrLen nTemp=nStart; nStart=nEnd; nEnd=nTemp;
117 [ # # ][ # # ]: 0 : bFound = (bool)(pSearchText->SearchBkwrd(aString, &nStart, &nEnd, &aSearchResult));
[ # # ]
118 : : // change results to definition before 614:
119 : 0 : --nEnd;
120 : : }
121 : : else
122 : : {
123 [ + - ][ + - ]: 376 : bFound = (bool)(pSearchText->SearchFrwrd(aString, &nStart, &nEnd, &aSearchResult));
[ + - ]
124 : : // change results to definition before 614:
125 : 376 : --nEnd;
126 : : }
127 : :
128 [ + + ][ - + ]: 376 : if (bFound && rSearchItem.GetWordOnly())
[ - + ]
129 [ # # ][ # # ]: 0 : bFound = (nStart == 0 && nEnd == aString.getLength() - 1);
130 : : }
131 : : else
132 : : {
133 : : OSL_FAIL("pSearchText == NULL");
134 : 0 : return bFound;
135 : : }
136 : :
137 : 376 : sal_uInt8 cMatrixFlag = MM_NONE;
138 [ + + + - : 552 : if ( bFound &&
+ + ][ - + ]
[ + - ][ + + ]
139 : 73 : ( (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE)
140 : 73 : ||(rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL) ) &&
141 : : // Matrix nicht zerreissen, nur Matrixformel ersetzen
142 : : !( (eCellType == CELLTYPE_FORMULA &&
143 [ # # ]: 0 : ((cMatrixFlag = ((ScFormulaCell*)pCell)->GetMatrixFlag()) == MM_REFERENCE))
144 : : // kein UndoDoc => Matrix nicht wiederherstellbar => nicht ersetzen
145 [ # # ][ - + ]: 30 : || (cMatrixFlag != MM_NONE && !pUndoDoc) ) &&
[ # # ]
146 [ + - ]: 30 : IsBlockEditable(nCol, nRow, nCol, nRow)
147 : : )
148 : : {
149 [ + - ][ - + ]: 30 : if ( cMatrixFlag == MM_NONE && rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE )
[ - + ]
150 : 0 : rUndoStr = aString;
151 [ + - ]: 30 : else if (pUndoDoc)
152 : : {
153 : 30 : ScAddress aAdr( nCol, nRow, nTab );
154 [ + - ]: 30 : ScBaseCell* pUndoCell = pCell->Clone( *pUndoDoc );
155 [ + - ]: 30 : pUndoDoc->PutCell( aAdr, pUndoCell);
156 : : }
157 : 30 : bool bRepeat = !rSearchItem.GetWordOnly();
158 [ - + ]: 30 : do
159 : : {
160 : : // wenn der gefundene Text leer ist, nicht weitersuchen,
161 : : // sonst wuerde man nie mehr aufhoeren (#35410#)
162 [ + - ][ - + ]: 30 : if ( nEnd < nStart || nEnd == STRING_MAXLEN )
163 : 0 : bRepeat = false;
164 : :
165 [ + - ]: 30 : String sReplStr = rSearchItem.GetReplaceString();
166 [ - + ]: 30 : if (rSearchItem.GetRegExp())
167 : : {
168 [ # # ][ # # ]: 0 : pSearchText->ReplaceBackReferences( sReplStr, aString, aSearchResult );
[ # # ]
169 [ # # ]: 0 : rtl::OUStringBuffer aStrBuffer(aString);
170 [ # # ]: 0 : aStrBuffer.remove(nStart, nEnd-nStart+1);
171 [ # # ][ # # ]: 0 : aStrBuffer.insert(nStart, sReplStr);
172 [ # # ]: 0 : aString = aStrBuffer.makeStringAndClear();
173 : : }
174 : : else
175 : : {
176 [ + - ]: 30 : rtl::OUStringBuffer aStrBuffer(aString);
177 [ + - ]: 30 : aStrBuffer.remove(nStart, nEnd-nStart+1);
178 [ + - ][ + - ]: 30 : aStrBuffer.insert(nStart, rSearchItem.GetReplaceString());
[ + - ][ + - ]
179 [ + - ]: 30 : aString = aStrBuffer.makeStringAndClear();
180 : : }
181 : :
182 : : // Indizes anpassen
183 [ - + ]: 30 : if (bDoBack)
184 : : {
185 : 0 : nEnd = nStart;
186 : 0 : nStart = 0;
187 : : }
188 : : else
189 : : {
190 : 30 : nStart = sal::static_int_cast<xub_StrLen>( nStart + sReplStr.Len() );
191 : 30 : nEnd = aString.getLength();
192 : : }
193 : :
194 : : // weitersuchen ?
195 [ + - ]: 30 : if (bRepeat)
196 : : {
197 [ + - ][ + - ]: 30 : if ( rSearchItem.GetCommand() != SVX_SEARCHCMD_REPLACE_ALL || nStart >= nEnd )
[ + - ]
198 : 30 : bRepeat = false;
199 [ # # ]: 0 : else if (bDoBack)
200 : : {
201 : 0 : xub_StrLen nTemp=nStart; nStart=nEnd; nEnd=nTemp;
202 [ # # ][ # # ]: 0 : bRepeat = ((bool)(pSearchText->SearchBkwrd(aString, &nStart, &nEnd, &aSearchResult)));
[ # # ]
203 : : // change results to definition before 614:
204 : 0 : --nEnd;
205 : : }
206 : : else
207 : : {
208 [ # # ][ # # ]: 0 : bRepeat = ((bool)(pSearchText->SearchFrwrd(aString, &nStart, &nEnd, &aSearchResult)));
[ # # ]
209 : : // change results to definition before 614:
210 : 0 : --nEnd;
211 : : }
212 [ + - ]: 30 : }
213 : : }
214 : : while (bRepeat);
215 : :
216 [ - + ]: 30 : if ( cMatrixFlag != MM_NONE )
217 : : { // Matrix nicht zerreissen
218 [ # # ]: 0 : if ( aString.getLength() > 2 )
219 : : { // {} raus, erst hier damit auch "{=" durch "{=..." ersetzt werden kann
220 [ # # ]: 0 : if ( aString[ aString.getLength()-1 ] == '}' )
221 : 0 : aString = aString.copy( 0, aString.getLength()-1 );
222 [ # # ]: 0 : if ( aString[0] == '{' )
223 : 0 : aString = aString.copy( 1 );
224 : : }
225 : 0 : ScAddress aAdr( nCol, nRow, nTab );
226 : : ScFormulaCell* pFCell = new ScFormulaCell( pDocument, aAdr,
227 [ # # ][ # # ]: 0 : aString, pDocument->GetGrammar(), cMatrixFlag );
[ # # ]
228 : : SCCOL nMatCols;
229 : : SCROW nMatRows;
230 [ # # ][ # # ]: 0 : ((ScFormulaCell*)pCell)->GetMatColsRows( nMatCols, nMatRows );
231 [ # # ]: 0 : pFCell->SetMatColsRows( nMatCols, nMatRows );
232 [ # # ][ # # ]: 0 : aCol[nCol].Insert( nRow, pFCell );
233 : : }
234 [ - + ][ # # ]: 30 : else if ( bMultiLine && aString.indexOf('\n') != -1 )
[ - + ]
235 [ # # ][ # # ]: 0 : PutCell( nCol, nRow, new ScEditCell( aString, pDocument ) );
[ # # ]
236 : : else
237 [ + - ][ + - ]: 376 : aCol[nCol].SetString(nRow, nTab, aString, pDocument->GetAddressConvention());
[ + - ][ + - ]
238 : : // pCell is invalid now (deleted)
239 [ + - ][ + - ]: 376 : }
240 : : }
241 : 985 : return bFound;
242 : : }
243 : :
244 : 985 : void ScTable::SkipFilteredRows(SCROW& rRow, SCROW& rLastNonFilteredRow, bool bForward)
245 : : {
246 [ + - ]: 985 : if (bForward)
247 : : {
248 : : // forward search
249 : :
250 [ + + ]: 985 : if (rRow <= rLastNonFilteredRow)
251 : : return;
252 : :
253 : 259 : SCROW nLastRow = rRow;
254 [ + - ][ - + ]: 259 : if (RowFiltered(rRow, NULL, &nLastRow))
255 : : // move to the first non-filtered row.
256 : 0 : rRow = nLastRow + 1;
257 : : else
258 : : // record the last non-filtered row to avoid checking
259 : : // the filtered state for each and every row.
260 : 985 : rLastNonFilteredRow = nLastRow;
261 : : }
262 : : else
263 : : {
264 : : // backward search
265 : :
266 [ # # ]: 0 : if (rRow >= rLastNonFilteredRow)
267 : : return;
268 : :
269 : 0 : SCROW nFirstRow = rRow;
270 [ # # ][ # # ]: 0 : if (RowFiltered(rRow, &nFirstRow, NULL))
271 : : // move to the first non-filtered row.
272 : 0 : rRow = nFirstRow - 1;
273 : : else
274 : : // record the last non-filtered row to avoid checking
275 : : // the filtered state for each and every row.
276 : 985 : rLastNonFilteredRow = nFirstRow;
277 : : }
278 : : }
279 : :
280 : 109 : bool ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
281 : : const ScMarkData& rMark, rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
282 : : {
283 : 109 : bool bFound = false;
284 : 109 : bool bAll = (rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND_ALL)
285 [ + + ][ + + ]: 109 : ||(rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL);
286 : 109 : SCCOL nCol = rCol;
287 : 109 : SCROW nRow = rRow;
288 : : SCCOL nLastCol;
289 : : SCROW nLastRow;
290 [ + - ]: 109 : GetLastDataPos(nLastCol, nLastRow);
291 : 109 : bool bSkipFiltered = !rSearchItem.IsSearchFiltered();
292 [ - + ][ - + ]: 109 : if (!bAll && rSearchItem.GetBackward())
[ + + ]
293 : : {
294 : 0 : SCROW nLastNonFilteredRow = MAXROW + 1;
295 : 0 : nCol = Min(nCol, (SCCOL)(nLastCol + 1));
296 : 0 : nRow = Min(nRow, (SCROW)(nLastRow + 1));
297 [ # # ]: 0 : if (rSearchItem.GetRowDirection())
298 : : {
299 : 0 : nCol--;
300 [ # # ][ # # ]: 0 : while (!bFound && ((SCsROW)nRow >= 0))
[ # # ]
301 : : {
302 [ # # ]: 0 : if (bSkipFiltered)
303 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, false);
304 : :
305 [ # # ][ # # ]: 0 : while (!bFound && ((SCsCOL)nCol >= 0))
[ # # ]
306 : : {
307 [ # # ]: 0 : bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
308 [ # # ]: 0 : if (!bFound)
309 : : {
310 : : bool bIsEmpty;
311 [ # # ][ # # ]: 0 : do
[ # # ]
312 : : {
313 : 0 : nCol--;
314 [ # # ]: 0 : if ((SCsCOL)nCol >= 0)
315 [ # # ]: 0 : bIsEmpty = aCol[nCol].IsEmptyData();
316 : : else
317 : 0 : bIsEmpty = true;
318 : : }
319 : : while (((SCsCOL)nCol >= 0) && bIsEmpty);
320 : : }
321 : : }
322 [ # # ]: 0 : if (!bFound)
323 : : {
324 : 0 : nCol = nLastCol;
325 : 0 : nRow--;
326 : : }
327 : : }
328 : : }
329 : : else
330 : : {
331 : 0 : nRow--;
332 [ # # ][ # # ]: 0 : while (!bFound && ((SCsCOL)nCol >= 0))
[ # # ]
333 : : {
334 [ # # ][ # # ]: 0 : while (!bFound && ((SCsROW)nRow >= 0))
[ # # ]
335 : : {
336 [ # # ]: 0 : if (bSkipFiltered)
337 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, false);
338 : :
339 [ # # ]: 0 : bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
340 [ # # ]: 0 : if (!bFound)
341 : : {
342 [ # # ][ # # ]: 0 : if (!aCol[nCol].GetPrevDataPos(nRow))
343 : 0 : nRow = -1;
344 : : }
345 : : }
346 [ # # ]: 0 : if (!bFound)
347 : : {
348 : : // Not found in this column. Move to the next column.
349 : : bool bIsEmpty;
350 : 0 : nRow = nLastRow;
351 : 0 : nLastNonFilteredRow = MAXROW + 1;
352 [ # # ][ # # ]: 0 : do
[ # # ]
353 : : {
354 : 0 : nCol--;
355 [ # # ]: 0 : if ((SCsCOL)nCol >= 0)
356 [ # # ]: 0 : bIsEmpty = aCol[nCol].IsEmptyData();
357 : : else
358 : 0 : bIsEmpty = true;
359 : : }
360 : : while (((SCsCOL)nCol >= 0) && bIsEmpty);
361 : : }
362 : : }
363 : : }
364 : : }
365 : : else
366 : : {
367 : 109 : SCROW nLastNonFilteredRow = -1;
368 [ + + ][ - + ]: 109 : if (!bAll && rSearchItem.GetRowDirection())
[ - + ]
369 : : {
370 : 0 : nCol++;
371 [ # # ][ # # ]: 0 : while (!bFound && (nRow <= nLastRow))
[ # # ]
372 : : {
373 [ # # ]: 0 : if (bSkipFiltered)
374 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, true);
375 : :
376 [ # # ][ # # ]: 0 : while (!bFound && (nCol <= nLastCol))
[ # # ]
377 : : {
378 [ # # ]: 0 : bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
379 [ # # ]: 0 : if (!bFound)
380 : : {
381 : 0 : nCol++;
382 [ # # ][ # # ]: 0 : while ((nCol <= nLastCol) && aCol[nCol].IsEmptyData()) nCol++;
[ # # ][ # # ]
383 : : }
384 : : }
385 [ # # ]: 0 : if (!bFound)
386 : : {
387 : 0 : nCol = 0;
388 : 0 : nRow++;
389 : : }
390 : : }
391 : : }
392 : : else
393 : : {
394 : 109 : nRow++;
395 [ + + ][ + + ]: 375 : while (!bFound && (nCol <= nLastCol))
[ + + ]
396 : : {
397 [ + + ][ + + ]: 1251 : while (!bFound && (nRow <= nLastRow))
[ + + ]
398 : : {
399 [ + - ]: 985 : if (bSkipFiltered)
400 [ + - ]: 985 : SkipFilteredRows(nRow, nLastNonFilteredRow, true);
401 : :
402 [ + - ]: 985 : bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
403 [ + + ]: 985 : if (!bFound)
404 : : {
405 [ + - ][ + + ]: 912 : if (!aCol[nCol].GetNextDataPos(nRow))
406 : 186 : nRow = MAXROW + 1;
407 : : }
408 : : }
409 [ + + ]: 266 : if (!bFound)
410 : : {
411 : : // Not found in this column. Move to the next column.
412 : 193 : nRow = 0;
413 : 193 : nLastNonFilteredRow = -1;
414 : 193 : nCol++;
415 [ + + ][ + - ]: 303 : while ((nCol <= nLastCol) && aCol[nCol].IsEmptyData()) nCol++;
[ + + ][ + + ]
416 : : }
417 : : }
418 : : }
419 : : }
420 [ + + ]: 109 : if (bFound)
421 : : {
422 : 73 : rCol = nCol;
423 : 73 : rRow = nRow;
424 : : }
425 : 109 : return bFound;
426 : : }
427 : :
428 : 7 : bool ScTable::SearchAll(const SvxSearchItem& rSearchItem, const ScMarkData& rMark,
429 : : ScRangeList& rMatchedRanges, rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
430 : : {
431 : 7 : bool bFound = true;
432 : 7 : SCCOL nCol = 0;
433 : 7 : SCROW nRow = -1;
434 : 7 : bool bEverFound = false;
435 : :
436 [ + + ]: 22 : do
437 : : {
438 [ + - ]: 22 : bFound = Search(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
439 [ + + ]: 22 : if (bFound)
440 : : {
441 : 15 : bEverFound = true;
442 [ + - ]: 15 : rMatchedRanges.Join(ScRange(nCol, nRow, nTab));
443 : : }
444 : : }
445 : : while (bFound);
446 : :
447 : 7 : return bEverFound;
448 : : }
449 : :
450 : 0 : bool ScTable::Replace(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
451 : : const ScMarkData& rMark, rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
452 : : {
453 : 0 : bool bFound = false;
454 : 0 : SCCOL nCol = rCol;
455 : 0 : SCROW nRow = rRow;
456 [ # # ]: 0 : if (rSearchItem.GetBackward())
457 : : {
458 [ # # ]: 0 : if (rSearchItem.GetRowDirection())
459 : 0 : nCol += 1;
460 : : else
461 : 0 : nRow += 1;
462 : : }
463 : : else
464 : : {
465 [ # # ]: 0 : if (rSearchItem.GetRowDirection())
466 : 0 : nCol -= 1;
467 : : else
468 : 0 : nRow -= 1;
469 : : }
470 [ # # ]: 0 : bFound = Search(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
471 [ # # ]: 0 : if (bFound)
472 : : {
473 : 0 : rCol = nCol;
474 : 0 : rRow = nRow;
475 : : }
476 : 0 : return bFound;
477 : : }
478 : :
479 : 14 : bool ScTable::ReplaceAll(
480 : : const SvxSearchItem& rSearchItem, const ScMarkData& rMark, ScRangeList& rMatchedRanges,
481 : : rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
482 : : {
483 : 14 : bool bOldDouble = ScColumn::bDoubleAlloc; // sollte immer sal_False sein?
484 : : OSL_ENSURE(!bOldDouble,"bDoubleAlloc ???");
485 : 14 : ScColumn::bDoubleAlloc = true; // fuer Undo-Doc
486 : :
487 : 14 : SCCOL nCol = 0;
488 : 14 : SCROW nRow = -1;
489 : :
490 : 14 : bool bEverFound = false;
491 : 30 : while (true)
492 : : {
493 [ + - ]: 44 : bool bFound = Search(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
494 : :
495 [ + + ]: 44 : if (bFound)
496 : : {
497 : 30 : bEverFound = true;
498 [ + - ]: 30 : rMatchedRanges.Join(ScRange(nCol, nRow, nTab));
499 : : }
500 : : else
501 : 14 : break;
502 : : }
503 : 14 : ScColumn::bDoubleAlloc = bOldDouble;
504 : 14 : return bEverFound;
505 : : }
506 : :
507 : 0 : bool ScTable::SearchStyle(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
508 : : const ScMarkData& rMark)
509 : : {
510 : : const ScStyleSheet* pSearchStyle = (const ScStyleSheet*)
511 : 0 : pDocument->GetStyleSheetPool()->Find(
512 [ # # ]: 0 : rSearchItem.GetSearchString(), SFX_STYLE_FAMILY_PARA );
513 : :
514 : 0 : SCsCOL nCol = rCol;
515 : 0 : SCsROW nRow = rRow;
516 : 0 : bool bFound = false;
517 : :
518 : 0 : bool bSelect = rSearchItem.GetSelection();
519 : 0 : bool bRows = rSearchItem.GetRowDirection();
520 : 0 : bool bBack = rSearchItem.GetBackward();
521 [ # # ]: 0 : short nAdd = bBack ? -1 : 1;
522 : :
523 [ # # ]: 0 : if (bRows) // zeilenweise
524 : : {
525 : 0 : nRow += nAdd;
526 [ # # # # ]: 0 : do
[ # # ]
527 : : {
528 : 0 : SCsROW nNextRow = aCol[nCol].SearchStyle( nRow, pSearchStyle, bBack, bSelect, rMark );
529 [ # # ]: 0 : if (!ValidRow(nNextRow))
530 : : {
531 [ # # ]: 0 : nRow = bBack ? MAXROW : 0;
532 : 0 : nCol = sal::static_int_cast<SCsCOL>( nCol + nAdd );
533 : : }
534 : : else
535 : : {
536 : 0 : nRow = nNextRow;
537 : 0 : bFound = true;
538 : : }
539 : : }
540 : 0 : while (!bFound && ValidCol(nCol));
541 : : }
542 : : else // spaltenweise
543 : : {
544 : : SCsROW nNextRows[MAXCOLCOUNT];
545 : : SCsCOL i;
546 [ # # ]: 0 : for (i=0; i<=MAXCOL; i++)
547 : : {
548 : 0 : SCsROW nSRow = nRow;
549 [ # # ][ # # ]: 0 : if (bBack) { if (i>=nCol) --nSRow; }
550 [ # # ]: 0 : else { if (i<=nCol) ++nSRow; }
551 [ # # ]: 0 : nNextRows[i] = aCol[i].SearchStyle( nSRow, pSearchStyle, bBack, bSelect, rMark );
552 : : }
553 [ # # ]: 0 : if (bBack) // rueckwaerts
554 : : {
555 : 0 : nRow = -1;
556 [ # # ]: 0 : for (i=MAXCOL; i>=0; i--)
557 [ # # ]: 0 : if (nNextRows[i]>nRow)
558 : : {
559 : 0 : nCol = i;
560 : 0 : nRow = nNextRows[i];
561 : 0 : bFound = true;
562 : : }
563 : : }
564 : : else // vorwaerts
565 : : {
566 : 0 : nRow = MAXROW+1;
567 [ # # ]: 0 : for (i=0; i<=MAXCOL; i++)
568 [ # # ]: 0 : if (nNextRows[i]<nRow)
569 : : {
570 : 0 : nCol = i;
571 : 0 : nRow = nNextRows[i];
572 : 0 : bFound = true;
573 : : }
574 : : }
575 : : }
576 : :
577 [ # # ]: 0 : if (bFound)
578 : : {
579 : 0 : rCol = (SCCOL) nCol;
580 : 0 : rRow = (SCROW) nRow;
581 : : }
582 : 0 : return bFound;
583 : : }
584 : :
585 : : //! einzelnes Pattern fuer Undo zurueckgeben
586 : :
587 : 0 : bool ScTable::ReplaceStyle(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
588 : : const ScMarkData& rMark, bool bIsUndo)
589 : : {
590 : : bool bRet;
591 [ # # ]: 0 : if (bIsUndo)
592 : 0 : bRet = true;
593 : : else
594 : 0 : bRet = SearchStyle(rSearchItem, rCol, rRow, rMark);
595 [ # # ]: 0 : if (bRet)
596 : : {
597 : : const ScStyleSheet* pReplaceStyle = (const ScStyleSheet*)
598 : 0 : pDocument->GetStyleSheetPool()->Find(
599 [ # # ]: 0 : rSearchItem.GetReplaceString(), SFX_STYLE_FAMILY_PARA );
600 : :
601 [ # # ]: 0 : if (pReplaceStyle)
602 : 0 : ApplyStyle( rCol, rRow, *pReplaceStyle );
603 : : else
604 : : {
605 : : OSL_FAIL("pReplaceStyle==0");
606 : : }
607 : : }
608 : :
609 : 0 : return bRet;
610 : : }
611 : :
612 : 0 : bool ScTable::SearchAllStyle(
613 : : const SvxSearchItem& rSearchItem, const ScMarkData& rMark, ScRangeList& rMatchedRanges)
614 : : {
615 : : const ScStyleSheet* pSearchStyle = (const ScStyleSheet*)
616 : 0 : pDocument->GetStyleSheetPool()->Find(
617 [ # # ]: 0 : rSearchItem.GetSearchString(), SFX_STYLE_FAMILY_PARA );
618 : 0 : bool bSelect = rSearchItem.GetSelection();
619 : 0 : bool bBack = rSearchItem.GetBackward();
620 : 0 : bool bEverFound = false;
621 : :
622 [ # # ]: 0 : for (SCCOL i=0; i<=MAXCOL; i++)
623 : : {
624 : 0 : bool bFound = true;
625 : 0 : SCsROW nRow = 0;
626 : : SCsROW nEndRow;
627 [ # # ][ # # ]: 0 : while (bFound && nRow <= MAXROW)
[ # # ]
628 : : {
629 [ # # ]: 0 : bFound = aCol[i].SearchStyleRange( nRow, nEndRow, pSearchStyle, bBack, bSelect, rMark );
630 [ # # ]: 0 : if (bFound)
631 : : {
632 [ # # ]: 0 : if (nEndRow<nRow)
633 : : {
634 : 0 : SCsROW nTemp = nRow;
635 : 0 : nRow = nEndRow;
636 : 0 : nEndRow = nTemp;
637 : : }
638 [ # # ]: 0 : rMatchedRanges.Join(ScRange(i, nRow, nTab, i, nEndRow, nTab));
639 : 0 : nRow = nEndRow + 1;
640 : 0 : bEverFound = true;
641 : : }
642 : : }
643 : : }
644 : :
645 : 0 : return bEverFound;
646 : : }
647 : :
648 : 0 : bool ScTable::ReplaceAllStyle(
649 : : const SvxSearchItem& rSearchItem, const ScMarkData& rMark, ScRangeList& rMatchedRanges,
650 : : ScDocument* pUndoDoc)
651 : : {
652 : 0 : bool bRet = SearchAllStyle(rSearchItem, rMark, rMatchedRanges);
653 [ # # ]: 0 : if (bRet)
654 : : {
655 : : const ScStyleSheet* pReplaceStyle = (const ScStyleSheet*)
656 : 0 : pDocument->GetStyleSheetPool()->Find(
657 [ # # ]: 0 : rSearchItem.GetReplaceString(), SFX_STYLE_FAMILY_PARA );
658 : :
659 [ # # ]: 0 : if (pReplaceStyle)
660 : : {
661 [ # # ]: 0 : if (pUndoDoc)
662 : : pDocument->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab,
663 : 0 : IDF_ATTRIB, true, pUndoDoc, &rMark );
664 : 0 : ApplySelectionStyle( *pReplaceStyle, rMark );
665 : : }
666 : : else
667 : : {
668 : : OSL_FAIL("pReplaceStyle==0");
669 : : }
670 : : }
671 : :
672 : 0 : return bRet;
673 : : }
674 : :
675 : 64 : bool ScTable::SearchAndReplace(
676 : : const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark,
677 : : ScRangeList& rMatchedRanges, rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
678 : : {
679 : 64 : sal_uInt16 nCommand = rSearchItem.GetCommand();
680 : 64 : bool bFound = false;
681 [ - + ][ # # ]: 103 : if ( ValidColRow(rCol, rRow) ||
[ + - ]
[ - + # # ]
[ + - ]
[ + - + - ]
[ + - ][ + + ]
682 : : ((nCommand == SVX_SEARCHCMD_FIND || nCommand == SVX_SEARCHCMD_REPLACE) &&
683 : 0 : (((rCol == MAXCOLCOUNT || rCol == -1) && VALIDROW(rRow)) ||
684 : 39 : ((rRow == MAXROWCOUNT || rRow == -1) && VALIDCOL(rCol))
685 : : )
686 : : )
687 : : )
688 : : {
689 : 64 : bool bStyles = rSearchItem.GetPattern();
690 [ - + ]: 64 : if (bStyles)
691 : : {
692 [ # # ]: 0 : if (nCommand == SVX_SEARCHCMD_FIND)
693 : 0 : bFound = SearchStyle(rSearchItem, rCol, rRow, rMark);
694 [ # # ]: 0 : else if (nCommand == SVX_SEARCHCMD_REPLACE)
695 : 0 : bFound = ReplaceStyle(rSearchItem, rCol, rRow, rMark, false);
696 [ # # ]: 0 : else if (nCommand == SVX_SEARCHCMD_FIND_ALL)
697 : 0 : bFound = SearchAllStyle(rSearchItem, rMark, rMatchedRanges);
698 [ # # ]: 0 : else if (nCommand == SVX_SEARCHCMD_REPLACE_ALL)
699 : 0 : bFound = ReplaceAllStyle(rSearchItem, rMark, rMatchedRanges, pUndoDoc);
700 : : }
701 : : else
702 : : {
703 : : // SearchParam no longer needed - SearchOptions contains all settings
704 : 64 : com::sun::star::util::SearchOptions aSearchOptions = rSearchItem.GetSearchOptions();
705 [ + - ]: 64 : aSearchOptions.Locale = *ScGlobal::GetLocale();
706 : :
707 [ - + ]: 64 : if (aSearchOptions.searchString.isEmpty())
708 : : {
709 : : // Search for empty cells.
710 [ # # ]: 0 : return SearchAndReplaceEmptyCells(rSearchItem, rCol, rRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
711 : : }
712 : :
713 : : // reflect UseAsianOptions flag in SearchOptions
714 : : // (use only ignore case and width if asian options are disabled).
715 : : // This is also done in SvxSearchDialog CommandHdl, but not in API object.
716 [ + - ]: 64 : if ( !rSearchItem.IsUseAsianOptions() )
717 : : aSearchOptions.transliterateFlags &=
718 : : ( com::sun::star::i18n::TransliterationModules_IGNORE_CASE |
719 : 64 : com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH );
720 : :
721 [ + - ][ + - ]: 64 : pSearchText = new utl::TextSearch( aSearchOptions );
722 : :
723 [ + + ]: 64 : if (nCommand == SVX_SEARCHCMD_FIND)
724 [ + - ]: 43 : bFound = Search(rSearchItem, rCol, rRow, rMark, rUndoStr, pUndoDoc);
725 [ + + ]: 21 : else if (nCommand == SVX_SEARCHCMD_FIND_ALL)
726 [ + - ]: 7 : bFound = SearchAll(rSearchItem, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
727 [ - + ]: 14 : else if (nCommand == SVX_SEARCHCMD_REPLACE)
728 [ # # ]: 0 : bFound = Replace(rSearchItem, rCol, rRow, rMark, rUndoStr, pUndoDoc);
729 [ + - ]: 14 : else if (nCommand == SVX_SEARCHCMD_REPLACE_ALL)
730 [ + - ]: 14 : bFound = ReplaceAll(rSearchItem, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
731 : :
732 [ + - ][ + - ]: 64 : delete pSearchText;
733 [ + - ]: 64 : pSearchText = NULL;
734 : : }
735 : : }
736 : 64 : return bFound;
737 : : }
738 : :
739 : 0 : bool ScTable::SearchAndReplaceEmptyCells(
740 : : const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark,
741 : : ScRangeList& rMatchedRanges, rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
742 : : {
743 : : SCCOL nColStart, nColEnd;
744 : : SCROW nRowStart, nRowEnd;
745 [ # # ]: 0 : GetFirstDataPos(nColStart, nRowStart);
746 [ # # ]: 0 : GetLastDataPos(nColEnd, nRowEnd);
747 : :
748 [ # # ]: 0 : ScRangeList aRanges;
749 [ # # ]: 0 : aRanges.Append(ScRange(nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab));
750 : :
751 [ # # ]: 0 : if (rSearchItem.GetSelection())
752 : : {
753 : : // current selection only.
754 [ # # ][ # # ]: 0 : if (!rMark.IsMarked() && !rMark.IsMultiMarked())
[ # # ]
755 : : // There is no selection. Bail out.
756 : 0 : return false;
757 : :
758 [ # # ][ # # ]: 0 : ScRangeList aMarkedRanges, aNewRanges;
759 [ # # ]: 0 : rMark.FillRangeListWithMarks(&aMarkedRanges, true);
760 [ # # ][ # # ]: 0 : for ( size_t i = 0, n = aMarkedRanges.size(); i < n; ++i )
761 : : {
762 [ # # ]: 0 : ScRange* p = aMarkedRanges[ i ];
763 [ # # ][ # # ]: 0 : if (p->aStart.Col() > nColEnd || p->aStart.Row() > nRowEnd)
[ # # ]
764 : : // This range is outside the data area. Skip it.
765 : 0 : continue;
766 : :
767 : : // Shrink the range into data area only.
768 [ # # ]: 0 : if (p->aStart.Col() < nColStart)
769 : 0 : p->aStart.SetCol(rCol);
770 [ # # ]: 0 : if (p->aStart.Row() < nRowStart)
771 : 0 : p->aStart.SetRow(rRow);
772 : :
773 [ # # ]: 0 : if (p->aEnd.Col() > nColEnd)
774 : 0 : p->aEnd.SetCol(nColEnd);
775 [ # # ]: 0 : if (p->aEnd.Row() > nRowEnd)
776 : 0 : p->aEnd.SetRow(nRowEnd);
777 : :
778 [ # # ]: 0 : aNewRanges.Append(*p);
779 : : }
780 [ # # ][ # # ]: 0 : aRanges = aNewRanges;
[ # # ]
781 : : }
782 : :
783 : 0 : sal_uInt16 nCommand = rSearchItem.GetCommand();
784 [ # # ][ # # ]: 0 : if (nCommand == SVX_SEARCHCMD_FIND || nCommand == SVX_SEARCHCMD_REPLACE)
785 : : {
786 [ # # ]: 0 : if (rSearchItem.GetBackward())
787 : : {
788 [ # # ][ # # ]: 0 : for ( size_t i = aRanges.size(); i > 0; --i )
789 : : {
790 [ # # ]: 0 : ScRange* p = aRanges[ i - 1 ];
791 [ # # ][ # # ]: 0 : if (SearchRangeForEmptyCell(*p, rSearchItem, rCol, rRow, rUndoStr))
792 : 0 : return true;
793 : : }
794 : : }
795 : : else
796 : : {
797 [ # # ][ # # ]: 0 : for ( size_t i = 0, nListSize = aRanges.size(); i < nListSize; ++i )
798 : : {
799 [ # # ]: 0 : ScRange* p = aRanges[ i ];
800 [ # # ][ # # ]: 0 : if (SearchRangeForEmptyCell(*p, rSearchItem, rCol, rRow, rUndoStr))
801 : 0 : return true;
802 : : }
803 : 0 : }
804 : : }
805 [ # # ][ # # ]: 0 : else if (nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL)
806 : : {
807 : 0 : bool bFound = false;
808 [ # # ][ # # ]: 0 : for ( size_t i = 0, nListSize = aRanges.size(); i < nListSize; ++i )
809 : : {
810 [ # # ]: 0 : ScRange* p = aRanges[ i ];
811 [ # # ]: 0 : bFound |= SearchRangeForAllEmptyCells(*p, rSearchItem, rMatchedRanges, rUndoStr, pUndoDoc);
812 : : }
813 : 0 : return bFound;
814 : : }
815 [ # # ]: 0 : return false;
816 : : }
817 : :
818 : : namespace {
819 : :
820 : 0 : bool lcl_maybeReplaceCellString(
821 : : ScColumn& rColObj, SCCOL& rCol, SCROW& rRow, rtl::OUString& rUndoStr, SCCOL nCol, SCROW nRow, const SvxSearchItem& rSearchItem)
822 : : {
823 : 0 : ScBaseCell* pCell = rColObj.GetCell(nRow);
824 [ # # ][ # # ]: 0 : if (!pCell || pCell->GetCellType() == CELLTYPE_NOTE)
[ # # ]
825 : : {
826 : : // empty cell found.
827 : 0 : rCol = nCol;
828 : 0 : rRow = nRow;
829 [ # # # # ]: 0 : if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
[ # # ]
830 [ # # ][ # # ]: 0 : rSearchItem.GetReplaceString().Len())
[ # # ]
831 : : {
832 [ # # ][ # # ]: 0 : rColObj.Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
[ # # ][ # # ]
833 : 0 : rUndoStr = rtl::OUString();
834 : : }
835 : 0 : return true;
836 : : }
837 : 0 : return false;
838 : : }
839 : :
840 : : }
841 : :
842 : 0 : bool ScTable::SearchRangeForEmptyCell(
843 : : const ScRange& rRange, const SvxSearchItem& rSearchItem,
844 : : SCCOL& rCol, SCROW& rRow, rtl::OUString& rUndoStr)
845 : : {
846 : 0 : sal_uInt16 nCmd = rSearchItem.GetCommand();
847 : 0 : bool bSkipFiltered = rSearchItem.IsSearchFiltered();
848 [ # # ]: 0 : if (rSearchItem.GetBackward())
849 : : {
850 : : // backward search
851 [ # # ]: 0 : if (rSearchItem.GetRowDirection())
852 : : {
853 : : // row direction.
854 : 0 : SCROW nLastNonFilteredRow = MAXROW + 1;
855 [ # # ]: 0 : SCROW nBeginRow = rRange.aEnd.Row() > rRow ? rRow : rRange.aEnd.Row();
856 [ # # ]: 0 : for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
857 : : {
858 [ # # ]: 0 : if (bSkipFiltered)
859 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, false);
860 [ # # ]: 0 : if (nRow < rRange.aStart.Row())
861 : 0 : break;
862 : :
863 : 0 : SCCOL nBeginCol = rRange.aEnd.Col();
864 [ # # ][ # # ]: 0 : if (nRow == rRow && nBeginCol >= rCol)
865 : : // always start from one cell before the cursor.
866 [ # # ]: 0 : nBeginCol = rCol - (nCmd == SVX_SEARCHCMD_FIND ? 1 : 0);
867 : :
868 [ # # ]: 0 : for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
869 : : {
870 [ # # ][ # # ]: 0 : if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
871 : 0 : return true;
872 : : }
873 : : }
874 : : }
875 : : else
876 : : {
877 : : // column direction.
878 [ # # ]: 0 : SCCOL nBeginCol = rRange.aEnd.Col() > rCol ? rCol : rRange.aEnd.Col();
879 [ # # ]: 0 : for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
880 : : {
881 : 0 : SCROW nLastNonFilteredRow = MAXROW + 1;
882 : 0 : SCROW nBeginRow = rRange.aEnd.Row();
883 [ # # ][ # # ]: 0 : if (nCol == rCol && nBeginRow >= rRow)
884 : : // always start from one cell before the cursor.
885 [ # # ]: 0 : nBeginRow = rRow - (nCmd == SVX_SEARCHCMD_FIND ? 1 : 0);
886 [ # # ]: 0 : for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
887 : : {
888 [ # # ]: 0 : if (bSkipFiltered)
889 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, false);
890 [ # # ]: 0 : if (nRow < rRange.aStart.Row())
891 : 0 : break;
892 : :
893 [ # # ][ # # ]: 0 : if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
894 : 0 : return true;
895 : : }
896 : : }
897 : : }
898 : : }
899 : : else
900 : : {
901 : : // forward search
902 [ # # ]: 0 : if (rSearchItem.GetRowDirection())
903 : : {
904 : : // row direction.
905 : 0 : SCROW nLastNonFilteredRow = -1;
906 [ # # ]: 0 : SCROW nBeginRow = rRange.aStart.Row() < rRow ? rRow : rRange.aStart.Row();
907 [ # # ]: 0 : for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
908 : : {
909 [ # # ]: 0 : if (bSkipFiltered)
910 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, true);
911 [ # # ]: 0 : if (nRow > rRange.aEnd.Row())
912 : 0 : break;
913 : :
914 : 0 : SCCOL nBeginCol = rRange.aStart.Col();
915 [ # # ][ # # ]: 0 : if (nRow == rRow && nBeginCol <= rCol)
916 : : // always start from one cell past the cursor.
917 [ # # ]: 0 : nBeginCol = rCol + (nCmd == SVX_SEARCHCMD_FIND ? 1 : 0);
918 [ # # ]: 0 : for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
919 : : {
920 [ # # ][ # # ]: 0 : if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
921 : 0 : return true;
922 : : }
923 : : }
924 : : }
925 : : else
926 : : {
927 : : // column direction.
928 [ # # ]: 0 : SCCOL nBeginCol = rRange.aStart.Col() < rCol ? rCol : rRange.aStart.Col();
929 [ # # ]: 0 : for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
930 : : {
931 : 0 : SCROW nLastNonFilteredRow = -1;
932 : 0 : SCROW nBeginRow = rRange.aStart.Row();
933 [ # # ][ # # ]: 0 : if (nCol == rCol && nBeginRow <= rRow)
934 : : // always start from one cell past the cursor.
935 [ # # ]: 0 : nBeginRow = rRow + (nCmd == SVX_SEARCHCMD_FIND ? 1 : 0);
936 [ # # ]: 0 : for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
937 : : {
938 [ # # ]: 0 : if (bSkipFiltered)
939 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, true);
940 [ # # ]: 0 : if (nRow > rRange.aEnd.Row())
941 : 0 : break;
942 : :
943 [ # # ][ # # ]: 0 : if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
944 : 0 : return true;
945 : : }
946 : : }
947 : : }
948 : : }
949 : 0 : return false;
950 : : }
951 : :
952 : 0 : bool ScTable::SearchRangeForAllEmptyCells(
953 : : const ScRange& rRange, const SvxSearchItem& rSearchItem,
954 : : ScRangeList& rMatchedRanges, rtl::OUString& rUndoStr, ScDocument* pUndoDoc)
955 : : {
956 : 0 : bool bFound = false;
957 : 0 : bool bReplace = (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL) &&
958 [ # # ][ # # ]: 0 : (rSearchItem.GetReplaceString().Len() > 0);
[ # # ][ # # ]
[ # # ]
959 : 0 : bool bSkipFiltered = rSearchItem.IsSearchFiltered();
960 : :
961 [ # # ]: 0 : for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
962 : : {
963 : 0 : SCROW nLastNonFilteredRow = -1;
964 [ # # ][ # # ]: 0 : if (aCol[nCol].IsEmptyData())
965 : : {
966 : : // The entire column is empty.
967 [ # # ]: 0 : for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
968 : : {
969 : : SCROW nLastRow;
970 [ # # ][ # # ]: 0 : if (!RowFiltered(nRow, NULL, &nLastRow))
971 : : {
972 [ # # ]: 0 : rMatchedRanges.Join(ScRange(nCol, nRow, nTab, nCol, nLastRow, nTab));
973 [ # # ]: 0 : if (bReplace)
974 : : {
975 [ # # ]: 0 : const String& rNewStr = rSearchItem.GetReplaceString();
976 [ # # ]: 0 : for (SCROW i = nRow; i <= nLastRow; ++i)
977 : : {
978 [ # # ][ # # ]: 0 : aCol[nCol].Insert(i, new ScStringCell(rNewStr));
[ # # ][ # # ]
979 [ # # ]: 0 : if (pUndoDoc)
980 : : // TODO: I'm using a string cell with empty content to
981 : : // trigger deletion of cell instance on undo. Maybe I
982 : : // should create a new cell type for this?
983 [ # # ][ # # ]: 0 : pUndoDoc->PutCell(nCol, i, nTab, new ScStringCell(String()));
[ # # ][ # # ]
[ # # ][ # # ]
984 : : }
985 [ # # ][ # # ]: 0 : rUndoStr = String();
[ # # ][ # # ]
986 : : }
987 : : }
988 : :
989 : 0 : nRow = nLastRow; // move to the last filtered row.
990 : : }
991 : 0 : bFound = true;
992 : 0 : continue;
993 : : }
994 : :
995 [ # # ]: 0 : for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
996 : : {
997 [ # # ]: 0 : if (bSkipFiltered)
998 [ # # ]: 0 : SkipFilteredRows(nRow, nLastNonFilteredRow, true);
999 [ # # ]: 0 : if (nRow > rRange.aEnd.Row())
1000 : 0 : break;
1001 : :
1002 [ # # ]: 0 : ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
1003 [ # # ]: 0 : if (!pCell)
1004 : : {
1005 : : // empty cell found
1006 [ # # ]: 0 : rMatchedRanges.Join(ScRange(nCol, nRow, nTab));
1007 : 0 : bFound = true;
1008 : :
1009 [ # # ]: 0 : if (bReplace)
1010 : : {
1011 [ # # ][ # # ]: 0 : aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
[ # # ][ # # ]
[ # # ][ # # ]
1012 [ # # ]: 0 : if (pUndoDoc)
1013 : : // TODO: I'm using a string cell with empty content to
1014 : : // trigger deletion of cell instance on undo. Maybe I
1015 : : // should create a new cell type for this?
1016 [ # # ][ # # ]: 0 : pUndoDoc->PutCell(nCol, nRow, nTab, new ScStringCell(String()));
[ # # ][ # # ]
[ # # ][ # # ]
1017 : : }
1018 : : }
1019 [ # # ]: 0 : else if (pCell->GetCellType() == CELLTYPE_NOTE)
1020 : : {
1021 [ # # ]: 0 : rMatchedRanges.Join(ScRange(nCol, nRow, nTab));
1022 : 0 : bFound = true;
1023 : :
1024 [ # # ]: 0 : if (bReplace)
1025 : : {
1026 [ # # ]: 0 : if (pUndoDoc)
1027 : : {
1028 : 0 : ScAddress aCellPos(nCol, nRow, nTab);
1029 [ # # ][ # # ]: 0 : pUndoDoc->PutCell(nCol, nRow, nTab, pCell->Clone(*pUndoDoc, aCellPos));
1030 [ # # ]: 0 : ScNotes* pNotes = pUndoDoc->GetNotes(nTab);
1031 [ # # ]: 0 : ScPostIt* pPostIt = maNotes.findByAddress(nCol, nRow);
1032 [ # # ]: 0 : if (pPostIt)
1033 : : {
1034 [ # # ][ # # ]: 0 : pNotes->insert(nCol, nRow, pPostIt->Clone(ScAddress(nCol, nRow, nTab), *pUndoDoc, ScAddress(nCol, nRow, nTab), true));
1035 : : }
1036 : : }
1037 [ # # ][ # # ]: 0 : aCol[nCol].SetString(nRow, nTab, rSearchItem.GetReplaceString(), pDocument->GetAddressConvention());
[ # # ][ # # ]
1038 : : }
1039 : : }
1040 : : }
1041 : : }
1042 : 0 : return bFound;
1043 : : }
1044 : :
1045 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|