Resolves: tdf#108788 update references for deletions at end of sheet

ie. when the last column or row is included in the deletion. This seems to have
never worked.

Change-Id: Ic1bd1944298fe248367597177ca01e109585fcd2
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 677eef6..a2d0682 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -983,7 +983,11 @@ void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
void ScDocument::UpdateReference(
    sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, bool bIncludeDraw, bool bUpdateNoteCaptionPos )
{
    if (!ValidRange(rCxt.maRange))
    if (!ValidRange(rCxt.maRange) && !(rCxt.meMode == URM_INSDEL &&
                ((rCxt.mnColDelta < 0 &&    // convention from ScDocument::DeleteCol()
                  rCxt.maRange.aStart.Col() == MAXCOLCOUNT && rCxt.maRange.aEnd.Col() == MAXCOLCOUNT) ||
                 (rCxt.mnRowDelta < 0 &&    // convention from ScDocument::DeleteRow()
                  rCxt.maRange.aStart.Row() == MAXROWCOUNT && rCxt.maRange.aEnd.Row() == MAXROWCOUNT))))
        return;

    std::unique_ptr<sc::ExpandRefsSwitch> pExpandRefsSwitch;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index b0a9538..2627a0c 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1416,12 +1416,21 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
    while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );

    sc::RefUpdateContext aCxt(*this);
    if ( ValidRow(nStartRow+nSize) )
    const bool bLastRowIncluded = (nStartRow + nSize == MAXROWCOUNT && ValidRow(nStartRow));
    if ( ValidRow(nStartRow+nSize) || bLastRowIncluded )
    {
        lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
        aCxt.meMode = URM_INSDEL;
        aCxt.maRange = ScRange(nStartCol, nStartRow+nSize, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
        aCxt.mnRowDelta = -(static_cast<SCROW>(nSize));
        if (bLastRowIncluded)
        {
            // Last row is included, shift a virtually non-existent row in.
            aCxt.maRange = ScRange( nStartCol, MAXROWCOUNT, nTabRangeStart, nEndCol, MAXROWCOUNT, nTabRangeEnd);
        }
        else
        {
            aCxt.maRange = ScRange( nStartCol, nStartRow+nSize, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
        }
        do
        {
            UpdateReference(aCxt, pRefUndoDoc, true, false);
@@ -1447,7 +1456,7 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
    // Mark all joined groups for group listening.
    SetNeedsListeningGroups(aGroupPos);

    if ( ValidRow(nStartRow+nSize) )
    if ( ValidRow(nStartRow+nSize) || bLastRowIncluded )
    {
        // Listeners have been removed in UpdateReference
        StartNeededListeners();
@@ -1616,12 +1625,22 @@ void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTA
    while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );

    sc::RefUpdateContext aCxt(*this);
    if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
    const bool bLastColIncluded = (nStartCol + nSize == MAXCOLCOUNT && ValidCol(nStartCol));
    if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) || bLastColIncluded )
    {
        lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
        aCxt.meMode = URM_INSDEL;
        aCxt.maRange = ScRange(sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart, MAXCOL, nEndRow, nTabRangeEnd);
        aCxt.mnColDelta = -(static_cast<SCCOL>(nSize));
        if (bLastColIncluded)
        {
            // Last column is included, shift a virtually non-existent column in.
            aCxt.maRange = ScRange( MAXCOLCOUNT, nStartRow, nTabRangeStart, MAXCOLCOUNT, nEndRow, nTabRangeEnd);
        }
        else
        {
            aCxt.maRange = ScRange( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart,
                    MAXCOL, nEndRow, nTabRangeEnd);
        }
        do
        {
            UpdateReference(aCxt, pRefUndoDoc, true, false);
@@ -1638,7 +1657,7 @@ void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTA
            maTabs[i]->DeleteCol(aCxt.maRegroupCols, nStartCol, nStartRow, nEndRow, nSize, pUndoOutline);
    }

    if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
    if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) || bLastColIncluded )
    {
        // Listeners have been removed in UpdateReference
        StartNeededListeners();
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 2e05497..0538a10 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2650,22 +2650,29 @@ void restoreDeletedRef( ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt
    restoreDeletedRef(rRef.Ref2, rCxt);
}

bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rDeletedRange,
enum ShrinkResult
{
    UNMODIFIED,
    SHRUNK,
    STICKY
};

ShrinkResult shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rDeletedRange,
        const ScComplexRefData& rRef )
{
    if (!rDeletedRange.Intersects(rRefRange))
        return false;
        return UNMODIFIED;

    if (rCxt.mnColDelta < 0)
    {
        if (rRef.IsEntireRow())
            // Entire rows are not affected, columns are anchored.
            return false;
            return STICKY;

        // Shifting left.
        if (rRefRange.aStart.Row() < rDeletedRange.aStart.Row() || rDeletedRange.aEnd.Row() < rRefRange.aEnd.Row())
            // Deleted range is only partially overlapping in vertical direction. Bail out.
            return false;
            return UNMODIFIED;

        if (rDeletedRange.aStart.Col() <= rRefRange.aStart.Col())
        {
@@ -2687,7 +2694,7 @@ bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const Sc
        {
            if (rRefRange.IsEndColSticky())
                // Sticky end not affected.
                return false;
                return STICKY;

            // Reference is deleted in the middle. Move the last column
            // position to the left.
@@ -2698,25 +2705,25 @@ bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const Sc
        {
            if (rRefRange.IsEndColSticky())
                // Sticky end not affected.
                return false;
                return STICKY;

            // The reference range is truncated on the right.
            SCCOL nDelta = rDeletedRange.aStart.Col() - rRefRange.aEnd.Col() - 1;
            rRefRange.IncEndColSticky(nDelta);
        }
        return true;
        return SHRUNK;
    }
    else if (rCxt.mnRowDelta < 0)
    {
        if (rRef.IsEntireCol())
            // Entire columns are not affected, rows are anchored.
            return false;
            return STICKY;

        // Shifting up.

        if (rRefRange.aStart.Col() < rDeletedRange.aStart.Col() || rDeletedRange.aEnd.Col() < rRefRange.aEnd.Col())
            // Deleted range is only partially overlapping in horizontal direction. Bail out.
            return false;
            return UNMODIFIED;

        if (rDeletedRange.aStart.Row() <= rRefRange.aStart.Row())
        {
@@ -2738,7 +2745,7 @@ bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const Sc
        {
            if (rRefRange.IsEndRowSticky())
                // Sticky end not affected.
                return false;
                return STICKY;

            // Reference is deleted in the middle. Move the last row
            // position upward.
@@ -2749,16 +2756,16 @@ bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const Sc
        {
            if (rRefRange.IsEndRowSticky())
                // Sticky end not affected.
                return false;
                return STICKY;

            // The reference range is truncated on the bottom.
            SCCOL nDelta = rDeletedRange.aStart.Row() - rRefRange.aEnd.Row() - 1;
            rRefRange.IncEndRowSticky(nDelta);
        }
        return true;
        return SHRUNK;
    }

    return false;
    return UNMODIFIED;
}

bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rSelectedRange,
@@ -3014,7 +3021,8 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
                            }
                            else if (aSelectedRange.Intersects(aAbs))
                            {
                                if (shrinkRange(rCxt, aAbs, aSelectedRange, rRef))
                                const ShrinkResult eSR = shrinkRange(rCxt, aAbs, aSelectedRange, rRef);
                                if (eSR == SHRUNK)
                                {
                                    // The reference range has been shrunk.
                                    rRef.SetRange(aAbs, aNewPos);
@@ -3022,6 +3030,13 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
                                    aRes.mbReferenceModified = true;
                                    break;
                                }
                                else if (eSR == STICKY)
                                {
                                    // The reference range stays the same but a
                                    // new (empty) cell range is shifted in and
                                    // may change the calculation result.
                                    aRes.mbValueChanged = true;
                                }
                            }
                        }