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 "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"
18 :
19 : #include <algorithm>
20 :
21 : namespace sc {
22 :
23 1053 : ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) :
24 1053 : maSpans(nStart, nEnd+1, bInit), miPos(maSpans.begin()) {}
25 :
26 55 : ColumnSpanSet::Action::~Action() {}
27 0 : void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}
28 :
29 731 : ColumnSpanSet::ColumnAction::~ColumnAction() {}
30 :
31 786 : ColumnSpanSet::ColumnSpanSet(bool bInit) : mbInit(bInit) {}
32 :
33 1572 : ColumnSpanSet::~ColumnSpanSet()
34 : {
35 786 : DocType::iterator itTab = maDoc.begin(), itTabEnd = maDoc.end();
36 4240 : for (; itTab != itTabEnd; ++itTab)
37 : {
38 3454 : TableType* pTab = *itTab;
39 3454 : if (!pTab)
40 2698 : continue;
41 :
42 756 : std::for_each(pTab->begin(), pTab->end(), ScDeleteObjectByPtr<ColumnType>());
43 756 : delete pTab;
44 : }
45 786 : }
46 :
47 1074 : ColumnSpanSet::ColumnType& ColumnSpanSet::getColumn(SCTAB nTab, SCCOL nCol)
48 : {
49 1074 : if (static_cast<size_t>(nTab) >= maDoc.size())
50 756 : maDoc.resize(nTab+1, NULL);
51 :
52 1074 : if (!maDoc[nTab])
53 756 : maDoc[nTab] = new TableType;
54 :
55 1074 : TableType& rTab = *maDoc[nTab];
56 1074 : if (static_cast<size_t>(nCol) >= rTab.size())
57 1053 : rTab.resize(nCol+1, NULL);
58 :
59 1074 : if (!rTab[nCol])
60 1053 : rTab[nCol] = new ColumnType(0, MAXROW, mbInit);
61 :
62 1074 : return *rTab[nCol];
63 : }
64 :
65 37 : void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
66 : {
67 37 : if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
68 37 : return;
69 :
70 37 : ColumnType& rCol = getColumn(nTab, nCol);
71 37 : rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow, nRow+1, bVal).first;
72 : }
73 :
74 70 : void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
75 : {
76 70 : if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
77 70 : return;
78 :
79 70 : ColumnType& rCol = getColumn(nTab, nCol);
80 70 : rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow1, nRow2+1, bVal).first;
81 : }
82 :
83 731 : void ColumnSpanSet::set(const ScRange& rRange, bool bVal)
84 : {
85 1462 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
86 : {
87 1698 : for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
88 : {
89 967 : ColumnType& rCol = getColumn(nTab, nCol);
90 967 : rCol.miPos = rCol.maSpans.insert(rCol.miPos, rRange.aStart.Row(), rRange.aEnd.Row()+1, bVal).first;
91 : }
92 : }
93 731 : }
94 :
95 55 : void ColumnSpanSet::executeAction(Action& ac) const
96 : {
97 80 : for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
98 : {
99 25 : if (!maDoc[nTab])
100 0 : continue;
101 :
102 25 : const TableType& rTab = *maDoc[nTab];
103 157 : for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
104 : {
105 132 : if (!rTab[nCol])
106 46 : continue;
107 :
108 86 : ac.startColumn(nTab, nCol);
109 86 : ColumnType& rCol = *rTab[nCol];
110 86 : ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
111 : SCROW nRow1, nRow2;
112 86 : nRow1 = it->first;
113 86 : bool bVal = it->second;
114 269 : for (++it; it != itEnd; ++it)
115 : {
116 183 : nRow2 = it->first-1;
117 183 : ac.execute(ScAddress(nCol, nRow1, nTab), nRow2-nRow1+1, bVal);
118 :
119 183 : nRow1 = nRow2+1; // for the next iteration.
120 183 : bVal = it->second;
121 : }
122 : }
123 : }
124 55 : }
125 :
126 731 : void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const
127 : {
128 4160 : for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
129 : {
130 3429 : if (!maDoc[nTab])
131 2698 : continue;
132 :
133 731 : const TableType& rTab = *maDoc[nTab];
134 9002 : for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
135 : {
136 8271 : if (!rTab[nCol])
137 14608 : continue;
138 :
139 967 : ScTable* pTab = rDoc.FetchTable(nTab);
140 967 : if (!pTab)
141 0 : continue;
142 :
143 967 : if (!ValidCol(nCol))
144 : {
145 : // End the loop.
146 0 : nCol = rTab.size();
147 0 : continue;
148 : }
149 :
150 967 : ScColumn& rColumn = pTab->aCol[nCol];
151 967 : ac.startColumn(&rColumn);
152 967 : ColumnType& rCol = *rTab[nCol];
153 967 : ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
154 : SCROW nRow1, nRow2;
155 967 : nRow1 = it->first;
156 967 : bool bVal = it->second;
157 3768 : for (++it; it != itEnd; ++it)
158 : {
159 2801 : nRow2 = it->first-1;
160 2801 : ac.execute(nRow1, nRow2, bVal);
161 :
162 2801 : nRow1 = nRow2+1; // for the next iteration.
163 2801 : bVal = it->second;
164 : }
165 : }
166 : }
167 731 : }
168 :
169 : namespace {
170 :
171 : class Scanner
172 : {
173 : SingleColumnSpanSet::ColumnSpansType& mrRanges;
174 : public:
175 886691 : Scanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {}
176 :
177 888301 : void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
178 : {
179 888301 : if (node.type == sc::element_type_empty)
180 1772610 : return;
181 :
182 3992 : size_t nRow = node.position + nOffset;
183 3992 : size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
184 3992 : mrRanges.insert_back(nRow, nEndRow, true);
185 : }
186 : };
187 :
188 : }
189 :
190 898441 : SingleColumnSpanSet::SingleColumnSpanSet() : maSpans(0, MAXROWCOUNT, false) {}
191 :
192 0 : void SingleColumnSpanSet::scan(const ScColumn& rColumn)
193 : {
194 0 : const CellStoreType& rCells = rColumn.maCells;
195 0 : sc::CellStoreType::const_iterator it = rCells.begin(), itEnd = rCells.end();
196 0 : SCROW nCurRow = 0;
197 0 : for (;it != itEnd; ++it)
198 : {
199 0 : SCROW nEndRow = nCurRow + it->size; // Last row of current block plus 1.
200 0 : if (it->type != sc::element_type_empty)
201 0 : maSpans.insert_back(nCurRow, nEndRow, true);
202 :
203 0 : nCurRow = nEndRow;
204 : }
205 0 : }
206 :
207 886688 : void SingleColumnSpanSet::scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
208 : {
209 886688 : const CellStoreType& rCells = rColumn.maCells;
210 886688 : Scanner aScanner(maSpans);
211 886688 : sc::ParseBlock(rCells.begin(), rCells, aScanner, nStart, nEnd);
212 886688 : }
213 :
214 3 : void SingleColumnSpanSet::scan(
215 : ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
216 : {
217 3 : const CellStoreType& rCells = rColumn.maCells;
218 3 : Scanner aScanner(maSpans);
219 3 : rBlockPos.miCellPos = sc::ParseBlock(rBlockPos.miCellPos, rCells, aScanner, nStart, nEnd);
220 3 : }
221 :
222 4166 : void SingleColumnSpanSet::scan(const ScMarkData& rMark, SCTAB nTab, SCCOL nCol)
223 : {
224 4166 : if (!rMark.GetTableSelect(nTab))
225 : // This table is not selected. Nothing to scan.
226 4166 : return;
227 :
228 4166 : ScRangeList aRanges = rMark.GetMarkedRanges();
229 14476 : for (size_t i = 0, n = aRanges.size(); i < n; ++i)
230 : {
231 10310 : const ScRange* p = aRanges[i];
232 10310 : if (nCol < p->aStart.Col() || p->aEnd.Col() < nCol)
233 : // This column is not in this range. Skip it.
234 10214 : continue;
235 :
236 96 : maSpans.insert_back(p->aStart.Row(), p->aEnd.Row()+1, true);
237 4166 : }
238 : }
239 :
240 1046 : void SingleColumnSpanSet::set(SCROW nRow1, SCROW nRow2, bool bVal)
241 : {
242 1046 : maSpans.insert_back(nRow1, nRow2+1, bVal);
243 1046 : }
244 :
245 7573 : void SingleColumnSpanSet::getRows(std::vector<SCROW> &rRows) const
246 : {
247 7573 : std::vector<SCROW> aRows;
248 :
249 15146 : SpansType aRanges;
250 7573 : getSpans(aRanges);
251 7573 : SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
252 8420 : for (; it != itEnd; ++it)
253 : {
254 2975 : for (SCROW nRow = it->mnRow1; nRow <= it->mnRow2; ++nRow)
255 2128 : aRows.push_back(nRow);
256 : }
257 :
258 15146 : rRows.swap(aRows);
259 7573 : }
260 :
261 902638 : void SingleColumnSpanSet::getSpans(SpansType& rSpans) const
262 : {
263 902638 : SpansType aSpans;
264 902638 : ColumnSpansType::const_iterator it = maSpans.begin(), itEnd = maSpans.end();
265 902638 : SCROW nLastRow = it->first;
266 902638 : bool bLastVal = it->second;
267 1813400 : for (++it; it != itEnd; ++it)
268 : {
269 910762 : SCROW nThisRow = it->first;
270 910762 : bool bThisVal = it->second;
271 :
272 910762 : if (bLastVal)
273 4816 : aSpans.push_back(Span(nLastRow, nThisRow-1));
274 :
275 910762 : nLastRow = nThisRow;
276 910762 : bLastVal = bThisVal;
277 : }
278 :
279 902638 : rSpans.swap(aSpans);
280 902638 : }
281 :
282 93 : }
283 :
284 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|