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 <cellvalues.hxx>
11 : #include <column.hxx>
12 : #include <cellvalue.hxx>
13 :
14 : #include <cassert>
15 : #include <boost/noncopyable.hpp>
16 : #include <boost/ptr_container/ptr_vector.hpp>
17 :
18 : namespace sc {
19 :
20 : namespace {
21 :
22 : struct BlockPos
23 : {
24 : size_t mnStart;
25 : size_t mnEnd;
26 : };
27 :
28 8 : CellType toCellType( mdds::mtv::element_t eType )
29 : {
30 8 : switch (eType)
31 : {
32 : case element_type_numeric:
33 2 : return CELLTYPE_VALUE;
34 : case element_type_string:
35 0 : return CELLTYPE_STRING;
36 : case element_type_edittext:
37 0 : return CELLTYPE_EDIT;
38 : case element_type_formula:
39 6 : return CELLTYPE_FORMULA;
40 : default:
41 : ;
42 : }
43 :
44 0 : return CELLTYPE_NONE;
45 : }
46 :
47 : }
48 :
49 8 : CellValueSpan::CellValueSpan( SCROW nRow1, SCROW nRow2, CellType eType ) :
50 8 : mnRow1(nRow1), mnRow2(nRow2), meType(eType) {}
51 :
52 22 : struct CellValuesImpl : boost::noncopyable
53 : {
54 : CellStoreType maCells;
55 : CellTextAttrStoreType maCellTextAttrs;
56 : CellStoreType::iterator miCellPos;
57 : CellTextAttrStoreType::iterator miAttrPos;
58 : };
59 :
60 11 : CellValues::CellValues() :
61 11 : mpImpl(new CellValuesImpl) {}
62 :
63 11 : CellValues::~CellValues()
64 : {
65 11 : delete mpImpl;
66 11 : }
67 :
68 0 : void CellValues::transferFrom( ScColumn& rCol, SCROW nRow, size_t nLen )
69 : {
70 0 : mpImpl->maCells.resize(nLen);
71 0 : mpImpl->maCellTextAttrs.resize(nLen);
72 0 : rCol.maCells.transfer(nRow, nRow+nLen-1, mpImpl->maCells, 0);
73 0 : rCol.maCellTextAttrs.transfer(nRow, nRow+nLen-1, mpImpl->maCellTextAttrs, 0);
74 0 : }
75 :
76 0 : void CellValues::transferTo( ScColumn& rCol, SCROW nRow )
77 : {
78 : assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
79 :
80 0 : size_t nLen = mpImpl->maCells.size();
81 0 : mpImpl->maCells.transfer(0, nLen-1, rCol.maCells, nRow);
82 0 : mpImpl->maCellTextAttrs.transfer(0, nLen-1, rCol.maCellTextAttrs, nRow);
83 0 : }
84 :
85 0 : void CellValues::copyTo( ScColumn& rCol, SCROW nRow ) const
86 : {
87 0 : copyCellsTo(rCol, nRow);
88 0 : copyCellTextAttrsTo(rCol, nRow);
89 0 : }
90 :
91 10 : void CellValues::swapNonEmpty( ScColumn& rCol )
92 : {
93 10 : std::vector<BlockPos> aBlocksToSwap;
94 :
95 : {
96 : // Go through static value blocks and record their positions and sizes.
97 10 : sc::CellStoreType::const_iterator it = mpImpl->maCells.begin(), itEnd = mpImpl->maCells.end();
98 44 : for (; it != itEnd; ++it)
99 : {
100 34 : if (it->type == sc::element_type_empty)
101 22 : continue;
102 :
103 : BlockPos aPos;
104 12 : aPos.mnStart = it->position;
105 12 : aPos.mnEnd = aPos.mnStart + it->size - 1;
106 12 : aBlocksToSwap.push_back(aPos);
107 : }
108 : }
109 :
110 : // Do the swapping. The undo storage will store the replaced formula cells after this.
111 10 : std::vector<BlockPos>::const_iterator it = aBlocksToSwap.begin(), itEnd = aBlocksToSwap.end();
112 22 : for (; it != itEnd; ++it)
113 : {
114 12 : rCol.maCells.swap(it->mnStart, it->mnEnd, mpImpl->maCells, it->mnStart);
115 12 : rCol.maCellTextAttrs.swap(it->mnStart, it->mnEnd, mpImpl->maCellTextAttrs, it->mnStart);
116 10 : }
117 10 : }
118 :
119 0 : void CellValues::assign( const std::vector<double>& rVals )
120 : {
121 0 : mpImpl->maCells.resize(rVals.size());
122 0 : mpImpl->maCells.set(0, rVals.begin(), rVals.end());
123 :
124 : // Set default text attributes.
125 0 : std::vector<CellTextAttr> aDefaults(rVals.size(), CellTextAttr());
126 0 : mpImpl->maCellTextAttrs.resize(rVals.size());
127 0 : mpImpl->maCellTextAttrs.set(0, aDefaults.begin(), aDefaults.end());
128 0 : }
129 :
130 0 : size_t CellValues::size() const
131 : {
132 : assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
133 0 : return mpImpl->maCells.size();
134 : }
135 :
136 3 : void CellValues::reset( size_t nSize )
137 : {
138 3 : mpImpl->maCells.clear();
139 3 : mpImpl->maCells.resize(nSize);
140 3 : mpImpl->maCellTextAttrs.clear();
141 3 : mpImpl->maCellTextAttrs.resize(nSize);
142 :
143 3 : mpImpl->miCellPos = mpImpl->maCells.begin();
144 3 : mpImpl->miAttrPos = mpImpl->maCellTextAttrs.begin();
145 3 : }
146 :
147 6 : void CellValues::setValue( size_t nRow, double fVal )
148 : {
149 6 : mpImpl->miCellPos = mpImpl->maCells.set(mpImpl->miCellPos, nRow, fVal);
150 6 : mpImpl->miAttrPos = mpImpl->maCellTextAttrs.set(mpImpl->miAttrPos, nRow, sc::CellTextAttr());
151 6 : }
152 :
153 0 : void CellValues::setValue( size_t nRow, const svl::SharedString& rStr )
154 : {
155 0 : mpImpl->miCellPos = mpImpl->maCells.set(mpImpl->miCellPos, nRow, rStr);
156 0 : mpImpl->miAttrPos = mpImpl->maCellTextAttrs.set(mpImpl->miAttrPos, nRow, sc::CellTextAttr());
157 0 : }
158 :
159 6 : void CellValues::swap( CellValues& r )
160 : {
161 6 : std::swap(mpImpl, r.mpImpl);
162 6 : }
163 :
164 7 : std::vector<CellValueSpan> CellValues::getNonEmptySpans() const
165 : {
166 7 : std::vector<CellValueSpan> aRet;
167 7 : CellStoreType::const_iterator it = mpImpl->maCells.begin(), itEnd = mpImpl->maCells.end();
168 30 : for (; it != itEnd; ++it)
169 : {
170 23 : if (it->type != element_type_empty)
171 : {
172 : // Record this span.
173 8 : size_t nRow1 = it->position;
174 8 : size_t nRow2 = nRow1 + it->size - 1;
175 8 : aRet.push_back(CellValueSpan(nRow1, nRow2, toCellType(it->type)));
176 : }
177 : }
178 7 : return aRet;
179 : }
180 :
181 0 : void CellValues::copyCellsTo( ScColumn& rCol, SCROW nRow ) const
182 : {
183 0 : CellStoreType& rDest = rCol.maCells;
184 0 : const CellStoreType& rSrc = mpImpl->maCells;
185 :
186 : // Caller must ensure the destination is long enough.
187 : assert(rSrc.size() + static_cast<size_t>(nRow) < rDest.size());
188 :
189 0 : SCROW nCurRow = nRow;
190 0 : CellStoreType::iterator itPos = rDest.begin();
191 :
192 0 : CellStoreType::const_iterator itBlk = rSrc.begin(), itBlkEnd = rSrc.end();
193 0 : for (; itBlk != itBlkEnd; ++itBlk)
194 : {
195 0 : switch (itBlk->type)
196 : {
197 : case element_type_numeric:
198 : {
199 0 : numeric_block::const_iterator it = numeric_block::begin(*itBlk->data);
200 0 : numeric_block::const_iterator itEnd = numeric_block::end(*itBlk->data);
201 0 : itPos = rDest.set(itPos, nCurRow, it, itEnd);
202 : }
203 0 : break;
204 : case element_type_string:
205 : {
206 0 : string_block::const_iterator it = string_block::begin(*itBlk->data);
207 0 : string_block::const_iterator itEnd = string_block::end(*itBlk->data);
208 0 : itPos = rDest.set(itPos, nCurRow, it, itEnd);
209 : }
210 0 : break;
211 : case element_type_edittext:
212 : {
213 0 : edittext_block::const_iterator it = edittext_block::begin(*itBlk->data);
214 0 : edittext_block::const_iterator itEnd = edittext_block::end(*itBlk->data);
215 0 : std::vector<EditTextObject*> aVals;
216 0 : aVals.reserve(itBlk->size);
217 0 : for (; it != itEnd; ++it)
218 : {
219 0 : const EditTextObject* p = *it;
220 0 : aVals.push_back(p->Clone());
221 : }
222 0 : itPos = rDest.set(itPos, nCurRow, aVals.begin(), aVals.end());
223 : }
224 0 : break;
225 : case element_type_formula:
226 : {
227 0 : formula_block::const_iterator it = formula_block::begin(*itBlk->data);
228 0 : formula_block::const_iterator itEnd = formula_block::end(*itBlk->data);
229 0 : std::vector<ScFormulaCell*> aVals;
230 0 : aVals.reserve(itBlk->size);
231 0 : for (; it != itEnd; ++it)
232 : {
233 0 : const ScFormulaCell* p = *it;
234 0 : aVals.push_back(p->Clone());
235 : }
236 0 : itPos = rDest.set(itPos, nCurRow, aVals.begin(), aVals.end());
237 : }
238 0 : break;
239 : default:
240 0 : itPos = rDest.set_empty(itPos, nCurRow, nCurRow+itBlk->size-1);
241 : }
242 :
243 0 : nCurRow += itBlk->size;
244 : }
245 0 : }
246 :
247 0 : void CellValues::copyCellTextAttrsTo( ScColumn& rCol, SCROW nRow ) const
248 : {
249 0 : CellTextAttrStoreType& rDest = rCol.maCellTextAttrs;
250 0 : const CellTextAttrStoreType& rSrc = mpImpl->maCellTextAttrs;
251 :
252 : // Caller must ensure the destination is long enough.
253 : assert(rSrc.size() + static_cast<size_t>(nRow) < rDest.size());
254 :
255 0 : SCROW nCurRow = nRow;
256 0 : CellTextAttrStoreType::iterator itPos = rDest.begin();
257 :
258 0 : CellTextAttrStoreType::const_iterator itBlk = rSrc.begin(), itBlkEnd = rSrc.end();
259 0 : for (; itBlk != itBlkEnd; ++itBlk)
260 : {
261 0 : switch (itBlk->type)
262 : {
263 : case element_type_celltextattr:
264 : {
265 0 : celltextattr_block::const_iterator it = celltextattr_block::begin(*itBlk->data);
266 0 : celltextattr_block::const_iterator itEnd = celltextattr_block::end(*itBlk->data);
267 0 : itPos = rDest.set(itPos, nCurRow, it, itEnd);
268 : }
269 0 : break;
270 : default:
271 0 : itPos = rDest.set_empty(itPos, nCurRow, nCurRow+itBlk->size-1);
272 : }
273 :
274 0 : nCurRow += itBlk->size;
275 : }
276 0 : }
277 :
278 : typedef boost::ptr_vector<CellValues> TableType;
279 : typedef boost::ptr_vector<TableType> TablesType;
280 :
281 4 : struct TableValues::Impl
282 : {
283 : ScRange maRange;
284 : TablesType maTables;
285 :
286 4 : Impl( const ScRange& rRange ) : maRange(rRange)
287 : {
288 4 : size_t nTabs = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
289 4 : size_t nCols = rRange.aEnd.Col() - rRange.aStart.Col() + 1;
290 :
291 8 : for (size_t nTab = 0; nTab < nTabs; ++nTab)
292 : {
293 4 : maTables.push_back(new TableType);
294 4 : TableType& rTab = maTables.back();
295 9 : for (size_t nCol = 0; nCol < nCols; ++nCol)
296 5 : rTab.push_back(new CellValues);
297 : }
298 4 : }
299 :
300 17 : CellValues* getCellValues( SCTAB nTab, SCCOL nCol )
301 : {
302 17 : if (nTab < maRange.aStart.Tab() || maRange.aEnd.Tab() < nTab)
303 : // sheet index out of bound.
304 0 : return NULL;
305 :
306 17 : if (nCol < maRange.aStart.Col() || maRange.aEnd.Col() < nCol)
307 : // column index out of bound.
308 0 : return NULL;
309 :
310 17 : size_t nTabOffset = nTab - maRange.aStart.Tab();
311 17 : if (nTabOffset >= maTables.size())
312 0 : return NULL;
313 :
314 17 : TableType& rTab = maTables[nTab-maRange.aStart.Tab()];
315 :
316 17 : size_t nColOffset = nCol - maRange.aStart.Col();
317 17 : if (nColOffset >= rTab.size())
318 0 : return NULL;
319 :
320 17 : return &rTab[nColOffset];
321 : }
322 : };
323 :
324 2 : TableValues::TableValues() :
325 2 : mpImpl(new Impl(ScRange(ScAddress::INITIALIZE_INVALID))) {}
326 :
327 2 : TableValues::TableValues( const ScRange& rRange ) :
328 2 : mpImpl(new Impl(rRange)) {}
329 :
330 4 : TableValues::~TableValues()
331 : {
332 4 : delete mpImpl;
333 4 : }
334 :
335 27 : const ScRange& TableValues::getRange() const
336 : {
337 27 : return mpImpl->maRange;
338 : }
339 :
340 3 : void TableValues::swap( SCTAB nTab, SCCOL nCol, CellValues& rColValue )
341 : {
342 3 : CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
343 3 : if (!pCol)
344 3 : return;
345 :
346 3 : pCol->swap(rColValue);
347 : }
348 :
349 7 : void TableValues::swapNonEmpty( SCTAB nTab, SCCOL nCol, ScColumn& rCol )
350 : {
351 7 : CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
352 7 : if (!pCol)
353 7 : return;
354 :
355 7 : pCol->swapNonEmpty(rCol);
356 : }
357 :
358 7 : std::vector<CellValueSpan> TableValues::getNonEmptySpans( SCTAB nTab, SCCOL nCol ) const
359 : {
360 7 : std::vector<CellValueSpan> aRet;
361 7 : CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
362 7 : if (pCol)
363 7 : aRet = pCol->getNonEmptySpans();
364 :
365 7 : return aRet;
366 : }
367 :
368 2 : void TableValues::swap( TableValues& rOther )
369 : {
370 2 : std::swap(mpImpl, rOther.mpImpl);
371 2 : }
372 :
373 156 : }
374 :
375 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|