summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/column.hxx3
-rw-r--r--sc/inc/table.hxx3
-rw-r--r--sc/source/core/data/column3.cxx65
-rw-r--r--sc/source/core/data/column4.cxx4
-rw-r--r--sc/source/core/data/table2.cxx13
-rw-r--r--sc/source/core/data/table3.cxx51
6 files changed, 129 insertions, 10 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index ecbfeea6d09f..d26214bfa9fd 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 ab3526d4e375..413152eadd1c 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 38a92c031979..3008fec88a30 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 2698f0b5f647..2bef7ba9f8cc 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 af2492ea4e11..8c1842c135fa 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 97c978ff149e..b8db3c614404 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
{