LCOV - code coverage report
Current view: top level - sc/source/core/data - columnspanset.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 162 184 88.0 %
Date: 2015-06-13 12:38:46 Functions: 30 35 85.7 %
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 "columnspanset.hxx"
      11             : #include "column.hxx"
      12             : #include "table.hxx"
      13             : #include "document.hxx"
      14             : #include "mtvfunctions.hxx"
      15             : #include "markdata.hxx"
      16             : #include "rangelst.hxx"
      17             : #include <fstalgorithm.hxx>
      18             : #include <boost/checked_delete.hpp>
      19             : 
      20             : #include <algorithm>
      21             : 
      22             : namespace sc {
      23             : 
      24             : namespace {
      25             : 
      26             : class ColumnScanner
      27             : {
      28             :     ColumnSpanSet::ColumnSpansType& mrRanges;
      29             :     bool mbVal;
      30             : public:
      31         157 :     ColumnScanner(ColumnSpanSet::ColumnSpansType& rRanges, bool bVal) :
      32         157 :         mrRanges(rRanges), mbVal(bVal) {}
      33             : 
      34         175 :     void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
      35             :     {
      36         175 :         if (node.type == sc::element_type_empty)
      37         283 :             return;
      38             : 
      39          67 :         size_t nRow = node.position + nOffset;
      40          67 :         size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
      41          67 :         mrRanges.insert_back(nRow, nEndRow, mbVal);
      42             :     }
      43             : };
      44             : 
      45             : }
      46             : 
      47        5761 : RowSpan::RowSpan(SCROW nRow1, SCROW nRow2) : mnRow1(nRow1), mnRow2(nRow2) {}
      48             : 
      49        7486 : ColRowSpan::ColRowSpan(SCCOLROW nStart, SCCOLROW nEnd) : mnStart(nStart), mnEnd(nEnd) {}
      50             : 
      51        3448 : ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) :
      52        3448 :     maSpans(nStart, nEnd+1, bInit), miPos(maSpans.begin()) {}
      53             : 
      54         440 : ColumnSpanSet::Action::~Action() {}
      55           0 : void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}
      56             : 
      57        1167 : ColumnSpanSet::ColumnAction::~ColumnAction() {}
      58             : 
      59        2858 : ColumnSpanSet::ColumnSpanSet(bool bInit) : mbInit(bInit) {}
      60             : 
      61        5716 : ColumnSpanSet::~ColumnSpanSet()
      62             : {
      63        2858 :     DocType::iterator itTab = maDoc.begin(), itTabEnd = maDoc.end();
      64        7000 :     for (; itTab != itTabEnd; ++itTab)
      65             :     {
      66        4142 :         TableType* pTab = *itTab;
      67        4142 :         if (!pTab)
      68        2817 :             continue;
      69             : 
      70        1325 :         std::for_each(pTab->begin(), pTab->end(), boost::checked_deleter<ColumnType>());
      71        1325 :         delete pTab;
      72             :     }
      73        2858 : }
      74             : 
      75        3693 : ColumnSpanSet::ColumnType& ColumnSpanSet::getColumn(SCTAB nTab, SCCOL nCol)
      76             : {
      77        3693 :     if (static_cast<size_t>(nTab) >= maDoc.size())
      78        1325 :         maDoc.resize(nTab+1, NULL);
      79             : 
      80        3693 :     if (!maDoc[nTab])
      81        1325 :         maDoc[nTab] = new TableType;
      82             : 
      83        3693 :     TableType& rTab = *maDoc[nTab];
      84        3693 :     if (static_cast<size_t>(nCol) >= rTab.size())
      85        3444 :         rTab.resize(nCol+1, NULL);
      86             : 
      87        3693 :     if (!rTab[nCol])
      88        3448 :         rTab[nCol] = new ColumnType(0, MAXROW, mbInit);
      89             : 
      90        3693 :     return *rTab[nCol];
      91             : }
      92             : 
      93         356 : void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
      94             : {
      95         356 :     if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
      96         356 :         return;
      97             : 
      98         356 :     ColumnType& rCol = getColumn(nTab, nCol);
      99         356 :     rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow, nRow+1, bVal).first;
     100             : }
     101             : 
     102         219 : void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
     103             : {
     104         219 :     if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
     105         219 :         return;
     106             : 
     107         219 :     ColumnType& rCol = getColumn(nTab, nCol);
     108         219 :     rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow1, nRow2+1, bVal).first;
     109             : }
     110             : 
     111        1081 : void ColumnSpanSet::set(const ScRange& rRange, bool bVal)
     112             : {
     113        2162 :     for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
     114             :     {
     115        4042 :         for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
     116             :         {
     117        2961 :             ColumnType& rCol = getColumn(nTab, nCol);
     118        2961 :             rCol.miPos = rCol.maSpans.insert(rCol.miPos, rRange.aStart.Row(), rRange.aEnd.Row()+1, bVal).first;
     119             :         }
     120             :     }
     121        1081 : }
     122             : 
     123           5 : void ColumnSpanSet::set( SCTAB nTab, SCCOL nCol, const SingleColumnSpanSet& rSingleSet, bool bVal )
     124             : {
     125           5 :     SingleColumnSpanSet::SpansType aSpans;
     126           5 :     rSingleSet.getSpans(aSpans);
     127           5 :     SingleColumnSpanSet::SpansType::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
     128           8 :     for (; it != itEnd; ++it)
     129           8 :         set(nTab, nCol, it->mnRow1, it->mnRow2, bVal);
     130           5 : }
     131             : 
     132          77 : void ColumnSpanSet::scan(
     133             :     const ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal)
     134             : {
     135          77 :     if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
     136           0 :         return;
     137             : 
     138          77 :     if (nCol1 > nCol2 || nRow1 > nRow2)
     139           0 :         return;
     140             : 
     141          77 :     const ScTable* pTab = rDoc.FetchTable(nTab);
     142          77 :     if (!pTab)
     143           0 :         return;
     144             : 
     145         234 :     for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
     146             :     {
     147         157 :         ColumnType& rCol = getColumn(nTab, nCol);
     148             : 
     149         157 :         const CellStoreType& rSrcCells = pTab->aCol[nCol].maCells;
     150             : 
     151         157 :         ColumnScanner aScanner(rCol.maSpans, bVal);
     152         157 :         ParseBlock(rSrcCells.begin(), rSrcCells, aScanner, nRow1, nRow2);
     153             :     }
     154             : }
     155             : 
     156         440 : void ColumnSpanSet::executeAction(Action& ac) const
     157             : {
     158         576 :     for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
     159             :     {
     160         136 :         if (!maDoc[nTab])
     161           5 :             continue;
     162             : 
     163         131 :         const TableType& rTab = *maDoc[nTab];
     164         653 :         for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
     165             :         {
     166         522 :             if (!rTab[nCol])
     167         305 :                 continue;
     168             : 
     169         217 :             ac.startColumn(nTab, nCol);
     170         217 :             ColumnType& rCol = *rTab[nCol];
     171         217 :             ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
     172             :             SCROW nRow1, nRow2;
     173         217 :             nRow1 = it->first;
     174         217 :             bool bVal = it->second;
     175         763 :             for (++it; it != itEnd; ++it)
     176             :             {
     177         546 :                 nRow2 = it->first-1;
     178         546 :                 ac.execute(ScAddress(nCol, nRow1, nTab), nRow2-nRow1+1, bVal);
     179             : 
     180         546 :                 nRow1 = nRow2+1; // for the next iteration.
     181         546 :                 bVal = it->second;
     182             :             }
     183             :         }
     184             :     }
     185         440 : }
     186             : 
     187        1167 : void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const
     188             : {
     189        5057 :     for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
     190             :     {
     191        3890 :         if (!maDoc[nTab])
     192        2808 :             continue;
     193             : 
     194        1082 :         const TableType& rTab = *maDoc[nTab];
     195       12016 :         for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
     196             :         {
     197       10934 :             if (!rTab[nCol])
     198       15800 :                 continue;
     199             : 
     200        3034 :             ScTable* pTab = rDoc.FetchTable(nTab);
     201        3034 :             if (!pTab)
     202           0 :                 continue;
     203             : 
     204        3034 :             if (!ValidCol(nCol))
     205             :             {
     206             :                 // End the loop.
     207           0 :                 nCol = rTab.size();
     208           0 :                 continue;
     209             :             }
     210             : 
     211        3034 :             ScColumn& rColumn = pTab->aCol[nCol];
     212        3034 :             ac.startColumn(&rColumn);
     213        3034 :             ColumnType& rCol = *rTab[nCol];
     214        3034 :             ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
     215             :             SCROW nRow1, nRow2;
     216        3034 :             nRow1 = it->first;
     217        3034 :             bool bVal = it->second;
     218       11752 :             for (++it; it != itEnd; ++it)
     219             :             {
     220        8718 :                 nRow2 = it->first-1;
     221        8718 :                 ac.execute(nRow1, nRow2, bVal);
     222             : 
     223        8718 :                 nRow1 = nRow2+1; // for the next iteration.
     224        8718 :                 bVal = it->second;
     225             :             }
     226             :         }
     227             :     }
     228        1167 : }
     229             : 
     230           0 : void ColumnSpanSet::swap( ColumnSpanSet& r )
     231             : {
     232           0 :     maDoc.swap(r.maDoc);
     233           0 :     std::swap(mbInit, r.mbInit);
     234           0 : }
     235             : 
     236             : namespace {
     237             : 
     238             : class Scanner
     239             : {
     240             :     SingleColumnSpanSet::ColumnSpansType& mrRanges;
     241             : public:
     242      862137 :     Scanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {}
     243             : 
     244      863800 :     void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
     245             :     {
     246      863800 :         if (node.type == sc::element_type_empty)
     247     1723420 :             return;
     248             : 
     249        4180 :         size_t nRow = node.position + nOffset;
     250        4180 :         size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
     251        4180 :         mrRanges.insert_back(nRow, nEndRow, true);
     252             :     }
     253             : };
     254             : 
     255             : }
     256             : 
     257     1148521 : SingleColumnSpanSet::SingleColumnSpanSet() : maSpans(0, MAXROWCOUNT, false) {}
     258             : 
     259           0 : void SingleColumnSpanSet::scan(const ScColumn& rColumn)
     260             : {
     261           0 :     const CellStoreType& rCells = rColumn.maCells;
     262           0 :     sc::CellStoreType::const_iterator it = rCells.begin(), itEnd = rCells.end();
     263           0 :     SCROW nCurRow = 0;
     264           0 :     for (;it != itEnd; ++it)
     265             :     {
     266           0 :         SCROW nEndRow = nCurRow + it->size; // Last row of current block plus 1.
     267           0 :         if (it->type != sc::element_type_empty)
     268           0 :             maSpans.insert_back(nCurRow, nEndRow, true);
     269             : 
     270           0 :         nCurRow = nEndRow;
     271             :     }
     272           0 : }
     273             : 
     274      862089 : void SingleColumnSpanSet::scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
     275             : {
     276      862089 :     const CellStoreType& rCells = rColumn.maCells;
     277      862089 :     Scanner aScanner(maSpans);
     278      862089 :     sc::ParseBlock(rCells.begin(), rCells, aScanner, nStart, nEnd);
     279      862089 : }
     280             : 
     281          48 : void SingleColumnSpanSet::scan(
     282             :     ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
     283             : {
     284          48 :     const CellStoreType& rCells = rColumn.maCells;
     285          48 :     Scanner aScanner(maSpans);
     286          48 :     rBlockPos.miCellPos = sc::ParseBlock(rBlockPos.miCellPos, rCells, aScanner, nStart, nEnd);
     287          48 : }
     288             : 
     289          77 : void SingleColumnSpanSet::scan(const ScMarkData& rMark, SCTAB nTab, SCCOL nCol)
     290             : {
     291          77 :     if (!rMark.GetTableSelect(nTab))
     292             :         // This table is not selected. Nothing to scan.
     293          77 :         return;
     294             : 
     295          77 :     ScRangeList aRanges = rMark.GetMarkedRanges();
     296          77 :     scan(aRanges, nTab, nCol);
     297             : }
     298             : 
     299      217165 : void SingleColumnSpanSet::scan(const ScRangeList& rRanges, SCTAB nTab, SCCOL nCol)
     300             : {
     301      454810 :     for (size_t i = 0, n = rRanges.size(); i < n; ++i)
     302             :     {
     303      237645 :         const ScRange* p = rRanges[i];
     304      237645 :         if (nTab < p->aStart.Tab() || p->aEnd.Tab() < nTab)
     305           0 :             continue;
     306             : 
     307      237645 :         if (nCol < p->aStart.Col() || p->aEnd.Col() < nCol)
     308             :             // This column is not in this range. Skip it.
     309      237322 :             continue;
     310             : 
     311         323 :         maSpans.insert_back(p->aStart.Row(), p->aEnd.Row()+1, true);
     312             :     }
     313      217165 : }
     314             : 
     315       40361 : void SingleColumnSpanSet::set(SCROW nRow1, SCROW nRow2, bool bVal)
     316             : {
     317       40361 :     maSpans.insert_back(nRow1, nRow2+1, bVal);
     318       40361 : }
     319             : 
     320       64131 : void SingleColumnSpanSet::getRows(std::vector<SCROW> &rRows) const
     321             : {
     322       64131 :     std::vector<SCROW> aRows;
     323             : 
     324      128262 :     SpansType aRanges;
     325       64131 :     getSpans(aRanges);
     326       64131 :     SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
     327       65151 :     for (; it != itEnd; ++it)
     328             :     {
     329        3770 :         for (SCROW nRow = it->mnRow1; nRow <= it->mnRow2; ++nRow)
     330        2750 :             aRows.push_back(nRow);
     331             :     }
     332             : 
     333      128262 :     rRows.swap(aRows);
     334       64131 : }
     335             : 
     336     1148038 : void SingleColumnSpanSet::getSpans(SpansType& rSpans) const
     337             : {
     338     1148038 :     SpansType aSpans = toSpanArray<SCROW,RowSpan>(maSpans);
     339     1148038 :     rSpans.swap(aSpans);
     340     1148038 : }
     341             : 
     342        4495 : void SingleColumnSpanSet::swap( SingleColumnSpanSet& r )
     343             : {
     344        4495 :     maSpans.swap(r.maSpans);
     345        4495 : }
     346             : 
     347         156 : }
     348             : 
     349             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11