summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-07-10 19:34:34 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-07-11 00:25:38 -0400
commit1fd0ab0c53e73b50857e5bfed4b307468202354f (patch)
treee280e158dce2b6674267aa486c38a61a5e30e9ea /sc/source/core
parent0797dd8714413f8319515df9831a86703b589558 (diff)
Move these methods out of ScColumn since they don't operate on column.
Change-Id: I1a03b9b18dd236138306fd545e961a5443e22bc8
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/data/column.cxx24
-rw-r--r--sc/source/core/data/column3.cxx78
-rw-r--r--sc/source/core/tool/sharedformula.cxx130
3 files changed, 147 insertions, 85 deletions
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index b777905332b7..730fed47753d 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -1383,12 +1383,12 @@ public:
sc::CellStoreType::position_type aPos =
rDestCells.position(maDestPos.miCellPos, nTopRow);
maDestPos.miCellPos = aPos.first;
- mrDestCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
size_t nLastRow = nTopRow + nDataSize;
if (nLastRow < static_cast<size_t>(MAXROW))
{
aPos = rDestCells.position(maDestPos.miCellPos, nLastRow+1);
- mrDestCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
}
setDefaultAttrsToDest(nTopRow, nDataSize);
@@ -2170,15 +2170,15 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
// Split the formula grouping at the top and bottom boundaries.
sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
aPos = maCells.position(aPos.first, nEndRow+1);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
// Do the same with the destination column.
aPos = rCol.maCells.position(nStartRow);
- rCol.SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
aPos = rCol.maCells.position(aPos.first, nEndRow+1);
- rCol.SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
// Move the broadcasters to the destination column.
maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
@@ -2187,9 +2187,9 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
// Re-group transferred formula cells.
aPos = rCol.maCells.position(nStartRow);
- rCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
aPos = rCol.maCells.position(aPos.first, nEndRow+1);
- rCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
CellStorageModified();
rCol.CellStorageModified();
@@ -2315,11 +2315,11 @@ bool ScColumn::UpdateReferenceOnCopy(
// The formula groups at the top and bottom boundaries are expected to
// have been split prior to this call. Here, we only do the joining.
- JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
if (rRange.aEnd.Row() < MAXROW)
{
aPos = maCells.position(aPos.first, rRange.aEnd.Row()+1);
- JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
}
return aHandler.isUpdated();
@@ -2341,12 +2341,12 @@ bool ScColumn::UpdateReference(
if (ValidRow(nSplitPos))
{
sc::CellStoreType::position_type aPos = maCells.position(nSplitPos);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
nSplitPos = rRange.aEnd.Row() + 1;
if (ValidRow(nSplitPos))
{
aPos = maCells.position(aPos.first, nSplitPos);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
}
}
}
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 4fb06c3bec33..de8adde65b8a 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -281,7 +281,7 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
ShiftFormulaPosHandler aShiftFormulaFunc;
sc::ProcessFormula(aPos.first, maCells, nStartRow, MAXROW, aShiftFormulaFunc);
- JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
// Single cell broadcasts on deleted cells.
BroadcastCells(aDeleteRowsFunc.getNonEmptyRows());
@@ -420,13 +420,13 @@ void ScColumn::DetachFormulaCells(
const sc::CellStoreType::position_type& aPos, size_t nLength )
{
// Split formula grouping at the top and bottom boundaries.
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
size_t nRow = aPos.first->position + aPos.second;
size_t nNextTopRow = nRow + nLength; // start row of next formula group.
if (ValidRow(nNextTopRow))
{
sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow);
- SplitFormulaCellGroup(aPos2);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos2);
}
if (pDocument->IsClipOrUndo())
@@ -555,74 +555,6 @@ void ScColumn::UnshareFormulaCell(
rCell.SetCellGroup(xNone);
}
-void ScColumn::SplitFormulaCellGroup( const sc::CellStoreType::position_type& aPos ) const
-{
- SCROW nRow = aPos.first->position + aPos.second;
-
- if (aPos.first->type != sc::element_type_formula)
- // Not a formula cell block.
- return;
-
- if (aPos.second == 0)
- // Split position coincides with the block border. Nothing to do.
- return;
-
- sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
- std::advance(it, aPos.second);
- ScFormulaCell& rTop = **it;
- if (!rTop.IsShared())
- // Not a shared formula.
- return;
-
- if (nRow == rTop.GetSharedTopRow())
- // Already the top cell of a shared group.
- return;
-
- ScFormulaCellGroupRef xGroup = rTop.GetCellGroup();
-
- ScFormulaCellGroupRef xGroup2(new ScFormulaCellGroup);
- xGroup2->mbInvariant = xGroup->mbInvariant;
- xGroup2->mnStart = nRow;
- xGroup2->mnLength = xGroup->mnStart + xGroup->mnLength - nRow;
-
- xGroup->mnLength = nRow - xGroup->mnStart;
-
- // 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();
- }
-#endif
- sc::formula_block::iterator itEnd = it;
- std::advance(itEnd, xGroup2->mnLength);
- for (; it != itEnd; ++it)
- {
- ScFormulaCell& rCell = **it;
- rCell.SetCellGroup(xGroup2);
- }
-}
-
-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;
-
- 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.
@@ -1545,14 +1477,14 @@ public:
// Merge with the previous formula group (if any).
aPos = rDestCells.position(itDestPos, nDestRow);
- mrDestColumn.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
// Merge with the next formula group (if any).
size_t nNextRow = nDestRow + it->size;
if (ValidRow(nNextRow))
{
aPos = rDestCells.position(aPos.first, nNextRow);
- mrDestColumn.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
}
}
break;
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index 7b6ac84cc8c8..c1bc56447dd6 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -8,10 +8,140 @@
*/
#include "sharedformula.hxx"
+#include "calcmacros.hxx"
namespace sc {
+void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type& aPos)
+{
+ SCROW nRow = aPos.first->position + aPos.second;
+ if (aPos.first->type != sc::element_type_formula)
+ // Not a formula cell block.
+ return;
+
+ if (aPos.second == 0)
+ // Split position coincides with the block border. Nothing to do.
+ return;
+
+ sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
+ std::advance(it, aPos.second);
+ ScFormulaCell& rTop = **it;
+ if (!rTop.IsShared())
+ // Not a shared formula.
+ return;
+
+ if (nRow == rTop.GetSharedTopRow())
+ // Already the top cell of a shared group.
+ return;
+
+ ScFormulaCellGroupRef xGroup = rTop.GetCellGroup();
+
+ ScFormulaCellGroupRef xGroup2(new ScFormulaCellGroup);
+ xGroup2->mbInvariant = xGroup->mbInvariant;
+ xGroup2->mnStart = nRow;
+ xGroup2->mnLength = xGroup->mnStart + xGroup->mnLength - nRow;
+
+ xGroup->mnLength = nRow - xGroup->mnStart;
+
+ // 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();
+ }
+#endif
+ sc::formula_block::iterator itEnd = it;
+ std::advance(itEnd, xGroup2->mnLength);
+ for (; it != itEnd; ++it)
+ {
+ ScFormulaCell& rCell = **it;
+ rCell.SetCellGroup(xGroup2);
+ }
+}
+
+namespace {
+
+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();
+ if (xGroup1)
+ {
+ if (xGroup2)
+ {
+ // 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;
+ 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
+ {
+ // cell 1 is shared but cell 2 is not.
+ rCell2.SetCellGroup(xGroup1);
+ ++xGroup1->mnLength;
+ }
+ }
+ else
+ {
+ if (xGroup2)
+ {
+ // cell 1 is not shared, but cell 2 is already shared.
+ rCell1.SetCellGroup(xGroup2);
+ xGroup2->mnStart = nRow;
+ ++xGroup2->mnLength;
+ }
+ else
+ {
+ // neither cells are shared.
+ xGroup1.reset(new ScFormulaCellGroup);
+ xGroup1->mnStart = nRow;
+ xGroup1->mbInvariant = (eState == ScFormulaCell::EqualInvariant);
+ xGroup1->mnLength = 2;
+
+ rCell1.SetCellGroup(xGroup1);
+ rCell2.SetCellGroup(xGroup1);
+ }
+ }
+}
+
+}
+
+void SharedFormulaUtil::joinFormulaCellAbove(const CellStoreType::position_type& aPos)
+{
+ 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;
+
+ 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);
+}
}