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