[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - 4 commits - sc/inc sc/qa sc/source

Eike Rathke erack at redhat.com
Fri Dec 11 07:49:32 PST 2015


 sc/inc/address.hxx                  |   24 +++-
 sc/qa/unit/ucalc_formula.cxx        |  184 ++++++++++++++++++++++++++++++++++++
 sc/source/core/data/column.cxx      |    6 -
 sc/source/core/data/conditio.cxx    |    6 -
 sc/source/core/data/documen7.cxx    |    6 -
 sc/source/core/data/drwlayer.cxx    |    6 -
 sc/source/core/data/formulacell.cxx |    6 -
 sc/source/core/tool/address.cxx     |   51 +++++++--
 sc/source/core/tool/refdata.cxx     |    9 +
 sc/source/core/tool/token.cxx       |   66 ++++++++++--
 sc/source/filter/html/htmlimp.cxx   |    6 -
 sc/source/filter/html/htmlpars.cxx  |   13 ++
 sc/source/ui/docshell/docfunc.cxx   |   18 ++-
 sc/source/ui/view/gridwin.cxx       |   12 +-
 14 files changed, 367 insertions(+), 46 deletions(-)

New commits:
commit 208c247edbef4449b8614dd3709e627edc546e46
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Dec 11 15:45:52 2015 +0100

    silence -Werror=strict-overflow
    
    error: assuming signed overflow does not occur when assuming that
    (X + c) < X is always false [-Werror=strict-overflow]
         if ( rAddress.Row() < Row() )
    
    Change-Id: Ia643491657680fffcaacae4a474af479b9a07e35
    (cherry picked from commit 0e40e1e3243d57fdf67c54d7c5b69e77fe7d03ce)

diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index ce58c88..ac203e1 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1584,7 +1584,7 @@ void Test::testFormulaRefUpdateRange()
 
     // Insert 2 rows in the middle to shift bottom reference down and make it
     // sticky.
-    m_pDoc->InsertRow( ScRange( aPos, ScAddress(MAXCOL,aPos.Row()+1,1)));
+    m_pDoc->InsertRow( ScRange( 0, aPos.Row(), 1, MAXCOL, aPos.Row()+1, 1));
 
     // A3:A18 must not result in #REF! anywhere.
     bool bCheck = true;
@@ -1681,9 +1681,9 @@ void Test::testFormulaRefUpdateRange()
     aPos.IncRow();
 
     // Insert 4 rows in the middle.
-    m_pDoc->InsertRow( ScRange( aPos, ScAddress(MAXCOL,aPos.Row()+3,1)));
+    m_pDoc->InsertRow( ScRange( 0, aPos.Row(), 1, MAXCOL, aPos.Row()+3, 1));
     // Delete 2 rows in the middle.
-    m_pDoc->DeleteRow( ScRange( aPos, ScAddress(MAXCOL,aPos.Row()+1,1)));
+    m_pDoc->DeleteRow( ScRange( 0, aPos.Row(), 1, MAXCOL, aPos.Row()+1, 1));
 
     // References in A2:A17 must still be the same.
     bCheck = true;
commit eaed8fe33bb677f668571771fa814b02ee1d6cca
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Dec 11 14:42:35 2015 +0100

    unit test for sticky end col/row anchors, tdf#92779
    
    Change-Id: I78584e37e5944327db9cc5b6472a9e7ea972b37e
    (cherry picked from commit fe445df126ff0be771494dfef3aec09ca82f8aef)

diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index be88c53..ce58c88 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1541,6 +1541,190 @@ void Test::testFormulaRefUpdateRange()
     if (!checkFormula(*m_pDoc, ScAddress(0,2,0), "SUM($C$6:$F$9)"))
         CPPUNIT_FAIL("Wrong formula in A3.");
 
+    m_pDoc->InsertTab(1, "StickyRange");
+
+    // A3:A18 all possible combinations of relative and absolute addressing,
+    // leaving one row above and below unreferenced.
+    ScAddress aPos(0,2,1);
+    m_pDoc->SetString( aPos, "=B2:B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=B2:B$1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=B2:$B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=B2:$B$1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=B$2:B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=B$2:B$1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=B$2:$B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=B$2:$B$1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B2:B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B2:B$1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B2:$B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B2:$B$1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B$2:B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B$2:B$1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B$2:$B1048575");
+    aPos.IncRow();
+    m_pDoc->SetString( aPos, "=$B$2:$B$1048575");
+    aPos.IncRow();
+    // A19 reference to two cells on one row.
+    m_pDoc->SetString( aPos, "=B1048575:C1048575");
+    aPos.IncRow();
+
+    // Insert 2 rows in the middle to shift bottom reference down and make it
+    // sticky.
+    m_pDoc->InsertRow( ScRange( aPos, ScAddress(MAXCOL,aPos.Row()+1,1)));
+
+    // A3:A18 must not result in #REF! anywhere.
+    bool bCheck = true;
+    aPos.Set(0,2,1);
+    bCheck &= checkFormula(*m_pDoc, aPos, "B2:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B2:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B2:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B2:$B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$2:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$2:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$2:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$2:$B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B2:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B2:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B2:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B2:$B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$2:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$2:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$2:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$2:$B$1048576");
+    aPos.IncRow();
+    if (!bCheck)
+        CPPUNIT_FAIL("Wrong reference in A3:A18 after insertion.");
+
+    // A19 reference to one row shifted out should be #REF!
+    bCheck &= checkFormula(*m_pDoc, aPos, "B#REF!:C#REF!");
+    if (!bCheck)
+        CPPUNIT_FAIL("Wrong reference in A19 after insertion.");
+    // A19 enter reference to last row.
+    m_pDoc->SetString( aPos, "=B1048576:C1048576");
+    aPos.IncRow();
+
+    // Delete row 1 to shift top reference up, bottom reference stays sticky.
+    m_pDoc->DeleteRow(ScRange(0,0,1,MAXCOL,0,1));
+
+    // Check sticky bottom references and display of entire column references,
+    // now in A2:A17.
+    bCheck = true;
+    aPos.Set(0,1,1);
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B1:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:$B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B1:$B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$1:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$1:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:$B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B1:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:$B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B1:$B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$1:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$1:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:$B");
+    aPos.IncRow();
+    if (!bCheck)
+        CPPUNIT_FAIL("Wrong reference in A2:A17 after deletion.");
+
+    // A18 reference to one last row should be shifted up.
+    bCheck &= checkFormula(*m_pDoc, aPos, "B1048575:C1048575");
+    if (!bCheck)
+        CPPUNIT_FAIL("Wrong reference in A18 after deletion.");
+    aPos.IncRow();
+
+    // Insert 4 rows in the middle.
+    m_pDoc->InsertRow( ScRange( aPos, ScAddress(MAXCOL,aPos.Row()+3,1)));
+    // Delete 2 rows in the middle.
+    m_pDoc->DeleteRow( ScRange( aPos, ScAddress(MAXCOL,aPos.Row()+1,1)));
+
+    // References in A2:A17 must still be the same.
+    bCheck = true;
+    aPos.Set(0,1,1);
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B1:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:$B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B1:$B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$1:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B$1:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "B:$B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B1:B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:$B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B1:$B$1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$1:B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:B");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B$1:$B1048576");
+    aPos.IncRow();
+    bCheck &= checkFormula(*m_pDoc, aPos, "$B:$B");
+    aPos.IncRow();
+    if (!bCheck)
+        CPPUNIT_FAIL("Wrong reference in A2:A17 after deletion.");
+
+    m_pDoc->DeleteTab(1);
+
     m_pDoc->DeleteTab(0);
 }
 
commit be39e7ea63423c1c9bab0d9410ffca93bdd474c4
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Dec 11 14:27:33 2015 +0100

    geez, how about actually checking the Move() error return? tdf#92779 related
    
    Handle failure condition where we know how to treat it, i.e. when
    updating references, assert in all other places that so far silently
    ignored it and implicitly assumed the failing Move() truncating at
    bounds would be alright. In case we'll encounter an assertion we'll have
    to inspect those places and decide what to do about it.
    
    Noticed this error with a reference like B1048575 and inserting two rows
    above, it became B1048576 instead of B#REF!
    
    Change-Id: I00757f3ed2e305b591178047933ed60f1533317e
    (cherry picked from commit 9c1ba0988f5db05bb796eaf7cf902a0b601c6736)

diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 4bf5ee5..34d49fb 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -305,9 +305,15 @@ public:
                                   const ScDocument* pDocument = nullptr,
                                   const Details& rDetails = detailsOOOa1) const;
 
-    // The document for the maximum defined sheet number
-    SC_DLLPUBLIC bool Move( SCsCOL nDeltaX, SCsROW nDeltaY, SCsTAB nDeltaZ,
-                            ScDocument* pDocument = nullptr );
+    /**
+        @param  rErrorPos
+                If FALSE is returned, the positions contain <0 or >MAX...
+                values if shifted out of bounds.
+        @param  pDocument
+                The document for the maximum defined sheet number.
+     */
+    SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool Move( SCsCOL nDeltaX, SCsROW nDeltaY, SCsTAB nDeltaZ,
+            ScAddress& rErrorPos, ScDocument* pDocument = nullptr );
 
     inline bool operator==( const ScAddress& rAddress ) const;
     inline bool operator!=( const ScAddress& rAddress ) const;
@@ -535,8 +541,16 @@ public:
     inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
                          SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const;
     SC_DLLPUBLIC void PutInOrder();
-    // The document for the maximum defined sheet number
-    SC_DLLPUBLIC bool Move( SCsCOL aDeltaX, SCsROW aDeltaY, SCsTAB aDeltaZ, ScDocument* pDocument = nullptr );
+
+    /**
+        @param  rErrorRange
+                If FALSE is returned, the positions contain <0 or >MAX...
+                values if shifted out of bounds.
+        @param  pDocument
+                The document for the maximum defined sheet number.
+     */
+    SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool Move( SCsCOL aDeltaX, SCsROW aDeltaY, SCsTAB aDeltaZ,
+            ScRange& rErrorRange, ScDocument* pDocument = nullptr );
     SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
     SC_DLLPUBLIC bool Intersects( const ScRange& rRange ) const;    // do two ranges intersect?
 
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index d820abc..c09f096 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2066,11 +2066,15 @@ class UpdateRefOnNonCopy : std::unary_function<sc::FormulaGroupEntry, void>
 
         if (pTop->UpdatePosOnShift(*mpCxt))
         {
+            ScAddress aErrorPos( ScAddress::UNINITIALIZED );
             // 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 (!pFC->aPos.Move(mpCxt->mnColDelta, mpCxt->mnRowDelta, mpCxt->mnTabDelta, aErrorPos))
+                {
+                    assert(!"can't move formula cell");
+                }
             }
 
             if (pCode->IsRecalcModeOnRefMove())
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index abcd231..6dd4c32 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -510,7 +510,11 @@ void ScConditionEntry::UpdateReference( sc::RefUpdateContext& rCxt )
     bool bChangedPos = false;
     if (rCxt.meMode == URM_INSDEL && rCxt.maRange.In(aSrcPos))
     {
-        aSrcPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+        ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+        if (!aSrcPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos))
+        {
+            assert(!"can't move ScConditionEntry");
+        }
         bChangedPos = aSrcPos != aOldSrcPos;
     }
 
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index 447a688..cfa3d2f 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -246,11 +246,15 @@ void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint )
 
     // Re-start area listeners on the new range.
     {
+        ScRange aErrorRange( ScAddress::UNINITIALIZED );
         std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
         for (; it != itEnd; ++it)
         {
             ScRange aNewRange = it->maArea;
-            aNewRange.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
+            if (!aNewRange.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab(), aErrorRange))
+            {
+                assert(!"can't move AreaListener");
+            }
             pBASM->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener);
         }
     }
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 6d48458..dbf1fe7 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -1425,6 +1425,7 @@ static bool lcl_MoveRanges( ::std::vector< ScRangeList >& rRangesVector, const S
 {
     bool bChanged = false;
 
+    ScRange aErrorRange( ScAddress::UNINITIALIZED );
     ::std::vector< ScRangeList >::iterator aIt = rRangesVector.begin();
     for( ;aIt!=rRangesVector.end(); ++aIt )
     {
@@ -1437,7 +1438,10 @@ static bool lcl_MoveRanges( ::std::vector< ScRangeList >& rRangesVector, const S
                 SCsCOL nDiffX = rDestPos.Col() - (SCsCOL)rSourceRange.aStart.Col();
                 SCsROW nDiffY = rDestPos.Row() - (SCsROW)rSourceRange.aStart.Row();
                 SCsTAB nDiffZ = rDestPos.Tab() - (SCsTAB)rSourceRange.aStart.Tab();
-                pRange->Move( nDiffX, nDiffY, nDiffZ );
+                if (!pRange->Move( nDiffX, nDiffY, nDiffZ, aErrorRange))
+                {
+                    assert(!"can't move range");
+                }
                 bChanged = true;
             }
         }
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 0c5edae..5c87b52 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2899,7 +2899,11 @@ bool ScFormulaCell::UpdatePosOnShift( const sc::RefUpdateContext& rCxt )
 
     // This formula cell itself is being shifted during cell range
     // insertion or deletion. Update its position.
-    aPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+    ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+    if (!aPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos))
+    {
+        assert(!"can't move ScFormulaCell");
+    }
 
     return true;
 }
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index a48baa5..e060f0a 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -2100,30 +2100,53 @@ OUString ScRange::Format( sal_uInt16 nFlags, const ScDocument* pDoc,
     return r.makeStringAndClear();
 }
 
-bool ScAddress::Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* pDoc )
+bool ScAddress::Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScAddress& rErrorPos, ScDocument* pDoc )
 {
     SCsTAB nMaxTab = pDoc ? pDoc->GetTableCount() : MAXTAB;
     dx = Col() + dx;
     dy = Row() + dy;
     dz = Tab() + dz;
     bool bValid = true;
+    rErrorPos.SetCol(dx);
     if( dx < 0 )
-        dx = 0, bValid = false;
+    {
+        dx = 0;
+        bValid = false;
+    }
     else if( dx > MAXCOL )
-        dx = MAXCOL, bValid =false;
+    {
+        dx = MAXCOL;
+        bValid =false;
+    }
+    rErrorPos.SetRow(dy);
     if( dy < 0 )
-        dy = 0, bValid = false;
+    {
+        dy = 0;
+        bValid = false;
+    }
     else if( dy > MAXROW )
-        dy = MAXROW, bValid =false;
+    {
+        dy = MAXROW;
+        bValid =false;
+    }
+    rErrorPos.SetTab(dz);
     if( dz < 0 )
-        dz = 0, bValid = false;
+    {
+        dz = 0;
+        bValid = false;
+    }
     else if( dz > nMaxTab )
-        dz = nMaxTab, bValid =false;
+    {
+        // Always set MAXTAB+1 so further checks without ScDocument detect invalid.
+        rErrorPos.SetTab(MAXTAB+1);
+        dz = nMaxTab;
+        bValid =false;
+    }
     Set( dx, dy, dz );
     return bValid;
 }
 
-bool ScRange::Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* pDoc )
+bool ScRange::Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScRange& rErrorRange, ScDocument* pDoc )
 {
     bool bColRange = (aStart.Col() < aEnd.Col());
     bool bRowRange = (aStart.Row() < aEnd.Row());
@@ -2131,18 +2154,22 @@ bool ScRange::Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* pDoc )
         dy = 0;     // Entire column not to be moved.
     if (dx && aStart.Col() == 0 && aEnd.Col() == MAXCOL)
         dx = 0;     // Entire row not to be moved.
-    bool b1 = aStart.Move( dx, dy, dz, pDoc );
+    bool b1 = aStart.Move( dx, dy, dz, rErrorRange.aStart, pDoc );
     if (dx && bColRange && aEnd.Col() == MAXCOL)
         dx = 0;     // End column sticky.
     if (dy && bRowRange && aEnd.Row() == MAXROW)
         dy = 0;     // End row sticky.
     SCTAB nOldTab = aEnd.Tab();
-    bool b2 = aEnd.Move( dx, dy, dz, pDoc );
+    bool b2 = aEnd.Move( dx, dy, dz, rErrorRange.aEnd, pDoc );
     if (!b2)
     {
         // End column or row of a range may have become sticky.
         bColRange = (!dx || (bColRange && aEnd.Col() == MAXCOL));
+        if (dx && bColRange)
+            rErrorRange.aEnd.SetCol(MAXCOL);
         bRowRange = (!dy || (bRowRange && aEnd.Row() == MAXROW));
+        if (dy && bRowRange)
+            rErrorRange.aEnd.SetRow(MAXROW);
         b2 = bColRange && bRowRange && (aEnd.Tab() - nOldTab == dz);
     }
     return b1 && b2;
diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
index 9811c08..a780364 100644
--- a/sc/source/core/tool/refdata.cxx
+++ b/sc/source/core/tool/refdata.cxx
@@ -207,15 +207,24 @@ void ScSingleRefData::SetAddress( const ScAddress& rAddr, const ScAddress& rPos
     else
         mnCol = rAddr.Col();
 
+    if (!ValidCol(rAddr.Col()))
+        SetColDeleted(true);
+
     if (Flags.bRowRel)
         mnRow = rAddr.Row() - rPos.Row();
     else
         mnRow = rAddr.Row();
 
+    if (!ValidRow(rAddr.Row()))
+        SetRowDeleted(true);
+
     if (Flags.bTabRel)
         mnTab = rAddr.Tab() - rPos.Tab();
     else
         mnTab = rAddr.Tab();
+
+    if (!ValidTab( rAddr.Tab(), MAXTAB))
+        SetTabDeleted(true);
 }
 
 SCROW ScSingleRefData::Row() const
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 49bbe2e..29274ae 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2861,7 +2861,13 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
     ScAddress aNewPos = rOldPos;
     bool bCellShifted = rCxt.maRange.In(rOldPos);
     if (bCellShifted)
-        aNewPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+    {
+        ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+        if (!aNewPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos))
+        {
+            assert(!"can't move");
+        }
+    }
 
     TokenPointers aPtrs( pCode, nLen, pRPN, nRPN);
     for (size_t j=0; j<2; ++j)
@@ -2903,7 +2909,9 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
 
                         if (rCxt.maRange.In(aAbs))
                         {
-                            aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                            ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+                            if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos))
+                                aAbs = aErrorPos;
                             aRes.mbReferenceModified = true;
                         }
 
@@ -2960,7 +2968,9 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
 
                         if (rCxt.maRange.In(aAbs))
                         {
-                            aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                            ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                            if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorRange))
+                                aAbs = aErrorRange;
                             aRes.mbReferenceModified = true;
                         }
                         else if (rCxt.maRange.Intersects(aAbs))
@@ -3031,7 +3041,11 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
     // When moving, the range is the destination range. We need to use the old
     // range prior to the move for hit analysis.
     ScRange aOldRange = rCxt.maRange;
-    aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
+    ScRange aErrorMoveRange( ScAddress::UNINITIALIZED );
+    if (!aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta, aErrorMoveRange))
+    {
+        assert(!"can't move");
+    }
 
     bool b3DFlag = rOldPos.Tab() != rNewPos.Tab() || rCxt.mnTabDelta;
 
@@ -3054,7 +3068,9 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
                         ScAddress aAbs = rRef.toAbs(rOldPos);
                         if (aOldRange.In(aAbs))
                         {
-                            aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                            ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+                            if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos))
+                                aAbs = aErrorPos;
                             aRes.mbReferenceModified = true;
                         }
 
@@ -3069,7 +3085,9 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
                         ScRange aAbs = rRef.toAbs(rOldPos);
                         if (aOldRange.In(aAbs))
                         {
-                            aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                            ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                            if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorRange))
+                                aAbs = aErrorRange;
                             aRes.mbReferenceModified = true;
                         }
 
@@ -3112,7 +3130,11 @@ sc::RefUpdateResult ScTokenArray::MoveReference( const ScAddress& rPos, const sc
     sc::RefUpdateResult aRes;
 
     ScRange aOldRange = rCxt.maRange;
-    aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
+    ScRange aErrorMoveRange( ScAddress::UNINITIALIZED );
+    if (!aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta, aErrorMoveRange))
+    {
+        assert(!"can't move");
+    }
 
     FormulaToken** p = pCode;
     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
@@ -3127,7 +3149,9 @@ sc::RefUpdateResult ScTokenArray::MoveReference( const ScAddress& rPos, const sc
                 ScAddress aAbs = rRef.toAbs(rPos);
                 if (aOldRange.In(aAbs))
                 {
-                    aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                    ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+                    if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos))
+                        aAbs = aErrorPos;
                     rRef.SetAddress(aAbs, rPos);
                     if (rCxt.mnTabDelta)
                         rRef.SetFlag3D(aAbs.Tab()!=rPos.Tab());
@@ -3141,7 +3165,9 @@ sc::RefUpdateResult ScTokenArray::MoveReference( const ScAddress& rPos, const sc
                 ScRange aAbs = rRef.toAbs(rPos);
                 if (aOldRange.In(aAbs))
                 {
-                    aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                    ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                    if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorRange))
+                        aAbs = aErrorRange;
                     rRef.SetRange(aAbs, rPos);
                     if (rCxt.mnTabDelta)
                         rRef.Ref1.SetFlag3D(aAbs.aStart.Tab()!=rPos.Tab());
@@ -3562,7 +3588,11 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdat
 {
     // When moving, the range is the destination range.
     ScRange aOldRange = rCxt.maRange;
-    aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
+    ScRange aErrorMoveRange( ScAddress::UNINITIALIZED );
+    if (!aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta, aErrorMoveRange))
+    {
+        assert(!"can't move");
+    }
 
     // In a named expression, we'll move the reference only when the reference
     // is entirely absolute.
@@ -3591,7 +3621,9 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdat
                         ScAddress aAbs = rRef.toAbs(rPos);
                         if (aOldRange.In(aAbs))
                         {
-                            aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                            ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+                            if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorPos))
+                                aAbs = aErrorPos;
                             aRes.mbReferenceModified = true;
                         }
 
@@ -3608,7 +3640,9 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdat
                         ScRange aAbs = rRef.toAbs(rPos);
                         if (aOldRange.In(aAbs))
                         {
-                            aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+                            ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                            if (!aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta, aErrorRange))
+                                aAbs = aErrorRange;
                             aRes.mbReferenceModified = true;
                         }
 
@@ -4141,8 +4175,14 @@ void checkBounds(
 
     ScRange aCheckRange = rCxt.maRange;
     if (rCxt.meMode == URM_MOVE)
+    {
         // Check bounds against the old range prior to the move.
-        aCheckRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
+        ScRange aErrorRange( ScAddress::UNINITIALIZED );
+        if (!aCheckRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta, aErrorRange))
+        {
+            assert(!"can't move");
+        }
+    }
 
     checkBounds(rPos, nGroupLen, aCheckRange, rRef, rBounds);
 }
diff --git a/sc/source/filter/html/htmlimp.cxx b/sc/source/filter/html/htmlimp.cxx
index 8e82e30..2be6faa 100644
--- a/sc/source/filter/html/htmlimp.cxx
+++ b/sc/source/filter/html/htmlimp.cxx
@@ -178,10 +178,14 @@ void ScHTMLImport::WriteToDocument(
 
     ScHTMLTable* pTable = nullptr;
     ScHTMLTableId nTableId = SC_HTML_GLOBAL_TABLE;
+    ScRange aErrorRange( ScAddress::UNINITIALIZED );
     while( (pTable = pGlobTable->FindNestedTable( ++nTableId )) != nullptr )
     {
         pTable->GetDocRange( aNewRange );
-        aNewRange.Move( nColDiff, nRowDiff, nTabDiff );
+        if (!aNewRange.Move( nColDiff, nRowDiff, nTabDiff, aErrorRange ))
+        {
+            assert(!"can't move");
+        }
         // insert table number as name
         InsertRangeName( mpDoc, ScfTools::GetNameFromHTMLIndex( nTableId ), aNewRange );
         // insert table id as name
diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx
index 8e906bd..5ecfeaa 100644
--- a/sc/source/filter/html/htmlpars.cxx
+++ b/sc/source/filter/html/htmlpars.cxx
@@ -2296,7 +2296,12 @@ ScHTMLPos ScHTMLTable::GetDocPos( const ScHTMLPos& rCellPos ) const
 void ScHTMLTable::GetDocRange( ScRange& rRange ) const
 {
     rRange.aStart = rRange.aEnd = maDocBasePos.MakeAddr();
-    rRange.aEnd.Move( static_cast< SCsCOL >( GetDocSize( tdCol ) ) - 1, static_cast< SCsROW >( GetDocSize( tdRow ) ) - 1, 0 );
+    ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+    if (!rRange.aEnd.Move( static_cast< SCsCOL >( GetDocSize( tdCol ) ) - 1,
+                static_cast< SCsROW >( GetDocSize( tdRow ) ) - 1, 0, aErrorPos))
+    {
+        assert(!"can't move");
+    }
 }
 
 void ScHTMLTable::ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos ) const
@@ -2479,7 +2484,11 @@ void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize )
 
     // insert the new range into the cell lists
     ScRange aNewRange( maCurrCell.MakeAddr() );
-    aNewRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0 );
+    ScAddress aErrorPos( ScAddress::UNINITIALIZED );
+    if (!aNewRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0, aErrorPos))
+    {
+        assert(!"can't move");
+    }
     if( rSpanSize.mnRows > 1 )
     {
         maVMergedCells.Append( aNewRange );
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 4b4afc13..41d23f5 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -1635,11 +1635,21 @@ bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark,
 
     // If insertion is for full cols/rows and after the current
     // selection, then shift the range accordingly
-    if ( eCmd == INS_INSROWS_AFTER ) {
-        aTargetRange.Move(0, rRange.aEnd.Row() - rRange.aStart.Row() + 1, 0);
+    if ( eCmd == INS_INSROWS_AFTER )
+    {
+        ScRange aErrorRange( ScAddress::UNINITIALIZED );
+        if (!aTargetRange.Move(0, rRange.aEnd.Row() - rRange.aStart.Row() + 1, 0, aErrorRange))
+        {
+            assert(!"can't move");
+        }
     }
-    if ( eCmd == INS_INSCOLS_AFTER ) {
-        aTargetRange.Move(rRange.aEnd.Col() - rRange.aStart.Col() + 1, 0, 0);
+    if ( eCmd == INS_INSCOLS_AFTER )
+    {
+        ScRange aErrorRange( ScAddress::UNINITIALIZED );
+        if (!aTargetRange.Move(rRange.aEnd.Col() - rRange.aStart.Col() + 1, 0, 0, aErrorRange))
+        {
+            assert(!"can't move");
+        }
     }
 
     SCCOL nStartCol = aTargetRange.aStart.Col();
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index e2d8ff0..bde0a4d 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -4255,13 +4255,15 @@ sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPos
                             if ( meDragInsertMode == INS_CELLSDOWN &&
                                  nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
                             {
-                                bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
+                                ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                                bDone = aSource.Move( 0, nSizeY, 0, aErrorRange, pSourceDoc );
                                 nCorrectCursorPosRow = nSizeY;
                             }
                             else if ( meDragInsertMode == INS_CELLSRIGHT &&
                                       nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
                             {
-                                bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
+                                ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                                bDone = aSource.Move( nSizeX, 0, 0, aErrorRange, pSourceDoc );
                                 nCorrectCursorPosCol = nSizeX;
                             }
                         }
@@ -4305,11 +4307,13 @@ sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPos
                         {
                             if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
                             {
-                                bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
+                                ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                                bDone = aDest.Move( 0, -nSizeY, 0, aErrorRange, pThisDoc );
                             }
                             else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
                             {
-                                bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
+                                ScRange aErrorRange( ScAddress::UNINITIALIZED );
+                                bDone = aDest.Move( -nSizeX, 0, 0, aErrorRange, pThisDoc );
                             }
                             pDocSh->UpdateOle( pViewData );
                             pView->CellContentChanged();
commit 74397f2fab816c11b73c36ef70bed97ae146969e
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Dec 10 16:50:06 2015 +0100

    sticky end only if it already was a range on the same axis, tdf#92779
    
    Change-Id: I66f624e696a4a6e681733ab863cd57c342cc0bc1
    (cherry picked from commit d6f6459350e9e661bc09191cfb31c5e779d522de)

diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index b7f9a5b..a48baa5 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -2132,9 +2132,9 @@ bool ScRange::Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* pDoc )
     if (dx && aStart.Col() == 0 && aEnd.Col() == MAXCOL)
         dx = 0;     // Entire row not to be moved.
     bool b1 = aStart.Move( dx, dy, dz, pDoc );
-    if (dx && aEnd.Col() == MAXCOL)
+    if (dx && bColRange && aEnd.Col() == MAXCOL)
         dx = 0;     // End column sticky.
-    if (dy && aEnd.Row() == MAXROW)
+    if (dy && bRowRange && aEnd.Row() == MAXROW)
         dy = 0;     // End row sticky.
     SCTAB nOldTab = aEnd.Tab();
     bool b2 = aEnd.Move( dx, dy, dz, pDoc );


More information about the Libreoffice-commits mailing list