diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-07-10 19:34:34 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-07-11 00:25:38 -0400 |
commit | 1fd0ab0c53e73b50857e5bfed4b307468202354f (patch) | |
tree | e280e158dce2b6674267aa486c38a61a5e30e9ea /sc | |
parent | 0797dd8714413f8319515df9831a86703b589558 (diff) |
Move these methods out of ScColumn since they don't operate on column.
Change-Id: I1a03b9b18dd236138306fd545e961a5443e22bc8
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 9 | ||||
-rw-r--r-- | sc/inc/sharedformula.hxx | 24 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 24 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 78 | ||||
-rw-r--r-- | sc/source/core/tool/sharedformula.cxx | 130 |
5 files changed, 171 insertions, 94 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 01e9ef72358e..2c59b77275f5 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -503,15 +503,6 @@ public: void UnshareFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const; /** - * Split existing shared formula range at specified position. The cell at - * specified position becomes the top cell of the lower shared formula - * range after this call. - */ - 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. */ void RegroupFormulaCells(); diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx index fcab6d7dba0d..6767d4a2c151 100644 --- a/sc/inc/sharedformula.hxx +++ b/sc/inc/sharedformula.hxx @@ -11,6 +11,7 @@ #define SC_SHAREDFORMULA_HXX #include "formulacell.hxx" +#include "mtvelements.hxx" namespace sc { @@ -18,6 +19,10 @@ class SharedFormulaUtil { public: + /** + * Group formula cells stored in the passed container. The formula cells + * in the container are assumed to be all <b>non-shared</b>. + */ template<typename _Iter> static void groupFormulaCells(const _Iter& itBeg, const _Iter& itEnd) { @@ -49,6 +54,25 @@ public: pCur->SetCellGroup(xGroup); } } + + /** + * Split existing shared formula range at specified position. The cell at + * specified position becomes the top cell of the lower shared formula + * range after this call. This method does nothing if the cell at + * specified position is not a formula cell. + * + * @param aPos position of cell to examine. + */ + static void splitFormulaCellGroup(const CellStoreType::position_type& aPos); + + /** + * Merge with an existing formula group (if any) located immediately above + * if the cell at specified position is a formula cell, and its formula + * tokens are identical to that of the above formula group. + * + * @param aPos position of cell to examine. + */ + static void joinFormulaCellAbove(const CellStoreType::position_type& aPos); }; } 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); +} } |