LCOV - code coverage report
Current view: top level - sc/source/core/tool - sharedformula.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 136 0.0 %
Date: 2014-04-14 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "sharedformula.hxx"
      11             : #include "calcmacros.hxx"
      12             : #include "tokenarray.hxx"
      13             : 
      14             : namespace sc {
      15             : 
      16           0 : void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type& aPos)
      17             : {
      18           0 :     SCROW nRow = aPos.first->position + aPos.second;
      19             : 
      20           0 :     if (aPos.first->type != sc::element_type_formula)
      21             :         // Not a formula cell block.
      22           0 :         return;
      23             : 
      24           0 :     if (aPos.second == 0)
      25             :         // Split position coincides with the block border. Nothing to do.
      26           0 :         return;
      27             : 
      28           0 :     sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
      29           0 :     std::advance(it, aPos.second);
      30           0 :     ScFormulaCell& rTop = **it;
      31           0 :     if (!rTop.IsShared())
      32             :         // Not a shared formula.
      33           0 :         return;
      34             : 
      35           0 :     if (nRow == rTop.GetSharedTopRow())
      36             :         // Already the top cell of a shared group.
      37           0 :         return;
      38             : 
      39           0 :     ScFormulaCellGroupRef xGroup = rTop.GetCellGroup();
      40             : 
      41           0 :     SCROW nLength2 = xGroup->mpTopCell->aPos.Row() + xGroup->mnLength - nRow;
      42           0 :     ScFormulaCellGroupRef xGroup2;
      43           0 :     if (nLength2 > 1)
      44             :     {
      45           0 :         xGroup2.reset(new ScFormulaCellGroup);
      46           0 :         xGroup2->mbInvariant = xGroup->mbInvariant;
      47           0 :         xGroup2->mpTopCell = &rTop;
      48           0 :         xGroup2->mnLength = nLength2;
      49           0 :         xGroup2->mpCode = xGroup->mpCode->Clone();
      50             :     }
      51             : 
      52           0 :     xGroup->mnLength = nRow - xGroup->mpTopCell->aPos.Row();
      53           0 :     if (xGroup->mnLength == 1)
      54             :     {
      55             :         // The top group consists of only one cell. Ungroup this.
      56           0 :         ScFormulaCellGroupRef xNone;
      57           0 :         ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
      58           0 :         rPrev.SetCellGroup(xNone);
      59             :     }
      60             : 
      61             :     // Apply the lower group object to the lower cells.
      62             : #if DEBUG_COLUMN_STORAGE
      63             :     if (xGroup2->mpTopCell->aPos.Row() + xGroup2->mnLength > aPos.first->position + aPos.first->size)
      64             :     {
      65             :         cerr << "ScColumn::SplitFormulaCellGroup: Shared formula region goes beyond the formula block. Not good." << endl;
      66             :         cerr.flush();
      67             :         abort();
      68             :     }
      69             : #endif
      70           0 :     sc::formula_block::iterator itEnd = it;
      71           0 :     std::advance(itEnd, nLength2);
      72           0 :     for (; it != itEnd; ++it)
      73             :     {
      74           0 :         ScFormulaCell& rCell = **it;
      75           0 :         rCell.SetCellGroup(xGroup2);
      76           0 :     }
      77             : }
      78             : 
      79           0 : void SharedFormulaUtil::splitFormulaCellGroups(CellStoreType& rCells, std::vector<SCROW>& rBounds)
      80             : {
      81           0 :     if (rBounds.empty())
      82           0 :         return;
      83             : 
      84             :     // Sort and remove duplicates.
      85           0 :     std::sort(rBounds.begin(), rBounds.end());
      86           0 :     std::vector<SCROW>::iterator it = std::unique(rBounds.begin(), rBounds.end());
      87           0 :     rBounds.erase(it, rBounds.end());
      88             : 
      89           0 :     it = rBounds.begin();
      90           0 :     SCROW nRow = *it;
      91           0 :     CellStoreType::position_type aPos = rCells.position(nRow);
      92           0 :     if (aPos.first == rCells.end())
      93           0 :         return;
      94             : 
      95           0 :     splitFormulaCellGroup(aPos);
      96           0 :     std::vector<SCROW>::iterator itEnd = rBounds.end();
      97           0 :     for (++it; it != itEnd; ++it)
      98             :     {
      99           0 :         nRow = *it;
     100           0 :         aPos = rCells.position(aPos.first, nRow);
     101           0 :         if (aPos.first == rCells.end())
     102           0 :             return;
     103             : 
     104           0 :         splitFormulaCellGroup(aPos);
     105             :     }
     106             : }
     107             : 
     108           0 : void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
     109             : {
     110           0 :     ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
     111           0 :     if (eState == ScFormulaCell::NotEqual)
     112           0 :         return;
     113             : 
     114             :     // Formula tokens equal those of the previous formula cell.
     115           0 :     ScFormulaCellGroupRef xGroup1 = rCell1.GetCellGroup();
     116           0 :     ScFormulaCellGroupRef xGroup2 = rCell2.GetCellGroup();
     117           0 :     if (xGroup1)
     118             :     {
     119           0 :         if (xGroup2)
     120             :         {
     121             :             // Both cell 1 and cell 2 are shared. Merge them together.
     122           0 :             if (xGroup1.get() == xGroup2.get())
     123             :                 // They belong to the same group.
     124           0 :                 return;
     125             : 
     126             :             // Set the group object from cell 1 to all cells in group 2.
     127           0 :             xGroup1->mnLength += xGroup2->mnLength;
     128           0 :             size_t nOffset = rPos.second + 1; // position of cell 2
     129           0 :             for (size_t i = 0, n = xGroup2->mnLength; i < n; ++i)
     130             :             {
     131           0 :                 ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, nOffset+i);
     132           0 :                 rCell.SetCellGroup(xGroup1);
     133             :             }
     134             :         }
     135             :         else
     136             :         {
     137             :             // cell 1 is shared but cell 2 is not.
     138           0 :             rCell2.SetCellGroup(xGroup1);
     139           0 :             ++xGroup1->mnLength;
     140             :         }
     141             :     }
     142             :     else
     143             :     {
     144           0 :         if (xGroup2)
     145             :         {
     146             :             // cell 1 is not shared, but cell 2 is already shared.
     147           0 :             rCell1.SetCellGroup(xGroup2);
     148           0 :             xGroup2->mpTopCell = &rCell1;
     149           0 :             ++xGroup2->mnLength;
     150             :         }
     151             :         else
     152             :         {
     153             :             // neither cells are shared.
     154             :             assert(rCell1.aPos.Row() == (SCROW)(rPos.first->position + rPos.second));
     155           0 :             xGroup1 = rCell1.CreateCellGroup(2, eState == ScFormulaCell::EqualInvariant);
     156           0 :             rCell2.SetCellGroup(xGroup1);
     157             :         }
     158           0 :     }
     159             : }
     160             : 
     161           0 : void SharedFormulaUtil::joinFormulaCellAbove(const CellStoreType::position_type& aPos)
     162             : {
     163           0 :     if (aPos.first->type != sc::element_type_formula)
     164             :         // This is not a formula cell.
     165           0 :         return;
     166             : 
     167           0 :     if (aPos.second == 0)
     168             :         // This cell is already the top cell in a formula block; the previous
     169             :         // cell is not a formula cell.
     170           0 :         return;
     171             : 
     172           0 :     ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
     173           0 :     ScFormulaCell& rCell = *sc::formula_block::at(*aPos.first->data, aPos.second);
     174           0 :     sc::CellStoreType::position_type aPosPrev = aPos;
     175           0 :     --aPosPrev.second;
     176           0 :     joinFormulaCells(aPosPrev, rPrev, rCell);
     177             : }
     178             : 
     179           0 : void SharedFormulaUtil::unshareFormulaCell(const CellStoreType::position_type& aPos, ScFormulaCell& rCell)
     180             : {
     181           0 :     if (!rCell.IsShared())
     182           0 :         return;
     183             : 
     184           0 :     ScFormulaCellGroupRef xNone;
     185           0 :     sc::CellStoreType::iterator it = aPos.first;
     186             : 
     187             :     // This formula cell is shared. Adjust the shared group.
     188           0 :     if (rCell.aPos.Row() == rCell.GetSharedTopRow())
     189             :     {
     190             :         // Top of the shared range.
     191           0 :         ScFormulaCellGroupRef xGroup = rCell.GetCellGroup();
     192           0 :         if (xGroup->mnLength == 2)
     193             :         {
     194             :             // Group consists only only two cells. Mark the second one non-shared.
     195             : #if DEBUG_COLUMN_STORAGE
     196             :             if (aPos.second+1 >= aPos.first->size)
     197             :             {
     198             :                 cerr << "ScColumn::UnshareFormulaCell: There is no next formula cell but there should be!" << endl;
     199             :                 cerr.flush();
     200             :                 abort();
     201             :             }
     202             : #endif
     203           0 :             ScFormulaCell& rNext = *sc::formula_block::at(*it->data, aPos.second+1);
     204           0 :             rNext.SetCellGroup(xNone);
     205             :         }
     206             :         else
     207             :         {
     208             :             // Move the top cell to the next formula cell down.
     209           0 :             ScFormulaCell& rNext = *sc::formula_block::at(*it->data, aPos.second+1);
     210           0 :             --xGroup->mnLength;
     211           0 :             xGroup->mpTopCell = &rNext;
     212           0 :         }
     213             :     }
     214           0 :     else if (rCell.aPos.Row() == rCell.GetSharedTopRow() + rCell.GetSharedLength() - 1)
     215             :     {
     216             :         // Bottom of the shared range.
     217           0 :         ScFormulaCellGroupRef xGroup = rCell.GetCellGroup();
     218           0 :         if (xGroup->mnLength == 2)
     219             :         {
     220             :             // Mark the top cell non-shared.
     221             : #if DEBUG_COLUMN_STORAGE
     222             :             if (aPos.second == 0)
     223             :             {
     224             :                 cerr << "ScColumn::UnshareFormulaCell: There is no previous formula cell but there should be!" << endl;
     225             :                 cerr.flush();
     226             :                 abort();
     227             :             }
     228             : #endif
     229           0 :             ScFormulaCell& rPrev = *sc::formula_block::at(*it->data, aPos.second-1);
     230           0 :             rPrev.SetCellGroup(xNone);
     231             :         }
     232             :         else
     233             :         {
     234             :             // Just shortern the shared range length by one.
     235           0 :             --xGroup->mnLength;
     236           0 :         }
     237             :     }
     238             :     else
     239             :     {
     240             :         // In the middle of the shared range. Split it into two groups.
     241           0 :         ScFormulaCellGroupRef xGroup = rCell.GetCellGroup();
     242           0 :         SCROW nEndRow = xGroup->mpTopCell->aPos.Row() + xGroup->mnLength - 1;
     243           0 :         xGroup->mnLength = rCell.aPos.Row() - xGroup->mpTopCell->aPos.Row(); // Shorten the top group.
     244           0 :         if (xGroup->mnLength == 1)
     245             :         {
     246             :             // Make the top cell non-shared.
     247             : #if DEBUG_COLUMN_STORAGE
     248             :             if (aPos.second == 0)
     249             :             {
     250             :                 cerr << "ScColumn::UnshareFormulaCell: There is no previous formula cell but there should be!" << endl;
     251             :                 cerr.flush();
     252             :                 abort();
     253             :             }
     254             : #endif
     255           0 :             ScFormulaCell& rPrev = *sc::formula_block::at(*it->data, aPos.second-1);
     256           0 :             rPrev.SetCellGroup(xNone);
     257             :         }
     258             : 
     259           0 :         SCROW nLength2 = nEndRow - rCell.aPos.Row();
     260           0 :         if (nLength2 >= 2)
     261             :         {
     262           0 :             ScFormulaCellGroupRef xGroup2;
     263           0 :             xGroup2.reset(new ScFormulaCellGroup);
     264           0 :             ScFormulaCell& rNext = *sc::formula_block::at(*it->data, aPos.second+1);
     265           0 :             xGroup2->mpTopCell = &rNext;
     266           0 :             xGroup2->mnLength = nLength2;
     267           0 :             xGroup2->mbInvariant = xGroup->mbInvariant;
     268           0 :             xGroup2->mpCode = xGroup->mpCode->Clone();
     269             : #if DEBUG_COLUMN_STORAGE
     270             :             if (xGroup2->mpTopCell->aPos.Row() + xGroup2->mnLength > it->position + it->size)
     271             :             {
     272             :                 cerr << "ScColumn::UnshareFormulaCell: Shared formula region goes beyond the formula block. Not good." << endl;
     273             :                 cerr.flush();
     274             :                 abort();
     275             :             }
     276             : #endif
     277           0 :             sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
     278           0 :             std::advance(itCell, aPos.second+1);
     279           0 :             sc::formula_block::iterator itCellEnd = itCell;
     280           0 :             std::advance(itCellEnd, xGroup2->mnLength);
     281           0 :             for (; itCell != itCellEnd; ++itCell)
     282             :             {
     283           0 :                 ScFormulaCell& rCell2 = **itCell;
     284           0 :                 rCell2.SetCellGroup(xGroup2);
     285           0 :             }
     286             :         }
     287             :         else
     288             :         {
     289             :             // Make the next cell non-shared.
     290           0 :             sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
     291           0 :             std::advance(itCell, aPos.second+1);
     292           0 :             ScFormulaCell& rCell2 = **itCell;
     293           0 :             rCell2.SetCellGroup(xNone);
     294           0 :         }
     295             :     }
     296             : 
     297           0 :     rCell.SetCellGroup(xNone);
     298             : }
     299             : 
     300             : }
     301             : 
     302             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10