Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / data / columnspanset.cxx
blobf8c7813daf038d3ca773ee064967fa44d64d48f5
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 "stlalgorithm.hxx"
12 #include "column.hxx"
13 #include "table.hxx"
14 #include "document.hxx"
15 #include "mtvfunctions.hxx"
16 #include "markdata.hxx"
17 #include "rangelst.hxx"
19 #include <algorithm>
21 namespace sc {
23 ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) :
24 maSpans(nStart, nEnd+1, bInit), miPos(maSpans.begin()) {}
26 ColumnSpanSet::Action::~Action() {}
27 void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}
29 ColumnSpanSet::ColumnAction::~ColumnAction() {}
31 ColumnSpanSet::ColumnSpanSet(bool bInit) : mbInit(bInit) {}
33 ColumnSpanSet::~ColumnSpanSet()
35 DocType::iterator itTab = maDoc.begin(), itTabEnd = maDoc.end();
36 for (; itTab != itTabEnd; ++itTab)
38 TableType* pTab = *itTab;
39 if (!pTab)
40 continue;
42 std::for_each(pTab->begin(), pTab->end(), ScDeleteObjectByPtr<ColumnType>());
43 delete pTab;
47 ColumnSpanSet::ColumnType& ColumnSpanSet::getColumn(SCTAB nTab, SCCOL nCol)
49 if (static_cast<size_t>(nTab) >= maDoc.size())
50 maDoc.resize(nTab+1, NULL);
52 if (!maDoc[nTab])
53 maDoc[nTab] = new TableType;
55 TableType& rTab = *maDoc[nTab];
56 if (static_cast<size_t>(nCol) >= rTab.size())
57 rTab.resize(nCol+1, NULL);
59 if (!rTab[nCol])
60 rTab[nCol] = new ColumnType(0, MAXROW, mbInit);
62 return *rTab[nCol];
65 void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
67 if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
68 return;
70 ColumnType& rCol = getColumn(nTab, nCol);
71 rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow, nRow+1, bVal).first;
74 void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
76 if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
77 return;
79 ColumnType& rCol = getColumn(nTab, nCol);
80 rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow1, nRow2+1, bVal).first;
83 void ColumnSpanSet::set(const ScRange& rRange, bool bVal)
85 for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
87 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
89 ColumnType& rCol = getColumn(nTab, nCol);
90 rCol.miPos = rCol.maSpans.insert(rCol.miPos, rRange.aStart.Row(), rRange.aEnd.Row()+1, bVal).first;
95 void ColumnSpanSet::executeAction(Action& ac) const
97 for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
99 if (!maDoc[nTab])
100 continue;
102 const TableType& rTab = *maDoc[nTab];
103 for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
105 if (!rTab[nCol])
106 continue;
108 ac.startColumn(nTab, nCol);
109 ColumnType& rCol = *rTab[nCol];
110 ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
111 SCROW nRow1, nRow2;
112 nRow1 = it->first;
113 bool bVal = it->second;
114 for (++it; it != itEnd; ++it)
116 nRow2 = it->first-1;
117 ac.execute(ScAddress(nCol, nRow1, nTab), nRow2-nRow1+1, bVal);
119 nRow1 = nRow2+1; // for the next iteration.
120 bVal = it->second;
126 void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const
128 for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
130 if (!maDoc[nTab])
131 continue;
133 const TableType& rTab = *maDoc[nTab];
134 for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
136 if (!rTab[nCol])
137 continue;
139 ScTable* pTab = rDoc.FetchTable(nTab);
140 if (!pTab)
141 continue;
143 if (!ValidCol(nCol))
145 // End the loop.
146 nCol = rTab.size();
147 continue;
150 ScColumn& rColumn = pTab->aCol[nCol];
151 ac.startColumn(&rColumn);
152 ColumnType& rCol = *rTab[nCol];
153 ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
154 SCROW nRow1, nRow2;
155 nRow1 = it->first;
156 bool bVal = it->second;
157 for (++it; it != itEnd; ++it)
159 nRow2 = it->first-1;
160 ac.execute(nRow1, nRow2, bVal);
162 nRow1 = nRow2+1; // for the next iteration.
163 bVal = it->second;
169 namespace {
171 class Scanner
173 SingleColumnSpanSet::ColumnSpansType& mrRanges;
174 public:
175 Scanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {}
177 void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
179 if (node.type == sc::element_type_empty)
180 return;
182 size_t nRow = node.position + nOffset;
183 size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
184 mrRanges.insert_back(nRow, nEndRow, true);
190 SingleColumnSpanSet::SingleColumnSpanSet() : maSpans(0, MAXROWCOUNT, false) {}
192 void SingleColumnSpanSet::scan(const ScColumn& rColumn)
194 const CellStoreType& rCells = rColumn.maCells;
195 sc::CellStoreType::const_iterator it = rCells.begin(), itEnd = rCells.end();
196 SCROW nCurRow = 0;
197 for (;it != itEnd; ++it)
199 SCROW nEndRow = nCurRow + it->size; // Last row of current block plus 1.
200 if (it->type != sc::element_type_empty)
201 maSpans.insert_back(nCurRow, nEndRow, true);
203 nCurRow = nEndRow;
207 void SingleColumnSpanSet::scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
209 const CellStoreType& rCells = rColumn.maCells;
210 Scanner aScanner(maSpans);
211 sc::ParseBlock(rCells.begin(), rCells, aScanner, nStart, nEnd);
214 void SingleColumnSpanSet::scan(
215 ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
217 const CellStoreType& rCells = rColumn.maCells;
218 Scanner aScanner(maSpans);
219 rBlockPos.miCellPos = sc::ParseBlock(rBlockPos.miCellPos, rCells, aScanner, nStart, nEnd);
222 void SingleColumnSpanSet::scan(const ScMarkData& rMark, SCTAB nTab, SCCOL nCol)
224 if (!rMark.GetTableSelect(nTab))
225 // This table is not selected. Nothing to scan.
226 return;
228 ScRangeList aRanges = rMark.GetMarkedRanges();
229 for (size_t i = 0, n = aRanges.size(); i < n; ++i)
231 const ScRange* p = aRanges[i];
232 if (nCol < p->aStart.Col() || p->aEnd.Col() < nCol)
233 // This column is not in this range. Skip it.
234 continue;
236 maSpans.insert_back(p->aStart.Row(), p->aEnd.Row()+1, true);
240 void SingleColumnSpanSet::set(SCROW nRow1, SCROW nRow2, bool bVal)
242 maSpans.insert_back(nRow1, nRow2+1, bVal);
245 void SingleColumnSpanSet::getRows(std::vector<SCROW> &rRows) const
247 std::vector<SCROW> aRows;
249 SpansType aRanges;
250 getSpans(aRanges);
251 SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
252 for (; it != itEnd; ++it)
254 for (SCROW nRow = it->mnRow1; nRow <= it->mnRow2; ++nRow)
255 aRows.push_back(nRow);
258 rRows.swap(aRows);
261 void SingleColumnSpanSet::getSpans(SpansType& rSpans) const
263 SpansType aSpans;
264 ColumnSpansType::const_iterator it = maSpans.begin(), itEnd = maSpans.end();
265 SCROW nLastRow = it->first;
266 bool bLastVal = it->second;
267 for (++it; it != itEnd; ++it)
269 SCROW nThisRow = it->first;
270 bool bThisVal = it->second;
272 if (bLastVal)
273 aSpans.push_back(Span(nLastRow, nThisRow-1));
275 nLastRow = nThisRow;
276 bLastVal = bThisVal;
279 rSpans.swap(aSpans);
284 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */