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