1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
11 #include <cellvalues.hxx>
13 #include <formulacell.hxx>
14 #include <editeng/editobj.hxx>
30 CellValueSpan::CellValueSpan( SCROW nRow1
, SCROW nRow2
) :
31 mnRow1(nRow1
), mnRow2(nRow2
) {}
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
)
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());
107 for (const auto* pCell
: rVals
)
109 aCopyVals
[nIdx
] = pCell
->Clone();
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
)
170 size_t nRow1
= rCell
.position
;
171 size_t nRow2
= nRow1
+ rCell
.size
- 1;
172 aRet
.emplace_back(nRow1
, nRow2
);
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
)
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
);
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
);
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());
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());
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
)
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
);
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
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.
300 if (nCol
< maRange
.aStart
.Col() || maRange
.aEnd
.Col() < nCol
)
301 // column index out of bound.
303 size_t nTabOffset
= nTab
- maRange
.aStart
.Tab();
304 if (nTabOffset
>= m_Tables
.size())
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())
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
);
335 pCol
->swap(rColValue
);
338 void TableValues::swapNonEmpty( SCTAB nTab
, SCCOL nCol
, ScColumn
& rCol
)
340 CellValues
* pCol
= mpImpl
->getCellValues(nTab
, nCol
);
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
);
352 aRet
= pCol
->getNonEmptySpans();
357 void TableValues::swap( TableValues
& rOther
)
359 std::swap(mpImpl
, rOther
.mpImpl
);
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */