[Libreoffice-commits] core.git: Branch 'private/kohei/calc-sort-fix' - 4 commits - sc/inc sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Apr 18 13:39:38 PDT 2014


 sc/inc/cellvalues.hxx              |    1 
 sc/inc/column.hxx                  |    5 +
 sc/inc/table.hxx                   |    3 
 sc/source/core/data/cellvalues.cxx |   54 ----------------
 sc/source/core/data/column2.cxx    |   11 +++
 sc/source/core/data/column3.cxx    |   65 ++++++++++++++++++-
 sc/source/core/data/table2.cxx     |   13 +++
 sc/source/core/data/table3.cxx     |  122 ++++++++++++++++++++++++++++++++-----
 8 files changed, 201 insertions(+), 73 deletions(-)

New commits:
commit f64f40d7e932d43afd03d30dfef4633fc4664c53
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Apr 18 16:39:35 2014 -0400

    Use correct index to access row arrays, to prevent out-of-range access.
    
    Change-Id: Ia74c0f07c7f1021de92f77fdb93b2279a3b8462c

diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 5bdc653..fb44fe0 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -292,7 +292,7 @@ public:
         {
             // Swap rows in data table.
             RowsType& rRows = *mpRows;
-            std::swap(rRows[nInd1], rRows[nInd2]);
+            std::swap(rRows[n1], rRows[n2]);
         }
     }
 
@@ -341,16 +341,16 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
 
         // Filll row-wise data table.
         ScSortInfoArray::RowsType& rRows = pArray->InitDataRows(
-            aSortParam.nRow2 - aSortParam.nRow1 + 1, aSortParam.nCol2 - aSortParam.nCol1 + 1);
+            nInd2 - nInd1 + 1, aSortParam.nCol2 - aSortParam.nCol1 + 1);
 
         for (SCCOL nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; ++nCol)
         {
             ScColumn& rCol = aCol[nCol];
             sc::ColumnBlockConstPosition aBlockPos;
             rCol.InitBlockPosition(aBlockPos);
-            for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; ++nRow)
+            for (SCROW nRow = nInd1; nRow <= nInd2; ++nRow)
             {
-                ScSortInfoArray::RowType& rRow = *rRows[nRow-aSortParam.nRow1];
+                ScSortInfoArray::RowType& rRow = *rRows[nRow-nInd1];
                 ScSortInfoArray::Cell& rCell = rRow[nCol-aSortParam.nCol1];
 
                 rCell.maCell = rCol.GetCellValue(aBlockPos, nRow);
@@ -431,12 +431,13 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
 
     if (aSortParam.bByRow)
     {
+        SCROW nRow1 = aSortParam.nRow1 + (aSortParam.bHasHeader ? 1 : 0);
         ScSortInfoArray::RowsType* pRows = pArray->GetDataRows();
         assert(pRows); // In sort-by-row mode we must have data rows already populated.
 
         // Detach all formula cells within the sorted range first.
         sc::EndListeningContext aCxt(*pDocument);
-        DetachFormulaCells(aCxt, aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2);
+        DetachFormulaCells(aCxt, aSortParam.nCol1, nRow1, aSortParam.nCol2, aSortParam.nRow2);
 
         // Cells in the data rows only reference values in the document. Make
         // a copy before updating the document.
@@ -450,11 +451,11 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
         for (size_t i = 0; i < pRows->size(); ++i)
         {
             ScSortInfoArray::RowType* pRow = (*pRows)[i];
-            for (size_t nCol = 0; nCol < pRow->size(); ++nCol)
+            for (size_t j = 0; j < pRow->size(); ++j)
             {
-                ScSortInfoArray::Cell& rCell = (*pRow)[nCol];
+                ScSortInfoArray::Cell& rCell = (*pRow)[j];
 
-                sc::CellStoreType& rCellStore = aSortedCols.at(nCol).maCells;
+                sc::CellStoreType& rCellStore = aSortedCols.at(j).maCells;
                 size_t n = rCellStore.size();
                 rCellStore.resize(n+1);
                 switch (rCell.maCell.meType)
@@ -474,7 +475,7 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
                     case CELLTYPE_FORMULA:
                     {
                         assert(rCell.mpAttr);
-                        ScAddress aCellPos(aSortParam.nCol1 + nCol, aSortParam.nRow1 + i, nTab);
+                        ScAddress aCellPos(aSortParam.nCol1 + j, nRow1 + i, nTab);
                         sc::CellStoreType::iterator itBlk = rCellStore.set(n, rCell.maCell.mpFormula->Clone(aCellPos));
 
                         size_t nOffset = n - itBlk->position;
@@ -486,7 +487,7 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
                         assert(!rCell.mpAttr);
                 }
 
-                sc::CellTextAttrStoreType& rAttrStore = aSortedCols.at(nCol).maCellTextAttrs;
+                sc::CellTextAttrStoreType& rAttrStore = aSortedCols.at(j).maCellTextAttrs;
                 rAttrStore.resize(n+1);
                 if (rCell.mpAttr)
                     rAttrStore.set(n, *rCell.mpAttr);
@@ -494,7 +495,7 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
                 // At this point each broadcaster instance is managed by 2
                 // containers. We will release those in the original storage
                 // below before transferring them to the document.
-                sc::BroadcasterStoreType& rBCStore = aSortedCols.at(nCol).maBroadcasters;
+                sc::BroadcasterStoreType& rBCStore = aSortedCols.at(j).maBroadcasters;
                 rBCStore.resize(n+1);
                 if (rCell.mpBroadcaster)
                     // A const pointer would be implicitly converted to a bool type.
@@ -512,13 +513,13 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
             {
                 sc::CellStoreType& rDest = aCol[nThisCol].maCells;
                 sc::CellStoreType& rSrc = aSortedCols[i].maCells;
-                rSrc.transfer(0, rSrc.size()-1, rDest, aSortParam.nRow1);
+                rSrc.transfer(0, rSrc.size()-1, rDest, nRow1);
             }
 
             {
                 sc::CellTextAttrStoreType& rDest = aCol[nThisCol].maCellTextAttrs;
                 sc::CellTextAttrStoreType& rSrc = aSortedCols[i].maCellTextAttrs;
-                rSrc.transfer(0, rSrc.size()-1, rDest, aSortParam.nRow1);
+                rSrc.transfer(0, rSrc.size()-1, rDest, nRow1);
             }
 
             {
@@ -526,12 +527,12 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
 
                 // Release current broadcasters first, to prevent them from getting deleted.
                 SvtBroadcaster* pBC = NULL;
-                for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; ++nRow)
+                for (SCROW nRow = nRow1; nRow <= aSortParam.nRow2; ++nRow)
                     rBCDest.release(nRow, pBC);
 
                 // Transfer sorted broadcaster segment to the document.
                 sc::BroadcasterStoreType& rBCSrc = aSortedCols[i].maBroadcasters;
-                rBCSrc.transfer(0, rBCSrc.size()-1, rBCDest, aSortParam.nRow1);
+                rBCSrc.transfer(0, rBCSrc.size()-1, rBCDest, nRow1);
             }
 
             aCol[nThisCol].CellStorageModified();
@@ -540,7 +541,7 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
         // Attach all formula cells within sorted range, to have them start listening again.
         sc::StartListeningContext aStartListenCxt(*pDocument);
         AttachFormulaCells(
-            aStartListenCxt, aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2);
+            aStartListenCxt, aSortParam.nCol1, nRow1, aSortParam.nCol2, aSortParam.nRow2);
     }
     else
     {
commit 93d47b3308cfdc6a0283f2898ae5dca0e454d92e
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Apr 18 15:40:24 2014 -0400

    Use the mdds storage types directly rather than using CellValues.
    
    Change-Id: I415b3cddc4b764668564affd573ae9cc00601278

diff --git a/sc/inc/cellvalues.hxx b/sc/inc/cellvalues.hxx
index c2bf1d3..3f36e01 100644
--- a/sc/inc/cellvalues.hxx
+++ b/sc/inc/cellvalues.hxx
@@ -49,7 +49,6 @@ public:
     void copyTo( ScColumn& rCol, SCROW nRow ) const;
 
     void assign( const std::vector<double>& rVals );
-    void append( ScRefCellValue& rVal, const CellTextAttr* pAttr, const ScAddress& rPos );
 
     size_t size() const;
 
diff --git a/sc/source/core/data/cellvalues.cxx b/sc/source/core/data/cellvalues.cxx
index 0740ab5..083b4d1 100644
--- a/sc/source/core/data/cellvalues.cxx
+++ b/sc/source/core/data/cellvalues.cxx
@@ -10,7 +10,6 @@
 #include <cellvalues.hxx>
 #include <column.hxx>
 #include <cellvalue.hxx>
-#include <sharedformula.hxx>
 
 #include <cassert>
 #include <boost/noncopyable.hpp>
@@ -65,59 +64,6 @@ void CellValues::assign( const std::vector<double>& rVals )
     mpImpl->maCellTextAttrs.set(0, aDefaults.begin(), aDefaults.end());
 }
 
-void CellValues::append( ScRefCellValue& rVal, const CellTextAttr* pAttr, const ScAddress& rPos )
-{
-    assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
-
-    size_t n = mpImpl->maCells.size();
-
-    bool bAppendAttr = true;
-
-    switch (rVal.meType)
-    {
-        case CELLTYPE_STRING:
-        {
-            mpImpl->maCells.resize(n+1);
-            mpImpl->maCells.set(n, *rVal.mpString);
-        }
-        break;
-        case CELLTYPE_VALUE:
-        {
-            mpImpl->maCells.resize(n+1);
-            mpImpl->maCells.set(n, rVal.mfValue);
-        }
-        break;
-        case CELLTYPE_EDIT:
-        {
-            mpImpl->maCells.resize(n+1);
-            mpImpl->maCells.set(n, rVal.mpEditText->Clone());
-        }
-        break;
-        case CELLTYPE_FORMULA:
-        {
-            mpImpl->maCells.resize(n+1);
-            CellStoreType::iterator itBlk = mpImpl->maCells.set(n, rVal.mpFormula->Clone(rPos));
-
-            size_t nOffset = n - itBlk->position;
-            CellStoreType::position_type aPos(itBlk, nOffset);
-            SharedFormulaUtil::joinFormulaCellAbove(aPos);
-        }
-        break;
-        default:
-            bAppendAttr = false;
-    }
-
-    if (bAppendAttr)
-    {
-        mpImpl->maCellTextAttrs.resize(n+1);
-
-        if (pAttr)
-            mpImpl->maCellTextAttrs.set(n, *pAttr);
-        else
-            mpImpl->maCellTextAttrs.set(n, CellTextAttr());
-    }
-}
-
 size_t CellValues::size() const
 {
     assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 2bef7ba..2698f0b 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -300,7 +300,7 @@ void ScColumn::TransferCellValuesFrom( SCROW nRow, sc::CellValues& rSrc )
         return;
 
     sc::CellStoreType::position_type aPos = maCells.position(nRow);
-//  DetachFormulaCells(aPos, rSrc.size());
+    DetachFormulaCells(aPos, rSrc.size());
 
     rSrc.transferTo(*this, nRow);
 
@@ -311,7 +311,7 @@ void ScColumn::TransferCellValuesFrom( SCROW nRow, sc::CellValues& rSrc )
     for (SCROW i = nRow; i <= nLastRow; ++i)
         aRows.push_back(i);
 
-//  BroadcastCells(aRows, SC_HINT_DATACHANGED);
+    BroadcastCells(aRows, SC_HINT_DATACHANGED);
 }
 
 void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc )
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index b8db3c6..5bdc653 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -57,8 +57,8 @@
 #include "mtvcellfunc.hxx"
 #include "columnspanset.hxx"
 #include <stlalgorithm.hxx>
-#include <cellvalues.hxx>
 #include <listenercontext.hxx>
+#include <sharedformula.hxx>
 
 #include "svl/sharedstringpool.hxx"
 
@@ -380,7 +380,8 @@ namespace {
 
 struct SortedColumn : boost::noncopyable
 {
-    sc::CellValues maCells; /// Stores cells and cell text attributes.
+    sc::CellStoreType maCells;
+    sc::CellTextAttrStoreType maCellTextAttrs;
     sc::BroadcasterStoreType maBroadcasters;
 };
 
@@ -453,15 +454,47 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
             {
                 ScSortInfoArray::Cell& rCell = (*pRow)[nCol];
 
-                sc::CellValues& rStore = aSortedCols.at(nCol).maCells;
-                ScAddress aCellPos(aSortParam.nCol1 + nCol, aSortParam.nRow1 + i, nTab);
-                rStore.append(rCell.maCell, rCell.mpAttr, aCellPos);
+                sc::CellStoreType& rCellStore = aSortedCols.at(nCol).maCells;
+                size_t n = rCellStore.size();
+                rCellStore.resize(n+1);
+                switch (rCell.maCell.meType)
+                {
+                    case CELLTYPE_STRING:
+                        assert(rCell.mpAttr);
+                        rCellStore.set(n, *rCell.maCell.mpString);
+                    break;
+                    case CELLTYPE_VALUE:
+                        assert(rCell.mpAttr);
+                        rCellStore.set(n, rCell.maCell.mfValue);
+                    break;
+                    case CELLTYPE_EDIT:
+                        assert(rCell.mpAttr);
+                        rCellStore.set(n, rCell.maCell.mpEditText->Clone());
+                    break;
+                    case CELLTYPE_FORMULA:
+                    {
+                        assert(rCell.mpAttr);
+                        ScAddress aCellPos(aSortParam.nCol1 + nCol, aSortParam.nRow1 + i, nTab);
+                        sc::CellStoreType::iterator itBlk = rCellStore.set(n, rCell.maCell.mpFormula->Clone(aCellPos));
+
+                        size_t nOffset = n - itBlk->position;
+                        sc::CellStoreType::position_type aPos(itBlk, nOffset);
+                        sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
+                    }
+                    break;
+                    default:
+                        assert(!rCell.mpAttr);
+                }
+
+                sc::CellTextAttrStoreType& rAttrStore = aSortedCols.at(nCol).maCellTextAttrs;
+                rAttrStore.resize(n+1);
+                if (rCell.mpAttr)
+                    rAttrStore.set(n, *rCell.mpAttr);
 
                 // At this point each broadcaster instance is managed by 2
                 // containers. We will release those in the original storage
                 // below before transferring them to the document.
                 sc::BroadcasterStoreType& rBCStore = aSortedCols.at(nCol).maBroadcasters;
-                size_t n = rBCStore.size();
                 rBCStore.resize(n+1);
                 if (rCell.mpBroadcaster)
                     // A const pointer would be implicitly converted to a bool type.
@@ -475,18 +508,33 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
         for (size_t i = 0, n = aSortedCols.size(); i < n; ++i)
         {
             SCCOL nThisCol = i + aSortParam.nCol1;
-            TransferCellValuesFrom(nThisCol, aSortParam.nRow1, aSortedCols[i].maCells);
 
-            sc::BroadcasterStoreType& rBCDest = aCol[nThisCol].maBroadcasters;
+            {
+                sc::CellStoreType& rDest = aCol[nThisCol].maCells;
+                sc::CellStoreType& rSrc = aSortedCols[i].maCells;
+                rSrc.transfer(0, rSrc.size()-1, rDest, aSortParam.nRow1);
+            }
 
-            // Release current broadcasters first, to prevent them from getting deleted.
-            SvtBroadcaster* pBC = NULL;
-            for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; ++nRow)
-                rBCDest.release(nRow, pBC);
+            {
+                sc::CellTextAttrStoreType& rDest = aCol[nThisCol].maCellTextAttrs;
+                sc::CellTextAttrStoreType& rSrc = aSortedCols[i].maCellTextAttrs;
+                rSrc.transfer(0, rSrc.size()-1, rDest, aSortParam.nRow1);
+            }
+
+            {
+                sc::BroadcasterStoreType& rBCDest = aCol[nThisCol].maBroadcasters;
+
+                // Release current broadcasters first, to prevent them from getting deleted.
+                SvtBroadcaster* pBC = NULL;
+                for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; ++nRow)
+                    rBCDest.release(nRow, pBC);
+
+                // Transfer sorted broadcaster segment to the document.
+                sc::BroadcasterStoreType& rBCSrc = aSortedCols[i].maBroadcasters;
+                rBCSrc.transfer(0, rBCSrc.size()-1, rBCDest, aSortParam.nRow1);
+            }
 
-            // Transfer sorted broadcaster segment to the document.
-            sc::BroadcasterStoreType& rBCSrc = aSortedCols[i].maBroadcasters;
-            rBCSrc.transfer(0, rBCSrc.size()-1, rBCDest, aSortParam.nRow1);
+            aCol[nThisCol].CellStorageModified();
         }
 
         // Attach all formula cells within sorted range, to have them start listening again.
commit 4f74be86d5724346992f8e16e87d85c1e25277a1
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Apr 18 15:19:29 2014 -0400

    Handle sorting of broadcasters correctly.
    
    Change-Id: Iab46c26606880f0fa7c7067d8514b8be3629fe0f

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 39cb015..62bb4c6 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -562,6 +562,9 @@ public:
 
     void DetachFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength );
 
+    void AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
+    void DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
+
     /**
      * Regroup formula cells for the entire column.
      */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 5ddcc5c..79b30f9 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -1041,6 +1041,9 @@ private:
     void EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener );
     void        StartAllListeners();
 
+    void AttachFormulaCells( sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+    void DetachFormulaCells( sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+
     void        SetLoadingMedium(bool bLoading);
 
     SCSIZE      FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2,
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 38a92c0..3008fec 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -340,15 +340,35 @@ void ScColumn::DetachFormulaCell(
 
 namespace {
 
+class AttachFormulaCellsHandler
+{
+    sc::StartListeningContext& mrCxt;
+
+public:
+    AttachFormulaCellsHandler( sc::StartListeningContext& rCxt ) :
+        mrCxt(rCxt) {}
+
+    void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
+    {
+        pCell->StartListeningTo(mrCxt);
+    }
+};
+
 class DetachFormulaCellsHandler
 {
     ScDocument* mpDoc;
+    sc::EndListeningContext* mpCxt;
+
 public:
-    DetachFormulaCellsHandler(ScDocument* pDoc) : mpDoc(pDoc) {}
+    DetachFormulaCellsHandler( ScDocument* pDoc, sc::EndListeningContext* pCxt ) :
+        mpDoc(pDoc), mpCxt(pCxt) {}
 
     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
     {
-        pCell->EndListeningTo(mpDoc);
+        if (mpCxt)
+            pCell->EndListeningTo(*mpCxt);
+        else
+            pCell->EndListeningTo(mpDoc);
     }
 };
 
@@ -370,10 +390,49 @@ void ScColumn::DetachFormulaCells(
     if (pDocument->IsClipOrUndo())
         return;
 
-    DetachFormulaCellsHandler aFunc(pDocument);
+    DetachFormulaCellsHandler aFunc(pDocument, NULL);
     sc::ProcessFormula(aPos.first, maCells, nRow, nNextTopRow-1, aFunc);
 }
 
+void ScColumn::AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 )
+{
+    sc::CellStoreType::position_type aPos = maCells.position(nRow1);
+    sc::CellStoreType::iterator it = aPos.first;
+
+    sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
+    if (ValidRow(nRow2+1))
+    {
+        aPos = maCells.position(it, nRow2+1);
+        sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
+    }
+
+    if (pDocument->IsClipOrUndo())
+        return;
+
+    AttachFormulaCellsHandler aFunc(rCxt);
+    sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc);
+}
+
+void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 )
+{
+    sc::CellStoreType::position_type aPos = maCells.position(nRow1);
+    sc::CellStoreType::iterator it = aPos.first;
+
+    // Split formula grouping at the top and bottom boundaries.
+    sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
+    if (ValidRow(nRow2+1))
+    {
+        aPos = maCells.position(it, nRow2+1);
+        sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
+    }
+
+    if (pDocument->IsClipOrUndo())
+        return;
+
+    DetachFormulaCellsHandler aFunc(pDocument, &rCxt);
+    sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc);
+}
+
 sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow )
 {
     // See if we are overwriting an existing formula cell.
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 2698f0b..2bef7ba 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -300,7 +300,7 @@ void ScColumn::TransferCellValuesFrom( SCROW nRow, sc::CellValues& rSrc )
         return;
 
     sc::CellStoreType::position_type aPos = maCells.position(nRow);
-    DetachFormulaCells(aPos, rSrc.size());
+//  DetachFormulaCells(aPos, rSrc.size());
 
     rSrc.transferTo(*this, nRow);
 
@@ -311,7 +311,7 @@ void ScColumn::TransferCellValuesFrom( SCROW nRow, sc::CellValues& rSrc )
     for (SCROW i = nRow; i <= nLastRow; ++i)
         aRows.push_back(i);
 
-    BroadcastCells(aRows, SC_HINT_DATACHANGED);
+//  BroadcastCells(aRows, SC_HINT_DATACHANGED);
 }
 
 void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc )
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index af2492e..8c1842c 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1031,6 +1031,19 @@ void ScTable::StartAllListeners()
         aCol[i].StartAllListeners();
 }
 
+void ScTable::AttachFormulaCells(
+    sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+{
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+        aCol[nCol].AttachFormulaCells(rCxt, nRow1, nRow2);
+}
+
+void ScTable::DetachFormulaCells(
+    sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+{
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+        aCol[nCol].DetachFormulaCells(rCxt, nRow1, nRow2);
+}
 
 void ScTable::StartNeededListeners()
 {
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 97c978f..b8db3c6 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -58,6 +58,7 @@
 #include "columnspanset.hxx"
 #include <stlalgorithm.hxx>
 #include <cellvalues.hxx>
+#include <listenercontext.hxx>
 
 #include "svl/sharedstringpool.hxx"
 
@@ -375,6 +376,15 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
     return pArray;
 }
 
+namespace {
+
+struct SortedColumn : boost::noncopyable
+{
+    sc::CellValues maCells; /// Stores cells and cell text attributes.
+    sc::BroadcasterStoreType maBroadcasters;
+};
+
+}
 
 bool ScTable::IsSortCollatorGlobal() const
 {
@@ -423,14 +433,18 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
         ScSortInfoArray::RowsType* pRows = pArray->GetDataRows();
         assert(pRows); // In sort-by-row mode we must have data rows already populated.
 
+        // Detach all formula cells within the sorted range first.
+        sc::EndListeningContext aCxt(*pDocument);
+        DetachFormulaCells(aCxt, aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2);
+
         // Cells in the data rows only reference values in the document. Make
         // a copy before updating the document.
 
         size_t nColCount = aSortParam.nCol2 - aSortParam.nCol1 + 1;
-        boost::ptr_vector<sc::CellValues> aSortedCols; // storage for copied cells.
+        boost::ptr_vector<SortedColumn> aSortedCols; // storage for copied cells.
         aSortedCols.reserve(nColCount);
         for (size_t i = 0; i < nColCount; ++i)
-            aSortedCols.push_back(new sc::CellValues);
+            aSortedCols.push_back(new SortedColumn);
 
         for (size_t i = 0; i < pRows->size(); ++i)
         {
@@ -438,9 +452,20 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
             for (size_t nCol = 0; nCol < pRow->size(); ++nCol)
             {
                 ScSortInfoArray::Cell& rCell = (*pRow)[nCol];
-                sc::CellValues& rStore = aSortedCols.at(nCol);
+
+                sc::CellValues& rStore = aSortedCols.at(nCol).maCells;
                 ScAddress aCellPos(aSortParam.nCol1 + nCol, aSortParam.nRow1 + i, nTab);
                 rStore.append(rCell.maCell, rCell.mpAttr, aCellPos);
+
+                // At this point each broadcaster instance is managed by 2
+                // containers. We will release those in the original storage
+                // below before transferring them to the document.
+                sc::BroadcasterStoreType& rBCStore = aSortedCols.at(nCol).maBroadcasters;
+                size_t n = rBCStore.size();
+                rBCStore.resize(n+1);
+                if (rCell.mpBroadcaster)
+                    // A const pointer would be implicitly converted to a bool type.
+                    rBCStore.set(n, const_cast<SvtBroadcaster*>(rCell.mpBroadcaster));
             }
 
             if (pProgress)
@@ -449,9 +474,25 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
 
         for (size_t i = 0, n = aSortedCols.size(); i < n; ++i)
         {
-            sc::CellValues& rSortedCol = aSortedCols[i];
-            TransferCellValuesFrom(i+aSortParam.nCol1, aSortParam.nRow1, rSortedCol);
+            SCCOL nThisCol = i + aSortParam.nCol1;
+            TransferCellValuesFrom(nThisCol, aSortParam.nRow1, aSortedCols[i].maCells);
+
+            sc::BroadcasterStoreType& rBCDest = aCol[nThisCol].maBroadcasters;
+
+            // Release current broadcasters first, to prevent them from getting deleted.
+            SvtBroadcaster* pBC = NULL;
+            for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; ++nRow)
+                rBCDest.release(nRow, pBC);
+
+            // Transfer sorted broadcaster segment to the document.
+            sc::BroadcasterStoreType& rBCSrc = aSortedCols[i].maBroadcasters;
+            rBCSrc.transfer(0, rBCSrc.size()-1, rBCDest, aSortParam.nRow1);
         }
+
+        // Attach all formula cells within sorted range, to have them start listening again.
+        sc::StartListeningContext aStartListenCxt(*pDocument);
+        AttachFormulaCells(
+            aStartListenCxt, aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2);
     }
     else
     {
commit 5ba7751debd320032c42d2b960f4d51100081bfb
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Apr 18 10:42:32 2014 -0400

    Retrieve and store broadcasters into data table.
    
    Change-Id: I107ccbbc61a5e8024f21a7a30fae9fea00c90bde

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 10970df..39cb015 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -514,6 +514,8 @@ public:
 
     SvtBroadcaster* GetBroadcaster( SCROW nRow );
     const SvtBroadcaster* GetBroadcaster( SCROW nRow ) const;
+    const SvtBroadcaster* GetBroadcaster( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const;
+
     void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 );
     void PrepareBroadcastersForDestruction();
     bool HasBroadcaster() const;
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 4e6de8d..ecdb50d 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1794,6 +1794,17 @@ const SvtBroadcaster* ScColumn::GetBroadcaster(SCROW nRow) const
     return maBroadcasters.get<SvtBroadcaster*>(nRow);
 }
 
+const SvtBroadcaster* ScColumn::GetBroadcaster( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const
+{
+    sc::BroadcasterStoreType::const_position_type aPos = maBroadcasters.position(rBlockPos.miBroadcasterPos, nRow);
+    rBlockPos.miBroadcasterPos = aPos.first;
+
+    if (aPos.first->type != sc::element_type_broadcaster)
+        return NULL;
+
+    return sc::broadcaster_block::at(*aPos.first->data, aPos.second);
+}
+
 void ScColumn::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 )
 {
     rBlockPos.miBroadcasterPos =
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index bb793dc..97c978f 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -226,8 +226,9 @@ public:
     {
         ScRefCellValue maCell;
         const sc::CellTextAttr* mpAttr;
+        const SvtBroadcaster* mpBroadcaster;
 
-        Cell() : mpAttr(NULL) {}
+        Cell() : mpAttr(NULL), mpBroadcaster(NULL) {}
     };
 
     typedef std::vector<Cell> RowType;
@@ -353,6 +354,7 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
 
                 rCell.maCell = rCol.GetCellValue(aBlockPos, nRow);
                 rCell.mpAttr = rCol.GetCellTextAttr(aBlockPos, nRow);
+                rCell.mpBroadcaster = rCol.GetBroadcaster(aBlockPos, nRow);
             }
         }
     }


More information about the Libreoffice-commits mailing list