diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-02-28 21:25:01 -0500 |
---|---|---|
committer | Fridrich Strba <fridrich@documentfoundation.org> | 2014-03-03 08:00:16 -0600 |
commit | cb83b334e489a4ec1cc067145c3f64b129475e7f (patch) | |
tree | a4e3e1871aac423c51ade747430153ac17933ac2 | |
parent | 4040c461fc244940c6817770104ccbcc013ac1f3 (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.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 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); |