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.yosh...@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.yosh...@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.yosh...@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.yosh...@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); } } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits