diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-02-28 21:25:01 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-02-28 21:28:57 -0500 |
commit | f32df2d590d0ee14f09664934457ba9e8de8cbe6 (patch) | |
tree | 931668661a90fbe8c6b8148e72ef218272fc7e17 /sc | |
parent | aa6c5b7faecdb57cbdeac051e304531c1a1cf63b (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
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/formulacell.hxx | 22 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 109 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 6 | ||||
-rw-r--r-- | sc/source/core/tool/compiler.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 31 |
5 files changed, 144 insertions, 28 deletions
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 42e00a9cdc55..f75895b4af4d 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, @@ -246,6 +239,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 4b8d38cd934b..b7fd47958f04 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 a872e91c8756..d0ebd2fa789e 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -957,6 +957,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 afb8f5fd77a5..68f2ba5fba4f 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -769,13 +769,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 7052049a9f44..c7c8e42314d5 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); |