fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / data / columnspanset.cxx
blob25f6b5baf45b9935daa878d9f524eaf886bb332d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
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>
20 #include <algorithm>
22 namespace sc {
24 namespace {
26 class ColumnScanner
28 ColumnSpanSet::ColumnSpansType& mrRanges;
29 bool mbVal;
30 public:
31 ColumnScanner(ColumnSpanSet::ColumnSpansType& rRanges, bool bVal) :
32 mrRanges(rRanges), mbVal(bVal) {}
34 void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
36 if (node.type == sc::element_type_empty)
37 return;
39 size_t nRow = node.position + nOffset;
40 size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
41 mrRanges.insert_back(nRow, nEndRow, mbVal);
47 RowSpan::RowSpan(SCROW nRow1, SCROW nRow2) : mnRow1(nRow1), mnRow2(nRow2) {}
49 ColRowSpan::ColRowSpan(SCCOLROW nStart, SCCOLROW nEnd) : mnStart(nStart), mnEnd(nEnd) {}
51 ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) :
52 maSpans(nStart, nEnd+1, bInit), miPos(maSpans.begin()) {}
54 ColumnSpanSet::Action::~Action() {}
55 void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}
57 ColumnSpanSet::ColumnAction::~ColumnAction() {}
59 ColumnSpanSet::ColumnSpanSet(bool bInit) : mbInit(bInit) {}
61 ColumnSpanSet::~ColumnSpanSet()
63 DocType::iterator itTab = maDoc.begin(), itTabEnd = maDoc.end();
64 for (; itTab != itTabEnd; ++itTab)
66 TableType* pTab = *itTab;
67 if (!pTab)
68 continue;
70 std::for_each(pTab->begin(), pTab->end(), boost::checked_deleter<ColumnType>());
71 delete pTab;
75 ColumnSpanSet::ColumnType& ColumnSpanSet::getColumn(SCTAB nTab, SCCOL nCol)
77 if (static_cast<size_t>(nTab) >= maDoc.size())
78 maDoc.resize(nTab+1, NULL);
80 if (!maDoc[nTab])
81 maDoc[nTab] = new TableType;
83 TableType& rTab = *maDoc[nTab];
84 if (static_cast<size_t>(nCol) >= rTab.size())
85 rTab.resize(nCol+1, NULL);
87 if (!rTab[nCol])
88 rTab[nCol] = new ColumnType(0, MAXROW, mbInit);
90 return *rTab[nCol];
93 void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
95 if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
96 return;
98 ColumnType& rCol = getColumn(nTab, nCol);
99 rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow, nRow+1, bVal).first;
102 void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
104 if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
105 return;
107 ColumnType& rCol = getColumn(nTab, nCol);
108 rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow1, nRow2+1, bVal).first;
111 void ColumnSpanSet::set(const ScRange& rRange, bool bVal)
113 for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
115 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
117 ColumnType& rCol = getColumn(nTab, nCol);
118 rCol.miPos = rCol.maSpans.insert(rCol.miPos, rRange.aStart.Row(), rRange.aEnd.Row()+1, bVal).first;
123 void ColumnSpanSet::set( SCTAB nTab, SCCOL nCol, const SingleColumnSpanSet& rSingleSet, bool bVal )
125 SingleColumnSpanSet::SpansType aSpans;
126 rSingleSet.getSpans(aSpans);
127 SingleColumnSpanSet::SpansType::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
128 for (; it != itEnd; ++it)
129 set(nTab, nCol, it->mnRow1, it->mnRow2, bVal);
132 void ColumnSpanSet::scan(
133 const ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal)
135 if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
136 return;
138 if (nCol1 > nCol2 || nRow1 > nRow2)
139 return;
141 const ScTable* pTab = rDoc.FetchTable(nTab);
142 if (!pTab)
143 return;
145 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
147 ColumnType& rCol = getColumn(nTab, nCol);
149 const CellStoreType& rSrcCells = pTab->aCol[nCol].maCells;
151 ColumnScanner aScanner(rCol.maSpans, bVal);
152 ParseBlock(rSrcCells.begin(), rSrcCells, aScanner, nRow1, nRow2);
156 void ColumnSpanSet::executeAction(Action& ac) const
158 for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
160 if (!maDoc[nTab])
161 continue;
163 const TableType& rTab = *maDoc[nTab];
164 for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
166 if (!rTab[nCol])
167 continue;
169 ac.startColumn(nTab, nCol);
170 ColumnType& rCol = *rTab[nCol];
171 ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
172 SCROW nRow1, nRow2;
173 nRow1 = it->first;
174 bool bVal = it->second;
175 for (++it; it != itEnd; ++it)
177 nRow2 = it->first-1;
178 ac.execute(ScAddress(nCol, nRow1, nTab), nRow2-nRow1+1, bVal);
180 nRow1 = nRow2+1; // for the next iteration.
181 bVal = it->second;
187 void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const
189 for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
191 if (!maDoc[nTab])
192 continue;
194 const TableType& rTab = *maDoc[nTab];
195 for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
197 if (!rTab[nCol])
198 continue;
200 ScTable* pTab = rDoc.FetchTable(nTab);
201 if (!pTab)
202 continue;
204 if (!ValidCol(nCol))
206 // End the loop.
207 nCol = rTab.size();
208 continue;
211 ScColumn& rColumn = pTab->aCol[nCol];
212 ac.startColumn(&rColumn);
213 ColumnType& rCol = *rTab[nCol];
214 ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
215 SCROW nRow1, nRow2;
216 nRow1 = it->first;
217 bool bVal = it->second;
218 for (++it; it != itEnd; ++it)
220 nRow2 = it->first-1;
221 ac.execute(nRow1, nRow2, bVal);
223 nRow1 = nRow2+1; // for the next iteration.
224 bVal = it->second;
230 void ColumnSpanSet::swap( ColumnSpanSet& r )
232 maDoc.swap(r.maDoc);
233 std::swap(mbInit, r.mbInit);
236 namespace {
238 class Scanner
240 SingleColumnSpanSet::ColumnSpansType& mrRanges;
241 public:
242 Scanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {}
244 void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
246 if (node.type == sc::element_type_empty)
247 return;
249 size_t nRow = node.position + nOffset;
250 size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
251 mrRanges.insert_back(nRow, nEndRow, true);
257 SingleColumnSpanSet::SingleColumnSpanSet() : maSpans(0, MAXROWCOUNT, false) {}
259 void SingleColumnSpanSet::scan(const ScColumn& rColumn)
261 const CellStoreType& rCells = rColumn.maCells;
262 sc::CellStoreType::const_iterator it = rCells.begin(), itEnd = rCells.end();
263 SCROW nCurRow = 0;
264 for (;it != itEnd; ++it)
266 SCROW nEndRow = nCurRow + it->size; // Last row of current block plus 1.
267 if (it->type != sc::element_type_empty)
268 maSpans.insert_back(nCurRow, nEndRow, true);
270 nCurRow = nEndRow;
274 void SingleColumnSpanSet::scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
276 const CellStoreType& rCells = rColumn.maCells;
277 Scanner aScanner(maSpans);
278 sc::ParseBlock(rCells.begin(), rCells, aScanner, nStart, nEnd);
281 void SingleColumnSpanSet::scan(
282 ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
284 const CellStoreType& rCells = rColumn.maCells;
285 Scanner aScanner(maSpans);
286 rBlockPos.miCellPos = sc::ParseBlock(rBlockPos.miCellPos, rCells, aScanner, nStart, nEnd);
289 void SingleColumnSpanSet::scan(const ScMarkData& rMark, SCTAB nTab, SCCOL nCol)
291 if (!rMark.GetTableSelect(nTab))
292 // This table is not selected. Nothing to scan.
293 return;
295 ScRangeList aRanges = rMark.GetMarkedRanges();
296 scan(aRanges, nTab, nCol);
299 void SingleColumnSpanSet::scan(const ScRangeList& rRanges, SCTAB nTab, SCCOL nCol)
301 for (size_t i = 0, n = rRanges.size(); i < n; ++i)
303 const ScRange* p = rRanges[i];
304 if (nTab < p->aStart.Tab() || p->aEnd.Tab() < nTab)
305 continue;
307 if (nCol < p->aStart.Col() || p->aEnd.Col() < nCol)
308 // This column is not in this range. Skip it.
309 continue;
311 maSpans.insert_back(p->aStart.Row(), p->aEnd.Row()+1, true);
315 void SingleColumnSpanSet::set(SCROW nRow1, SCROW nRow2, bool bVal)
317 maSpans.insert_back(nRow1, nRow2+1, bVal);
320 void SingleColumnSpanSet::getRows(std::vector<SCROW> &rRows) const
322 std::vector<SCROW> aRows;
324 SpansType aRanges;
325 getSpans(aRanges);
326 SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
327 for (; it != itEnd; ++it)
329 for (SCROW nRow = it->mnRow1; nRow <= it->mnRow2; ++nRow)
330 aRows.push_back(nRow);
333 rRows.swap(aRows);
336 void SingleColumnSpanSet::getSpans(SpansType& rSpans) const
338 SpansType aSpans = toSpanArray<SCROW,RowSpan>(maSpans);
339 rSpans.swap(aSpans);
342 void SingleColumnSpanSet::swap( SingleColumnSpanSet& r )
344 maSpans.swap(r.maSpans);
349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */