LCOV - code coverage report
Current view: top level - sc/source/core/data - table6.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 189 517 36.6 %
Date: 2015-06-13 12:38:46 Functions: 9 20 45.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11