summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/sharedformula.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/tool/sharedformula.cxx')
-rw-r--r--sc/source/core/tool/sharedformula.cxx130
1 files changed, 130 insertions, 0 deletions
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);
+}
}