summaryrefslogtreecommitdiff
path: root/sc
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:49 -0500
commit7d52a5dff557117c0f8710eb27e61b328323ac90 (patch)
treeada43bcb8a7ed736d55c840760bc58135b98f85e /sc
parent847ac84d64cbbebe50d4ac5c21f5bda9e83d7fa4 (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 (cherry picked from commit 0dae7466fff1e742543ef7512b7dd22472c75624)
Diffstat (limited to 'sc')
-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
25 files changed, 427 insertions, 76 deletions
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 dfeda726016f..a34d3fb139f4 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -61,6 +61,7 @@
#include <grouparealistener.hxx>
#include <boost/scoped_ptr.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
using namespace formula;
@@ -382,6 +383,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
@@ -406,7 +441,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),
@@ -450,6 +491,7 @@ ScFormulaCellGroup::~ScFormulaCellGroup()
#endif
delete mpCode;
delete mpCompiledFormula;
+ delete mpImpl;
}
void ScFormulaCellGroup::scheduleCompilation()
@@ -512,24 +554,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