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 314 : ColumnScanner(ColumnSpanSet::ColumnSpansType& rRanges, bool bVal) :
32 314 : mrRanges(rRanges), mbVal(bVal) {}
33 :
34 350 : void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
35 : {
36 350 : if (node.type == sc::element_type_empty)
37 566 : return;
38 :
39 134 : size_t nRow = node.position + nOffset;
40 134 : size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
41 134 : mrRanges.insert_back(nRow, nEndRow, mbVal);
42 : }
43 : };
44 :
45 : }
46 :
47 13761 : RowSpan::RowSpan(SCROW nRow1, SCROW nRow2) : mnRow1(nRow1), mnRow2(nRow2) {}
48 :
49 13834 : ColRowSpan::ColRowSpan(SCCOLROW nStart, SCCOLROW nEnd) : mnStart(nStart), mnEnd(nEnd) {}
50 :
51 3036 : ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) :
52 3036 : maSpans(nStart, nEnd+1, bInit), miPos(maSpans.begin()) {}
53 :
54 274 : ColumnSpanSet::Action::~Action() {}
55 0 : void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}
56 :
57 1795 : ColumnSpanSet::ColumnAction::~ColumnAction() {}
58 :
59 2363 : ColumnSpanSet::ColumnSpanSet(bool bInit) : mbInit(bInit) {}
60 :
61 4726 : ColumnSpanSet::~ColumnSpanSet()
62 : {
63 2363 : DocType::iterator itTab = maDoc.begin(), itTabEnd = maDoc.end();
64 9970 : for (; itTab != itTabEnd; ++itTab)
65 : {
66 7607 : TableType* pTab = *itTab;
67 7607 : if (!pTab)
68 5472 : continue;
69 :
70 2135 : std::for_each(pTab->begin(), pTab->end(), boost::checked_deleter<ColumnType>());
71 2135 : delete pTab;
72 : }
73 2363 : }
74 :
75 3322 : ColumnSpanSet::ColumnType& ColumnSpanSet::getColumn(SCTAB nTab, SCCOL nCol)
76 : {
77 3322 : if (static_cast<size_t>(nTab) >= maDoc.size())
78 2135 : maDoc.resize(nTab+1, NULL);
79 :
80 3322 : if (!maDoc[nTab])
81 2135 : maDoc[nTab] = new TableType;
82 :
83 3322 : TableType& rTab = *maDoc[nTab];
84 3322 : if (static_cast<size_t>(nCol) >= rTab.size())
85 3028 : rTab.resize(nCol+1, NULL);
86 :
87 3322 : if (!rTab[nCol])
88 3036 : rTab[nCol] = new ColumnType(0, MAXROW, mbInit);
89 :
90 3322 : return *rTab[nCol];
91 : }
92 :
93 482 : void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
94 : {
95 482 : if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
96 482 : return;
97 :
98 482 : ColumnType& rCol = getColumn(nTab, nCol);
99 482 : rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow, nRow+1, bVal).first;
100 : }
101 :
102 92 : void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
103 : {
104 92 : if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
105 92 : return;
106 :
107 92 : ColumnType& rCol = getColumn(nTab, nCol);
108 92 : rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow1, nRow2+1, bVal).first;
109 : }
110 :
111 1789 : void ColumnSpanSet::set(const ScRange& rRange, bool bVal)
112 : {
113 3578 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
114 : {
115 4223 : for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
116 : {
117 2434 : ColumnType& rCol = getColumn(nTab, nCol);
118 2434 : rCol.miPos = rCol.maSpans.insert(rCol.miPos, rRange.aStart.Row(), rRange.aEnd.Row()+1, bVal).first;
119 : }
120 : }
121 1789 : }
122 :
123 154 : void ColumnSpanSet::scan(
124 : const ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal)
125 : {
126 154 : if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
127 0 : return;
128 :
129 154 : if (nCol1 > nCol2 || nRow1 > nRow2)
130 0 : return;
131 :
132 154 : const ScTable* pTab = rDoc.FetchTable(nTab);
133 154 : if (!pTab)
134 0 : return;
135 :
136 468 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
137 : {
138 314 : ColumnType& rCol = getColumn(nTab, nCol);
139 :
140 314 : const CellStoreType& rSrcCells = pTab->aCol[nCol].maCells;
141 :
142 314 : ColumnScanner aScanner(rCol.maSpans, bVal);
143 314 : ParseBlock(rSrcCells.begin(), rSrcCells, aScanner, nRow1, nRow2);
144 : }
145 : }
146 :
147 274 : void ColumnSpanSet::executeAction(Action& ac) const
148 : {
149 434 : for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
150 : {
151 160 : if (!maDoc[nTab])
152 4 : continue;
153 :
154 156 : const TableType& rTab = *maDoc[nTab];
155 1010 : for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
156 : {
157 854 : if (!rTab[nCol])
158 610 : continue;
159 :
160 244 : ac.startColumn(nTab, nCol);
161 244 : ColumnType& rCol = *rTab[nCol];
162 244 : ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
163 : SCROW nRow1, nRow2;
164 244 : nRow1 = it->first;
165 244 : bool bVal = it->second;
166 870 : for (++it; it != itEnd; ++it)
167 : {
168 626 : nRow2 = it->first-1;
169 626 : ac.execute(ScAddress(nCol, nRow1, nTab), nRow2-nRow1+1, bVal);
170 :
171 626 : nRow1 = nRow2+1; // for the next iteration.
172 626 : bVal = it->second;
173 : }
174 : }
175 : }
176 274 : }
177 :
178 1795 : void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const
179 : {
180 9058 : for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
181 : {
182 7263 : if (!maDoc[nTab])
183 5468 : continue;
184 :
185 1795 : const TableType& rTab = *maDoc[nTab];
186 19255 : for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
187 : {
188 17460 : if (!rTab[nCol])
189 30040 : continue;
190 :
191 2440 : ScTable* pTab = rDoc.FetchTable(nTab);
192 2440 : if (!pTab)
193 0 : continue;
194 :
195 2440 : if (!ValidCol(nCol))
196 : {
197 : // End the loop.
198 0 : nCol = rTab.size();
199 0 : continue;
200 : }
201 :
202 2440 : ScColumn& rColumn = pTab->aCol[nCol];
203 2440 : ac.startColumn(&rColumn);
204 2440 : ColumnType& rCol = *rTab[nCol];
205 2440 : ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
206 : SCROW nRow1, nRow2;
207 2440 : nRow1 = it->first;
208 2440 : bool bVal = it->second;
209 9256 : for (++it; it != itEnd; ++it)
210 : {
211 6816 : nRow2 = it->first-1;
212 6816 : ac.execute(nRow1, nRow2, bVal);
213 :
214 6816 : nRow1 = nRow2+1; // for the next iteration.
215 6816 : bVal = it->second;
216 : }
217 : }
218 : }
219 1795 : }
220 :
221 : namespace {
222 :
223 : class Scanner
224 : {
225 : SingleColumnSpanSet::ColumnSpansType& mrRanges;
226 : public:
227 2807646 : Scanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {}
228 :
229 2810960 : void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
230 : {
231 2810960 : if (node.type == sc::element_type_empty)
232 5611529 : return;
233 :
234 10391 : size_t nRow = node.position + nOffset;
235 10391 : size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
236 10391 : mrRanges.insert_back(nRow, nEndRow, true);
237 : }
238 : };
239 :
240 : }
241 :
242 3284610 : SingleColumnSpanSet::SingleColumnSpanSet() : maSpans(0, MAXROWCOUNT, false) {}
243 :
244 0 : void SingleColumnSpanSet::scan(const ScColumn& rColumn)
245 : {
246 0 : const CellStoreType& rCells = rColumn.maCells;
247 0 : sc::CellStoreType::const_iterator it = rCells.begin(), itEnd = rCells.end();
248 0 : SCROW nCurRow = 0;
249 0 : for (;it != itEnd; ++it)
250 : {
251 0 : SCROW nEndRow = nCurRow + it->size; // Last row of current block plus 1.
252 0 : if (it->type != sc::element_type_empty)
253 0 : maSpans.insert_back(nCurRow, nEndRow, true);
254 :
255 0 : nCurRow = nEndRow;
256 : }
257 0 : }
258 :
259 2807562 : void SingleColumnSpanSet::scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
260 : {
261 2807562 : const CellStoreType& rCells = rColumn.maCells;
262 2807562 : Scanner aScanner(maSpans);
263 2807562 : sc::ParseBlock(rCells.begin(), rCells, aScanner, nStart, nEnd);
264 2807562 : }
265 :
266 84 : void SingleColumnSpanSet::scan(
267 : ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
268 : {
269 84 : const CellStoreType& rCells = rColumn.maCells;
270 84 : Scanner aScanner(maSpans);
271 84 : rBlockPos.miCellPos = sc::ParseBlock(rBlockPos.miCellPos, rCells, aScanner, nStart, nEnd);
272 84 : }
273 :
274 154 : void SingleColumnSpanSet::scan(const ScMarkData& rMark, SCTAB nTab, SCCOL nCol)
275 : {
276 154 : if (!rMark.GetTableSelect(nTab))
277 : // This table is not selected. Nothing to scan.
278 154 : return;
279 :
280 154 : ScRangeList aRanges = rMark.GetMarkedRanges();
281 154 : scan(aRanges, nTab, nCol);
282 : }
283 :
284 438426 : void SingleColumnSpanSet::scan(const ScRangeList& rRanges, SCTAB nTab, SCCOL nCol)
285 : {
286 917812 : for (size_t i = 0, n = rRanges.size(); i < n; ++i)
287 : {
288 479386 : const ScRange* p = rRanges[i];
289 479386 : if (nTab < p->aStart.Tab() || p->aEnd.Tab() < nTab)
290 0 : continue;
291 :
292 479386 : if (nCol < p->aStart.Col() || p->aEnd.Col() < nCol)
293 : // This column is not in this range. Skip it.
294 478736 : continue;
295 :
296 650 : maSpans.insert_back(p->aStart.Row(), p->aEnd.Row()+1, true);
297 : }
298 438426 : }
299 :
300 76792 : void SingleColumnSpanSet::set(SCROW nRow1, SCROW nRow2, bool bVal)
301 : {
302 76792 : maSpans.insert_back(nRow1, nRow2+1, bVal);
303 76792 : }
304 :
305 38504 : void SingleColumnSpanSet::getRows(std::vector<SCROW> &rRows) const
306 : {
307 38504 : std::vector<SCROW> aRows;
308 :
309 77008 : SpansType aRanges;
310 38504 : getSpans(aRanges);
311 38504 : SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
312 40994 : for (; it != itEnd; ++it)
313 : {
314 9086 : for (SCROW nRow = it->mnRow1; nRow <= it->mnRow2; ++nRow)
315 6596 : aRows.push_back(nRow);
316 : }
317 :
318 77008 : rRows.swap(aRows);
319 38504 : }
320 :
321 3293436 : void SingleColumnSpanSet::getSpans(SpansType& rSpans) const
322 : {
323 3293436 : SpansType aSpans = toSpanArray<SCROW,RowSpan>(maSpans);
324 3293436 : rSpans.swap(aSpans);
325 3293436 : }
326 :
327 228 : }
328 :
329 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|