summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2019-03-15 19:43:00 +0100
committerEike Rathke <erack@redhat.com>2019-03-16 02:41:54 +0100
commit564d0d145cf9c164ea9c717b4b2113fd971fa0af (patch)
tree4ce72f219b3178b565134d4cc0ca2f0b6973b1ea /sc
parentafcf3c7fdef0c9b167b1346873bf1936050a4605 (diff)
Related: tdf#123736 re-establish listeners also for vector unsharing
... via DetachFormulaCells() Change-Id: Ia57308495a06e0df612eb1610b5f387d6b60ce08 Reviewed-on: https://gerrit.libreoffice.org/69320 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/column.hxx10
-rw-r--r--sc/inc/sharedformula.hxx3
-rw-r--r--sc/source/core/data/column3.cxx111
-rw-r--r--sc/source/core/data/column4.cxx11
-rw-r--r--sc/source/core/data/table2.cxx2
-rw-r--r--sc/source/core/tool/sharedformula.cxx16
6 files changed, 136 insertions, 17 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 8664c81c0c20..da635280c71d 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -647,10 +647,12 @@ public:
/** Re-establish listeners on unshared formula groups */
void StartListeningUnshared( const std::vector<SCROW>& rNewSharedRows );
- void DetachFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength );
+ void DetachFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength,
+ std::vector<SCROW>* pNewSharedRows );
void AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
- void DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
+ void DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2,
+ std::vector<SCROW>* pNewSharedRows );
/**
* Regroup formula cells for the entire column.
@@ -714,7 +716,9 @@ private:
const std::vector<SCROW>& rNewSharedRows,
bool bJoin = true, sc::StartListeningType eListenType = sc::SingleCellListening );
- void AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength );
+ void AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength,
+ const std::vector<SCROW>& rNewSharedRows );
+
void BroadcastNewCell( SCROW nRow );
bool UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow, sc::CellStoreType::iterator& itr );
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index 97e7fc053a9f..b7c9577b2dfa 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -57,6 +57,9 @@ public:
}
}
+ /** Get shared formula top cell from position, if any, else nullptr. */
+ static const ScFormulaCell* getSharedTopFormulaCell(const CellStoreType::position_type& aPos);
+
/**
* Split existing shared formula range at specified position. The cell at
* specified position becomes the top cell of the lower shared formula
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 1d69e3515e1a..8af8464a7a1a 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -387,14 +387,59 @@ public:
}
void ScColumn::DetachFormulaCells(
- const sc::CellStoreType::position_type& aPos, size_t nLength )
+ const sc::CellStoreType::position_type& aPos, size_t nLength, std::vector<SCROW>* pNewSharedRows )
{
+ const size_t nRow = aPos.first->position + aPos.second;
+ const size_t nNextTopRow = nRow + nLength; // start row of next formula group.
+
+ bool bLowerSplitOff = false;
+ if (pNewSharedRows && !GetDoc()->IsClipOrUndo())
+ {
+ const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos);
+ if (pFC)
+ {
+ const SCROW nTopRow = pFC->GetSharedTopRow();
+ const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
+ // nTopRow <= nRow <= nBotRow, because otherwise pFC would not exist.
+ if (nTopRow < static_cast<SCROW>(nRow))
+ {
+ // Upper part will be split off.
+ pNewSharedRows->push_back(nTopRow);
+ pNewSharedRows->push_back(nRow - 1);
+ }
+ if (static_cast<SCROW>(nNextTopRow) <= nBotRow)
+ {
+ // Lower part will be split off.
+ pNewSharedRows->push_back(nNextTopRow);
+ pNewSharedRows->push_back(nBotRow);
+ bLowerSplitOff = true;
+ }
+ }
+ }
+
// Split formula grouping at the top and bottom boundaries.
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr);
- size_t nRow = aPos.first->position + aPos.second;
- size_t nNextTopRow = nRow + nLength; // start row of next formula group.
- if (ValidRow(nNextTopRow))
+
+ if (nLength > 0 && ValidRow(nNextTopRow))
{
+ if (pNewSharedRows && !bLowerSplitOff && !GetDoc()->IsClipOrUndo())
+ {
+ sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow-1);
+ const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos2);
+ if (pFC)
+ {
+ const SCROW nTopRow = pFC->GetSharedTopRow();
+ const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
+ // nRow < nTopRow < nNextTopRow <= nBotRow
+ if (static_cast<SCROW>(nNextTopRow) <= nBotRow)
+ {
+ // Lower part will be split off.
+ pNewSharedRows->push_back(nNextTopRow);
+ pNewSharedRows->push_back(nBotRow);
+ }
+ }
+ }
+
sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos2, nullptr);
}
@@ -425,15 +470,59 @@ void ScColumn::AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1,
sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc);
}
-void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2 )
+void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2,
+ std::vector<SCROW>* pNewSharedRows )
{
sc::CellStoreType::position_type aPos = maCells.position(nRow1);
sc::CellStoreType::iterator it = aPos.first;
+ bool bLowerSplitOff = false;
+ if (pNewSharedRows && !GetDoc()->IsClipOrUndo())
+ {
+ const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos);
+ if (pFC)
+ {
+ const SCROW nTopRow = pFC->GetSharedTopRow();
+ const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
+ // nTopRow <= nRow1 <= nBotRow, because otherwise pFC would not exist.
+ if (nTopRow < nRow1)
+ {
+ // Upper part will be split off.
+ pNewSharedRows->push_back(nTopRow);
+ pNewSharedRows->push_back(nRow1 - 1);
+ }
+ if (nRow2 < nBotRow)
+ {
+ // Lower part will be split off.
+ pNewSharedRows->push_back(nRow2 + 1);
+ pNewSharedRows->push_back(nBotRow);
+ bLowerSplitOff = true;
+ }
+ }
+ }
+
// Split formula grouping at the top and bottom boundaries.
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt);
if (ValidRow(nRow2+1))
{
+ if (pNewSharedRows && !bLowerSplitOff && !GetDoc()->IsClipOrUndo())
+ {
+ sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nRow2);
+ const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos2);
+ if (pFC)
+ {
+ const SCROW nTopRow = pFC->GetSharedTopRow();
+ const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
+ // nRow1 < nTopRow <= nRow2 < nBotRow
+ if (nRow2 < nBotRow)
+ {
+ // Lower part will be split off.
+ pNewSharedRows->push_back(nRow2 + 1);
+ pNewSharedRows->push_back(nBotRow);
+ }
+ }
+ }
+
aPos = maCells.position(it, nRow2+1);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt);
}
@@ -535,7 +624,8 @@ void ScColumn::AttachNewFormulaCell(
rCell.SetDirty();
}
-void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength )
+void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength,
+ const std::vector<SCROW>& rNewSharedRows )
{
// Make sure the whole length consists of formula cells.
if (aPos.first->type != sc::element_type_formula)
@@ -557,6 +647,8 @@ void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aP
ScDocument* pDocument = GetDoc();
if (!pDocument->IsClipOrUndo() && !pDocument->IsInsertingFromOtherDoc())
{
+ StartListeningUnshared( rNewSharedRows);
+
sc::StartListeningContext aCxt(*pDocument);
ScFormulaCell** pp = &sc::formula_block::at(*aPos.first->data, aPos.second);
ScFormulaCell** ppEnd = pp + nLength;
@@ -1601,7 +1693,7 @@ public:
// Stop all formula cells in the destination range first.
sc::CellStoreType::position_type aPos = rDestCells.position(mrBlockPos.miCellPos, mnRowOffset);
- mrDestColumn.DetachFormulaCells(aPos, maNewCells.size());
+ mrDestColumn.DetachFormulaCells(aPos, maNewCells.size(), nullptr);
// Move the new cells to the destination range.
sc::CellStoreType::iterator& itDestPos = mrBlockPos.miCellPos;
@@ -2104,7 +2196,8 @@ bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells
sc::CellStoreType::position_type aPos = maCells.position(nRow);
// Detach all formula cells that will be overwritten.
- DetachFormulaCells(aPos, rCells.size());
+ std::vector<SCROW> aNewSharedRows;
+ DetachFormulaCells(aPos, rCells.size(), &aNewSharedRows);
if (!GetDoc()->IsClipOrUndo())
{
@@ -2124,7 +2217,7 @@ bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells
CellStorageModified();
- AttachNewFormulaCells(aPos, rCells.size());
+ AttachNewFormulaCells(aPos, rCells.size(), aNewSharedRows);
return true;
}
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 11a06090ad9c..bdefbe8e2b3e 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -317,7 +317,8 @@ void ScColumn::SetValues( const SCROW nRow, const std::vector<double>& rVals )
return;
sc::CellStoreType::position_type aPos = maCells.position(nRow);
- DetachFormulaCells(aPos, rVals.size());
+ std::vector<SCROW> aNewSharedRows;
+ DetachFormulaCells(aPos, rVals.size(), &aNewSharedRows);
maCells.set(nRow, rVals.begin(), rVals.end());
std::vector<sc::CellTextAttr> aDefaults(rVals.size());
@@ -325,6 +326,8 @@ void ScColumn::SetValues( const SCROW nRow, const std::vector<double>& rVals )
CellStorageModified();
+ StartListeningUnshared( aNewSharedRows);
+
std::vector<SCROW> aRows;
aRows.reserve(rVals.size());
for (SCROW i = nRow; i <= nLastRow; ++i)
@@ -344,7 +347,7 @@ void ScColumn::TransferCellValuesTo( SCROW nRow, size_t nLen, sc::CellValues& rD
return;
sc::CellStoreType::position_type aPos = maCells.position(nRow);
- DetachFormulaCells(aPos, nLen);
+ DetachFormulaCells(aPos, nLen, nullptr);
rDest.transferFrom(*this, nRow, nLen);
@@ -369,7 +372,7 @@ void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc )
return;
sc::CellStoreType::position_type aPos = maCells.position(nRow);
- DetachFormulaCells(aPos, rSrc.size());
+ DetachFormulaCells(aPos, rSrc.size(), nullptr);
rSrc.copyTo(*this, nRow);
@@ -445,7 +448,7 @@ void ScColumn::ConvertFormulaToValue(
// No formula cells encountered.
return;
- DetachFormulaCells(rCxt, nRow1, nRow2);
+ DetachFormulaCells(rCxt, nRow1, nRow2, nullptr);
// Undo storage to hold static values which will get swapped to the cell storage later.
sc::CellValues aUndoCells;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 65d87fb28162..bc2293f3bd9c 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1085,7 +1085,7 @@ 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);
+ aCol[nCol].DetachFormulaCells(rCxt, nRow1, nRow2, nullptr);
}
void ScTable::SetDirtyFromClip(
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index bcfa04594df8..ea815b115aeb 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -17,6 +17,22 @@
namespace sc {
+const ScFormulaCell* SharedFormulaUtil::getSharedTopFormulaCell(const CellStoreType::position_type& aPos)
+{
+ if (aPos.first->type != sc::element_type_formula)
+ // Not a formula cell block.
+ return nullptr;
+
+ sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
+ std::advance(it, aPos.second);
+ const ScFormulaCell* pCell = *it;
+ if (!pCell->IsShared())
+ // Not a shared formula.
+ return nullptr;
+
+ return pCell->GetCellGroup()->mpTopCell;
+}
+
bool SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type& aPos, sc::EndListeningContext* pCxt)
{
SCROW nRow = aPos.first->position + aPos.second;