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: */
|