Use group-area listeners during copy & paste if we can.
This should reduce the number of area listeners generated esp. when
replicating tons of formula cells down the column.
Change-Id: I1ea8f51f667e6b0e1a646f84d79f5e8430b478d5
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index adcd17a..6187d4e 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -255,7 +255,8 @@
void CopyFromClip(
sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, long nDy, ScColumn& rColumn );
void StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 );
void StartListeningInArea(
sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt, SCROW nRow1, SCROW nRow2 );
void RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index ea1e2a3..b1e06e1 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -437,7 +437,8 @@
SCsCOL nDx, SCsROW nDy, ScTable* pTable );
void StartListeningInArea(
sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
void SetDirtyFromClip(
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans );
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 6f31cf5..67c51be 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1535,28 +1535,6 @@
namespace {
class StartListeningInAreaHandler
{
sc::StartListeningContext& mrCxt;
public:
StartListeningInAreaHandler(sc::StartListeningContext& rCxt) : mrCxt(rCxt) {}
void operator() (size_t /*nRow*/, ScFormulaCell* p)
{
p->StartListeningTo(mrCxt);
}
};
}
void ScColumn::StartListeningInArea( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 )
{
StartListeningInAreaHandler aFunc(rCxt);
sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
}
namespace {
void applyTextNumFormat( ScColumn& rCol, SCROW nRow, SvNumberFormatter* pFormatter )
{
sal_uInt32 nFormat = pFormatter->GetStandardFormat(NUMBERFORMAT_TEXT);
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index f0d28eb..925bb4c 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1135,4 +1135,97 @@
return aRet.first != maCells.end();
}
namespace {
class StartListeningInAreaHandler
{
sc::StartListeningContext& mrStartCxt;
sc::EndListeningContext& mrEndCxt;
public:
StartListeningInAreaHandler( sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt ) :
mrStartCxt(rStartCxt), mrEndCxt(rEndCxt) {}
void operator() ( const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize )
{
if (node.type != sc::element_type_formula)
// We are only interested in formulas.
return;
ScFormulaCell** ppBeg = &sc::formula_block::at(*node.data, nOffset);
ScFormulaCell** ppEnd = ppBeg + nDataSize;
ScFormulaCell** pp = ppBeg;
// If the first formula cell belongs to a group and it's not the top
// cell, move up to the top cell of the group, and have all the extra
// formula cells stop listening.
ScFormulaCell* pFC = *pp;
if (pFC->IsShared() && !pFC->IsSharedTop())
{
SCROW nBackTrackSize = pFC->aPos.Row() - pFC->GetSharedTopRow();
if (nBackTrackSize > 0)
{
assert(static_cast<size_t>(nBackTrackSize) <= nOffset);
for (SCROW i = 0; i < nBackTrackSize; ++i)
--pp;
endListening(pp, ppBeg);
}
}
for (; pp != ppEnd; ++pp)
{
pFC = *pp;
if (!pFC->IsSharedTop())
{
pFC->StartListeningTo(mrStartCxt);
continue;
}
// If This is the last group in the range, see if the group
// extends beyond the range, in which case have the excess
// formula cells stop listening.
size_t nEndGroupPos = (pp - ppBeg) + pFC->GetSharedLength();
if (nEndGroupPos > nDataSize)
{
size_t nExcessSize = nEndGroupPos - nDataSize;
ScFormulaCell** ppGrpEnd = pp + pFC->GetSharedLength();
ScFormulaCell** ppGrp = ppGrpEnd - nExcessSize;
endListening(ppGrp, ppGrpEnd);
// Register formula cells as a group.
sc::SharedFormulaUtil::startListeningAsGroup(mrStartCxt, pp);
pp = ppEnd - 1; // Move to the one before the end position.
}
else
{
// Register formula cells as a group.
sc::SharedFormulaUtil::startListeningAsGroup(mrStartCxt, pp);
pp += pFC->GetSharedLength() - 1; // Move to the last one in the group.
}
}
}
private:
void endListening( ScFormulaCell** pp, ScFormulaCell** ppEnd )
{
for (; pp != ppEnd; ++pp)
{
ScFormulaCell& rFC = **pp;
rFC.EndListeningTo(mrEndCxt);
}
}
};
}
void ScColumn::StartListeningInArea(
sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt, SCROW nRow1, SCROW nRow2 )
{
StartListeningInAreaHandler aFunc(rStartCxt, rEndCxt);
sc::ProcessBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 8440e2b..8e3871f 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2420,12 +2420,17 @@
{
if (nInsFlag & IDF_CONTENTS)
{
sc::StartListeningContext aCxt(*this);
boost::shared_ptr<sc::ColumnBlockPositionSet> pSet(
new sc::ColumnBlockPositionSet(*this));
sc::StartListeningContext aStartCxt(*this, pSet);
sc::EndListeningContext aEndCxt(*this, pSet, NULL);
SCTAB nMax = static_cast<SCTAB>(maTabs.size());
ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
for (; itr != itrEnd && *itr < nMax; ++itr)
if (maTabs[*itr])
maTabs[*itr]->StartListeningInArea(aCxt, nCol1, nRow1, nCol2, nRow2);
maTabs[*itr]->StartListeningInArea(aStartCxt, aEndCxt, nCol1, nRow1, nCol2, nRow2);
}
}
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 6b3cbe4..788cb73 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3947,6 +3947,9 @@
if (pDoc->IsClipOrUndo() || IsInChangeTrack())
return;
if (!HasBroadcaster())
return;
pDoc->SetDetectiveDirty(true); // It has changed something
if ( GetCode()->IsRecalcModeAlways() )
@@ -3989,6 +3992,9 @@
if (rCxt.getDoc().IsClipOrUndo() || IsInChangeTrack())
return;
if (!HasBroadcaster())
return;
ScDocument& rDoc = rCxt.getDoc();
rDoc.SetDetectiveDirty(true); // It has changed something
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 66db45d..8d7ecc6 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1060,13 +1060,14 @@
}
void ScTable::StartListeningInArea(
sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
{
if (nCol2 > MAXCOL) nCol2 = MAXCOL;
if (nRow2 > MAXROW) nRow2 = MAXROW;
if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
for (SCCOL i = nCol1; i <= nCol2; i++)
aCol[i].StartListeningInArea(rCxt, nRow1, nRow2);
aCol[i].StartListeningInArea(rStartCxt, rEndCxt, nRow1, nRow2);
}
void ScTable::CopyToTable(