summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-02-28 21:25:01 -0500
committerFridrich Strba <fridrich@documentfoundation.org>2014-03-03 08:00:16 -0600
commitcb83b334e489a4ec1cc067145c3f64b129475e7f (patch)
treea4e3e1871aac423c51ade747430153ac17933ac2
parent4040c461fc244940c6817770104ccbcc013ac1f3 (diff)
fdo#75053: Adjust reference update on shift for formula groups.
This is similar to my earlier fix for reference update on moving of cells. Change-Id: I592599507bfcab12f611eeae7b56c99da6c31919 (cherry picked from commit f32df2d590d0ee14f09664934457ba9e8de8cbe6) Reviewed-on: https://gerrit.libreoffice.org/8403 Reviewed-by: Fridrich Strba <fridrich@documentfoundation.org> Tested-by: Fridrich Strba <fridrich@documentfoundation.org>
-rw-r--r--sc/inc/formulacell.hxx22
-rw-r--r--sc/source/core/data/column.cxx109
-rw-r--r--sc/source/core/data/formulacell.cxx6
-rw-r--r--sc/source/core/tool/compiler.cxx4
-rw-r--r--sc/source/core/tool/token.cxx31
5 files changed, 144 insertions, 28 deletions
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 7e40ddd33bc2..7361b66c3120 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -132,14 +132,6 @@ private:
};
void InterpretTail( ScInterpretTailParameter );
- bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
-
- /**
- * Update reference in response to cell insertion or deletion.
- */
- bool UpdateReferenceOnShift(
- const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
-
/**
* Update reference in response to cell copy-n-paste.
*/
@@ -213,6 +205,7 @@ public:
void ResetDirty();
bool NeedsListening() const;
void SetNeedsListening( bool bVar );
+ void SetNeedsDirty( bool bVar );
void SetNeedNumberFormat( bool bVal );
short GetFormatType() const;
void Compile(const OUString& rFormula,
@@ -247,6 +240,19 @@ public:
const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = NULL, const ScAddress* pUndoCellPos = NULL );
/**
+ * Shift the position of formula cell as part of reference update.
+ *
+ * @return true if the position has shifted, false otherwise.
+ */
+ bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
+
+ /**
+ * Update reference in response to cell insertion or deletion.
+ */
+ bool UpdateReferenceOnShift(
+ const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
+
+ /**
* Update reference in response to cell move.
*/
bool UpdateReferenceOnMove(
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index db8cf962eac0..e573defa3087 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2428,6 +2428,68 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void>
ScDocument* mpUndoDoc;
bool mbUpdated;
+ void updateRefOnShift( FormulaGroup& rGroup )
+ {
+ if (!rGroup.mbShared)
+ {
+ ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
+ mbUpdated |= rGroup.mpCell->UpdateReferenceOnShift(*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 aOldPos = pTop->aPos;
+
+ // Run this before the position gets updated.
+ sc::RefUpdateResult aRes = pCode->AdjustReferenceOnShift(*mpCxt, aOldPos);
+
+ if (pTop->UpdatePosOnShift(*mpCxt))
+ {
+ // Update the positions of all formula cells.
+ for (++pp; pp != ppEnd; ++pp) // skip the top cell.
+ {
+ ScFormulaCell* pFC = *pp;
+ pFC->aPos.Move(mpCxt->mnColDelta, mpCxt->mnRowDelta, mpCxt->mnTabDelta);
+ }
+
+ if (pCode->IsRecalcModeOnRefMove())
+ aRes.mbValueChanged = true;
+ }
+
+ if (aRes.mbReferenceModified)
+ {
+ sc::StartListeningContext aStartCxt(mpCxt->mrDoc);
+ sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pOldCode.get());
+ aEndCxt.setPositionDelta(
+ ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
+
+ for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
+ {
+ ScFormulaCell* p = *pp;
+ p->EndListeningTo(aEndCxt);
+ p->SetNeedsListening(true);
+ }
+
+ mbUpdated = true;
+
+ fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
+ }
+
+ if (aRes.mbValueChanged)
+ {
+ for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
+ {
+ ScFormulaCell* p = *pp;
+ p->SetNeedsDirty(true);
+ }
+ }
+ }
+
void updateRefOnMove( FormulaGroup& rGroup )
{
if (!rGroup.mbShared)
@@ -2484,21 +2546,26 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void>
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);
- }
- }
+ fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
+ }
+ }
+
+ void fillUndoDoc( const ScAddress& rOldPos, SCROW nLength, const ScTokenArray& rOldCode )
+ {
+ if (!mpUndoDoc)
+ return;
+
+ // Insert the old formula group into the undo document.
+ ScAddress aUndoPos = rOldPos;
+ ScFormulaCell* pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, rOldCode.Clone());
+ ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false);
+
+ mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
+ aUndoPos.IncRow();
+ for (SCROW i = 1; i < nLength; ++i, aUndoPos.IncRow())
+ {
+ pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, xGroup);
+ mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
}
}
@@ -2511,10 +2578,16 @@ public:
void operator() ( FormulaGroup& rGroup )
{
- if (mpCxt->meMode == URM_MOVE)
+ switch (mpCxt->meMode)
{
- updateRefOnMove(rGroup);
- return;
+ case URM_INSDEL:
+ updateRefOnShift(rGroup);
+ return;
+ case URM_MOVE:
+ updateRefOnMove(rGroup);
+ return;
+ default:
+ ;
}
if (rGroup.mbShared)
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 6da276a7f6f9..d7335259dcc3 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -958,6 +958,12 @@ bool ScFormulaCell::GetDirty() const { return bDirty; }
void ScFormulaCell::ResetDirty() { bDirty = bTableOpDirty = mbPostponedDirty = false; }
bool ScFormulaCell::NeedsListening() const { return bNeedListening; }
void ScFormulaCell::SetNeedsListening( bool bVar ) { bNeedListening = bVar; }
+
+void ScFormulaCell::SetNeedsDirty( bool bVar )
+{
+ mbPostponedDirty = bVar;
+}
+
void ScFormulaCell::SetNeedNumberFormat( bool bVal ) { mbNeedsNumberFormat = bVal; }
short ScFormulaCell::GetFormatType() const { return nFormatType; }
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 4c63a4ba2efb..fa133d3699b9 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -770,13 +770,13 @@ struct ConventionOOO_A1 : public Convention_A1
rBuffer.append('.');
if (!rRef.IsColRel())
rBuffer.append('$');
- if (!ValidCol(rAbsRef.Col()))
+ if (!ValidCol(rAbsRef.Col()) || rRef.IsColDeleted())
rBuffer.append(rErrRef);
else
MakeColStr(rBuffer, rAbsRef.Col());
if (!rRef.IsRowRel())
rBuffer.append('$');
- if (!ValidRow(rAbsRef.Row()))
+ if (!ValidRow(rAbsRef.Row()) || rRef.IsRowDeleted())
rBuffer.append(rErrRef);
else
MakeRowStr(rBuffer, rAbsRef.Row());
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 92a9c77be623..eb2acb9624a7 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2480,6 +2480,25 @@ void setRefDeleted( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
rRef.SetTabDeleted(true);
}
+void restoreDeletedRef( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
+{
+ if (rCxt.mnColDelta)
+ {
+ if (rRef.IsColDeleted())
+ rRef.SetColDeleted(false);
+ }
+ else if (rCxt.mnRowDelta)
+ {
+ if (rRef.IsRowDeleted())
+ rRef.SetRowDeleted(false);
+ }
+ else if (rCxt.mnTabDelta)
+ {
+ if (rRef.IsTabDeleted())
+ rRef.SetTabDeleted(false);
+ }
+}
+
void setRefDeleted( ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt )
{
if (rCxt.mnColDelta < 0)
@@ -2647,6 +2666,18 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
break;
}
+ if (!rCxt.isDeleted() && rRef.IsDeleted())
+ {
+ // Check if the token has reference to previously deleted region.
+ ScAddress aCheckPos = rRef.toAbs(aNewPos);
+ if (rCxt.maRange.In(aCheckPos))
+ {
+ restoreDeletedRef(rRef, rCxt);
+ aRes.mbValueChanged = true;
+ break;
+ }
+ }
+
if (rCxt.maRange.In(aAbs))
{
aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);