Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / sc / source / core / data / cellvalues.cxx
blobd23d7a9eccca8b64a9dbb9de12c6c3208e599680
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <memory>
11 #include <cellvalues.hxx>
12 #include <column.hxx>
13 #include <formulacell.hxx>
14 #include <editeng/editobj.hxx>
16 #include <cassert>
18 namespace sc {
20 namespace {
22 struct BlockPos
24 size_t mnStart;
25 size_t mnEnd;
30 CellValueSpan::CellValueSpan( SCROW nRow1, SCROW nRow2 ) :
31 mnRow1(nRow1), mnRow2(nRow2) {}
33 struct CellValuesImpl
35 CellStoreType maCells;
36 CellTextAttrStoreType maCellTextAttrs;
37 CellStoreType::iterator miCellPos;
38 CellTextAttrStoreType::iterator miAttrPos;
40 CellValuesImpl() = default;
42 CellValuesImpl(const CellValuesImpl&) = delete;
43 const CellValuesImpl& operator=(const CellValuesImpl&) = delete;
46 CellValues::CellValues() :
47 mpImpl(new CellValuesImpl) {}
49 CellValues::~CellValues()
53 void CellValues::transferFrom( ScColumn& rCol, SCROW nRow, size_t nLen )
55 mpImpl->maCells.resize(nLen);
56 mpImpl->maCellTextAttrs.resize(nLen);
57 rCol.maCells.transfer(nRow, nRow+nLen-1, mpImpl->maCells, 0);
58 rCol.maCellTextAttrs.transfer(nRow, nRow+nLen-1, mpImpl->maCellTextAttrs, 0);
62 void CellValues::copyTo( ScColumn& rCol, SCROW nRow ) const
64 copyCellsTo(rCol, nRow);
65 copyCellTextAttrsTo(rCol, nRow);
68 void CellValues::swapNonEmpty( ScColumn& rCol )
70 std::vector<BlockPos> aBlocksToSwap;
72 // Go through static value blocks and record their positions and sizes.
73 for (const auto& rCell : mpImpl->maCells)
75 if (rCell.type == sc::element_type_empty)
76 continue;
78 BlockPos aPos;
79 aPos.mnStart = rCell.position;
80 aPos.mnEnd = aPos.mnStart + rCell.size - 1;
81 aBlocksToSwap.push_back(aPos);
84 // Do the swapping. The undo storage will store the replaced formula cells after this.
85 for (const auto& rBlock : aBlocksToSwap)
87 rCol.maCells.swap(rBlock.mnStart, rBlock.mnEnd, mpImpl->maCells, rBlock.mnStart);
88 rCol.maCellTextAttrs.swap(rBlock.mnStart, rBlock.mnEnd, mpImpl->maCellTextAttrs, rBlock.mnStart);
92 void CellValues::assign( const std::vector<double>& rVals )
94 mpImpl->maCells.resize(rVals.size());
95 mpImpl->maCells.set(0, rVals.begin(), rVals.end());
97 // Set default text attributes.
98 std::vector<CellTextAttr> aDefaults(rVals.size(), CellTextAttr());
99 mpImpl->maCellTextAttrs.resize(rVals.size());
100 mpImpl->maCellTextAttrs.set(0, aDefaults.begin(), aDefaults.end());
103 void CellValues::assign( const std::vector<ScFormulaCell*>& rVals )
105 std::vector<ScFormulaCell*> aCopyVals(rVals.size());
106 size_t nIdx = 0;
107 for (const auto* pCell : rVals)
109 aCopyVals[nIdx] = pCell->Clone();
110 ++nIdx;
113 mpImpl->maCells.resize(aCopyVals.size());
114 mpImpl->maCells.set(0, aCopyVals.begin(), aCopyVals.end());
116 // Set default text attributes.
117 std::vector<CellTextAttr> aDefaults(rVals.size(), CellTextAttr());
118 mpImpl->maCellTextAttrs.resize(rVals.size());
119 mpImpl->maCellTextAttrs.set(0, aDefaults.begin(), aDefaults.end());
122 size_t CellValues::size() const
124 assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
125 return mpImpl->maCells.size();
128 void CellValues::reset( size_t nSize )
130 mpImpl->maCells.clear();
131 mpImpl->maCells.resize(nSize);
132 mpImpl->maCellTextAttrs.clear();
133 mpImpl->maCellTextAttrs.resize(nSize);
135 mpImpl->miCellPos = mpImpl->maCells.begin();
136 mpImpl->miAttrPos = mpImpl->maCellTextAttrs.begin();
139 void CellValues::setValue( size_t nRow, double fVal )
141 mpImpl->miCellPos = mpImpl->maCells.set(mpImpl->miCellPos, nRow, fVal);
142 mpImpl->miAttrPos = mpImpl->maCellTextAttrs.set(mpImpl->miAttrPos, nRow, sc::CellTextAttr());
145 void CellValues::setValue( size_t nRow, const svl::SharedString& rStr )
147 mpImpl->miCellPos = mpImpl->maCells.set(mpImpl->miCellPos, nRow, rStr);
148 mpImpl->miAttrPos = mpImpl->maCellTextAttrs.set(mpImpl->miAttrPos, nRow, sc::CellTextAttr());
151 void CellValues::setValue( size_t nRow, std::unique_ptr<EditTextObject> pEditText )
153 mpImpl->miCellPos = mpImpl->maCells.set(mpImpl->miCellPos, nRow, pEditText.release());
154 mpImpl->miAttrPos = mpImpl->maCellTextAttrs.set(mpImpl->miAttrPos, nRow, sc::CellTextAttr());
157 void CellValues::swap( CellValues& r )
159 std::swap(mpImpl, r.mpImpl);
162 std::vector<CellValueSpan> CellValues::getNonEmptySpans() const
164 std::vector<CellValueSpan> aRet;
165 for (const auto& rCell : mpImpl->maCells)
167 if (rCell.type != element_type_empty)
169 // Record this span.
170 size_t nRow1 = rCell.position;
171 size_t nRow2 = nRow1 + rCell.size - 1;
172 aRet.emplace_back(nRow1, nRow2);
175 return aRet;
178 void CellValues::copyCellsTo( ScColumn& rCol, SCROW nRow ) const
180 CellStoreType& rDest = rCol.maCells;
181 const CellStoreType& rSrc = mpImpl->maCells;
183 // Caller must ensure the destination is long enough.
184 assert(rSrc.size() + static_cast<size_t>(nRow) <= rDest.size());
186 SCROW nCurRow = nRow;
187 CellStoreType::iterator itPos = rDest.begin();
189 for (const auto& rBlk : rSrc)
191 switch (rBlk.type)
193 case element_type_numeric:
195 numeric_block::const_iterator it = numeric_block::begin(*rBlk.data);
196 numeric_block::const_iterator itEnd = numeric_block::end(*rBlk.data);
197 itPos = rDest.set(itPos, nCurRow, it, itEnd);
199 break;
200 case element_type_string:
202 string_block::const_iterator it = string_block::begin(*rBlk.data);
203 string_block::const_iterator itEnd = string_block::end(*rBlk.data);
204 itPos = rDest.set(itPos, nCurRow, it, itEnd);
206 break;
207 case element_type_edittext:
209 edittext_block::const_iterator it = edittext_block::begin(*rBlk.data);
210 edittext_block::const_iterator itEnd = edittext_block::end(*rBlk.data);
211 std::vector<EditTextObject*> aVals;
212 aVals.reserve(rBlk.size);
213 for (; it != itEnd; ++it)
215 const EditTextObject* p = *it;
216 aVals.push_back(p->Clone().release());
218 itPos = rDest.set(itPos, nCurRow, aVals.begin(), aVals.end());
220 break;
221 case element_type_formula:
223 formula_block::const_iterator it = formula_block::begin(*rBlk.data);
224 formula_block::const_iterator itEnd = formula_block::end(*rBlk.data);
225 std::vector<ScFormulaCell*> aVals;
226 aVals.reserve(rBlk.size);
227 for (; it != itEnd; ++it)
229 const ScFormulaCell* p = *it;
230 aVals.push_back(p->Clone());
232 itPos = rDest.set(itPos, nCurRow, aVals.begin(), aVals.end());
234 break;
235 default:
236 itPos = rDest.set_empty(itPos, nCurRow, nCurRow+rBlk.size-1);
239 nCurRow += rBlk.size;
243 void CellValues::copyCellTextAttrsTo( ScColumn& rCol, SCROW nRow ) const
245 CellTextAttrStoreType& rDest = rCol.maCellTextAttrs;
246 const CellTextAttrStoreType& rSrc = mpImpl->maCellTextAttrs;
248 // Caller must ensure the destination is long enough.
249 assert(rSrc.size() + static_cast<size_t>(nRow) <= rDest.size());
251 SCROW nCurRow = nRow;
252 CellTextAttrStoreType::iterator itPos = rDest.begin();
254 for (const auto& rBlk : rSrc)
256 switch (rBlk.type)
258 case element_type_celltextattr:
260 celltextattr_block::const_iterator it = celltextattr_block::begin(*rBlk.data);
261 celltextattr_block::const_iterator itEnd = celltextattr_block::end(*rBlk.data);
262 itPos = rDest.set(itPos, nCurRow, it, itEnd);
264 break;
265 default:
266 itPos = rDest.set_empty(itPos, nCurRow, nCurRow+rBlk.size-1);
269 nCurRow += rBlk.size;
273 typedef std::vector<std::unique_ptr<CellValues>> TableType;
274 typedef std::vector<std::unique_ptr<TableType>> TablesType;
276 struct TableValues::Impl
278 ScRange maRange;
279 TablesType m_Tables;
281 explicit Impl( const ScRange& rRange ) : maRange(rRange)
283 size_t nTabs = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
284 size_t nCols = rRange.aEnd.Col() - rRange.aStart.Col() + 1;
286 for (size_t nTab = 0; nTab < nTabs; ++nTab)
288 m_Tables.push_back(std::make_unique<TableType>());
289 std::unique_ptr<TableType>& rTab2 = m_Tables.back();
290 for (size_t nCol = 0; nCol < nCols; ++nCol)
291 rTab2->push_back(std::make_unique<CellValues>());
295 CellValues* getCellValues( SCTAB nTab, SCCOL nCol )
297 if (nTab < maRange.aStart.Tab() || maRange.aEnd.Tab() < nTab)
298 // sheet index out of bound.
299 return nullptr;
300 if (nCol < maRange.aStart.Col() || maRange.aEnd.Col() < nCol)
301 // column index out of bound.
302 return nullptr;
303 size_t nTabOffset = nTab - maRange.aStart.Tab();
304 if (nTabOffset >= m_Tables.size())
305 return nullptr;
306 std::unique_ptr<TableType>& rTab2 = m_Tables[nTab-maRange.aStart.Tab()];
307 size_t nColOffset = nCol - maRange.aStart.Col();
308 if (nColOffset >= rTab2->size())
309 return nullptr;
310 return &rTab2.get()[0][nColOffset].get()[0];
314 TableValues::TableValues() :
315 mpImpl(new Impl(ScRange(ScAddress::INITIALIZE_INVALID))) {}
317 TableValues::TableValues( const ScRange& rRange ) :
318 mpImpl(new Impl(rRange)) {}
320 TableValues::~TableValues()
324 const ScRange& TableValues::getRange() const
326 return mpImpl->maRange;
329 void TableValues::swap( SCTAB nTab, SCCOL nCol, CellValues& rColValue )
331 CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
332 if (!pCol)
333 return;
335 pCol->swap(rColValue);
338 void TableValues::swapNonEmpty( SCTAB nTab, SCCOL nCol, ScColumn& rCol )
340 CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
341 if (!pCol)
342 return;
344 pCol->swapNonEmpty(rCol);
347 std::vector<CellValueSpan> TableValues::getNonEmptySpans( SCTAB nTab, SCCOL nCol ) const
349 std::vector<CellValueSpan> aRet;
350 CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
351 if (pCol)
352 aRet = pCol->getNonEmptySpans();
354 return aRet;
357 void TableValues::swap( TableValues& rOther )
359 std::swap(mpImpl, rOther.mpImpl);
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */