summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-11-25 00:02:21 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-11-25 10:00:14 -0500
commit0dae7466fff1e742543ef7512b7dd22472c75624 (patch)
treec9f146abd01a7cabd81944fd794c133cdecadca3
parent8c041824b67caa53d3f7f96803b7a69ced6614b5 (diff)
Adjust ref undo to ensure group area listeners are used.
When undoing row deletion (and possibly other similar undo's). And write test for it. Change-Id: I04b4fd9932f4236f124dcd25967355c6055dec33
-rw-r--r--include/svl/broadcast.hxx10
-rw-r--r--sc/inc/cellvalue.hxx2
-rw-r--r--sc/inc/clipcontext.hxx5
-rw-r--r--sc/inc/column.hxx17
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/formulacell.hxx9
-rw-r--r--sc/inc/grouparealistener.hxx6
-rw-r--r--sc/inc/stringutil.hxx3
-rw-r--r--sc/inc/table.hxx5
-rw-r--r--sc/inc/types.hxx7
-rw-r--r--sc/qa/unit/ucalc.hxx25
-rw-r--r--sc/qa/unit/ucalc_sharedformula.cxx101
-rw-r--r--sc/source/core/data/bcaslot.cxx24
-rw-r--r--sc/source/core/data/cellvalue.cxx4
-rw-r--r--sc/source/core/data/clipcontext.cxx14
-rw-r--r--sc/source/core/data/column.cxx36
-rw-r--r--sc/source/core/data/column3.cxx43
-rw-r--r--sc/source/core/data/column4.cxx2
-rw-r--r--sc/source/core/data/document.cxx28
-rw-r--r--sc/source/core/data/document10.cxx34
-rw-r--r--sc/source/core/data/formulacell.cxx59
-rw-r--r--sc/source/core/data/table2.cxx14
-rw-r--r--sc/source/core/inc/bcaslot.hxx5
-rw-r--r--sc/source/core/tool/grouparealistener.cxx17
-rw-r--r--sc/source/core/tool/stringutil.cxx3
-rw-r--r--sc/source/ui/undo/refundo.cxx38
-rw-r--r--svl/source/notify/broadcast.cxx4
27 files changed, 435 insertions, 82 deletions
diff --git a/include/svl/broadcast.hxx b/include/svl/broadcast.hxx
index 5615255e030e..a73abea3956e 100644
--- a/include/svl/broadcast.hxx
+++ b/include/svl/broadcast.hxx
@@ -41,7 +41,7 @@ private:
* entries. As a side effect, the listeners get sorted by pointer values
* after this call.
*/
- void Normalize();
+ void Normalize() const;
void Add( SvtListener* p );
void Remove( SvtListener* p );
@@ -74,16 +74,16 @@ public:
void PrepareForDestruction();
private:
- ListenersType maListeners;
+ mutable ListenersType maListeners;
/// When the broadcaster is about to die, collect listeners that asked for removal.
- ListenersType maDestructedListeners;
+ mutable ListenersType maDestructedListeners;
/// Indicate that this broadcaster will be destructed (we indicate this on all ScColumn's broadcasters during the ScTable destruction, eg.)
bool mbAboutToDie:1;
bool mbDisposing:1;
- bool mbNormalized:1;
- bool mbDestNormalized:1;
+ mutable bool mbNormalized:1;
+ mutable bool mbDestNormalized:1;
};
diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index 9154e30ddacd..3a2d3c8678d1 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -76,7 +76,7 @@ struct SC_DLLPUBLIC ScCellValue
*/
void release( ScDocument& rDoc, const ScAddress& rPos );
- void release( ScColumn& rColumn, SCROW nRow );
+ void release( ScColumn& rColumn, SCROW nRow, sc::StartListeningType eListenType = sc::SingleCellListening );
OUString getString( const ScDocument* pDoc );
diff --git a/sc/inc/clipcontext.hxx b/sc/inc/clipcontext.hxx
index 3891274d7283..aa783e4aa203 100644
--- a/sc/inc/clipcontext.hxx
+++ b/sc/inc/clipcontext.hxx
@@ -144,9 +144,14 @@ public:
class CopyToDocContext : public ClipContextBase
{
+ bool mbStartListening;
+
public:
CopyToDocContext(ScDocument& rDoc);
virtual ~CopyToDocContext();
+
+ void setStartListening( bool b );
+ bool isStartListening() const;
};
class MixDocContext : public ClipContextBase
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 102af126fc78..7f883a63ed76 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -314,8 +314,12 @@ public:
* @return pCell if it was successfully inserted, NULL otherwise. pCell
* is deleted automatically on failure to insert.
*/
- ScFormulaCell* SetFormulaCell( SCROW nRow, ScFormulaCell* pCell, bool bSingle = false );
- ScFormulaCell* SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell );
+ ScFormulaCell* SetFormulaCell(
+ SCROW nRow, ScFormulaCell* pCell,
+ sc::StartListeningType eListenType = sc::SingleCellListening );
+ ScFormulaCell* SetFormulaCell(
+ sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell,
+ sc::StartListeningType eListenType = sc::SingleCellListening );
bool SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells );
@@ -639,10 +643,15 @@ private:
sc::CellStoreType::iterator GetPositionToInsert( SCROW nRow );
sc::CellStoreType::iterator GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow );
+
void AttachNewFormulaCell(
- const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin = true, bool bSingle = false );
+ const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell,
+ bool bJoin = true, sc::StartListeningType eListenType = sc::SingleCellListening );
+
void AttachNewFormulaCell(
- const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin = true, bool bSingle = false );
+ const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell,
+ bool bJoin = true, sc::StartListeningType eListenType = sc::SingleCellListening );
+
void AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength );
void BroadcastNewCell( SCROW nRow );
bool UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow, const sc::CellStoreType::iterator& itr );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 554ee3a9afc1..31fde4db04c5 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1916,6 +1916,8 @@ public:
void SetHardRecalcState( bool bVal ) { bHardRecalcState = bVal; }
void StartAllListeners();
void StartNeededListeners();
+ void StartAllListeners( const ScRange& rRange );
+ void EndAllListeners( const ScRange& rRange );
const ScFormulaCell* GetFormulaTree() const { return pFormulaTree; }
bool HasForcedFormulas() const { return bHasForcedFormulas; }
void SetForcedFormulas( bool bVal ) { bHasForcedFormulas = bVal; }
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 50a6f6cb3a64..86b8045ee1d6 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -23,7 +23,6 @@
#include <set>
#include <boost/noncopyable.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
#include <formula/tokenarray.hxx>
#include <osl/conditn.hxx>
@@ -58,7 +57,11 @@ class ScTokenArray;
struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable
{
- typedef boost::ptr_vector<sc::FormulaGroupAreaListener> AreaListenersType;
+private:
+ struct Impl;
+ Impl* mpImpl;
+
+public:
mutable size_t mnRefCount;
@@ -73,8 +76,6 @@ struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable
sal_uInt8 meCalcState;
sal_uInt8 meKernelState;
- AreaListenersType maAreaListeners;
-
ScFormulaCellGroup();
~ScFormulaCellGroup();
diff --git a/sc/inc/grouparealistener.hxx b/sc/inc/grouparealistener.hxx
index 5abb0e8ebb92..2c6ea50e2f8c 100644
--- a/sc/inc/grouparealistener.hxx
+++ b/sc/inc/grouparealistener.hxx
@@ -32,6 +32,7 @@ class FormulaGroupAreaListener : public SvtListener
FormulaGroupAreaListener(); // disabled
public:
+
FormulaGroupAreaListener(
const ScRange& rRange, ScFormulaCell** ppTopCell, SCROW nGroupLen, bool bStartFixed, bool bEndFixed );
@@ -52,10 +53,11 @@ public:
*/
void collectFormulaCells( SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, std::vector<ScFormulaCell*>& rCells ) const;
-#if DEBUG_AREA_BROADCASTER
ScAddress getTopCellPos() const;
+ const ScRange& getRange() const;
SCROW getGroupLength() const;
-#endif
+ bool isStartFixed() const;
+ bool isEndFixed() const;
private:
void notifyCellChange( const SfxHint& rHint, const ScAddress& rPos );
diff --git a/sc/inc/stringutil.hxx b/sc/inc/stringutil.hxx
index 0d536db87836..ef7bd50f3db6 100644
--- a/sc/inc/stringutil.hxx
+++ b/sc/inc/stringutil.hxx
@@ -23,6 +23,7 @@
#include <rtl/ustring.hxx>
#include "scdllapi.h"
#include <i18nlangtag/lang.h>
+#include <types.hxx>
class SvNumberFormatter;
@@ -79,6 +80,8 @@ struct SC_DLLPUBLIC ScSetStringParam
*/
bool mbHandleApostrophe;
+ sc::StartListeningType meStartListening;
+
ScSetStringParam();
/**
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 0d0a5c43a9c0..df3372ecef3f 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -437,10 +437,13 @@ public:
sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
SCsCOL nDx, SCsROW nDy, ScTable* pTable );
- void StartListeningFromClip(
+ void StartListeningFormulaCells(
sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+ void EndListeningFormulaCells(
+ 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/inc/types.hxx b/sc/inc/types.hxx
index e483b1eff98e..d92c9b5b9430 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -108,6 +108,13 @@ enum AreaOverlapType
OneColumnInsideArea
};
+enum StartListeningType
+{
+ ConvertToGroupListening,
+ SingleCellListening,
+ NoListening
+};
+
}
#endif
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 7cad0ad9d299..e20b069895ea 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -12,6 +12,7 @@
#include "helper/qahelper.hxx"
#include "document.hxx"
+#include <stringutil.hxx>
struct TestImpl;
class ScUndoPaste;
@@ -55,9 +56,16 @@ public:
static void setCalcAsShown(ScDocument* pDoc, bool bCalcAsShown);
+
template<size_t _Size>
- static ScRange insertRangeData(ScDocument* pDoc, const ScAddress& rPos, const char* aData[][_Size], size_t nRowCount)
+ static ScRange insertRangeData(
+ ScDocument* pDoc, const ScAddress& rPos, const char* aData[][_Size], size_t nRowCount,
+ bool bGroupListening = false )
{
+ // TODO : Ideally bGroupListening should be always true for all tests.
+ // Eventually we want to drop this parameter once all tests pass with
+ // group listening turned on.
+
ScRange aRange(rPos);
aRange.aEnd.SetCol(rPos.Col()+_Size-1);
aRange.aEnd.SetRow(rPos.Row()+nRowCount-1);
@@ -73,10 +81,21 @@ public:
SCCOL nCol = i + rPos.Col();
SCROW nRow = j + rPos.Row();
- pDoc->SetString(nCol, nRow, rPos.Tab(), OUString(aData[j][i], strlen(aData[j][i]), RTL_TEXTENCODING_UTF8));
+ OUString aStr(aData[j][i], strlen(aData[j][i]), RTL_TEXTENCODING_UTF8);
+ if (bGroupListening)
+ {
+ ScSetStringParam aParam; // Leave default.
+ aParam.meStartListening = sc::NoListening;
+ pDoc->SetString(nCol, nRow, rPos.Tab(), aStr, &aParam);
+ }
+ else
+ pDoc->SetString(nCol, nRow, rPos.Tab(), aStr, NULL);
}
}
+ if (bGroupListening)
+ pDoc->StartAllListeners(aRange);
+
printRange(pDoc, aRange, "Range data content");
return aRange;
}
@@ -300,6 +319,7 @@ public:
void testSharedFormulasRefUpdateMove();
void testSharedFormulasRefUpdateMove2();
void testSharedFormulasRefUpdateRange();
+ void testSharedFormulasRefUpdateRangeDeleteRow();
void testSharedFormulasRefUpdateExternal();
void testSharedFormulasInsertRow();
void testSharedFormulasDeleteRows();
@@ -529,6 +549,7 @@ public:
CPPUNIT_TEST(testSharedFormulasRefUpdateMove);
CPPUNIT_TEST(testSharedFormulasRefUpdateMove2);
CPPUNIT_TEST(testSharedFormulasRefUpdateRange);
+ CPPUNIT_TEST(testSharedFormulasRefUpdateRangeDeleteRow);
CPPUNIT_TEST(testSharedFormulasRefUpdateExternal);
CPPUNIT_TEST(testSharedFormulasInsertRow);
CPPUNIT_TEST(testSharedFormulasDeleteRows);
diff --git a/sc/qa/unit/ucalc_sharedformula.cxx b/sc/qa/unit/ucalc_sharedformula.cxx
index 16d55771f9d7..811612379163 100644
--- a/sc/qa/unit/ucalc_sharedformula.cxx
+++ b/sc/qa/unit/ucalc_sharedformula.cxx
@@ -21,6 +21,7 @@
#include <tokenstringcontext.hxx>
#include <globalnames.hxx>
#include <dbdata.hxx>
+#include <bcaslot.hxx>
#include <svl/sharedstring.hxx>
@@ -580,6 +581,106 @@ void Test::testSharedFormulasRefUpdateRange()
m_pDoc->DeleteTab(0);
}
+void Test::testSharedFormulasRefUpdateRangeDeleteRow()
+{
+ sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
+ m_pDoc->InsertTab(0, "Formula");
+
+ ScRange aWholeArea(0, 0, 0, 100, 100, 0); // Large enough for all references used in the test.
+
+ const char* aData[][3] = {
+ { "1", "2", "=SUM(A1:B1)" },
+ { "3", "4", "=SUM(A2:B2)" },
+ { 0, 0, 0 },
+ { "5", "6", "=SUM(A4:B4)" },
+ { "7", "8", "=SUM(A5:B5)" }
+ };
+
+ insertRangeData(m_pDoc, ScAddress(0,0,0), aData, SAL_N_ELEMENTS(aData), true);
+
+ // Check initial formula values.
+ CPPUNIT_ASSERT_EQUAL( 3.0, m_pDoc->GetValue(ScAddress(2,0,0)));
+ CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(ScAddress(2,1,0)));
+ CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc->GetValue(ScAddress(2,3,0)));
+ CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(2,4,0)));
+
+ // Check the area listener status.
+ ScBroadcastAreaSlotMachine* pBASM = m_pDoc->GetBASM();
+ CPPUNIT_ASSERT(pBASM);
+ std::vector<sc::AreaListener> aListeners = pBASM->GetAllListeners(aWholeArea, sc::AreaInside);
+ std::sort(aListeners.begin(), aListeners.end(), sc::AreaListener::SortByArea());
+
+ CPPUNIT_ASSERT_MESSAGE("There should only be 2 area listeners.", aListeners.size() == 2);
+ // First one should be group-listening on A1:B2.
+ CPPUNIT_ASSERT_MESSAGE("This listener should be listening on A1:B2.", aListeners[0].maArea == ScRange(0,0,0,1,1,0));
+ CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening);
+ // Second one should be group-listening on A4:B5.
+ CPPUNIT_ASSERT_MESSAGE("This listener should be listening on A1:B2.", aListeners[0].maArea == ScRange(0,0,0,1,1,0));
+ CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening);
+
+ // Make sure that C1:C2 and C4:C5 are formula groups.
+ const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(2,0,0));
+ CPPUNIT_ASSERT(pFC);
+ CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+
+ pFC = m_pDoc->GetFormulaCell(ScAddress(2,3,0));
+ CPPUNIT_ASSERT(pFC);
+ CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedTopRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+
+ // Delete row 3. This will merge the two formula groups.
+ ScDocFunc& rFunc = getDocShell().GetDocFunc();
+ ScMarkData aMark;
+ aMark.SelectOneTable(0);
+ rFunc.DeleteCells(ScRange(0,2,0,MAXCOL,2,0), &aMark, DEL_DELROWS, true, true);
+
+ // Make sure C1:C4 belong to the same group.
+ pFC = m_pDoc->GetFormulaCell(ScAddress(2,0,0));
+ CPPUNIT_ASSERT(pFC);
+ CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), pFC->GetSharedTopRow());
+ CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
+
+ // We should only have one listener group-listening on A1:B4.
+ aListeners = pBASM->GetAllListeners(aWholeArea, sc::AreaInside);
+ CPPUNIT_ASSERT_MESSAGE("There should only be 1 area listener.", aListeners.size() == 1);
+ CPPUNIT_ASSERT_MESSAGE("This listener should be listening on A1:B4.", aListeners[0].maArea == ScRange(0,0,0,1,3,0));
+ CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening);
+
+ // Change the value of B4 and make sure the value of C4 changes.
+ rFunc.SetValueCell(ScAddress(1,3,0), 100.0, false);
+ CPPUNIT_ASSERT_EQUAL(107.0, m_pDoc->GetValue(ScAddress(2,3,0)));
+
+ SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
+ CPPUNIT_ASSERT(pUndoMgr);
+
+ // Undo the value change in B4, and make sure C4 follows.
+ pUndoMgr->Undo();
+ CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(2,3,0)));
+
+ // Undo the deletion of row 3.
+ pUndoMgr->Undo();
+
+ // Check the values of formula cells again.
+ CPPUNIT_ASSERT_EQUAL( 3.0, m_pDoc->GetValue(ScAddress(2,0,0)));
+ CPPUNIT_ASSERT_EQUAL( 7.0, m_pDoc->GetValue(ScAddress(2,1,0)));
+ CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc->GetValue(ScAddress(2,3,0)));
+ CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(2,4,0)));
+
+ aListeners = pBASM->GetAllListeners(aWholeArea, sc::AreaInside);
+ std::sort(aListeners.begin(), aListeners.end(), sc::AreaListener::SortByArea());
+
+ CPPUNIT_ASSERT_MESSAGE("There should only be 2 area listeners.", aListeners.size() == 2);
+ // First one should be group-listening on A1:B2.
+ CPPUNIT_ASSERT_MESSAGE("This listener should be listening on A1:B2.", aListeners[0].maArea == ScRange(0,0,0,1,1,0));
+ CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening);
+ // Second one should be group-listening on A4:B5.
+ CPPUNIT_ASSERT_MESSAGE("This listener should be listening on A1:B2.", aListeners[0].maArea == ScRange(0,0,0,1,1,0));
+ CPPUNIT_ASSERT_MESSAGE("This listener should be group-listening.", aListeners[0].mbGroupListening);
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testSharedFormulasRefUpdateExternal()
{
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calc.
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index 0678a7febc70..4290fbd402ea 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -64,6 +64,30 @@
// STATIC DATA -----------------------------------------------------------
+namespace sc {
+
+bool AreaListener::SortByArea::operator ()( const AreaListener& rLeft, const AreaListener& rRight ) const
+{
+ if (rLeft.maArea.aStart.Tab() != rRight.maArea.aStart.Tab())
+ return rLeft.maArea.aStart.Tab() < rRight.maArea.aStart.Tab();
+
+ if (rLeft.maArea.aStart.Col() != rRight.maArea.aStart.Col())
+ return rLeft.maArea.aStart.Col() < rRight.maArea.aStart.Col();
+
+ if (rLeft.maArea.aStart.Row() != rRight.maArea.aStart.Row())
+ return rLeft.maArea.aStart.Row() < rRight.maArea.aStart.Row();
+
+ if (rLeft.maArea.aEnd.Tab() != rRight.maArea.aEnd.Tab())
+ return rLeft.maArea.aEnd.Tab() < rRight.maArea.aEnd.Tab();
+
+ if (rLeft.maArea.aEnd.Col() != rRight.maArea.aEnd.Col())
+ return rLeft.maArea.aEnd.Col() < rRight.maArea.aEnd.Col();
+
+ return rLeft.maArea.aEnd.Row() < rRight.maArea.aEnd.Row();
+}
+
+}
+
struct ScSlotData
{
SCROW nStartRow; // first row of this segment
diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx
index b9eb32b2bc34..8a69d12dafbe 100644
--- a/sc/source/core/data/cellvalue.cxx
+++ b/sc/source/core/data/cellvalue.cxx
@@ -440,7 +440,7 @@ void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
mfValue = 0.0;
}
-void ScCellValue::release( ScColumn& rColumn, SCROW nRow )
+void ScCellValue::release( ScColumn& rColumn, SCROW nRow, sc::StartListeningType eListenType )
{
switch (meType)
{
@@ -460,7 +460,7 @@ void ScCellValue::release( ScColumn& rColumn, SCROW nRow )
break;
case CELLTYPE_FORMULA:
// This formula cell instance is directly placed in the document without copying.
- rColumn.SetFormulaCell(nRow, mpFormula);
+ rColumn.SetFormulaCell(nRow, mpFormula, eListenType);
break;
default:
rColumn.Delete(nRow);
diff --git a/sc/source/core/data/clipcontext.cxx b/sc/source/core/data/clipcontext.cxx
index 5fd08da7ef0c..83003273b62b 100644
--- a/sc/source/core/data/clipcontext.cxx
+++ b/sc/source/core/data/clipcontext.cxx
@@ -327,9 +327,21 @@ bool CopyToClipContext::isCloneNotes() const
return mbCloneNotes;
}
-CopyToDocContext::CopyToDocContext(ScDocument& rDoc) : ClipContextBase(rDoc) {}
+CopyToDocContext::CopyToDocContext(ScDocument& rDoc) :
+ ClipContextBase(rDoc), mbStartListening(true) {}
+
CopyToDocContext::~CopyToDocContext() {}
+void CopyToDocContext::setStartListening( bool b )
+{
+ mbStartListening = b;
+}
+
+bool CopyToDocContext::isStartListening() const
+{
+ return mbStartListening;
+}
+
MixDocContext::MixDocContext(ScDocument& rDoc) : ClipContextBase(rDoc) {}
MixDocContext::~MixDocContext() {}
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index c0e2991912c3..d9532307409e 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -1232,6 +1232,8 @@ class CopyAsLinkHandler
sc::ColumnBlockPosition* mpDestPos;
InsertDeleteFlags mnCopyFlags;
+ sc::StartListeningType meListenType;
+
void setDefaultAttrToDest(size_t nRow)
{
maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
@@ -1263,7 +1265,7 @@ class CopyAsLinkHandler
for (size_t i = 0; i < nDataSize; ++i)
{
SCROW nRow = nTopRow + i;
- mrDestCol.SetFormulaCell(maDestPos, nRow, createRefCell(nRow));
+ mrDestCol.SetFormulaCell(maDestPos, nRow, createRefCell(nRow), meListenType);
}
setDefaultAttrsToDest(nTopRow, nDataSize);
@@ -1276,7 +1278,11 @@ class CopyAsLinkHandler
public:
CopyAsLinkHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, InsertDeleteFlags nCopyFlags) :
- mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mnCopyFlags(nCopyFlags)
+ mrSrcCol(rSrcCol),
+ mrDestCol(rDestCol),
+ mpDestPos(pDestPos),
+ mnCopyFlags(nCopyFlags),
+ meListenType(sc::SingleCellListening)
{
if (mpDestPos)
maDestPos = *mpDestPos;
@@ -1288,6 +1294,11 @@ public:
*mpDestPos = maDestPos;
}
+ void setStartListening( bool b )
+ {
+ meListenType = b ? sc::SingleCellListening : sc::NoListening;
+ }
+
void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
{
size_t nRow = aNode.position + nOffset;
@@ -1353,6 +1364,8 @@ class CopyByCloneHandler
svl::SharedStringPool* mpSharedStringPool;
InsertDeleteFlags mnCopyFlags;
+ sc::StartListeningType meListenType;
+
void setDefaultAttrToDest(size_t nRow)
{
maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
@@ -1396,7 +1409,7 @@ class CopyByCloneHandler
// Clone as formula cell.
ScFormulaCell* pCell = new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos);
pCell->SetDirtyVar();
- mrDestCol.SetFormulaCell(maDestPos, nRow, pCell);
+ mrDestCol.SetFormulaCell(maDestPos, nRow, pCell, meListenType);
setDefaultAttrToDest(nRow);
return;
}
@@ -1412,7 +1425,7 @@ class CopyByCloneHandler
// error codes are cloned with values
ScFormulaCell* pErrCell = new ScFormulaCell(&mrDestCol.GetDoc(), aDestPos);
pErrCell->SetErrCode(nErr);
- mrDestCol.SetFormulaCell(maDestPos, nRow, pErrCell);
+ mrDestCol.SetFormulaCell(maDestPos, nRow, pErrCell, meListenType);
setDefaultAttrToDest(nRow);
return;
}
@@ -1466,8 +1479,12 @@ class CopyByCloneHandler
public:
CopyByCloneHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos,
InsertDeleteFlags nCopyFlags, svl::SharedStringPool* pSharedStringPool) :
- mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mpSharedStringPool(pSharedStringPool),
- mnCopyFlags(nCopyFlags)
+ mrSrcCol(rSrcCol),
+ mrDestCol(rDestCol),
+ mpDestPos(pDestPos),
+ mpSharedStringPool(pSharedStringPool),
+ mnCopyFlags(nCopyFlags),
+ meListenType(sc::SingleCellListening)
{
if (mpDestPos)
maDestPos = *mpDestPos;
@@ -1479,6 +1496,11 @@ public:
*mpDestPos = maDestPos;
}
+ void setStartListening( bool b )
+ {
+ meListenType = b ? sc::SingleCellListening : sc::NoListening;
+ }
+
void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
{
size_t nRow = aNode.position + nOffset;
@@ -1642,6 +1664,7 @@ void ScColumn::CopyToColumn(
if (bAsLink)
{
CopyAsLinkHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags);
+ aFunc.setStartListening(rCxt.isStartListening());
sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
}
else
@@ -1653,6 +1676,7 @@ void ScColumn::CopyToColumn(
&rColumn.pDocument->GetSharedStringPool() : NULL;
CopyByCloneHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags,
pSharedStringPool);
+ aFunc.setStartListening(rCxt.isStartListening());
sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
}
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index ae58aecf50a5..803bd3520811 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -377,13 +377,15 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreTy
}
void ScColumn::AttachNewFormulaCell(
- const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin, bool bSingle )
+ const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell,
+ bool bJoin, sc::StartListeningType eListenType )
{
- AttachNewFormulaCell(maCells.position(itPos, nRow), rCell, bJoin, bSingle);
+ AttachNewFormulaCell(maCells.position(itPos, nRow), rCell, bJoin, eListenType);
}
void ScColumn::AttachNewFormulaCell(
- const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin, bool bSingle )
+ const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell,
+ bool bJoin, sc::StartListeningType eListenType )
{
if (bJoin)
// See if this new formula cell can join an existing shared formula group.
@@ -394,9 +396,12 @@ void ScColumn::AttachNewFormulaCell(
// we call StartListeningFromClip and BroadcastFromClip.
// If we insert into the Clipboard/andoDoc, we do not use a Broadcast.
// After Import we call CalcAfterLoad and in there Listening.
- if (!pDocument->IsClipOrUndo() && !pDocument->IsInsertingFromOtherDoc())
+ if (pDocument->IsClipOrUndo() || pDocument->IsInsertingFromOtherDoc())
+ return;
+
+ switch (eListenType)
{
- if (bSingle)
+ case sc::ConvertToGroupListening:
{
boost::shared_ptr<sc::ColumnBlockPositionSet> pPosSet(new sc::ColumnBlockPositionSet(*pDocument));
sc::StartListeningContext aStartCxt(*pDocument, pPosSet);
@@ -404,12 +409,18 @@ void ScColumn::AttachNewFormulaCell(
SCROW nRow = aPos.first->position + aPos.second;
StartListeningFormulaCells(aStartCxt, aEndCxt, nRow, nRow);
}
- else
+ break;
+ case sc::SingleCellListening:
rCell.StartListeningTo(pDocument);
+ break;
+ case sc::NoListening:
+ default:
+ ;
- if (!pDocument->IsCalcingAfterLoad())
- rCell.SetDirty();
}
+
+ if (!pDocument->IsCalcingAfterLoad())
+ rCell.SetDirty();
}
void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength )
@@ -1734,7 +1745,10 @@ bool ScColumn::SetString( SCROW nRow, SCTAB nTabP, const OUString& rString,
ScCellValue aNewCell;
bool bNumFmtSet = ParseString(aNewCell, nRow, nTabP, rString, eConv, pParam);
- aNewCell.release(*this, nRow);
+ if (pParam)
+ aNewCell.release(*this, nRow, pParam->meStartListening);
+ else
+ aNewCell.release(*this, nRow);
// Do not set Formats and Formulas here anymore!
// These are queried during output
@@ -1834,7 +1848,8 @@ void ScColumn::SetFormula( SCROW nRow, const OUString& rFormula, formula::Formul
AttachNewFormulaCell(it, nRow, *pCell);
}
-ScFormulaCell* ScColumn::SetFormulaCell( SCROW nRow, ScFormulaCell* pCell, bool bSingle )
+ScFormulaCell* ScColumn::SetFormulaCell(
+ SCROW nRow, ScFormulaCell* pCell, sc::StartListeningType eListenType )
{
sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
sal_uInt32 nCellFormat = GetNumberFormat(nRow);
@@ -1845,11 +1860,13 @@ ScFormulaCell* ScColumn::SetFormulaCell( SCROW nRow, ScFormulaCell* pCell, bool
CellStorageModified();
- AttachNewFormulaCell(it, nRow, *pCell, true, bSingle);
+ AttachNewFormulaCell(it, nRow, *pCell, true, eListenType);
return pCell;
}
-ScFormulaCell* ScColumn::SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell )
+ScFormulaCell* ScColumn::SetFormulaCell(
+ sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell,
+ sc::StartListeningType eListenType )
{
rBlockPos.miCellPos = GetPositionToInsert(rBlockPos.miCellPos, nRow);
sal_uInt32 nCellFormat = GetNumberFormat(nRow);
@@ -1861,7 +1878,7 @@ ScFormulaCell* ScColumn::SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCR
CellStorageModified();
- AttachNewFormulaCell(rBlockPos.miCellPos, nRow, *pCell);
+ AttachNewFormulaCell(rBlockPos.miCellPos, nRow, *pCell, true, eListenType);
return pCell;
}
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 42d166a0e7c0..ab804ddf4340 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1240,8 +1240,6 @@ public:
{
return mnEndRow;
}
-
-private:
};
class EndListeningFormulaCellsHandler
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index a206c09b5e04..660b39469133 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1960,8 +1960,8 @@ void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
PutInOrder( nTab1, nTab2 );
if (ValidTab(nTab1) && ValidTab(nTab2))
{
- bool bOldAutoCalc = pDestDoc->GetAutoCalc();
- pDestDoc->SetAutoCalc( false ); // avoid multiple calculations
+ sc::AutoCalcSwitch aACSwitch(*pDestDoc, false); // avoid multiple calculations
+
if (nTab1 > 0)
CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, false, pDestDoc, pMarks );
@@ -1976,7 +1976,6 @@ void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
if (nTab2 < MAXTAB)
CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, false, pDestDoc, pMarks );
- pDestDoc->SetAutoCalc( bOldAutoCalc );
}
}
@@ -1989,21 +1988,26 @@ void ScDocument::CopyToDocument(const ScRange& rRange,
if( pDestDoc->aDocName.isEmpty() )
pDestDoc->aDocName = aDocName;
- bool bOldAutoCalc = pDestDoc->GetAutoCalc();
- pDestDoc->SetAutoCalc( false ); // avoid multiple calculations
+
+ sc::AutoCalcSwitch aACSwitch(*pDestDoc, false); // avoid multiple calculations
+
sc::CopyToDocContext aCxt(*pDestDoc);
+ aCxt.setStartListening(false);
+
SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
for (SCTAB i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab() && i < nMinSizeBothTabs; i++)
{
- if (!TableExists(i) || !pDestDoc->TableExists(i))
+ ScTable* pTab = FetchTable(i);
+ ScTable* pDestTab = pDestDoc->FetchTable(i);
+ if (!pTab || !pDestTab)
continue;
- maTabs[i]->CopyToTable(aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(),
- aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
- nFlags, bOnlyMarked, pDestDoc->maTabs[i],
- pMarks, false, bColRowFlags);
+ pTab->CopyToTable(
+ aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(), aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
+ nFlags, bOnlyMarked, pDestTab, pMarks, false, bColRowFlags);
}
- pDestDoc->SetAutoCalc( bOldAutoCalc );
+
+ pDestDoc->StartAllListeners(aNewRange);
}
void ScDocument::UndoToDocument(const ScRange& rRange,
@@ -2452,7 +2456,7 @@ void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
for (; itr != itrEnd && *itr < nMax; ++itr)
if (maTabs[*itr])
- maTabs[*itr]->StartListeningFromClip(aStartCxt, aEndCxt, nCol1, nRow1, nCol2, nRow2);
+ maTabs[*itr]->StartListeningFormulaCells(aStartCxt, aEndCxt, nCol1, nRow1, nCol2, nRow2);
}
}
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index d1b41687fb3e..c01b2647a755 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -423,4 +423,38 @@ void ScDocument::StartNeededListeners()
std::for_each(maTabs.begin(), maTabs.end(), StartNeededListenersHandler(*this));
}
+void ScDocument::StartAllListeners( const ScRange& rRange )
+{
+ boost::shared_ptr<sc::ColumnBlockPositionSet> pPosSet(new sc::ColumnBlockPositionSet(*this));
+ sc::StartListeningContext aStartCxt(*this, pPosSet);
+ sc::EndListeningContext aEndCxt(*this, pPosSet);
+
+ for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+ {
+ ScTable* pTab = FetchTable(nTab);
+ if (!pTab)
+ continue;
+
+ pTab->StartListeningFormulaCells(
+ aStartCxt, aEndCxt,
+ rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
+ }
+}
+
+void ScDocument::EndAllListeners( const ScRange& rRange )
+{
+ sc::EndListeningContext aEndCxt(*this);
+
+ for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+ {
+ ScTable* pTab = FetchTable(nTab);
+ if (!pTab)
+ continue;
+
+ pTab->EndListeningFormulaCells(
+ aEndCxt,
+ rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index f8a6c9cbce36..5574c902ebf9 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -62,6 +62,7 @@
#include <officecfg/Office/Common.hxx>
#include <boost/scoped_ptr.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
using namespace formula;
@@ -383,6 +384,40 @@ void adjustDBRange(formula::FormulaToken* pToken, ScDocument& rNewDoc, const ScD
pToken->SetIndex(pNewDBData->GetIndex());
}
+struct AreaListenerKey
+{
+ ScRange maRange;
+ bool mbStartFixed;
+ bool mbEndFixed;
+
+ AreaListenerKey( const ScRange& rRange, bool bStartFixed, bool bEndFixed ) :
+ maRange(rRange), mbStartFixed(bStartFixed), mbEndFixed(bEndFixed) {}
+
+ bool operator < ( const AreaListenerKey& r ) const
+ {
+ if (maRange.aStart.Tab() != r.maRange.aStart.Tab())
+ return maRange.aStart.Tab() < r.maRange.aStart.Tab();
+ if (maRange.aStart.Col() != r.maRange.aStart.Col())
+ return maRange.aStart.Col() < r.maRange.aStart.Col();
+ if (maRange.aStart.Row() != r.maRange.aStart.Row())
+ return maRange.aStart.Row() < r.maRange.aStart.Row();
+ if (maRange.aEnd.Tab() != r.maRange.aEnd.Tab())
+ return maRange.aEnd.Tab() < r.maRange.aEnd.Tab();
+ if (maRange.aEnd.Col() != r.maRange.aEnd.Col())
+ return maRange.aEnd.Col() < r.maRange.aEnd.Col();
+ if (maRange.aEnd.Row() != r.maRange.aEnd.Row())
+ return maRange.aEnd.Row() < r.maRange.aEnd.Row();
+ if (mbStartFixed != r.mbStartFixed)
+ return r.mbStartFixed;
+ if (mbEndFixed != r.mbEndFixed)
+ return r.mbEndFixed;
+
+ return false;
+ }
+};
+
+typedef boost::ptr_map<AreaListenerKey, sc::FormulaGroupAreaListener> AreaListenersType;
+
}
#if ENABLE_THREADED_OPENCL_KERNEL_COMPILATION
@@ -407,7 +442,13 @@ int ScFormulaCellGroup::snCount = 0;
rtl::Reference<sc::CLBuildKernelThread> ScFormulaCellGroup::sxCompilationThread;
#endif
+struct ScFormulaCellGroup::Impl
+{
+ AreaListenersType maAreaListeners;
+};
+
ScFormulaCellGroup::ScFormulaCellGroup() :
+ mpImpl(new Impl),
mnRefCount(0),
mpCode(NULL),
mpCompiledFormula(NULL),
@@ -451,6 +492,7 @@ ScFormulaCellGroup::~ScFormulaCellGroup()
#endif
delete mpCode;
delete mpCompiledFormula;
+ delete mpImpl;
}
void ScFormulaCellGroup::scheduleCompilation()
@@ -513,24 +555,29 @@ void ScFormulaCellGroup::compileOpenCLKernel()
sc::FormulaGroupAreaListener* ScFormulaCellGroup::getAreaListener(
ScFormulaCell** ppTopCell, const ScRange& rRange, bool bStartFixed, bool bEndFixed )
{
- // TODO : Find existing one with the same criteria.
- maAreaListeners.push_back(new sc::FormulaGroupAreaListener(rRange, ppTopCell, mnLength, bStartFixed, bEndFixed));
- return &maAreaListeners.back();
+ AreaListenerKey aKey(rRange, bStartFixed, bEndFixed);
+
+ std::pair<AreaListenersType::iterator, bool> r =
+ mpImpl->maAreaListeners.insert(
+ aKey, new sc::FormulaGroupAreaListener(
+ rRange, ppTopCell, mnLength, bStartFixed, bEndFixed));
+
+ return r.first->second;
}
void ScFormulaCellGroup::endAllGroupListening( ScDocument& rDoc )
{
- AreaListenersType::iterator it = maAreaListeners.begin(), itEnd = maAreaListeners.end();
+ AreaListenersType::iterator it = mpImpl->maAreaListeners.begin(), itEnd = mpImpl->maAreaListeners.end();
for (; it != itEnd; ++it)
{
- sc::FormulaGroupAreaListener* pListener = &(*it);
+ sc::FormulaGroupAreaListener* pListener = it->second;
ScRange aListenRange = pListener->getListeningRange();
// This "always listen" special range is never grouped.
bool bGroupListening = (aListenRange != BCA_LISTEN_ALWAYS);
rDoc.EndListeningArea(aListenRange, bGroupListening, pListener);
}
- maAreaListeners.clear();
+ mpImpl->maAreaListeners.clear();
}
ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos ) :
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 97355424c8c3..608ec13014a4 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1057,7 +1057,7 @@ void ScTable::SetDirtyFromClip(
aCol[i].SetDirtyFromClip(nRow1, nRow2, rBroadcastSpans);
}
-void ScTable::StartListeningFromClip(
+void ScTable::StartListeningFormulaCells(
sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
{
@@ -1068,6 +1068,16 @@ void ScTable::StartListeningFromClip(
aCol[i].StartListeningFormulaCells(rStartCxt, rEndCxt, nRow1, nRow2);
}
+void ScTable::EndListeningFormulaCells(
+ 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].EndListeningFormulaCells(rEndCxt, nRow1, nRow2);
+}
+
void ScTable::CopyToTable(
sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
InsertDeleteFlags nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData,
@@ -1413,7 +1423,7 @@ ScFormulaCell* ScTable::SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* p
return NULL;
}
- return aCol[nCol].SetFormulaCell(nRow, pCell, true);
+ return aCol[nCol].SetFormulaCell(nRow, pCell, sc::ConvertToGroupListening);
}
bool ScTable::SetFormulaCells( SCCOL nCol, SCROW nRow, std::vector<ScFormulaCell*>& rCells )
diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx
index 63e5a6b8802a..7eea13654fad 100644
--- a/sc/source/core/inc/bcaslot.hxx
+++ b/sc/source/core/inc/bcaslot.hxx
@@ -40,6 +40,11 @@ struct AreaListener
ScRange maArea;
bool mbGroupListening;
SvtListener* mpListener;
+
+ struct SortByArea : std::binary_function<AreaListener, AreaListener, bool>
+ {
+ bool operator() ( const AreaListener& rLeft, const AreaListener& rRight ) const;
+ };
};
}
diff --git a/sc/source/core/tool/grouparealistener.cxx b/sc/source/core/tool/grouparealistener.cxx
index e93d2fc92364..4a13398c2e46 100644
--- a/sc/source/core/tool/grouparealistener.cxx
+++ b/sc/source/core/tool/grouparealistener.cxx
@@ -219,18 +219,31 @@ void FormulaGroupAreaListener::collectFormulaCells(
}
}
-#if DEBUG_AREA_BROADCASTER
ScAddress FormulaGroupAreaListener::getTopCellPos() const
{
const ScFormulaCell& rFC = **mppTopCell;
return rFC.aPos;
}
+const ScRange& FormulaGroupAreaListener::getRange() const
+{
+ return maRange;
+}
+
SCROW FormulaGroupAreaListener::getGroupLength() const
{
return mnGroupLen;
}
-#endif
+
+bool FormulaGroupAreaListener::isStartFixed() const
+{
+ return mbStartFixed;
+}
+
+bool FormulaGroupAreaListener::isEndFixed() const
+{
+ return mbEndFixed;
+}
void FormulaGroupAreaListener::notifyCellChange( const SfxHint& rHint, const ScAddress& rPos )
{
diff --git a/sc/source/core/tool/stringutil.cxx b/sc/source/core/tool/stringutil.cxx
index ce83c33d6af5..158b54f1a3d5 100644
--- a/sc/source/core/tool/stringutil.cxx
+++ b/sc/source/core/tool/stringutil.cxx
@@ -29,7 +29,8 @@ ScSetStringParam::ScSetStringParam() :
mpNumFormatter(NULL),
mbDetectNumberFormat(true),
meSetTextNumFormat(Never),
- mbHandleApostrophe(true)
+ mbHandleApostrophe(true),
+ meStartListening(sc::SingleCellListening)
{
}
diff --git a/sc/source/ui/undo/refundo.cxx b/sc/source/ui/undo/refundo.cxx
index 623e7b6a7a18..a5c38548d337 100644
--- a/sc/source/ui/undo/refundo.cxx
+++ b/sc/source/ui/undo/refundo.cxx
@@ -35,28 +35,36 @@
#include <refupdatecontext.hxx>
ScRefUndoData::ScRefUndoData( const ScDocument* pDoc ) :
- pUnoRefs( NULL )
+ pDBCollection(NULL),
+ pRangeName(NULL),
+ pPrintRanges(pDoc->CreatePrintRangeSaver()),
+ pDPCollection(NULL),
+ pDetOpList(NULL),
+ pChartListenerCollection(NULL),
+ pAreaLinks(NULL),
+ pUnoRefs(NULL)
{
- ScDBCollection* pOldDBColl = pDoc->GetDBCollection();
- pDBCollection = pOldDBColl ? new ScDBCollection(*pOldDBColl) : NULL;
+ const ScDBCollection* pOldDBColl = pDoc->GetDBCollection();
+ if (pOldDBColl && !pOldDBColl->empty())
+ pDBCollection = new ScDBCollection(*pOldDBColl);
- ScRangeName* pOldRanges = ((ScDocument*)pDoc)->GetRangeName(); //! const
- pRangeName = pOldRanges ? new ScRangeName(*pOldRanges) : NULL;
-
- pPrintRanges = pDoc->CreatePrintRangeSaver(); // recreated
+ const ScRangeName* pOldRanges = pDoc->GetRangeName();
+ if (pOldRanges && !pOldRanges->empty())
+ pRangeName = new ScRangeName(*pOldRanges);
// when handling Pivot solely keep the range?
- ScDPCollection* pOldDP = ((ScDocument*)pDoc)->GetDPCollection(); //! const
- pDPCollection = pOldDP ? new ScDPCollection(*pOldDP) : NULL;
+ const ScDPCollection* pOldDP = pDoc->GetDPCollection();
+ if (pOldDP && pOldDP->GetCount())
+ pDPCollection = new ScDPCollection(*pOldDP);
- ScDetOpList* pOldDetOp = pDoc->GetDetOpList();
- pDetOpList = pOldDetOp ? new ScDetOpList(*pOldDetOp) : 0;
+ const ScDetOpList* pOldDetOp = pDoc->GetDetOpList();
+ if (pOldDetOp && pOldDetOp->Count())
+ pDetOpList = new ScDetOpList(*pOldDetOp);
- ScChartListenerCollection* pOldChartListenerCollection =
- pDoc->GetChartListenerCollection();
- pChartListenerCollection = pOldChartListenerCollection ?
- new ScChartListenerCollection( *pOldChartListenerCollection ) : NULL;
+ const ScChartListenerCollection* pOldChartLisColl = pDoc->GetChartListenerCollection();
+ if (pOldChartLisColl)
+ pChartListenerCollection = new ScChartListenerCollection(*pOldChartLisColl);
pAreaLinks = ScAreaLinkSaveCollection::CreateFromDoc(pDoc); // returns NULL if empty
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index c0dfe4f4e69f..8399a79d40a5 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -21,7 +21,7 @@
#include <svl/listener.hxx>
#include <svl/smplhint.hxx>
-void SvtBroadcaster::Normalize()
+void SvtBroadcaster::Normalize() const
{
if (!mbNormalized)
{
@@ -140,11 +140,13 @@ void SvtBroadcaster::ListenersGone() {}
SvtBroadcaster::ListenersType& SvtBroadcaster::GetAllListeners()
{
+ Normalize();
return maListeners;
}
const SvtBroadcaster::ListenersType& SvtBroadcaster::GetAllListeners() const
{
+ Normalize();
return maListeners;
}