fdo#74322: Handle moving of named ranges correctly.

But named ranges are adjusted if and only if the references are absolute.

Change-Id: I6c5287b413884b045f1a798c6c6683aa17863f24
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index eb68997..e8b96cc 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -163,6 +163,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 5c196a0..e08766e 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2537,8 +2537,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 320a2c2..b4b3ddf 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2833,7 +2833,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 f1982bd..e2a0fdb 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:
                ;
        }
@@ -2967,6 +2977,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;
@@ -3029,6 +3042,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 )
@@ -3112,17 +3186,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:
@@ -3165,17 +3230,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:
@@ -3239,17 +3295,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: