summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/formulacell.hxx12
-rw-r--r--sc/inc/listenercontext.hxx11
-rw-r--r--sc/inc/refupdatecontext.hxx18
-rw-r--r--sc/source/core/data/column.cxx234
-rw-r--r--sc/source/core/data/formulacell.cxx17
-rw-r--r--sc/source/core/data/listenercontext.cxx24
-rw-r--r--sc/source/core/tool/token.cxx17
-rw-r--r--sc/source/ui/inc/undoblk.hxx5
-rw-r--r--sc/source/ui/undo/undoblk.cxx19
9 files changed, 293 insertions, 64 deletions
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index e901c6e2b10e..7e40ddd33bc2 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -141,12 +141,6 @@ private:
const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
/**
- * Update reference in response to cell move.
- */
- bool UpdateReferenceOnMove(
- const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
-
- /**
* Update reference in response to cell copy-n-paste.
*/
bool UpdateReferenceOnCopy(
@@ -252,6 +246,12 @@ public:
bool UpdateReference(
const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = NULL, const ScAddress* pUndoCellPos = NULL );
+ /**
+ * Update reference in response to cell move.
+ */
+ bool UpdateReferenceOnMove(
+ const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
+
void TransposeReference();
void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
ScDocument* pUndoDoc );
diff --git a/sc/inc/listenercontext.hxx b/sc/inc/listenercontext.hxx
index 1e7d067f6f9f..c0260ef8be1a 100644
--- a/sc/inc/listenercontext.hxx
+++ b/sc/inc/listenercontext.hxx
@@ -17,6 +17,7 @@
#include <boost/scoped_ptr.hpp>
class ScDocument;
+class ScTokenArray;
namespace sc {
@@ -39,9 +40,17 @@ class EndListeningContext : boost::noncopyable
ScDocument& mrDoc;
ColumnSpanSet maSet;
boost::scoped_ptr<ColumnBlockPositionSet> mpPosSet;
+ ScTokenArray* mpOldCode;
+ ScAddress maPosDelta; // Add this to get the old position prior to the move.
+
public:
- EndListeningContext(ScDocument& rDoc);
+ EndListeningContext(ScDocument& rDoc, ScTokenArray* pOldCode = NULL);
+
+ void setPositionDelta( const ScAddress& rDelta );
+
ScDocument& getDoc();
+ ScTokenArray* getOldCode();
+ ScAddress getOldPosition( const ScAddress& rPos ) const;
ColumnBlockPosition* getBlockPosition(SCTAB nTab, SCCOL nCol);
diff --git a/sc/inc/refupdatecontext.hxx b/sc/inc/refupdatecontext.hxx
index ba0beedbc161..c8e52d8acdf0 100644
--- a/sc/inc/refupdatecontext.hxx
+++ b/sc/inc/refupdatecontext.hxx
@@ -55,7 +55,8 @@ struct RefUpdateContext
/**
* Range of cells that are about to be moved for insert/delete/move modes.
* For copy mode, it's the destination range of cells that are about to be
- * pasted.
+ * pasted. When moving a range of cells, it's the destination range, not
+ * the source range.
*/
ScRange maRange;
@@ -77,8 +78,23 @@ struct RefUpdateContext
struct RefUpdateResult
{
+ /**
+ * When this flag is true, the result of the formula needs to be
+ * re-calculated either because it contains a reference that's been
+ * deleted, or the size of a range reference has changed.
+ */
bool mbValueChanged;
+
+ /**
+ * This flag indicates whether any reference in the token array has been
+ * modified.
+ */
bool mbReferenceModified;
+
+ /**
+ * When this flag is true, it indicates that the token array contains a
+ * range name that's been updated.
+ */
bool mbNameModified;
RefUpdateResult();
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 47ef9cbdde62..db8cf962eac0 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -41,6 +41,7 @@
#include "scopetools.hxx"
#include "sharedformula.hxx"
#include "refupdatecontext.hxx"
+#include <listenercontext.hxx>
#include <svl/poolcach.hxx>
#include <svl/zforlist.hxx>
@@ -2328,6 +2329,67 @@ void ScColumn::MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCROW nRow1, SCROW nR
namespace {
+struct FormulaGroup
+{
+ struct {
+ ScFormulaCell* mpCell; // non-shared formula cell
+ ScFormulaCell** mpCells; // pointer to the top formula cell in a shared group.
+ };
+ size_t mnRow;
+ size_t mnLength;
+ bool mbShared;
+
+ FormulaGroup( ScFormulaCell** pCells, size_t nRow, size_t nLength ) :
+ mpCells(pCells), mnRow(nRow), mnLength(nLength), mbShared(true) {}
+
+ FormulaGroup( ScFormulaCell* pCell, size_t nRow ) :
+ mpCell(pCell), mnRow(nRow), mnLength(0), mbShared(false) {}
+};
+
+class SharedTopFormulaCellPicker : std::unary_function<sc::CellStoreType::value_type, void>
+{
+public:
+ virtual ~SharedTopFormulaCellPicker() {}
+
+ void operator() ( sc::CellStoreType::value_type& node )
+ {
+ if (node.type != sc::element_type_formula)
+ return;
+
+ size_t nTopRow = node.position;
+
+ sc::formula_block::iterator itBeg = sc::formula_block::begin(*node.data);
+ sc::formula_block::iterator itEnd = sc::formula_block::end(*node.data);
+
+ // Only pick shared formula cells that are the top cells of their
+ // respective shared ranges.
+ for (sc::formula_block::iterator it = itBeg; it != itEnd; ++it)
+ {
+ ScFormulaCell* pCell = *it;
+ size_t nRow = nTopRow + std::distance(itBeg, it);
+ if (!pCell->IsShared())
+ {
+ processNonShared(pCell, nRow);
+ continue;
+ }
+
+ if (pCell->IsSharedTop())
+ {
+ ScFormulaCell** pp = &(*it);
+ processSharedTop(pp, nRow, pCell->GetSharedLength());
+
+ // Move to the last cell in the group, to get incremented to
+ // the next cell in the next iteration.
+ size_t nOffsetToLast = pCell->GetSharedLength() - 1;
+ std::advance(it, nOffsetToLast);
+ }
+ }
+ }
+
+ virtual void processNonShared( ScFormulaCell* /*pCell*/, size_t /*nRow*/ ) {}
+ virtual void processSharedTop( ScFormulaCell** /*ppCells*/, size_t /*nRow*/, size_t /*nLength*/ ) {}
+};
+
class UpdateRefOnCopy
{
const sc::RefUpdateContext& mrCxt;
@@ -2358,67 +2420,162 @@ public:
}
};
-class UpdateRefOnNonCopy
+class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void>
{
SCCOL mnCol;
SCROW mnTab;
- const sc::RefUpdateContext& mrCxt;
+ const sc::RefUpdateContext* mpCxt;
ScDocument* mpUndoDoc;
bool mbUpdated;
+ void updateRefOnMove( FormulaGroup& rGroup )
+ {
+ if (!rGroup.mbShared)
+ {
+ ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
+ mbUpdated |= rGroup.mpCell->UpdateReferenceOnMove(*mpCxt, mpUndoDoc, &aUndoPos);
+ return;
+ }
+
+ // Update references of a formula group.
+ ScFormulaCell** pp = rGroup.mpCells;
+ ScFormulaCell** ppEnd = pp + rGroup.mnLength;
+ ScFormulaCell* pTop = *pp;
+ ScTokenArray* pCode = pTop->GetCode();
+ boost::scoped_ptr<ScTokenArray> pOldCode(pCode->Clone());
+
+ ScAddress aPos = pTop->aPos;
+ ScAddress aOldPos = aPos;
+
+ if (mpCxt->maRange.In(aPos))
+ {
+ // The cell is being moved or copied to a new position. The
+ // position has already been updated prior to this call.
+ // Determine its original position before the move which will be
+ // used to adjust relative references later.
+
+ aOldPos.Set(
+ aPos.Col() - mpCxt->mnColDelta,
+ aPos.Row() - mpCxt->mnRowDelta,
+ aPos.Tab() - mpCxt->mnTabDelta);
+ }
+
+ bool bRecalcOnMove = pCode->IsRecalcModeOnRefMove();
+ if (bRecalcOnMove)
+ bRecalcOnMove = aPos != aOldPos;
+
+ sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(*mpCxt, aOldPos, aPos);
+ if (aRes.mbReferenceModified || bRecalcOnMove)
+ {
+ // Perform end-listening, start-listening, and dirtying on all
+ // formula cells in the group.
+
+ sc::StartListeningContext aStartCxt(mpCxt->mrDoc);
+
+ sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pOldCode.get());
+ aEndCxt.setPositionDelta(
+ ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
+
+ for (; pp != ppEnd; ++pp)
+ {
+ ScFormulaCell* p = *pp;
+ p->EndListeningTo(aEndCxt);
+ p->StartListeningTo(aStartCxt);
+ p->SetDirty();
+ }
+
+ if (mpUndoDoc)
+ {
+ // Insert the old formula group into the undo document.
+ ScAddress aUndoPos = aOldPos;
+ ScFormulaCell* pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, pOldCode->Clone());
+ ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(rGroup.mnLength, false);
+
+ mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
+ aUndoPos.IncRow();
+ for (size_t i = 1; i < rGroup.mnLength; ++i, aUndoPos.IncRow())
+ {
+ pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, xGroup);
+ mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
+ }
+ }
+ }
+ }
+
public:
UpdateRefOnNonCopy(
- SCCOL nCol, SCTAB nTab, const sc::RefUpdateContext& rCxt,
+ SCCOL nCol, SCTAB nTab, const sc::RefUpdateContext* pCxt,
ScDocument* pUndoDoc) :
- mnCol(nCol), mnTab(nTab), mrCxt(rCxt),
+ mnCol(nCol), mnTab(nTab), mpCxt(pCxt),
mpUndoDoc(pUndoDoc), mbUpdated(false) {}
- void operator() (size_t nRow, ScFormulaCell* pCell)
+ void operator() ( FormulaGroup& rGroup )
{
- ScAddress aUndoPos(mnCol, nRow, mnTab);
- mbUpdated |= pCell->UpdateReference(mrCxt, mpUndoDoc, &aUndoPos);
+ if (mpCxt->meMode == URM_MOVE)
+ {
+ updateRefOnMove(rGroup);
+ return;
+ }
+
+ if (rGroup.mbShared)
+ {
+ ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
+ ScFormulaCell** pp = rGroup.mpCells;
+ ScFormulaCell** ppEnd = pp + rGroup.mnLength;
+ for (; pp != ppEnd; ++pp, aUndoPos.IncRow())
+ {
+ ScFormulaCell* p = *pp;
+ mbUpdated |= p->UpdateReference(*mpCxt, mpUndoDoc, &aUndoPos);
+ }
+ }
+ else
+ {
+ ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
+ mbUpdated |= rGroup.mpCell->UpdateReference(*mpCxt, mpUndoDoc, &aUndoPos);
+ }
}
bool isUpdated() const { return mbUpdated; }
};
-class UpdateRefGroupBoundChecker : std::unary_function<sc::CellStoreType::value_type, void>
+class UpdateRefGroupBoundChecker : public SharedTopFormulaCellPicker
{
const sc::RefUpdateContext& mrCxt;
std::vector<SCROW>& mrBounds;
+
public:
UpdateRefGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
mrCxt(rCxt), mrBounds(rBounds) {}
- void operator() (const sc::CellStoreType::value_type& node)
+ virtual ~UpdateRefGroupBoundChecker() {}
+
+ virtual void processSharedTop( ScFormulaCell** ppCells, size_t /*nRow*/, size_t /*nLength*/ )
{
- if (node.type != sc::element_type_formula)
- return;
+ // Check its tokens and record its reference boundaries.
+ ScFormulaCell& rCell = **ppCells;
+ const ScTokenArray& rCode = *rCell.GetCode();
+ rCode.CheckRelativeReferenceBounds(
+ mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
+ }
+};
- sc::formula_block::const_iterator it = sc::formula_block::begin(*node.data);
- sc::formula_block::const_iterator itEnd = sc::formula_block::end(*node.data);
+class FormulaGroupPicker : public SharedTopFormulaCellPicker
+{
+ std::vector<FormulaGroup>& mrGroups;
- // Only pick shared formula cells that are the top cells of their
- // respective shared ranges.
- for (; it != itEnd; ++it)
- {
- const ScFormulaCell& rCell = **it;
- if (!rCell.IsShared())
- continue;
+public:
+ FormulaGroupPicker( std::vector<FormulaGroup>& rGroups ) : mrGroups(rGroups) {}
- if (rCell.IsSharedTop())
- {
- // Check its tokens and record its reference boundaries.
- const ScTokenArray& rCode = *rCell.GetCode();
- rCode.CheckRelativeReferenceBounds(
- mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
+ virtual ~FormulaGroupPicker() {}
- // Move to the last cell in the group, to get incremented to
- // the next cell in the next iteration.
- size_t nOffsetToLast = rCell.GetSharedLength() - 1;
- std::advance(it, nOffsetToLast);
- }
- }
+ virtual void processNonShared( ScFormulaCell* pCell, size_t nRow )
+ {
+ mrGroups.push_back(FormulaGroup(pCell, nRow));
+ }
+
+ virtual void processSharedTop( ScFormulaCell** ppCells, size_t nRow, size_t nLength )
+ {
+ mrGroups.push_back(FormulaGroup(ppCells, nRow, nLength));
}
};
@@ -2451,8 +2608,8 @@ bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc
if (rCxt.meMode == URM_COPY)
return UpdateReferenceOnCopy(rCxt, pUndoDoc);
- if (IsEmptyData())
- // Cells in this column are all empty.
+ if (IsEmptyData() || pDocument->IsClipOrUndo())
+ // Cells in this column are all empty, or clip or undo doc. No update needed.
return false;
std::vector<SCROW> aBounds;
@@ -2490,8 +2647,13 @@ bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc
// Do the actual splitting.
sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
- UpdateRefOnNonCopy aHandler(nCol, nTab, rCxt, pUndoDoc);
- sc::ProcessFormula(maCells, aHandler);
+ // Collect all formula groups.
+ std::vector<FormulaGroup> aGroups;
+ std::for_each(maCells.begin(), maCells.end(), FormulaGroupPicker(aGroups));
+
+ // Process all collected formula groups.
+ UpdateRefOnNonCopy aHandler(nCol, nTab, &rCxt, pUndoDoc);
+ aHandler = std::for_each(aGroups.begin(), aGroups.end(), aHandler);
if (aHandler.isUpdated())
rCxt.maRegroupCols.set(nTab, nCol);
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 0de5c8729506..6da276a7f6f9 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3944,7 +3944,7 @@ void ScFormulaCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr,
{
case svSingleRef:
{
- ScAddress aCell = t->GetSingleRef().toAbs(aPos);
+ ScAddress aCell = t->GetSingleRef().toAbs(aCellPos);
if (aCell.IsValid())
pDoc->EndListeningCell(aCell, this);
}
@@ -3966,27 +3966,32 @@ void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt )
ScDocument& rDoc = rCxt.getDoc();
rDoc.SetDetectiveDirty(true); // It has changed something
- if (pCode->IsRecalcModeAlways())
+ ScTokenArray* pArr = rCxt.getOldCode();
+ ScAddress aCellPos = rCxt.getOldPosition(aPos);
+ if (!pArr)
+ pArr = pCode;
+
+ if (pArr->IsRecalcModeAlways())
{
rDoc.EndListeningArea(BCA_LISTEN_ALWAYS, this);
return;
}
- pCode->Reset();
+ pArr->Reset();
ScToken* t;
- while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceRPN()) ) != NULL )
+ while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
{
switch (t->GetType())
{
case svSingleRef:
{
- ScAddress aCell = t->GetSingleRef().toAbs(aPos);
+ ScAddress aCell = t->GetSingleRef().toAbs(aCellPos);
if (aCell.IsValid())
rDoc.EndListeningCell(rCxt, aCell, *this);
}
break;
case svDoubleRef:
- endListeningArea(this, rDoc, aPos, *t);
+ endListeningArea(this, rDoc, aCellPos, *t);
break;
default:
; // nothing
diff --git a/sc/source/core/data/listenercontext.cxx b/sc/source/core/data/listenercontext.cxx
index dc9234681acb..3dfe5edb0b37 100644
--- a/sc/source/core/data/listenercontext.cxx
+++ b/sc/source/core/data/listenercontext.cxx
@@ -52,14 +52,34 @@ ColumnBlockPosition* StartListeningContext::getBlockPosition(SCTAB nTab, SCCOL n
return mpSet->getBlockPosition(nTab, nCol);
}
-EndListeningContext::EndListeningContext(ScDocument& rDoc) :
- mrDoc(rDoc), maSet(false), mpPosSet(new ColumnBlockPositionSet(rDoc)) {}
+EndListeningContext::EndListeningContext(ScDocument& rDoc, ScTokenArray* pOldCode) :
+ mrDoc(rDoc), maSet(false), mpPosSet(new ColumnBlockPositionSet(rDoc)),
+ mpOldCode(pOldCode), maPosDelta(0,0,0) {}
+
+void EndListeningContext::setPositionDelta( const ScAddress& rDelta )
+{
+ maPosDelta = rDelta;
+}
ScDocument& EndListeningContext::getDoc()
{
return mrDoc;
}
+ScTokenArray* EndListeningContext::getOldCode()
+{
+ return mpOldCode;
+}
+
+ScAddress EndListeningContext::getOldPosition( const ScAddress& rPos ) const
+{
+ ScAddress aOldPos = rPos;
+ aOldPos.IncCol(maPosDelta.Col());
+ aOldPos.IncRow(maPosDelta.Row());
+ aOldPos.IncTab(maPosDelta.Tab());
+ return aOldPos;
+}
+
ColumnBlockPosition* EndListeningContext::getBlockPosition(SCTAB nTab, SCCOL nCol)
{
return mpPosSet->getBlockPosition(nTab, nCol);
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index fc9ad75e476d..92a9c77be623 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -3155,17 +3155,22 @@ void checkBounds(
if (!rRef.IsRowRel())
return;
+ ScRange aCheckRange = rCxt.maRange;
+ if (rCxt.meMode == URM_MOVE)
+ // Check bounds against the old range prior to the move.
+ aCheckRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
+
ScRange aAbs(rRef.toAbs(rPos));
aAbs.aEnd.IncRow(nGroupLen-1);
- if (!rCxt.maRange.Intersects(aAbs))
+ if (!aCheckRange.Intersects(aAbs))
return;
// Get the boundary row positions.
- if (aAbs.aEnd.Row() < rCxt.maRange.aStart.Row())
+ if (aAbs.aEnd.Row() < aCheckRange.aStart.Row())
// No intersections.
return;
- if (aAbs.aStart.Row() <= rCxt.maRange.aStart.Row())
+ if (aAbs.aStart.Row() <= aCheckRange.aStart.Row())
{
// +-+ <---- top
// | |
@@ -3175,11 +3180,11 @@ void checkBounds(
// +-------+
// Add offset from the reference top to the cell position.
- SCROW nOffset = rCxt.maRange.aStart.Row() - aAbs.aStart.Row();
+ SCROW nOffset = aCheckRange.aStart.Row() - aAbs.aStart.Row();
rBounds.push_back(rPos.Row()+nOffset);
}
- if (aAbs.aEnd.Row() >= rCxt.maRange.aEnd.Row())
+ if (aAbs.aEnd.Row() >= aCheckRange.aEnd.Row())
{
// only check for end range
@@ -3191,7 +3196,7 @@ void checkBounds(
// +-+
// Ditto.
- SCROW nOffset = rCxt.maRange.aEnd.Row() + 1 - aAbs.aStart.Row();
+ SCROW nOffset = aCheckRange.aEnd.Row() + 1 - aAbs.aStart.Row();
rBounds.push_back(rPos.Row()+nOffset);
}
}
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index 1b10216b3ebd..758e5bb91357 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -239,6 +239,9 @@ public:
virtual OUString GetComment() const;
private:
+ sal_uInt16 mnPaintExtFlags;
+ ScRangeList maPaintRanges;
+
ScRange aSrcRange;
ScRange aDestRange;
sal_uLong nStartChangeAction;
@@ -247,7 +250,7 @@ private:
sal_Bool bKeepScenarioFlags;
void PaintArea( ScRange aRange, sal_uInt16 nExtFlags ) const;
- void DoUndo( ScRange aRange ) const;
+ void DoUndo( ScRange aRange );
void SetChangeTrack();
};
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 6497f0e17849..aebdb3ee9afc 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -1218,7 +1218,7 @@ void ScUndoDragDrop::PaintArea( ScRange aRange, sal_uInt16 nExtFlags ) const
pDocShell->PostPaint( aRange, nPaint, nExtFlags );
}
-void ScUndoDragDrop::DoUndo( ScRange aRange ) const
+void ScUndoDragDrop::DoUndo( ScRange aRange )
{
ScDocument* pDoc = pDocShell->GetDocument();
@@ -1231,8 +1231,7 @@ void ScUndoDragDrop::DoUndo( ScRange aRange ) const
ScRange aPaintRange = aRange;
pDoc->ExtendMerge( aPaintRange ); // before deleting
- sal_uInt16 nExtFlags = 0;
- pDocShell->UpdatePaintExt( nExtFlags, aPaintRange );
+ pDocShell->UpdatePaintExt(mnPaintExtFlags, aPaintRange);
// do not undo objects and note captions, they are handled via drawing undo
sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
@@ -1245,16 +1244,26 @@ void ScUndoDragDrop::DoUndo( ScRange aRange ) const
aPaintRange.aEnd.SetCol( std::max( aPaintRange.aEnd.Col(), aRange.aEnd.Col() ) );
aPaintRange.aEnd.SetRow( std::max( aPaintRange.aEnd.Row(), aRange.aEnd.Row() ) );
- pDocShell->UpdatePaintExt( nExtFlags, aPaintRange );
- PaintArea( aPaintRange, nExtFlags );
+ pDocShell->UpdatePaintExt(mnPaintExtFlags, aPaintRange);
+ maPaintRanges.Join(aPaintRange);
}
void ScUndoDragDrop::Undo()
{
+ mnPaintExtFlags = 0;
+ maPaintRanges.RemoveAll();
+
BeginUndo();
DoUndo(aDestRange);
if (bCut)
DoUndo(aSrcRange);
+
+ for (size_t i = 0; i < maPaintRanges.size(); ++i)
+ {
+ const ScRange* p = maPaintRanges[i];
+ PaintArea(*p, mnPaintExtFlags);
+ }
+
EndUndo();
SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
}