Kaydet (Commit) 84926c11 authored tarafından Eike Rathke's avatar Eike Rathke Kaydeden (comit) Andras Timar

Resolves: tdf#94249 do not remove broadcasters while iterators are in use

EndListeningContext holds BroadcasterStoreType iterators in its
ColumnBlockPositionSet and collects broadcasters to purge them at the
end. Removing broadcasters from ScColumn::maBroadcasters in between
invalidates the iterators. Hence calling the "normal" EndListening()
that removes a broadcaster when all listeners are gone while an
EndListeningContext is in use is bad.

Change-Id: Ibdd88469e91e6173ceff1f391c23ef7cb7c6f596
(cherry picked from commit e4a8ae0b)
Reviewed-on: https://gerrit.libreoffice.org/18615Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarCaolán McNamara <caolanm@redhat.com>
Tested-by: 's avatarCaolán McNamara <caolanm@redhat.com>
üst 2314f95e
...@@ -64,8 +64,9 @@ public: ...@@ -64,8 +64,9 @@ public:
* specified position is not a formula cell. * specified position is not a formula cell.
* *
* @param aPos position of cell to examine. * @param aPos position of cell to examine.
* @param pCxt context to be used, if any, may be nullptr.
*/ */
static void splitFormulaCellGroup(const CellStoreType::position_type& aPos); static void splitFormulaCellGroup(const CellStoreType::position_type& aPos, sc::EndListeningContext* pCxt);
/** /**
* Split existing shared formula ranges at specified row positions. * Split existing shared formula ranges at specified row positions.
......
...@@ -1908,15 +1908,15 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol) ...@@ -1908,15 +1908,15 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
// Split the formula grouping at the top and bottom boundaries. // Split the formula grouping at the top and bottom boundaries.
sc::CellStoreType::position_type aPos = maCells.position(nStartRow); sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr);
aPos = maCells.position(aPos.first, nEndRow+1); aPos = maCells.position(aPos.first, nEndRow+1);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr);
// Do the same with the destination column. // Do the same with the destination column.
aPos = rCol.maCells.position(nStartRow); aPos = rCol.maCells.position(nStartRow);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr);
aPos = rCol.maCells.position(aPos.first, nEndRow+1); aPos = rCol.maCells.position(aPos.first, nEndRow+1);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr);
// Move the broadcasters to the destination column. // Move the broadcasters to the destination column.
maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow); maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
......
...@@ -327,13 +327,13 @@ void ScColumn::DetachFormulaCells( ...@@ -327,13 +327,13 @@ void ScColumn::DetachFormulaCells(
const sc::CellStoreType::position_type& aPos, size_t nLength ) const sc::CellStoreType::position_type& aPos, size_t nLength )
{ {
// Split formula grouping at the top and bottom boundaries. // Split formula grouping at the top and bottom boundaries.
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr);
size_t nRow = aPos.first->position + aPos.second; size_t nRow = aPos.first->position + aPos.second;
size_t nNextTopRow = nRow + nLength; // start row of next formula group. size_t nNextTopRow = nRow + nLength; // start row of next formula group.
if (ValidRow(nNextTopRow)) if (ValidRow(nNextTopRow))
{ {
sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow); sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos2); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos2, nullptr);
} }
if (pDocument->IsClipOrUndo()) if (pDocument->IsClipOrUndo())
...@@ -368,11 +368,11 @@ void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, S ...@@ -368,11 +368,11 @@ void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, S
sc::CellStoreType::iterator it = aPos.first; sc::CellStoreType::iterator it = aPos.first;
// Split formula grouping at the top and bottom boundaries. // Split formula grouping at the top and bottom boundaries.
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt);
if (ValidRow(nRow2+1)) if (ValidRow(nRow2+1))
{ {
aPos = maCells.position(it, nRow2+1); aPos = maCells.position(it, nRow2+1);
sc::SharedFormulaUtil::splitFormulaCellGroup(aPos); sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt);
} }
if (pDocument->IsClipOrUndo()) if (pDocument->IsClipOrUndo())
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
namespace sc { namespace sc {
void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type& aPos) void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type& aPos, sc::EndListeningContext* pCxt)
{ {
SCROW nRow = aPos.first->position + aPos.second; SCROW nRow = aPos.first->position + aPos.second;
...@@ -61,7 +61,14 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type ...@@ -61,7 +61,14 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
// other listeners, all listeners of this group's top cell are to be reset. // other listeners, all listeners of this group's top cell are to be reset.
if (nLength2) if (nLength2)
{ {
rPrevTop.EndListeningTo( rPrevTop.GetDocument(), NULL, ScAddress( ScAddress::UNINITIALIZED)); // If a context exists it has to be used to not interfere with
// ScColumn::maBroadcasters iterators, which the EndListeningTo()
// without context would do when removing a broadcaster that had its
// last listener removed.
if (pCxt)
rPrevTop.EndListeningTo(*pCxt);
else
rPrevTop.EndListeningTo( rPrevTop.GetDocument(), NULL, ScAddress( ScAddress::UNINITIALIZED));
rPrevTop.SetNeedsListening(true); rPrevTop.SetNeedsListening(true);
} }
#endif #endif
...@@ -107,7 +114,7 @@ void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vecto ...@@ -107,7 +114,7 @@ void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vecto
if (aPos.first == rCells.end()) if (aPos.first == rCells.end())
return; return;
splitFormulaCellGroup(aPos); splitFormulaCellGroup(aPos, nullptr);
std::vector<SCROW>::iterator itEnd = rBounds.end(); std::vector<SCROW>::iterator itEnd = rBounds.end();
for (++it; it != itEnd; ++it) for (++it; it != itEnd; ++it)
{ {
...@@ -116,7 +123,7 @@ void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vecto ...@@ -116,7 +123,7 @@ void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vecto
if (aPos.first == rCells.end()) if (aPos.first == rCells.end())
return; return;
splitFormulaCellGroup(aPos); splitFormulaCellGroup(aPos, nullptr);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment