sc/inc/tokenarray.hxx | 2 sc/source/core/data/column.cxx | 15 +++- sc/source/core/data/formulacell.cxx | 2 sc/source/core/tool/token.cxx | 135 ++++++++++++++++++++++++------------ 4 files changed, 108 insertions(+), 46 deletions(-)
New commits: commit 0568f9f55b0054629e86561e96e78ecf13a8df5f Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Tue Mar 25 22:34:18 2014 -0400 fdo#74322: Handle moving of named ranges correctly. But named ranges are adjusted if and only if the references are absolute. Change-Id: I6c5287b413884b045f1a798c6c6683aa17863f24 (cherry picked from commit 003a27a14d5cf65fe0b528b6d6015e37a64dbb8e) Reviewed-on: https://gerrit.libreoffice.org/8756 Reviewed-by: Andras Timar <andras.ti...@collabora.com> Tested-by: Andras Timar <andras.ti...@collabora.com> diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index 58ff8d4..5b3e080 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -164,6 +164,8 @@ public: */ sc::RefUpdateResult AdjustReferenceInName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ); + sc::RefUpdateResult AdjustReferenceInMovedName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ); + /** * Adjust all references on sheet deletion. * diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 7a448fd..518766d 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2529,8 +2529,21 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void> bRecalcOnMove = aPos != aOldPos; sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(*mpCxt, aOldPos, aPos); - if (aRes.mbReferenceModified || bRecalcOnMove) + + if (aRes.mbReferenceModified || aRes.mbNameModified || bRecalcOnMove) { + sc::AutoCalcSwitch(mpCxt->mrDoc, false); + + if (aRes.mbNameModified) + { + // We need to re-compile the token array when a range name is + // modified, to correctly reflect the new references in the + // name. + ScCompiler aComp(&mpCxt->mrDoc, aPos, *pCode); + aComp.SetGrammar(mpCxt->mrDoc.GetGrammar()); + aComp.CompileTokenArray(); + } + // Perform end-listening, start-listening, and dirtying on all // formula cells in the group. diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index eb40441..10c4c14 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2801,7 +2801,7 @@ bool ScFormulaCell::UpdateReferenceOnMove( { // Update cell or range references. sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(rCxt, aOldPos, aPos); - bRefModified = aRes.mbReferenceModified; + bRefModified = aRes.mbReferenceModified || aRes.mbNameModified; bValChanged = aRes.mbValueChanged; } diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 77cc06d..5618ed38 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2634,6 +2634,19 @@ bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, co return false; } +bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const formula::FormulaToken& rToken ) +{ + if (rToken.GetOpCode() != ocName) + return false; + + SCTAB nTab = -1; + if (!rToken.IsGlobal()) + nTab = nOldTab; + + // Check if this named expression has been modified. + return rUpdatedNames.isNameUpdated(nTab, rToken.GetIndex()); +} + } sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos ) @@ -2772,17 +2785,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: @@ -2837,6 +2841,12 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( rRef.SetRange(aAbs, rNewPos); } break; + case svIndex: + { + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; + } + break; default: ; } @@ -2954,6 +2964,9 @@ bool adjustDoubleRefInName( sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ) { + if (rCxt.meMode == URM_MOVE) + return AdjustReferenceInMovedName(rCxt, rPos); + sc::RefUpdateResult aRes; FormulaToken** p = pCode; @@ -3004,6 +3017,67 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( return aRes; } +sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos ) +{ + // When moving, the range is the destination range. + ScRange aOldRange = rCxt.maRange; + aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta); + + // In a named expression, we'll move the reference only when the reference + // is entirely absolute. + + sc::RefUpdateResult aRes; + + + FormulaToken** p = pCode; + FormulaToken** pEnd = p + static_cast<size_t>(nLen); + for (; p != pEnd; ++p) + { + switch ((*p)->GetType()) + { + case svSingleRef: + { + ScToken* pToken = static_cast<ScToken*>(*p); + ScSingleRefData& rRef = pToken->GetSingleRef(); + if (rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()) + continue; + + ScAddress aAbs = rRef.toAbs(rPos); + if (aOldRange.In(aAbs)) + { + aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); + aRes.mbReferenceModified = true; + } + + rRef.SetAddress(aAbs, rPos); + } + break; + case svDoubleRef: + { + ScToken* pToken = static_cast<ScToken*>(*p); + ScComplexRefData& rRef = pToken->GetDoubleRef(); + if (rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() || + rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel()) + continue; + + ScRange aAbs = rRef.toAbs(rPos); + if (aOldRange.In(aAbs)) + { + aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); + aRes.mbReferenceModified = true; + } + + rRef.SetRange(aAbs, rPos); + } + break; + default: + ; + } + } + + return aRes; +} + namespace { bool adjustSingleRefOnDeletedTab( ScSingleRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos ) @@ -3087,17 +3161,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( sc::RefUpdateDele break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: @@ -3140,17 +3205,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( sc::RefUpdateIns break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: @@ -3214,17 +3270,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( sc::RefUpdateMoveTa break; case svIndex: { - const formula::FormulaToken* pToken = *p; - if (pToken->GetOpCode() == ocName) - { - SCTAB nTab = -1; - if (!pToken->IsGlobal()) - nTab = rOldPos.Tab(); - - // Check if this named expression has been modified. - if (rCxt.maUpdatedNames.isNameUpdated(nTab, pToken->GetIndex())) - aRes.mbNameModified = true; - } + if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p)) + aRes.mbNameModified = true; } break; default: _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits