[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - 2 commits - sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Fri Jun 21 17:20:26 PDT 2013


 sc/inc/dociter.hxx               |    7 +++++++
 sc/source/core/data/dociter.cxx  |   28 +++++++++++++++++++++++-----
 sc/source/core/data/documen8.cxx |    2 ++
 sc/source/core/data/fillinfo.cxx |   18 ++++++++++--------
 4 files changed, 42 insertions(+), 13 deletions(-)

New commits:
commit 38afe6ebddcc54534930941c936437b508a2ca47
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Jun 21 20:11:27 2013 -0400

    Prevent crash during on-line spell checking.
    
    The new ScHorizontalCellIterator internally uses iterators for each
    column to track positions. This means that, if a cell value in the iteration
    range chnages while the iteration is on-going, those internal iterators
    get invalidated. Allow the client code to rehash the iterators when modifying
    a cell content during iteration.
    
    Having said that, it's best not to modify cells during iteration.
    
    Change-Id: Ida453d4f883e1fbcbab4eb0401e37fea8c0b901d

diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index 2452a60..9458aae 100644
--- a/sc/inc/dociter.hxx
+++ b/sc/inc/dociter.hxx
@@ -441,6 +441,13 @@ public:
     /// Set a(nother) sheet and (re)init.
     void            SetTab( SCTAB nTab );
 
+    /**
+     * When modifying a cell while still in iteration, call this to re-fetch
+     * the column iterators used internally because the old iterators have
+     * been invalidated.
+     */
+    void RehashCol( SCCOL nCol );
+
 private:
     void            Advance();
 };
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 9c24aae..1cdc52c 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -1695,7 +1695,7 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB
     nEndRow( nRow2 ),
     mnCol( nCol1 ),
     mnRow( nRow1 ),
-    bMore( true )
+    bMore(false)
 {
     if (mnTab >= pDoc->GetTableCount())
         OSL_FAIL("try to access index out of bounds, FIX IT");
@@ -1714,24 +1714,42 @@ ScHorizontalCellIterator::~ScHorizontalCellIterator()
 
 void ScHorizontalCellIterator::SetTab( SCTAB nTabP )
 {
+    bMore = false;
     mnTab = nTabP;
     mnRow = nStartRow;
     mnCol = nStartCol;
-    bMore = true;
 
     // Set the start position in each column.
     for (SCCOL i = nStartCol; i <= nEndCol; ++i)
     {
         ScColumn* pCol = &pDoc->maTabs[mnTab]->aCol[i];
-        maColPositions[i-nStartCol].maPos = pCol->maCells.position(nStartRow).first;
-        maColPositions[i-nStartCol].maEnd = pCol->maCells.end();
+        ColParam& rParam = maColPositions[i-nStartCol];
+        rParam.maPos = pCol->maCells.position(nStartRow).first;
+        rParam.maEnd = pCol->maCells.end();
+        if (rParam.maPos != rParam.maEnd)
+            bMore = true;
     }
 
-    if (maColPositions[0].maPos->type == sc::element_type_empty)
+    if (!bMore)
+        return;
+
+    ColParam& rParam = maColPositions[0];
+    if (rParam.maPos == rParam.maEnd || rParam.maPos->type == sc::element_type_empty)
         // Skip to the first non-empty cell.
         Advance();
 }
 
+void ScHorizontalCellIterator::RehashCol( SCCOL nCol )
+{
+    if (nCol < nStartCol || nEndCol < nCol)
+        return;
+
+    ColParam& rParam = maColPositions[nCol-nStartCol];
+    ScColumn& rCol = pDoc->maTabs[mnTab]->aCol[nCol];
+    rParam.maPos = rCol.maCells.position(mnRow).first;
+    rParam.maEnd = rCol.maCells.end();
+}
+
 ScRefCellValue* ScHorizontalCellIterator::GetNext( SCCOL& rCol, SCROW& rRow )
 {
     if (!bMore)
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 570a14c..4c64c45 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -827,12 +827,14 @@ bool ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpe
                 {
                     // The cell will take ownership of pNewData.
                     SetEditText(ScAddress(nCol,nRow,nTab), pEngine->CreateTextObject());
+                    aIter.RehashCol(nCol);
                 }
                 else
                 {
                     ScSetStringParam aParam;
                     aParam.setTextInput();
                     SetString(ScAddress(nCol,nRow,nTab), pEngine->GetText(), &aParam);
+                    aIter.RehashCol(nCol);
                 }
 
                 //  Paint
commit d873f62d49c61a7943dd6ea2ade9d3549ce5a965
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Jun 21 18:05:46 2013 -0400

    Fix my wrong logic in row info iteration.
    
    Align the array position of RowInfo by comparing its nRowNo value with
    the current row number.
    
    Change-Id: Idd26636cac0ba4ade1b538dd68580b469611da04

diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx
index 34c2562..5f9b6ce 100644
--- a/sc/source/core/data/fillinfo.cxx
+++ b/sc/source/core/data/fillinfo.cxx
@@ -145,8 +145,16 @@ class RowInfoFiller
         return mbHiddenRow;
     }
 
-    void setInfo(size_t /*nRow*/, const ScRefCellValue& rCell)
+    void alignArray(size_t nRow)
     {
+        while (mpRowInfo[mrArrY].nRowNo < static_cast<SCROW>(nRow))
+            ++mrArrY;
+    }
+
+    void setInfo(size_t nRow, const ScRefCellValue& rCell)
+    {
+        alignArray(nRow);
+
         RowInfo* pThisRowInfo = &mpRowInfo[mrArrY];
         CellInfo* pInfo = &pThisRowInfo->pCellInfo[mnArrX];
         pInfo->maCell = rCell;
@@ -183,12 +191,6 @@ public:
         if (!isHidden(nRow))
             setInfo(nRow, ScRefCellValue(const_cast<ScFormulaCell*>(p)));
     }
-
-    void operator() (mdds::mtv::element_t, size_t, size_t nDataSize)
-    {
-        // Skip all empty cells.
-        mrArrY += nDataSize;
-    }
 };
 
 }
@@ -430,7 +432,7 @@ void ScDocument::FillInfo(
                 // cells that are not hidden.
                 RowInfoFiller aFunc(*this, nTab, pRowInfo, nArrCol, nArrRow);
                 sc::ParseAllNonEmpty(
-                    pThisCol->maCells.begin(), pThisCol->maCells, nRow1, nRow2, aFunc, aFunc);
+                    pThisCol->maCells.begin(), pThisCol->maCells, nRow1, nRow2, aFunc);
 
                 if (nX+1 >= nCol1)                                // Attribute/Blockmarken ab nX1-1
                 {


More information about the Libreoffice-commits mailing list