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

Kohei Yoshida kohei.yoshida at gmail.com
Fri May 17 18:31:09 PDT 2013


 sc/inc/column.hxx                      |    6 +++
 sc/source/core/data/column2.cxx        |   26 ++++++++++++++++
 sc/source/core/data/column3.cxx        |   52 +++++++++++++++++++++++++++------
 sc/source/core/data/documentimport.cxx |    9 -----
 4 files changed, 77 insertions(+), 16 deletions(-)

New commits:
commit fb7279c92834ef57b243c0242cb2b1f6dc7d914d
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri May 17 21:23:22 2013 -0400

    Optimize ScColumn::MixData() to remove several bottlenecks.
    
    The use case that would previously make Calc freeze.
    
    1) type in "test" in A1.
    2) Select A1:A2 and Ctrl-C to copy to the clipboard.
    3) select the whole column B.
    4) paste special, select "Add" operation and click OK to paste.
    
    With this change, the above scenario no longer freezes Calc.
    
    Change-Id: I98b1f1e6c25b853aa884e7598c04b1457fab4636

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index c71ffea..46ffbd9 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -497,6 +497,12 @@ private:
     void SetCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScBaseCell* pNewCell );
     void SetCell( SCROW nRow, ScBaseCell* pNewCell );
     void PostSetCell( SCROW nRow, ScBaseCell* pNewCell );
+
+    /**
+     * Clear and re-populate the cell text attribute array from the non-empty
+     * cells stored in the cell array.
+     */
+    void ResetCellTextAttrs();
 };
 
 
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 05430f3..196eba1 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1569,6 +1569,32 @@ void ScColumn::PostSetCell( SCROW nRow, ScBaseCell* pNewCell )
     }
 }
 
+namespace {
+
+class SetEmptyAttr : std::unary_function<ColEntry, void>
+{
+    sc::CellTextAttrStoreType& mrAttrStore;
+    sc::CellTextAttrStoreType::iterator miPos;
+public:
+    SetEmptyAttr(sc::CellTextAttrStoreType& rAttrStore) :
+        mrAttrStore(rAttrStore), miPos(rAttrStore.begin()) {}
+
+    void operator() (const ColEntry& rEntry)
+    {
+        miPos = mrAttrStore.set(miPos, rEntry.nRow, sc::CellTextAttr());
+    }
+};
+
+}
+
+void ScColumn::ResetCellTextAttrs()
+{
+    maCellTextAttrs.clear();
+    maCellTextAttrs.resize(MAXROWCOUNT);
+
+    std::for_each(maItems.begin(), maItems.end(), SetEmptyAttr(maCellTextAttrs));
+}
+
 SvtBroadcaster* ScColumn::GetBroadcaster(SCROW nRow)
 {
     return maBroadcasters.get<SvtBroadcaster*>(nRow);
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index b530184..9339e8b 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -842,11 +842,12 @@ void ScColumn::MixMarked(
     }
 }
 
+namespace {
 
 // Result in rVal1
-static sal_Bool lcl_DoFunction( double& rVal1, double nVal2, sal_uInt16 nFunction )
+bool lcl_DoFunction( double& rVal1, double nVal2, sal_uInt16 nFunction )
 {
-    sal_Bool bOk = false;
+    bool bOk = false;
     switch (nFunction)
     {
         case PASTE_ADD:
@@ -866,8 +867,7 @@ static sal_Bool lcl_DoFunction( double& rVal1, double nVal2, sal_uInt16 nFunctio
     return bOk;
 }
 
-
-static void lcl_AddCode( ScTokenArray& rArr, ScFormulaCell* pCell )
+void lcl_AddCode( ScTokenArray& rArr, ScFormulaCell* pCell )
 {
     rArr.AddOpCode(ocOpen);
 
@@ -885,6 +885,15 @@ static void lcl_AddCode( ScTokenArray& rArr, ScFormulaCell* pCell )
     rArr.AddOpCode(ocClose);
 }
 
+struct FindRemovedCell : std::unary_function<ColEntry, bool>
+{
+    bool operator() (const ColEntry& rEntry) const
+    {
+        return rEntry.pCell == NULL;
+    }
+};
+
+}
 
 void ScColumn::MixData(
     sc::MixDocContext& rCxt, SCROW nRow1, SCROW nRow2, sal_uInt16 nFunction,
@@ -892,11 +901,13 @@ void ScColumn::MixData(
 {
     SCSIZE nSrcCount = rSrcCol.maItems.size();
 
+    sc::ColumnBlockPosition* p = rCxt.getBlockPosition(nTab, nCol);
+
     SCSIZE nIndex;
     Search( nRow1, nIndex );
 
 //  SCSIZE nSrcIndex = 0;
-    SCSIZE nSrcIndex;
+    SCSIZE nSrcIndex, nDestIndex;
     rSrcCol.Search( nRow1, nSrcIndex ); // See if data is at the beginning
 
     SCROW nNextThis = MAXROW+1;
@@ -906,6 +917,7 @@ void ScColumn::MixData(
     if ( nSrcIndex < nSrcCount )
         nNextSrc = rSrcCol.maItems[nSrcIndex].nRow;
 
+    bool bDeferredDelete = false;
     while ( nNextThis <= nRow2 || nNextSrc <= nRow2 )
     {
         SCROW nRow = std::min( nNextThis, nNextSrc );
@@ -913,13 +925,16 @@ void ScColumn::MixData(
         ScBaseCell* pSrc = NULL;
         ScBaseCell* pDest = NULL;
         ScBaseCell* pNew = NULL;
-        sal_Bool bDelete = false;
+        bool bDelete = false;
 
         if ( nSrcIndex < nSrcCount && nNextSrc == nRow )
             pSrc = rSrcCol.maItems[nSrcIndex].pCell;
 
         if ( nIndex < maItems.size() && nNextThis == nRow )
+        {
             pDest = maItems[nIndex].pCell;
+            nDestIndex = nIndex;
+        }
 
         OSL_ENSURE( pSrc || pDest, "What happened?" );
 
@@ -1024,10 +1039,18 @@ void ScColumn::MixData(
 
         if ( pNew || bDelete ) // New result?
         {
-            sc::ColumnBlockPosition* p = rCxt.getBlockPosition(nTab, nCol);
             if (pDest && !pNew) // Old cell present?
             {
-                Delete(nRow); // -> Delete
+                // Delete the destination cell because the cell was originally
+                // empty.  Don't erase its slot in the cell array yet.
+                OSL_ASSERT(pDest == maItems[nDestIndex].pCell);
+                maItems[nDestIndex].pCell = NULL;
+
+                if (pDest->GetCellType() == CELLTYPE_FORMULA)
+                    static_cast<ScFormulaCell*>(pDest)->EndListeningTo(pDocument);
+                pDest->Delete();
+
+                bDeferredDelete = true;
             }
             if (pNew)
             {
@@ -1057,6 +1080,19 @@ void ScColumn::MixData(
                             MAXROW+1;
         }
     }
+
+    if (bDeferredDelete)
+    {
+        // Erase all the slots in the cell array where the deleted cells
+        // previously occupied.
+        std::vector<ColEntry>::iterator it =
+            std::remove_if(maItems.begin(), maItems.end(), FindRemovedCell());
+
+        maItems.erase(it, maItems.end());
+
+        // Reset the cell text attriute array to keep it in sync again.
+        ResetCellTextAttrs();
+    }
 }
 
 
diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx
index ced0936..ec5b1c4 100644
--- a/sc/source/core/data/documentimport.cxx
+++ b/sc/source/core/data/documentimport.cxx
@@ -118,14 +118,7 @@ void ScDocumentImport::finalize()
         for (; pCol != pColEnd; ++pCol)
         {
             ScColumn& rCol = *pCol;
-            if (rCol.maItems.empty())
-                // Column has no cells. Skip it.
-                continue;
-
-            sc::CellTextAttrStoreType::iterator itCTAPos = rCol.maCellTextAttrs.begin();
-            std::vector<ColEntry>::iterator itCell = rCol.maItems.begin(), itCellEnd = rCol.maItems.end();
-            for (; itCell != itCellEnd; ++itCell)
-                itCTAPos = rCol.maCellTextAttrs.set<sc::CellTextAttr>(itCTAPos, itCell->nRow, sc::CellTextAttr());
+            rCol.ResetCellTextAttrs();
         }
     }
 }


More information about the Libreoffice-commits mailing list