[Libreoffice-commits] core.git: Branch 'feature/calc-group-interpreter' - 9 commits - sc/inc sc/qa sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Mon Aug 12 14:45:56 PDT 2013


 sc/inc/formulacell.hxx                |    3 +
 sc/inc/sharedformula.hxx              |   14 +++++
 sc/inc/tokenarray.hxx                 |    3 +
 sc/qa/unit/ucalc.cxx                  |    6 +-
 sc/source/core/data/column.cxx        |   62 +++++++++++++++++++++++--
 sc/source/core/data/formulacell.cxx   |   58 +++++++++++++++++++-----
 sc/source/core/tool/sharedformula.cxx |   65 +++++++++++++++++++++-----
 sc/source/core/tool/token.cxx         |   82 ++++++++++++++++++++++++++++++++++
 sc/source/filter/excel/xetable.cxx    |   39 ++++++++--------
 sc/source/filter/excel/xlformula.cxx  |    7 --
 sc/source/filter/inc/xetable.hxx      |    3 -
 sc/source/filter/inc/xlformula.hxx    |    8 ---
 12 files changed, 281 insertions(+), 69 deletions(-)

New commits:
commit 05effa857e3b03ac894c8a44cd8129374da8c9a7
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Aug 12 17:46:45 2013 -0400

    Re-enable these tests. They pass now.
    
    Change-Id: I408f42a849e7635ef53d4b8c142a0d90ac37bb05

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index d65be47..675e0dba 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -297,7 +297,7 @@ public:
     CPPUNIT_TEST(testHorizontalIterator);
     CPPUNIT_TEST(testFormulaDepTracking);
     CPPUNIT_TEST(testFormulaDepTracking2);
-//  CPPUNIT_TEST(testCellBroadcaster);
+    CPPUNIT_TEST(testCellBroadcaster);
     CPPUNIT_TEST(testFuncParam);
     CPPUNIT_TEST(testNamedRange);
     CPPUNIT_TEST(testCSV);
@@ -341,8 +341,8 @@ public:
     CPPUNIT_TEST(testSetBackgroundColor);
     CPPUNIT_TEST(testRenameTable);
     CPPUNIT_TEST(testAutoFill);
-//  CPPUNIT_TEST(testCopyPasteFormulas);
-//  CPPUNIT_TEST(testCopyPasteFormulasExternalDoc);
+    CPPUNIT_TEST(testCopyPasteFormulas);
+    CPPUNIT_TEST(testCopyPasteFormulasExternalDoc);
     CPPUNIT_TEST(testFindAreaPosVertical);
     CPPUNIT_TEST(testFindAreaPosColRight);
     CPPUNIT_TEST(testSort);
commit 56f048dbee4603adce5af80d2896a2d10cd2524b
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Aug 12 17:23:30 2013 -0400

    This is clearly a bug. Let's fix it.
    
    Change-Id: I83aa2c108e7d8561d28d76b69a8763a15a20a2bd

diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index 0b49751..11493e646 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -34,7 +34,7 @@ public:
         for (++it; it != itEnd; ++it, pPrev = pCur)
         {
             pCur = *it;
-            ScFormulaCell::CompareState eState = pPrev->CompareByTokenArray(*pPrev);
+            ScFormulaCell::CompareState eState = pCur->CompareByTokenArray(*pPrev);
             if (eState == ScFormulaCell::NotEqual)
                 continue;
 
commit 05271f9a742e6c40540ae6db1211d9ceb95a57e6
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Aug 12 16:42:53 2013 -0400

    Ungroup a cell when the group length becomes 1.
    
    Change-Id: Ic656d4837ab1fc5feb4b19765ae427371dfdfe10

diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index 07d9029..6583ac9 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -38,13 +38,25 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
 
     ScFormulaCellGroupRef xGroup = rTop.GetCellGroup();
 
-    ScFormulaCellGroupRef xGroup2(new ScFormulaCellGroup);
-    xGroup2->mbInvariant = xGroup->mbInvariant;
-    xGroup2->mnStart = nRow;
-    xGroup2->mnLength = xGroup->mnStart + xGroup->mnLength - nRow;
-    xGroup2->mpCode = xGroup->mpCode->Clone();
+    SCROW nLength2 = xGroup->mnStart + xGroup->mnLength - nRow;
+    ScFormulaCellGroupRef xGroup2;
+    if (nLength2 > 1)
+    {
+        xGroup2.reset(new ScFormulaCellGroup);
+        xGroup2->mbInvariant = xGroup->mbInvariant;
+        xGroup2->mnStart = nRow;
+        xGroup2->mnLength = nLength2;
+        xGroup2->mpCode = xGroup->mpCode->Clone();
+    }
 
     xGroup->mnLength = nRow - xGroup->mnStart;
+    if (xGroup->mnLength == 1)
+    {
+        // The top group consists of only one cell. Ungroup this.
+        ScFormulaCellGroupRef xNone;
+        ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
+        rPrev.SetCellGroup(xNone);
+    }
 
     // Apply the lower group object to the lower cells.
 #if DEBUG_COLUMN_STORAGE
@@ -56,7 +68,7 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
     }
 #endif
     sc::formula_block::iterator itEnd = it;
-    std::advance(itEnd, xGroup2->mnLength);
+    std::advance(itEnd, nLength2);
     for (; it != itEnd; ++it)
     {
         ScFormulaCell& rCell = **it;
commit 7ad68e3e8d97de37ca347deb50db379c252236e1
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Aug 12 16:28:29 2013 -0400

    Fix indentation.
    
    Change-Id: I2caebb42d92bf81e3ba8809a47f833a9379e769d

diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index 9299e33..07d9029 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -48,12 +48,12 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
 
     // Apply the lower group object to the lower cells.
 #if DEBUG_COLUMN_STORAGE
-        if (xGroup2->mnStart + xGroup2->mnLength > aPos.first->position + aPos.first->size)
-        {
-            cerr << "ScColumn::SplitFormulaCellGroup: Shared formula region goes beyond the formula block. Not good." << endl;
-            cerr.flush();
-            abort();
-        }
+    if (xGroup2->mnStart + xGroup2->mnLength > aPos.first->position + aPos.first->size)
+    {
+        cerr << "ScColumn::SplitFormulaCellGroup: Shared formula region goes beyond the formula block. Not good." << endl;
+        cerr.flush();
+        abort();
+    }
 #endif
     sc::formula_block::iterator itEnd = it;
     std::advance(itEnd, xGroup2->mnLength);
commit 3f06d624d8505b86a88a96b7eaa9910604aab9a7
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Aug 12 15:48:50 2013 -0400

    We still need to update cell positions for non-top cells.
    
    Change-Id: If967247ed5d916535e7b52af14b00090b7c9d0d2

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 6a1bbb0..c8e7f35 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -112,6 +112,8 @@ private:
                     };
     void            InterpretTail( ScInterpretTailParameter );
 
+    bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
+
     /**
      * Update reference in response to cell insertion or deletion.
      */
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 102de63..76582a0 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2128,6 +2128,29 @@ bool ScFormulaCell::HasColRowName() const
     return (pCode->GetNextColRowName() != NULL);
 }
 
+bool ScFormulaCell::UpdatePosOnShift( const sc::RefUpdateContext& rCxt )
+{
+    if (rCxt.meMode != URM_INSDEL)
+        // Just in case...
+        return false;
+
+    if (!rCxt.mnColDelta && !rCxt.mnRowDelta && !rCxt.mnTabDelta)
+        // No movement.
+        return false;
+
+    if (!rCxt.maRange.In(aPos))
+        return false;
+
+    // This formula cell itself is being shifted during cell range
+    // insertion or deletion. Update its position.
+    if (mxGroup && mxGroup->mnStart == aPos.Row())
+        mxGroup->mnStart += rCxt.mnRowDelta;
+
+    aPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+
+    return true;
+}
+
 namespace {
 
 /**
@@ -2245,17 +2268,7 @@ bool ScFormulaCell::UpdateReferenceOnShift(
     if ( pUndoCellPos )
         aUndoPos = *pUndoCellPos;
     ScAddress aOldPos( aPos );
-
-    if (rCxt.maRange.In(aPos))
-    {
-        // This formula cell itself is being shifted during cell range
-        // insertion or deletion. Update its position.
-        aPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
-        if (mxGroup && mxGroup->mnStart == aOldPos.Row())
-            mxGroup->mnStart += rCxt.mnRowDelta;
-
-        bCellStateChanged = aPos != aOldPos;
-    }
+    bCellStateChanged = UpdatePosOnShift(rCxt);
 
     // Check presence of any references or column row names.
     pCode->Reset();
@@ -2554,8 +2567,19 @@ bool ScFormulaCell::UpdateReference(
         return false;
 
     if (mxGroup && mxGroup->mnStart != aPos.Row())
-        // Update only the top cell in case the cell is part of a formula group.
+    {
+        // This is not a top cell of a formula group. Don't update references.
+
+        switch (rCxt.meMode)
+        {
+            case URM_INSDEL:
+                return UpdatePosOnShift(rCxt);
+            break;
+            default:
+                ;
+        }
         return false;
+    }
 
     switch (rCxt.meMode)
     {
commit 4625f6f699dfcc41b8e7ce2b86aedc1429eb4cf1
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Aug 12 15:23:28 2013 -0400

    Do the splitting of formula groups.
    
    Change-Id: I5a8661895b558b67abc19cdc39de9eb027bc1c34

diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index 9423384..0b49751 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -63,7 +63,15 @@ public:
      */
     static void splitFormulaCellGroup(const CellStoreType::position_type& aPos);
 
-    static void splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds);
+    /**
+     * Split existing shared formula ranges at specified row positions.
+     *
+     * @param rCells cell storage container
+     * @param rBounds row positions at which to split existing shared formula
+     *                ranges. Note that this method will directly modify this
+     *                parameter to sort and remove duplicates.
+     */
+    static void splitFormulaCellGroups(CellStoreType& rCells, std::vector<SCROW>& rBounds);
 
     /**
      * See if two specified adjacent formula cells can be merged, and if they
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 3cacf7c..25e2f84 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2364,6 +2364,10 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU
     if (rCxt.meMode == URM_COPY)
         return UpdateReferenceOnCopy(rCxt, pUndoDoc);
 
+    if (IsEmptyData())
+        // Cells in this column are all empty.
+        return false;
+
     std::vector<SCROW> aBounds;
 
     bool bThisColShifted = (rCxt.maRange.aStart.Tab() <= nTab && nTab <= rCxt.maRange.aEnd.Tab() &&
@@ -2387,11 +2391,6 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU
     UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds);
     std::for_each(maCells.begin(), maCells.end(), aBoundChecker);
 
-    // Sort and remove duplicates.
-    std::sort(aBounds.begin(), aBounds.end());
-    std::vector<SCROW>::iterator it = std::unique(aBounds.begin(), aBounds.end());
-    aBounds.erase(it, aBounds.end());
-
     // Do the actual splitting.
     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
 
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index d9f3a25..9299e33 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -64,9 +64,33 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
     }
 }
 
-void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds)
+void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vector<SCROW>& rBounds)
 {
-    // TODO: Implement this.
+    if (rBounds.empty())
+        return;
+
+    // Sort and remove duplicates.
+    std::sort(rBounds.begin(), rBounds.end());
+    std::vector<SCROW>::iterator it = std::unique(rBounds.begin(), rBounds.end());
+    rBounds.erase(it, rBounds.end());
+
+    it = rBounds.begin();
+    SCROW nRow = *it;
+    CellStoreType::position_type aPos = rCells.position(nRow);
+    if (aPos.first == rCells.end())
+        return;
+
+    splitFormulaCellGroup(aPos);
+    std::vector<SCROW>::iterator itEnd = rBounds.end();
+    for (++it; it != itEnd; ++it)
+    {
+        nRow = *it;
+        aPos = rCells.position(aPos.first, nRow);
+        if (aPos.first == rCells.end())
+            return;
+
+        splitFormulaCellGroup(aPos);
+    }
 }
 
 void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 6cd491c..701e235 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2981,7 +2981,7 @@ void checkBounds(
     SCROW nOffset = rCxt.maRange.aStart.Row() - aAbs.aStart.Row();
     rBounds.push_back(rPos.Row()+nOffset);
     // Ditto.
-    nOffset = rCxt.maRange.aEnd.Row() - aAbs.aStart.Row();
+    nOffset = rCxt.maRange.aEnd.Row() + 1 - aAbs.aStart.Row();
     rBounds.push_back(rPos.Row()+nOffset);
 }
 
commit 9d27add20779382192d3530178c9d0ca365c56c9
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Sat Aug 10 23:31:38 2013 -0400

    Collect all boundaries at which to split the formula group.
    
    Change-Id: Ic78d7a06991b983e625b161f11fbbabce02334f3

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 2a2b61c..6a1bbb0 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -352,6 +352,7 @@ public:
 
     bool IsShared() const;
     bool IsSharedInvariant() const;
+    bool IsSharedTop() const;
     SCROW GetSharedTopRow() const;
     SCROW GetSharedLength() const;
     ScTokenArray* GetSharedCode();
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index 232c4bc..9423384 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -13,6 +13,8 @@
 #include "formulacell.hxx"
 #include "mtvelements.hxx"
 
+#include <vector>
+
 namespace sc {
 
 class SharedFormulaUtil
@@ -61,6 +63,8 @@ public:
      */
     static void splitFormulaCellGroup(const CellStoreType::position_type& aPos);
 
+    static void splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds);
+
     /**
      * See if two specified adjacent formula cells can be merged, and if they
      * can, merge them into the same group.
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 09a9798..00f192d 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -166,6 +166,9 @@ public:
 
     sc::RefUpdateResult AdjustReferenceOnMovedTab( sc::RefUpdateMoveTabContext& rCxt, const ScAddress& rOldPos );
 
+    void CheckRelativeReferenceBounds(
+        const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const;
+
 #if DEBUG_FORMULA_COMPILER
     void Dump() const;
 #endif
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ba9b35e..3cacf7c 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2295,6 +2295,46 @@ public:
     bool isUpdated() const { return mbUpdated; }
 };
 
+class UpdateRefGroupBoundChecker : std::unary_function<sc::CellStoreType::value_type, void>
+{
+    const sc::RefUpdateContext& mrCxt;
+    std::vector<SCROW>& mrBounds;
+public:
+    UpdateRefGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
+        mrCxt(rCxt), mrBounds(rBounds) {}
+
+    void operator() (const sc::CellStoreType::value_type& node)
+    {
+        if (node.type != sc::element_type_formula)
+            return;
+
+        sc::formula_block::const_iterator it = sc::formula_block::begin(*node.data);
+        sc::formula_block::const_iterator itEnd = sc::formula_block::end(*node.data);
+
+        // Only pick shared formula cells that are the top cells of their
+        // respective shared ranges.
+        for (; it != itEnd; ++it)
+        {
+            const ScFormulaCell& rCell = **it;
+            if (!rCell.IsShared())
+                continue;
+
+            if (rCell.IsSharedTop())
+            {
+                // Check its tokens and record its reference boundaries.
+                const ScTokenArray& rCode = *rCell.GetCode();
+                rCode.CheckRelativeReferenceBounds(
+                    mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
+
+                // Move to the last cell in the group, to get incremented to
+                // the next cell in the next iteration.
+                size_t nOffsetToLast = rCell.GetSharedLength() - 1;
+                std::advance(it, nOffsetToLast);
+            }
+        }
+    }
+};
+
 }
 
 bool ScColumn::UpdateReferenceOnCopy( const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc )
@@ -2324,6 +2364,8 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU
     if (rCxt.meMode == URM_COPY)
         return UpdateReferenceOnCopy(rCxt, pUndoDoc);
 
+    std::vector<SCROW> aBounds;
+
     bool bThisColShifted = (rCxt.maRange.aStart.Tab() <= nTab && nTab <= rCxt.maRange.aEnd.Tab() &&
                             rCxt.maRange.aStart.Col() <= nCol && nCol <= rCxt.maRange.aEnd.Col());
     if (bThisColShifted)
@@ -2333,17 +2375,26 @@ bool ScColumn::UpdateReference( const sc::RefUpdateContext& rCxt, ScDocument* pU
         SCROW nSplitPos = rCxt.maRange.aStart.Row();
         if (ValidRow(nSplitPos))
         {
-            sc::CellStoreType::position_type aPos = maCells.position(nSplitPos);
-            sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
+            aBounds.push_back(nSplitPos);
             nSplitPos = rCxt.maRange.aEnd.Row() + 1;
             if (ValidRow(nSplitPos))
-            {
-                aPos = maCells.position(aPos.first, nSplitPos);
-                sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
-            }
+                aBounds.push_back(nSplitPos);
         }
     }
 
+    // Check the row positions at which the group must be split per relative
+    // references.
+    UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds);
+    std::for_each(maCells.begin(), maCells.end(), aBoundChecker);
+
+    // Sort and remove duplicates.
+    std::sort(aBounds.begin(), aBounds.end());
+    std::vector<SCROW>::iterator it = std::unique(aBounds.begin(), aBounds.end());
+    aBounds.erase(it, aBounds.end());
+
+    // Do the actual splitting.
+    sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
+
     UpdateRefOnNonCopy aHandler(nCol, nTab, rCxt, pUndoDoc);
     sc::ProcessFormula(maCells, aHandler);
     return aHandler.isUpdated();
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 962b2dc..102de63 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3774,6 +3774,14 @@ bool ScFormulaCell::IsSharedInvariant() const
     return mxGroup ? mxGroup->mbInvariant : false;
 }
 
+bool ScFormulaCell::IsSharedTop() const
+{
+    if (!mxGroup)
+        return false;
+
+    return mxGroup->mnStart == aPos.Row();
+}
+
 SCROW ScFormulaCell::GetSharedTopRow() const
 {
     return mxGroup ? mxGroup->mnStart : -1;
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index 3e77934..d9f3a25 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -64,6 +64,11 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
     }
 }
 
+void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, const std::vector<SCROW>& rBounds)
+{
+    // TODO: Implement this.
+}
+
 void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
 {
     ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index d231007..6cd491c 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2934,6 +2934,88 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( sc::RefUpdateMoveTa
     return aRes;
 }
 
+namespace {
+
+void checkBounds(
+    const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen,
+    const ScSingleRefData& rRef, std::vector<SCROW>& rBounds)
+{
+    if (!rRef.IsRowRel())
+        return;
+
+    ScRange aAbs(rRef.toAbs(rPos));
+    aAbs.aEnd.IncRow(nGroupLen-1);
+    if (!rCxt.maRange.Intersects(aAbs))
+        return;
+
+    // Get the boundary row positions.
+    if (aAbs.aEnd.Row() < rCxt.maRange.aStart.Row())
+        // No intersections.
+        return;
+
+    if (aAbs.aEnd.Row() <= rCxt.maRange.aEnd.Row())
+    {
+        //    +-+ <---- top
+        //    | |
+        // +--+-+--+ <---- boundary row position
+        // |  | |  |
+        // |  +-+  |
+        // +-------+
+
+        // Add offset from the reference top to the cell position.
+        SCROW nOffset = rCxt.maRange.aStart.Row() - aAbs.aStart.Row();
+        rBounds.push_back(rPos.Row()+nOffset);
+        return;
+    }
+
+    //    +-+ <---- top
+    //    | |
+    // +--+-+--+ <---- boundary row position
+    // |  | |  |
+    // |  | |  |
+    // +--+-+--+ <---- boundary row position
+    //    | |
+    //    +-+
+
+    // Add offset from the reference top to the cell position.
+    SCROW nOffset = rCxt.maRange.aStart.Row() - aAbs.aStart.Row();
+    rBounds.push_back(rPos.Row()+nOffset);
+    // Ditto.
+    nOffset = rCxt.maRange.aEnd.Row() - aAbs.aStart.Row();
+    rBounds.push_back(rPos.Row()+nOffset);
+}
+
+}
+
+void ScTokenArray::CheckRelativeReferenceBounds(
+    const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
+{
+    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);
+                checkBounds(rCxt, rPos, nGroupLen, pToken->GetSingleRef(), rBounds);
+            }
+            break;
+            case svDoubleRef:
+            {
+                ScToken* pToken = static_cast<ScToken*>(*p);
+                const ScComplexRefData& rRef = pToken->GetDoubleRef();
+                checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds);
+                checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds);
+            }
+            break;
+            default:
+                ;
+        }
+    }
+}
+
 #if DEBUG_FORMULA_COMPILER
 void ScTokenArray::Dump() const
 {
commit 9531c75056cf24cd2c15408dccf5318cf44b4499
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Aug 9 16:41:22 2013 -0400

    If the formula cell is grouped, update reference only on the top cell.
    
    Change-Id: I5e2e9db621a61deba39a46962e0ca877235d7c90

diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index f755c98..962b2dc 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2553,6 +2553,10 @@ bool ScFormulaCell::UpdateReference(
     if (pDocument->IsClipOrUndo())
         return false;
 
+    if (mxGroup && mxGroup->mnStart != aPos.Row())
+        // Update only the top cell in case the cell is part of a formula group.
+        return false;
+
     switch (rCxt.meMode)
     {
         case URM_INSDEL:
commit 2ce9380ad1cac8b3cb741dabcf11e91c4ff37d75
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Aug 9 12:09:44 2013 -0400

    Export shared formulas to xls, from the new shared formula in the core.
    
    Turns out we don't export shared formulas to xlsx, so no work is needed
    there.
    
    Change-Id: I85604f3b80c95c5b6179bbdac41e758c5de7854a

diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx
index b436a3d..b13c5bb 100644
--- a/sc/source/filter/excel/xetable.cxx
+++ b/sc/source/filter/excel/xetable.cxx
@@ -207,28 +207,29 @@ XclExpShrfmlaBuffer::XclExpShrfmlaBuffer( const XclExpRoot& rRoot ) :
 }
 
 XclExpShrfmlaRef XclExpShrfmlaBuffer::CreateOrExtendShrfmla(
-        const ScTokenArray& rScTokArr, const ScAddress& rScPos )
+    const ScFormulaCell& rScCell, const ScAddress& rScPos )
 {
     XclExpShrfmlaRef xRec;
-    if( const ScTokenArray* pShrdScTokArr = XclTokenArrayHelper::GetSharedFormula( GetRoot(), rScTokArr ) )
+    const ScTokenArray* pShrdScTokArr = rScCell.GetSharedCode();
+    if (!pShrdScTokArr)
+        // This formula cell is not shared formula cell.
+        return xRec;
+
+    XclExpShrfmlaMap::iterator aIt = maRecMap.find( pShrdScTokArr );
+    if( aIt == maRecMap.end() )
     {
-        XclExpShrfmlaMap::iterator aIt = maRecMap.find( pShrdScTokArr );
-        if( aIt == maRecMap.end() )
-        {
-            // create a new record
-            XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_SHARED, *pShrdScTokArr, &rScPos );
-            xRec.reset( new XclExpShrfmla( xTokArr, rScPos ) );
-            maRecMap[ pShrdScTokArr ] = xRec;
-        }
-        else
-        {
-            // extend existing record
-            OSL_ENSURE( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" );
-            xRec = aIt->second;
-            xRec->ExtendRange( rScPos );
-        }
+        // create a new record
+        XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_SHARED, *pShrdScTokArr, &rScPos );
+        xRec.reset( new XclExpShrfmla( xTokArr, rScPos ) );
+        maRecMap[ pShrdScTokArr ] = xRec;
+    }
+    else
+    {
+        // extend existing record
+        OSL_ENSURE( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" );
+        xRec = aIt->second;
+        xRec->ExtendRange( rScPos );
     }
-    return xRec;
 }
 
 // Multiple operations ========================================================
@@ -851,7 +852,7 @@ XclExpFormulaCell::XclExpFormulaCell(
 
     // no matrix found - try to create shared formula
     if( !mxAddRec )
-        mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla( rScTokArr, aScPos );
+        mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla(mrScFmlaCell, aScPos);
 
     // no shared formula found - create a simple cell formula
     if( !mxAddRec )
diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx
index 356a348..a04ebfd 100644
--- a/sc/source/filter/excel/xlformula.cxx
+++ b/sc/source/filter/excel/xlformula.cxx
@@ -759,13 +759,6 @@ void XclTokenArrayHelper::ConvertStringToList( ScTokenArray& rScTokArr, sal_Unic
     }
 }
 
-// shared formulas ------------------------------------------------------------
-
-const ScTokenArray* XclTokenArrayHelper::GetSharedFormula( const XclRoot& /*rRoot*/, const ScTokenArray& /*rScTokArr*/ )
-{
-    return NULL;
-}
-
 // multiple operations --------------------------------------------------------
 
 namespace {
diff --git a/sc/source/filter/inc/xetable.hxx b/sc/source/filter/inc/xetable.hxx
index 533d2ec..0e47052 100644
--- a/sc/source/filter/inc/xetable.hxx
+++ b/sc/source/filter/inc/xetable.hxx
@@ -189,8 +189,7 @@ public:
             function updates its cell range to include the passed cell position,
             if there is a SHRFMLA record for the passed token array; otherwise
             this function creates and returns a new SHRFMLA record. */
-    XclExpShrfmlaRef    CreateOrExtendShrfmla(
-                            const ScTokenArray& rScTokArr, const ScAddress& rScPos );
+    XclExpShrfmlaRef CreateOrExtendShrfmla( const ScFormulaCell& rScCell, const ScAddress& rScPos );
 
 private:
     typedef ::std::map< const ScTokenArray*, XclExpShrfmlaRef > XclExpShrfmlaMap;
diff --git a/sc/source/filter/inc/xlformula.hxx b/sc/source/filter/inc/xlformula.hxx
index fdf395e..0a90e08 100644
--- a/sc/source/filter/inc/xlformula.hxx
+++ b/sc/source/filter/inc/xlformula.hxx
@@ -523,14 +523,6 @@ public:
         @param bTrimLeadingSpaces  true = remove leading spaces from each token. */
     static void         ConvertStringToList( ScTokenArray& rScTokArr, sal_Unicode cStringSep, bool bTrimLeadingSpaces );
 
-    // shared formulas --------------------------------------------------------
-
-    /** Tries to extract the definition of a shared formula from the passed token array.
-        @descr  Shared formulas are stored as hidden defined names in Calc. This
-        function looks if the passed token array consists of the reference to
-        such a hidden defined name and returns its definition on success. */
-    static const ScTokenArray* GetSharedFormula( const XclRoot& rRoot, const ScTokenArray& rScTokArr );
-
     // multiple operations ----------------------------------------------------
 
     /** Parses the passed formula and tries to extract references of a multiple operation.


More information about the Libreoffice-commits mailing list