sc/inc/refupdatecontext.hxx              |    3 
 sc/qa/unit/ucalc_formula.cxx             |   85 +++++++++++++++++++++++++
 sc/source/core/data/documen3.cxx         |    2 
 sc/source/core/data/refupdatecontext.cxx |    9 ++
 sc/source/core/tool/token.cxx            |  104 +++++++++++++++++++++++++------
 5 files changed, 182 insertions(+), 21 deletions(-)

New commits:
commit 57f9317a487f23f3f675de81bc045f3869568376
Author: Kohei Yoshida <kohei.yosh...@gmail.com>
Date:   Fri Jul 19 15:39:36 2013 -0400

    Handle range reference expansion on insertion.
    
    Change-Id: I128ed26b6d6319a7e227885801e0683b517eb439

diff --git a/sc/inc/refupdatecontext.hxx b/sc/inc/refupdatecontext.hxx
index 2f33767..91607ea 100644
--- a/sc/inc/refupdatecontext.hxx
+++ b/sc/inc/refupdatecontext.hxx
@@ -40,7 +40,8 @@ struct RefUpdateContext
 
     RefUpdateContext();
 
-    bool hasDelta() const;
+    bool isInserted() const;
+    bool isDeleted() const;
 };
 
 struct RefUpdateResult
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 53769ef..04973f4 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -981,7 +981,7 @@ void ScDocument::UpdateReference(
         return;
 
     boost::scoped_ptr<sc::ExpandRefsSwitch> pExpandRefsSwitch;
-    if (rCxt.meMode == URM_INSDEL && rCxt.hasDelta())
+    if (rCxt.isInserted())
         pExpandRefsSwitch.reset(new sc::ExpandRefsSwitch(*this, 
SC_MOD()->GetInputOptions().GetExpandRefs()));
 
     size_t nFirstTab, nLastTab;
diff --git a/sc/source/core/data/refupdatecontext.cxx 
b/sc/source/core/data/refupdatecontext.cxx
index 9f39f44..1ba6a6b 100644
--- a/sc/source/core/data/refupdatecontext.cxx
+++ b/sc/source/core/data/refupdatecontext.cxx
@@ -14,9 +14,14 @@ namespace sc {
 RefUpdateContext::RefUpdateContext() :
     meMode(URM_INSDEL), mnColDelta(0), mnRowDelta(0), mnTabDelta(0) {}
 
-bool RefUpdateContext::hasDelta() const
+bool RefUpdateContext::isInserted() const
 {
-    return (mnColDelta > 0 || mnRowDelta > 0 || mnTabDelta > 0);
+    return (meMode == URM_INSDEL) && (mnColDelta > 0 || mnRowDelta > 0 || 
mnTabDelta > 0);
+}
+
+bool RefUpdateContext::isDeleted() const
+{
+    return (meMode == URM_INSDEL) && (mnColDelta < 0 || mnRowDelta < 0 || 
mnTabDelta < 0);
 }
 
 RefUpdateResult::RefUpdateResult() : mbValueChanged(false), 
mbRangeSizeModified(false) {}
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 981e898..30bef7b 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2195,28 +2195,45 @@ void ScTokenArray::AdjustAbsoluteRefs( const 
ScDocument* pOldDoc, const ScAddres
 
 namespace {
 
-ScRange getDeletedRange( const sc::RefUpdateContext& rCxt )
+ScRange getSelectedRange( const sc::RefUpdateContext& rCxt )
 {
-    ScRange aDeletedRange(ScAddress::INITIALIZE_INVALID);
+    ScRange aSelectedRange(ScAddress::INITIALIZE_INVALID);
     if (rCxt.mnColDelta < 0)
     {
         // Delete and shift to left.
-        aDeletedRange.aStart = 
ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), 
rCxt.maRange.aStart.Tab());
-        aDeletedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, 
rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
+        aSelectedRange.aStart = 
ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), 
rCxt.maRange.aStart.Tab());
+        aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, 
rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
     }
     else if (rCxt.mnRowDelta < 0)
     {
         // Delete and shift up.
-        aDeletedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), 
rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab());
-        aDeletedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), 
rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab());
+        aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), 
rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab());
+        aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), 
rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab());
     }
     else if (rCxt.mnTabDelta < 0)
     {
         // Deleting sheets.
         // TODO : Figure out what to do here.
     }
+    else if (rCxt.mnColDelta > 0)
+    {
+        // Insert and shift to the right.
+        aSelectedRange.aStart = rCxt.maRange.aStart;
+        aSelectedRange.aEnd = 
ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta-1, rCxt.maRange.aEnd.Row(), 
rCxt.maRange.aEnd.Tab());
+    }
+    else if (rCxt.mnRowDelta > 0)
+    {
+        // Insert and shift down.
+        aSelectedRange.aStart = rCxt.maRange.aStart;
+        aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), 
rCxt.maRange.aStart.Row()+rCxt.mnRowDelta-1, rCxt.maRange.aEnd.Tab());
+    }
+    else if (rCxt.mnTabDelta > 0)
+    {
+        // Inserting sheets.
+        // TODO : Figure out what to do here.
+    }
 
-    return aDeletedRange;
+    return aSelectedRange;
 }
 
 void setRefDeleted( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
@@ -2279,11 +2296,48 @@ bool shrinkRange( const sc::RefUpdateContext& rCxt, 
ScRange& rRefRange, const Sc
     return false;
 }
 
+bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const 
ScRange& rInsertedRange )
+{
+    if (rCxt.mnColDelta > 0)
+    {
+        // Insert and shifting right.
+        if (rRefRange.aStart.Row() < rInsertedRange.aStart.Row() || 
rInsertedRange.aEnd.Row() < rRefRange.aEnd.Row())
+            // Inserted range is only partially overlapping in vertical 
direction. Bail out.
+            return false;
+
+        if (rInsertedRange.aStart.Col() == rRefRange.aStart.Col())
+            // Inserted range is at the left end.  No expansion.
+            return false;
+
+        // Move the last column position to the right.
+        SCCOL nDelta = rInsertedRange.aEnd.Col() - rInsertedRange.aStart.Col() 
+ 1;
+        rRefRange.aEnd.IncCol(nDelta);
+        return true;
+    }
+    else if (rCxt.mnRowDelta > 0)
+    {
+        // Insert and shifting down.
+        if (rRefRange.aStart.Col() < rInsertedRange.aStart.Col() || 
rInsertedRange.aEnd.Col() < rRefRange.aEnd.Col())
+            // Inserted range is only partially overlapping in horizontal 
direction. Bail out.
+            return false;
+
+        if (rInsertedRange.aStart.Row() == rRefRange.aStart.Row())
+            // Inserted range is at the top end.  No expansion.
+            return false;
+
+        // Move the last row position down.
+        SCROW nDelta = rInsertedRange.aEnd.Row() - rInsertedRange.aStart.Row() 
+ 1;
+        rRefRange.aEnd.IncRow(nDelta);
+        return true;
+    }
+    return false;
+}
+
 }
 
 sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const 
sc::RefUpdateContext& rCxt, const ScAddress& rOldPos )
 {
-    ScRange aDeletedRange = getDeletedRange(rCxt);
+    ScRange aSelectedRange = getSelectedRange(rCxt);
 
     sc::RefUpdateResult aRes;
     ScAddress aNewPos = rOldPos;
@@ -2303,7 +2357,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( 
const sc::RefUpdateCon
                 ScSingleRefData& rRef = pToken->GetSingleRef();
                 ScAddress aAbs = rRef.toAbs(rOldPos);
 
-                if (aDeletedRange.In(aAbs))
+                if (rCxt.isDeleted() && aSelectedRange.In(aAbs))
                 {
                     // This reference is in the deleted region.
                     setRefDeleted(rRef, rCxt);
@@ -2322,20 +2376,36 @@ sc::RefUpdateResult 
ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
                 ScComplexRefData& rRef = pToken->GetDoubleRef();
                 ScRange aAbs = rRef.toAbs(rOldPos);
 
-                if (aDeletedRange.In(aAbs))
+                if (rCxt.isDeleted())
                 {
-                    // This reference is in the deleted region.
-                    setRefDeleted(rRef, rCxt);
-                    aRes.mbValueChanged = true;
-                    break;
+                    if (aSelectedRange.In(aAbs))
+                    {
+                        // This reference is in the deleted region.
+                        setRefDeleted(rRef, rCxt);
+                        aRes.mbValueChanged = true;
+                        break;
+                    }
+                    else if (aSelectedRange.Intersects(aAbs))
+                    {
+                        if (shrinkRange(rCxt, aAbs, aSelectedRange))
+                        {
+                            // The reference range has been shrunk.
+                            rRef.SetRange(aAbs, aNewPos);
+                            aRes.mbValueChanged = true;
+                            aRes.mbRangeSizeModified = true;
+                            break;
+                        }
+                    }
                 }
-                else if (aDeletedRange.Intersects(aAbs))
+
+                if (rCxt.isInserted() && aSelectedRange.Intersects(aAbs))
                 {
-                    if (shrinkRange(rCxt, aAbs, aDeletedRange))
+                    if (expandRange(rCxt, aAbs, aSelectedRange))
                     {
-                        // The reference range has been shrunk.
+                        // The reference range has been expanded.
                         rRef.SetRange(aAbs, aNewPos);
                         aRes.mbValueChanged = true;
+                        aRes.mbRangeSizeModified = true;
                         break;
                     }
                 }
commit 043e733c15255122d6d28ca3c7f34e46449ffc08
Author: Kohei Yoshida <kohei.yosh...@gmail.com>
Date:   Fri Jul 19 15:38:03 2013 -0400

    Add test for range reference expansion on cell insertions.
    
    Change-Id: Idd8d37be518cef87ea00633774c3de846b27083a

diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 6310297..07335d4 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -568,6 +568,91 @@ void Test::testFormulaRefUpdateRange()
     CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,1,0)));
     CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,2,0)));
 
+    // Clear the range and start over.
+    clearRange(m_pDoc, ScRange(0,0,0,20,20,0));
+
+    // Disable expansion of range reference on insertion in adjacent areas.
+    m_pDoc->SetExpandRefs(false);
+
+    // Fill C2:D3 with values.
+    m_pDoc->SetValue(ScAddress(2,1,0), 1);
+    m_pDoc->SetValue(ScAddress(3,1,0), 2);
+    m_pDoc->SetValue(ScAddress(2,2,0), 3);
+    m_pDoc->SetValue(ScAddress(3,2,0), 4);
+
+    // Set formulas at A5 and A6.
+    m_pDoc->SetString(ScAddress(0,4,0), "=SUM(C2:D3)");
+    m_pDoc->SetString(ScAddress(0,5,0), "=SUM($C$2:$D$3)");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:D3)"))
+        CPPUNIT_FAIL("Wrong formula in A5.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$D$3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    // Insert a column at column C. This should simply shift the reference 
without expansion.
+    m_pDoc->InsertCol(ScRange(2,0,0,2,MAXROW,0));
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(D2:E3)"))
+        CPPUNIT_FAIL("Wrong formula in A5.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($D$2:$E$3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    // Shift it back.
+    m_pDoc->DeleteCol(ScRange(2,0,0,2,MAXROW,0));
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:D3)"))
+        CPPUNIT_FAIL("Wrong formula in A5.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$D$3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    // Insert at column D. This should expand the reference by one column 
length.
+    m_pDoc->InsertCol(ScRange(3,0,0,3,MAXROW,0));
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:E3)"))
+        CPPUNIT_FAIL("Wrong formula in A5.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$E$3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    // Insert at column F. No expansion should occur since the edge expansion 
is turned off.
+    m_pDoc->InsertCol(ScRange(5,0,0,5,MAXROW,0));
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,4,0), "SUM(C2:E3)"))
+        CPPUNIT_FAIL("Wrong formula in A5.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM($C$2:$E$3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    // Insert at row 2. No expansion should occur with edge expansion turned 
off.
+    m_pDoc->InsertRow(ScRange(0,1,0,MAXCOL,1,0));
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,5,0), "SUM(C3:E4)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "SUM($C$3:$E$4)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    // Insert at row 4 to expand the reference range.
+    m_pDoc->InsertRow(ScRange(0,3,0,MAXCOL,3,0));
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,6,0), "SUM(C3:E5)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "SUM($C$3:$E$5)"))
+        CPPUNIT_FAIL("Wrong formula in A8.");
+
+    // Insert at row 6. No expansion with edge expansion turned off.
+    m_pDoc->InsertRow(ScRange(0,5,0,MAXCOL,5,0));
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,7,0), "SUM(C3:E5)"))
+        CPPUNIT_FAIL("Wrong formula in A8.");
+
+    if (!checkFormula(*m_pDoc, ScAddress(0,8,0), "SUM($C$3:$E$5)"))
+        CPPUNIT_FAIL("Wrong formula in A9.");
+
     m_pDoc->DeleteTab(0);
 }
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to