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