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

Kohei Yoshida kohei.yoshida at gmail.com
Mon Jul 8 11:33:37 PDT 2013


 sc/inc/column.hxx                   |    2 
 sc/qa/unit/ucalc.cxx                |  129 ++++++++++++++++++++++++--
 sc/source/core/data/column.cxx      |  110 +++++++++++++++-------
 sc/source/core/data/column2.cxx     |    4 
 sc/source/core/data/column3.cxx     |  173 +++++++++++++++++++++++++-----------
 sc/source/core/data/formulacell.cxx |    3 
 6 files changed, 322 insertions(+), 99 deletions(-)

New commits:
commit 3caaac486fbe9a575e602c54f418483cf9dedded
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Jul 8 13:50:23 2013 -0400

    Remove this marker.
    
    Change-Id: Iab8695f579abb009f12aa76f4e161f106527f493

diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 89d26c1..e7e98f8 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2293,7 +2293,6 @@ bool ScColumn::UpdateReference(
     }
 
     UpdateRefOnNonCopy aHandler(nCol, nTab, rRange, nDx, nDy, nDz, eUpdateRefMode, pUndoDoc);
-    FormulaCellsUndecided(0, MAXROW);
     sc::ProcessFormula(maCells, aHandler);
     return aHandler.isUpdated();
 }
commit 9e874bc0854cab345da8df0a64442c6c4fe04824
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Jul 8 13:48:07 2013 -0400

    Adjust formula grouping in InsertRow().
    
    Change-Id: I82723a30edc361b627246b66d21dc04cd639caa6

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 96221cf..5ea6597 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -6447,8 +6447,20 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
 
-    m_pDoc->DeleteTab(0);
+    // Insert 2 rows at row 4, to split it into B2:B3 and B6:B7.
+    m_pDoc->InsertRow(ScRange(0,3,0,MAXCOL,4,0));
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
 
+    aPos.SetRow(5);
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B6 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+
+    m_pDoc->DeleteTab(0);
 }
 
 namespace {
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 6f87a93..89d26c1 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2273,6 +2273,25 @@ bool ScColumn::UpdateReference(
         return aHandler.isUpdated();
     }
 
+    bool bThisColShifted = (rRange.aStart.Tab() <= nTab && nTab <= rRange.aEnd.Tab() && rRange.aStart.Col() <= nCol && nCol <= rRange.aEnd.Col());
+    if (bThisColShifted)
+    {
+        // Cells in this column is being shifted.  Split formula grouping at
+        // the top and bottom boundaries before they get shifted.
+        SCROW nSplitPos = rRange.aStart.Row();
+        if (ValidRow(nSplitPos))
+        {
+            sc::CellStoreType::position_type aPos = maCells.position(nSplitPos);
+            SplitFormulaCellGroup(aPos);
+            nSplitPos = rRange.aEnd.Row() + 1;
+            if (ValidRow(nSplitPos))
+            {
+                aPos = maCells.position(aPos.first, nSplitPos);
+                SplitFormulaCellGroup(aPos);
+            }
+        }
+    }
+
     UpdateRefOnNonCopy aHandler(nCol, nTab, rRange, nDx, nDy, nDz, eUpdateRefMode, pUndoDoc);
     FormulaCellsUndecided(0, MAXROW);
     sc::ProcessFormula(maCells, aHandler);
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index e146f4a..b693502 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2099,6 +2099,9 @@ bool ScFormulaCell::UpdateReference(
         // This formula cell itself is being shifted during cell range
         // insertion or deletion. Update its position.
         aPos.Move(nDx, nDy, nDz);
+        if (xGroup && xGroup->mnStart == aOldPos.Row())
+            xGroup->mnStart += nDy;
+
         bCellStateChanged = aPos != aOldPos;
     }
     else if (rRange.In(aPos))
commit 48aece30a2cdde4b9bea4146e9868e0bfdaab448
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Jul 8 11:48:00 2013 -0400

    Add test for re-grouping of formulas in DeleteRow().
    
    Change-Id: Iea7fafedc2a5f1549a701d1fa768c127e3236246

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index f04726f..96221cf 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -6438,6 +6438,15 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
 
+    // Delete rows 4:8 and shift row 9 and below up to row 4.  This should
+    // re-merge the two into a group of B2:B5.
+    m_pDoc->DeleteRow(ScRange(0,3,0,MAXCOL,7,0));
+    aPos.SetRow(1);
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
+
     m_pDoc->DeleteTab(0);
 
 }
commit e72e5a33505ad3b756b3a73975d223eb9565f441
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Jul 8 10:15:27 2013 -0400

    Re-group formula cells in DeleteRow().
    
    Change-Id: Ic67af048baa55cf1aee118ec741f140831127a95

diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 0667d38..3c35b80 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -296,9 +296,14 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
     maCells.erase(nStartRow, nEndRow);
     maCells.resize(MAXROWCOUNT);
 
+    // Get the position again after the container change.
+    aPos = maCells.position(nStartRow);
+
     // Shift the formula cell positions below the start row.
     ShiftFormulaPosHandler aShiftFormulaFunc;
-    sc::ProcessFormula(maCells.begin(), maCells, nStartRow, MAXROW, aShiftFormulaFunc);
+    sc::ProcessFormula(aPos.first, maCells, nStartRow, MAXROW, aShiftFormulaFunc);
+
+    JoinFormulaCellAbove(aPos);
 
     // Single cell broadcasts on deleted cells.
     BroadcastCells(aDeleteRowsFunc.getNonEmptyRows());
@@ -307,7 +312,6 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
     maCellTextAttrs.erase(nStartRow, nEndRow);
     maCellTextAttrs.resize(MAXROWCOUNT);
 
-    RegroupFormulaCells(nStartRow);
     CellStorageModified();
 
     if (!bShiftCells)
@@ -598,8 +602,6 @@ void ScColumn::JoinFormulaCellAbove( const sc::CellStoreType::position_type& aPo
         // cell is not a formula cell.
         return;
 
-    SCROW nRow = aPos.first->position + aPos.second;
-
     ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
     ScFormulaCell& rCell = *sc::formula_block::at(*aPos.first->data, aPos.second);
     sc::CellStoreType::position_type aPosPrev = aPos;
commit 547e939d0226bb7e62705f2171a58aa77aa5d3da
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Jul 4 02:17:03 2013 -0400

    More on regrouping of formula cells.
    
    Change-Id: Icd3403e759841dce351c932ea8915ba9819e5a29

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index c36b804..6704fb4 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -498,6 +498,8 @@ public:
      */
     void SplitFormulaCellGroup( const sc::CellStoreType::position_type& aPos ) const;
 
+    void JoinFormulaCellAbove( const sc::CellStoreType::position_type& aPos ) const;
+
     /**
      * Regroup formula cells for the entire column.
      */
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 3a74780..6f87a93 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2127,13 +2127,29 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
     sc::SingleColumnSpanSet::SpansType aRanges;
     aNonEmpties.getSpans(aRanges);
 
+    // Split the formula grouping at the top and bottom boundaries.
+    sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
+    SplitFormulaCellGroup(aPos);
+    aPos = maCells.position(aPos.first, nEndRow+1);
+    SplitFormulaCellGroup(aPos);
+
+    // Do the same with the destination column.
+    aPos = rCol.maCells.position(nStartRow);
+    rCol.SplitFormulaCellGroup(aPos);
+    aPos = rCol.maCells.position(aPos.first, nEndRow+1);
+    rCol.SplitFormulaCellGroup(aPos);
+
     // Move the broadcasters to the destination column.
     maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
     maCells.transfer(nStartRow, nEndRow, rCol.maCells, nStartRow);
     maCellTextAttrs.transfer(nStartRow, nEndRow, rCol.maCellTextAttrs, nStartRow);
 
-    RegroupFormulaCells(nStartRow, nEndRow);
-    rCol.RegroupFormulaCells(nStartRow, nEndRow);
+    // Re-group transferred formula cells.
+    aPos = rCol.maCells.position(nStartRow);
+    rCol.JoinFormulaCellAbove(aPos);
+    aPos = rCol.maCells.position(aPos.first, nEndRow+1);
+    rCol.JoinFormulaCellAbove(aPos);
+
     CellStorageModified();
     rCol.CellStorageModified();
 
@@ -2267,31 +2283,47 @@ namespace {
 
 class UpdateTransHandler
 {
+    ScColumn& mrColumn;
+    sc::CellStoreType::iterator miPos;
     ScRange maSource;
     ScAddress maDest;
     ScDocument* mpUndoDoc;
 public:
-    UpdateTransHandler(const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
+    UpdateTransHandler(ScColumn& rColumn, const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
+        mrColumn(rColumn),
+        miPos(rColumn.GetCellStore().begin()),
         maSource(rSource), maDest(rDest), mpUndoDoc(pUndoDoc) {}
 
-    void operator() (size_t, ScFormulaCell* pCell)
+    void operator() (size_t nRow, ScFormulaCell* pCell)
     {
+        sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
+        miPos = aPos.first;
+        mrColumn.UnshareFormulaCell(aPos, *pCell);
         pCell->UpdateTranspose(maSource, maDest, mpUndoDoc);
+        mrColumn.JoinNewFormulaCell(aPos, *pCell);
     }
 };
 
 class UpdateGrowHandler
 {
+    ScColumn& mrColumn;
+    sc::CellStoreType::iterator miPos;
     ScRange maArea;
     SCCOL mnGrowX;
     SCROW mnGrowY;
 public:
-    UpdateGrowHandler(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
+    UpdateGrowHandler(ScColumn& rColumn, const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
+        mrColumn(rColumn),
+        miPos(rColumn.GetCellStore().begin()),
         maArea(rArea), mnGrowX(nGrowX), mnGrowY(nGrowY) {}
 
-    void operator() (size_t, ScFormulaCell* pCell)
+    void operator() (size_t nRow, ScFormulaCell* pCell)
     {
+        sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
+        miPos = aPos.first;
+        mrColumn.UnshareFormulaCell(aPos, *pCell);
         pCell->UpdateGrow(maArea, mnGrowX, mnGrowY);
+        mrColumn.JoinNewFormulaCell(aPos, *pCell);
     }
 };
 
@@ -2638,14 +2670,22 @@ public:
 
 class CompileErrorCellsHandler
 {
+    ScColumn& mrColumn;
+    sc::CellStoreType::iterator miPos;
     sal_uInt16 mnErrCode;
     FormulaGrammar::Grammar meGram;
     bool mbCompiled;
 public:
-    CompileErrorCellsHandler(sal_uInt16 nErrCode, FormulaGrammar::Grammar eGram) :
-        mnErrCode(nErrCode), meGram(eGram), mbCompiled(false) {}
+    CompileErrorCellsHandler(ScColumn& rColumn, sal_uInt16 nErrCode, FormulaGrammar::Grammar eGram) :
+        mrColumn(rColumn),
+        miPos(mrColumn.GetCellStore().begin()),
+        mnErrCode(nErrCode),
+        meGram(eGram),
+        mbCompiled(false)
+    {
+    }
 
-    void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
+    void operator() (size_t nRow, ScFormulaCell* pCell)
     {
         sal_uInt16 nCurError = pCell->GetRawError();
         if (!nCurError)
@@ -2656,10 +2696,14 @@ public:
             // Error code is specified, and it doesn't match. Skip it.
             return;
 
+        sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
+        miPos = aPos.first;
+        mrColumn.UnshareFormulaCell(aPos, *pCell);
         pCell->GetCode()->SetCodeError(0);
         OUStringBuffer aBuf;
         pCell->GetFormula(aBuf, meGram);
         pCell->Compile(aBuf.makeStringAndClear(), false, meGram);
+        mrColumn.JoinNewFormulaCell(aPos, *pCell);
 
         mbCompiled = true;
     }
@@ -2735,17 +2779,15 @@ public:
 void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
                                     ScDocument* pUndoDoc )
 {
-    UpdateTransHandler aFunc(rSource, rDest, pUndoDoc);
+    UpdateTransHandler aFunc(*this, rSource, rDest, pUndoDoc);
     sc::ProcessFormula(maCells, aFunc);
-    RegroupFormulaCells();
 }
 
 
 void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
 {
-    UpdateGrowHandler aFunc(rArea, nGrowX, nGrowY);
+    UpdateGrowHandler aFunc(*this, rArea, nGrowX, nGrowY);
     sc::ProcessFormula(maCells, aFunc);
-    RegroupFormulaCells();
 }
 
 
@@ -2765,10 +2807,7 @@ void ScColumn::UpdateInsertTabOnlyCells(SCTAB nInsPos, SCTAB nNewSheets)
     InsertTabUpdater aFunc(maCellTextAttrs, nTab, nInsPos, nNewSheets);
     sc::ProcessFormulaEditText(maCells, aFunc);
     if (aFunc.isModified())
-    {
-        RegroupFormulaCells();
         CellStorageModified();
-    }
 }
 
 void ScColumn::UpdateDeleteTab(SCTAB nDelPos, bool bIsMove, ScColumn* /*pRefUndo*/, SCTAB nSheets)
@@ -2911,12 +2950,8 @@ void ScColumn::CompileXML( ScProgress& rProgress )
 
 bool ScColumn::CompileErrorCells(sal_uInt16 nErrCode)
 {
-    CompileErrorCellsHandler aHdl(nErrCode, pDocument->GetGrammar());
+    CompileErrorCellsHandler aHdl(*this, nErrCode, pDocument->GetGrammar());
     sc::ProcessFormula(maCells, aHdl);
-    if (aHdl.isCompiled())
-        // TODO: Probably more efficient to do this individually rather than the whole column.
-        RegroupFormulaCells();
-
     return aHdl.isCompiled();
 }
 
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 932e613..46bf525 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1533,10 +1533,6 @@ void ScColumn::CellStorageModified()
 #endif
 }
 
-void ScColumn::RegroupFormulaCells()
-{
-}
-
 void ScColumn::RegroupFormulaCells( SCROW /*nRow*/ )
 {
 }
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index bddbd5a..0667d38 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -326,12 +326,14 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( SCROW nRow )
 
 namespace {
 
-void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
+void joinFormulaCells(const sc::CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
 {
     ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
     if (eState == ScFormulaCell::NotEqual)
         return;
 
+    SCROW nRow = rPos.first->position + rPos.second;
+
     // Formula tokens equal those of the previous formula cell.
     ScFormulaCellGroupRef xGroup1 = rCell1.GetCellGroup();
     ScFormulaCellGroupRef xGroup2 = rCell2.GetCellGroup();
@@ -339,13 +341,23 @@ void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
     {
         if (xGroup2)
         {
-            // Both cell1 and cell2 are shared. Merge them together.
+            // Both cell 1 and cell 2 are shared. Merge them together.
+            if (xGroup1.get() == xGroup2.get())
+                // They belong to the same group.
+                return;
+
+            // Set the group object from cell 1 to all cells in group 2.
             xGroup1->mnLength += xGroup2->mnLength;
-            rCell2.SetCellGroup(xGroup1);
+            size_t nOffset = rPos.second + 1; // position of cell 2
+            for (size_t i = 0, n = xGroup2->mnLength; i < n; ++i)
+            {
+                ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, nOffset+i);
+                rCell.SetCellGroup(xGroup1);
+            }
         }
         else
         {
-            // cell1 is shared but cell2 is not.
+            // cell 1 is shared but cell 2 is not.
             rCell2.SetCellGroup(xGroup1);
             ++xGroup1->mnLength;
         }
@@ -354,7 +366,7 @@ void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
     {
         if (xGroup2)
         {
-            // cell1 is not shared, but cell2 is already shared.
+            // cell 1 is not shared, but cell 2 is already shared.
             rCell1.SetCellGroup(xGroup2);
             xGroup2->mnStart = nRow;
             ++xGroup2->mnLength;
@@ -378,20 +390,20 @@ void joinFormulaCells(SCROW nRow, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
 void ScColumn::JoinNewFormulaCell(
     const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const
 {
-    SCROW nRow = aPos.first->position + aPos.second;
-
     // Check the previous row position for possible grouping.
     if (aPos.first->type == sc::element_type_formula && aPos.second > 0)
     {
         ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
-        joinFormulaCells(nRow-1, rPrev, rCell);
+        sc::CellStoreType::position_type aPosPrev = aPos;
+        --aPosPrev.second;
+        joinFormulaCells(aPosPrev, rPrev, rCell);
     }
 
     // Check the next row position for possible grouping.
     if (aPos.first->type == sc::element_type_formula && aPos.second+1 < aPos.first->size)
     {
         ScFormulaCell& rNext = *sc::formula_block::at(*aPos.first->data, aPos.second+1);
-        joinFormulaCells(nRow, rCell, rNext);
+        joinFormulaCells(aPos, rCell, rNext);
     }
 }
 
@@ -575,6 +587,26 @@ void ScColumn::SplitFormulaCellGroup( const sc::CellStoreType::position_type& aP
     }
 }
 
+void ScColumn::JoinFormulaCellAbove( const sc::CellStoreType::position_type& aPos ) const
+{
+    if (aPos.first->type != sc::element_type_formula)
+        // This is not a formula cell.
+        return;
+
+    if (aPos.second == 0)
+        // This cell is already the top cell in a formula block; the previous
+        // cell is not a formula cell.
+        return;
+
+    SCROW nRow = aPos.first->position + aPos.second;
+
+    ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
+    ScFormulaCell& rCell = *sc::formula_block::at(*aPos.first->data, aPos.second);
+    sc::CellStoreType::position_type aPosPrev = aPos;
+    --aPosPrev.second;
+    joinFormulaCells(aPosPrev, rPrev, rCell);
+}
+
 sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow )
 {
     // See if we are overwriting an existing formula cell.
@@ -742,7 +774,7 @@ class EmptyCells
     sc::ColumnBlockPosition& mrPos;
     sc::CellStoreType::iterator miPos;
 
-    void splitFormulaGrouping(sc::CellStoreType& rCells, const sc::CellStoreType::position_type& rPos)
+    void splitFormulaGrouping(const sc::CellStoreType::position_type& rPos)
     {
         if (rPos.first->type == sc::element_type_formula)
         {
@@ -762,9 +794,9 @@ public:
         // First, split formula grouping at the top and bottom boundaries
         // before emptying the cells.
         sc::CellStoreType::position_type aPos = rCells.position(mrPos.miCellPos, rSpan.mnRow1);
-        splitFormulaGrouping(rCells, aPos);
+        splitFormulaGrouping(aPos);
         aPos = rCells.position(aPos.first, rSpan.mnRow2);
-        splitFormulaGrouping(rCells, aPos);
+        splitFormulaGrouping(aPos);
 
         mrPos.miCellPos = rCells.set_empty(mrPos.miCellPos, rSpan.mnRow1, rSpan.mnRow2);
         mrPos.miCellTextAttrPos = mrColumn.GetCellAttrStore().set_empty(mrPos.miCellTextAttrPos, rSpan.mnRow1, rSpan.mnRow2);
@@ -2863,15 +2895,19 @@ void ScColumn::RebuildFormulaGroups()
     if (!mbDirtyGroups)
         return;
 
-    // clear previous formula groups.
+    RegroupFormulaCells();
+    mbDirtyGroups = false;
+}
+
+void ScColumn::RegroupFormulaCells()
+{
+    // clear previous formula groups (if any)
     ScFormulaCellGroupRef xNone;
     CellGroupSetter aFunc(xNone);
     sc::ProcessFormula(maCells, aFunc);
 
     // re-build formula groups.
     std::for_each(maCells.begin(), maCells.end(), GroupFormulaCells());
-
-    mbDirtyGroups = false;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 5cbeb9c56db071b9c658ba4e4997b424fd4fbd4f
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 3 22:48:31 2013 -0400

    Adjust formula grouping on range deletion.
    
    Change-Id: Id3c2cd0a3cffa299c8424f9c9e4989ce8bd60719

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 219638d..f04726f 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -6397,7 +6397,49 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_MESSAGE("B18 should be a formula cell.", pFC);
     CPPUNIT_ASSERT_MESSAGE("B18 should be non-shared.", !pFC->IsShared());
 
+    // Set up a new group for shared formulas in B2:B10.
+    clearRange(m_pDoc, ScRange(0,0,0,2,100,0));
+
+    aPos.SetRow(1);
+    m_pDoc->SetString(aPos, "=A2*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A3*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A4*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A5*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A6*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A7*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A8*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A9*10");
+    aPos.IncRow();
+    m_pDoc->SetString(aPos, "=A10*10");
+
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B10 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedLength());
+
+    // Delete A4:B8. This should splite the grouping to B2:B3 and B9:B10.
+    clearRange(m_pDoc, ScRange(0,3,0,1,7,0));
+    aPos.SetRow(1);
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B2 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+
+    aPos.SetRow(8);
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B9 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+
     m_pDoc->DeleteTab(0);
+
 }
 
 namespace {
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index af683fe..3a74780 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2809,7 +2809,6 @@ void ScColumn::UpdateCompile( bool bForceIfNameInUse )
 {
     UpdateCompileHandler aFunc(bForceIfNameInUse);
     sc::ProcessFormula(maCells, aFunc);
-    RegroupFormulaCells();
 }
 
 
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index f02a6a8..bddbd5a 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -741,17 +741,33 @@ class EmptyCells
     ScColumn& mrColumn;
     sc::ColumnBlockPosition& mrPos;
     sc::CellStoreType::iterator miPos;
-    sc::CellStoreType& mrCells;
-    sc::CellTextAttrStoreType& mrAttrs;
+
+    void splitFormulaGrouping(sc::CellStoreType& rCells, const sc::CellStoreType::position_type& rPos)
+    {
+        if (rPos.first->type == sc::element_type_formula)
+        {
+            ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, rPos.second);
+            mrColumn.UnshareFormulaCell(rPos, rCell);
+        }
+    }
+
 public:
-    EmptyCells(sc::ColumnBlockPosition& rPos, ScColumn& rColumn, sc::CellStoreType& rCells, sc::CellTextAttrStoreType& rAttrs) :
-        mrColumn(rColumn), mrPos(rPos), mrCells(rCells), mrAttrs(rAttrs) {}
+    EmptyCells(sc::ColumnBlockPosition& rPos, ScColumn& rColumn) :
+        mrColumn(rColumn), mrPos(rPos) {}
 
     void operator() (const sc::SingleColumnSpanSet::Span& rSpan)
     {
-        mrPos.miCellPos = mrCells.set_empty(mrPos.miCellPos, rSpan.mnRow1, rSpan.mnRow2);
-        mrPos.miCellTextAttrPos = mrAttrs.set_empty(mrPos.miCellTextAttrPos, rSpan.mnRow1, rSpan.mnRow2);
-        mrColumn.RegroupFormulaCells(rSpan.mnRow1, rSpan.mnRow2);
+        sc::CellStoreType& rCells = mrColumn.GetCellStore();
+
+        // First, split formula grouping at the top and bottom boundaries
+        // before emptying the cells.
+        sc::CellStoreType::position_type aPos = rCells.position(mrPos.miCellPos, rSpan.mnRow1);
+        splitFormulaGrouping(rCells, aPos);
+        aPos = rCells.position(aPos.first, rSpan.mnRow2);
+        splitFormulaGrouping(rCells, aPos);
+
+        mrPos.miCellPos = rCells.set_empty(mrPos.miCellPos, rSpan.mnRow1, rSpan.mnRow2);
+        mrPos.miCellTextAttrPos = mrColumn.GetCellAttrStore().set_empty(mrPos.miCellTextAttrPos, rSpan.mnRow1, rSpan.mnRow2);
     }
 };
 
@@ -785,7 +801,7 @@ void ScColumn::DeleteArea(SCROW nStartRow, SCROW nEndRow, sal_uInt16 nDelFlag)
         aBlockPos.miCellTextAttrPos = maCellTextAttrs.begin();
 
         // Delete the cells for real.
-        std::for_each(aSpans.begin(), aSpans.end(), EmptyCells(aBlockPos, *this, maCells, maCellTextAttrs));
+        std::for_each(aSpans.begin(), aSpans.end(), EmptyCells(aBlockPos, *this));
         CellStorageModified();
     }
 
commit f08bad7134cf618da82d387195c3c4557e476893
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 3 21:38:53 2013 -0400

    ???
    
    Change-Id: Id13bf81cd65fdc0677832993bded37e08f226c0d

diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 4fa2a18..af683fe 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2015,8 +2015,7 @@ void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
         {
             rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
-            ((ScColumn*)this)->
-                CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, rDestCol);
+            CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, rDestCol);
 
             //  UpdateUsed not needed, is already done in TestCopyScenario (obsolete comment ?)
 
commit 79b074e8bdd13a655f66616df1fbc12012e613e4
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 3 21:34:13 2013 -0400

    These methods shouldn't affect formula grouping.
    
    They only change sheet index values in all formula cells uniformly;
    they should not affect how they are grouped.
    
    Change-Id: Ie05152de1d6fc5799145e5721c57fd74f8f58239

diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 44e808a..4fa2a18 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2783,10 +2783,7 @@ void ScColumn::UpdateDeleteTab(SCTAB nDelPos, bool bIsMove, ScColumn* /*pRefUndo
     DeleteTabUpdater aFunc(maCellTextAttrs, nDelPos, nSheets, nTab, bIsMove);
     sc::ProcessFormulaEditText(maCells, aFunc);
     if (aFunc.isModified())
-    {
-        RegroupFormulaCells();
         CellStorageModified();
-    }
 }
 
 void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
@@ -2794,10 +2791,7 @@ void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
     InsertAbsTabUpdater aFunc(maCellTextAttrs, nTab, nNewPos);
     sc::ProcessFormulaEditText(maCells, aFunc);
     if (aFunc.isModified())
-    {
-        RegroupFormulaCells();
         CellStorageModified();
-    }
 }
 
 void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
@@ -2808,10 +2802,7 @@ void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
     MoveTabUpdater aFunc(maCellTextAttrs, nTab, nOldPos, nNewPos);
     sc::ProcessFormulaEditText(maCells, aFunc);
     if (aFunc.isModified())
-    {
-        RegroupFormulaCells();
         CellStorageModified();
-    }
 }
 
 
commit 18d707b6cfa5675de5fa0d5d64684e54db29ed10
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 3 19:32:31 2013 -0400

    More test on shared formula group adjustment on value insertions.
    
    Change-Id: Icaa48ef790cd71abdfc1d026ac912a88f727c0d5

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index c241dfb..219638d 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -54,6 +54,7 @@
 #include "tokenarray.hxx"
 #include "scopetools.hxx"
 #include "dociter.hxx"
+#include "editutil.hxx"
 
 #include "formula/IFunctionDescription.hxx"
 
@@ -6364,6 +6365,38 @@ void Test::testSharedFormulas()
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(14), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
 
+    // Set numeric value to B15, to make B16:B18 shared.
+    aPos.SetRow(14);
+    m_pDoc->SetValue(aPos, 1.2);
+    aPos.SetRow(15);
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    // B16:B18 should be shared.
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(15), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
+
+    // Set string value to B16 to make B17:B18 shared.
+    aPos.SetRow(15);
+    ScCellValue aCell("Test");
+    CPPUNIT_ASSERT_MESSAGE("This should be a string value.", aCell.meType == CELLTYPE_STRING);
+    aCell.commit(*m_pDoc, aPos);
+    CPPUNIT_ASSERT_EQUAL(*aCell.mpString, m_pDoc->GetString(aPos));
+    aPos.SetRow(16);
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    // B17:B18 should be shared.
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(16), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), pFC->GetSharedLength());
+
+    // Set edit text to B17. Now B18 should be non-shared.
+    ScFieldEditEngine& rEditEngine = m_pDoc->GetEditEngine();
+    rEditEngine.SetText("Edit Text");
+    aPos.SetRow(16);
+    m_pDoc->SetEditText(aPos, rEditEngine.CreateTextObject());
+    CPPUNIT_ASSERT_EQUAL(CELLTYPE_EDIT, m_pDoc->GetCellType(aPos));
+    aPos.SetRow(17);
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B18 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_MESSAGE("B18 should be non-shared.", !pFC->IsShared());
+
     m_pDoc->DeleteTab(0);
 }
 
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 88f52db..f02a6a8 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1765,7 +1765,6 @@ void ScColumn::SetEditText( SCROW nRow, EditTextObject* pEditText )
     sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
     maCells.set(it, nRow, pEditText);
     maCellTextAttrs.set(nRow, sc::CellTextAttr());
-    RegroupFormulaCells(nRow);
     CellStorageModified();
 
     BroadcastNewCell(nRow);
@@ -1777,7 +1776,6 @@ void ScColumn::SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, Edit
     rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, pEditText);
     rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
         rBlockPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
-    RegroupFormulaCells(nRow);
     CellStorageModified();
 
     BroadcastNewCell(nRow);
@@ -2280,7 +2278,6 @@ void ScColumn::SetError( SCROW nRow, const sal_uInt16 nError)
     sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
     it = maCells.set(it, nRow, pCell);
     maCellTextAttrs.set(nRow, sc::CellTextAttr());
-    RegroupFormulaCells(nRow);
     CellStorageModified();
 
     ActivateNewFormulaCell(it, nRow, *pCell);
@@ -2294,7 +2291,6 @@ void ScColumn::SetRawString( SCROW nRow, const OUString& rStr, bool bBroadcast )
     sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
     maCells.set(it, nRow, rStr);
     maCellTextAttrs.set(nRow, sc::CellTextAttr());
-    RegroupFormulaCells(nRow);
     CellStorageModified();
 
     if (bBroadcast)
@@ -2311,7 +2307,6 @@ void ScColumn::SetRawString(
     rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, rStr);
     rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
         rBlockPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
-    RegroupFormulaCells(nRow);
     CellStorageModified();
 
     if (bBroadcast)
@@ -2326,7 +2321,6 @@ void ScColumn::SetValue( SCROW nRow, double fVal )
     sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
     maCells.set(it, nRow, fVal);
     maCellTextAttrs.set(nRow, sc::CellTextAttr());
-    RegroupFormulaCells(nRow);
     CellStorageModified();
 
     BroadcastNewCell(nRow);
@@ -2342,7 +2336,6 @@ void ScColumn::SetValue(
     rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, fVal);
     rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
         rBlockPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
-    RegroupFormulaCells(nRow);
     CellStorageModified();
 
     if (bBroadcast)
commit c2325143d38d633b0788ac0104a7d3fc95819ce8
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 3 18:51:59 2013 -0400

    Adjust formula cell grouping on cell deletion without shifting.
    
    Change-Id: I4dad09faf10406163b5944933422d50b832f45bc

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index d05b7eb..c241dfb 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -6331,25 +6331,38 @@ void Test::testSharedFormulas()
     m_pDoc->SetString(aPos, "=A20*2");
     pFC = m_pDoc->GetFormulaCell(aPos);
     CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
+    // B13:B20 shuld be shared.
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(8), pFC->GetSharedLength());
 
-#if 0
-    // Insert empty rows at B16 to split B13:B20 into B13:B15 and B21:B25.
-    m_pDoc->InsertRow(1, 0, 1, 0, 15, 5);
-
+    // Empty B19. This should split it into B13:B18, and B20 non-shared.
+    aPos.SetRow(18);
+    m_pDoc->SetEmptyCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("This cell should have been emptied.", m_pDoc->GetCellType(aPos) == CELLTYPE_NONE);
     aPos.SetRow(12); // B13
     pFC = m_pDoc->GetFormulaCell(aPos);
-    CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
+    // B13:B18 should be shared.
     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), pFC->GetSharedTopRow());
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), pFC->GetSharedLength());
+    // B20 shold be non-shared.
+    aPos.SetRow(19); // B20
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_MESSAGE("B20 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_MESSAGE("This cell should be non-shared.", !pFC->IsShared());
 
-    aPos.SetRow(23); // B24
+    // Empty B14, to make B13 non-shared and B15:B18 shared.
+    aPos.SetRow(13); // B14
+    m_pDoc->SetEmptyCell(aPos);
+    aPos.SetRow(12); // B13
     pFC = m_pDoc->GetFormulaCell(aPos);
-    CPPUNIT_ASSERT_MESSAGE("This cell is expected to be a shared formula cell.", pFC && pFC->IsShared());
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(20), pFC->GetSharedTopRow());
-    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), pFC->GetSharedLength());
-#endif
+    // B13 should be non-shared.
+    CPPUNIT_ASSERT_MESSAGE("B13 should be a formula cell.", pFC);
+    CPPUNIT_ASSERT_MESSAGE("This cell should be non-shared.", !pFC->IsShared());
+    // B15:B18 should be shared.
+    aPos.SetRow(14); // B15
+    pFC = m_pDoc->GetFormulaCell(aPos);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(14), pFC->GetSharedTopRow());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
 
     m_pDoc->DeleteTab(0);
 }
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index b46f1df..88f52db 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -131,16 +131,16 @@ void ScColumn::InterpretDirtyCells( SCROW nRow1, SCROW nRow2 )
 
 void ScColumn::Delete( SCROW nRow )
 {
-    std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(nRow);
+    sc::CellStoreType::position_type aPos = maCells.position(nRow);
     sc::CellStoreType::iterator it = aPos.first;
     if (it == maCells.end())
         return;
 
-    bool bFormulaCell = it->type == sc::element_type_formula;
-    if (bFormulaCell)
+    if (it->type == sc::element_type_formula)
     {
         ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
         p->EndListeningTo(pDocument);
+        UnshareFormulaCell(aPos, *p);
     }
     maCells.set_empty(nRow, nRow);
     maCellTextAttrs.set_empty(nRow, nRow);
@@ -148,9 +148,6 @@ void ScColumn::Delete( SCROW nRow )
     pDocument->Broadcast(
         ScHint(SC_HINT_DATACHANGED, ScAddress(nCol, nRow, nTab)));
 
-    if (bFormulaCell)
-        RegroupFormulaCells(nRow);
-
     CellStorageModified();
 }
 
@@ -474,27 +471,54 @@ void ScColumn::UnshareFormulaCell(
         ScFormulaCellGroupRef xGroup = rCell.GetCellGroup();
         SCROW nEndRow = xGroup->mnStart + xGroup->mnLength - 1;
         xGroup->mnLength = rCell.aPos.Row() - xGroup->mnStart; // Shorten the top group.
-
-        ScFormulaCellGroupRef xGroup2(new ScFormulaCellGroup);
-        xGroup2->mnStart = rCell.aPos.Row() + 1;
-        xGroup2->mnLength = nEndRow - rCell.aPos.Row();
-        xGroup2->mbInvariant = xGroup->mbInvariant;
-#if DEBUG_COLUMN_STORAGE
-        if (xGroup2->mnStart + xGroup2->mnLength > it->position + it->size)
+        if (xGroup->mnLength == 1)
         {
-            cerr << "ScColumn::UnshareFormulaCell: Shared formula region goes beyond the formula block. Not good." << endl;
-            cerr.flush();
-            abort();
+            // Make the top cell non-shared.
+#if DEBUG_COLUMN_STORAGE
+            if (aPos.second == 0)
+            {
+                cerr << "ScColumn::UnshareFormulaCell: There is no previous formula cell but there should be!" << endl;
+                cerr.flush();
+                abort();
+            }
+#endif
+            ScFormulaCell& rPrev = *sc::formula_block::at(*it->data, aPos.second-1);
+            rPrev.SetCellGroup(xNone);
         }
+
+        SCROW nLength2 = nEndRow - rCell.aPos.Row();
+        if (nLength2 >= 2)
+        {
+            ScFormulaCellGroupRef xGroup2;
+            xGroup2.reset(new ScFormulaCellGroup);
+            xGroup2->mnStart = rCell.aPos.Row() + 1;
+            xGroup2->mnLength = nLength2;
+            xGroup2->mbInvariant = xGroup->mbInvariant;
+#if DEBUG_COLUMN_STORAGE
+            if (xGroup2->mnStart + xGroup2->mnLength > it->position + it->size)
+            {
+                cerr << "ScColumn::UnshareFormulaCell: Shared formula region goes beyond the formula block. Not good." << endl;
+                cerr.flush();
+                abort();
+            }
 #endif
-        sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
-        std::advance(itCell, aPos.second+1);
-        sc::formula_block::iterator itCellEnd = itCell;
-        std::advance(itCellEnd, xGroup2->mnLength);
-        for (; itCell != itCellEnd; ++itCell)
+            sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
+            std::advance(itCell, aPos.second+1);
+            sc::formula_block::iterator itCellEnd = itCell;
+            std::advance(itCellEnd, xGroup2->mnLength);
+            for (; itCell != itCellEnd; ++itCell)
+            {
+                ScFormulaCell& rCell2 = **itCell;
+                rCell2.SetCellGroup(xGroup2);
+            }
+        }
+        else
         {
+            // Make the next cell non-shared.
+            sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
+            std::advance(itCell, aPos.second+1);
             ScFormulaCell& rCell2 = **itCell;
-            rCell2.SetCellGroup(xGroup2);
+            rCell2.SetCellGroup(xNone);
         }
     }
 


More information about the Libreoffice-commits mailing list