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/.
10 #include <cellvalues.hxx>
12 #include <cellvalue.hxx>
15 #include <boost/noncopyable.hpp>
16 #include <boost/ptr_container/ptr_vector.hpp>
28 CellType
toCellType( mdds::mtv::element_t eType
)
32 case element_type_numeric
:
33 return CELLTYPE_VALUE
;
34 case element_type_string
:
35 return CELLTYPE_STRING
;
36 case element_type_edittext
:
38 case element_type_formula
:
39 return CELLTYPE_FORMULA
;
49 CellValueSpan::CellValueSpan( SCROW nRow1
, SCROW nRow2
, CellType eType
) :
50 mnRow1(nRow1
), mnRow2(nRow2
), meType(eType
) {}
52 struct CellValuesImpl
: boost::noncopyable
54 CellStoreType maCells
;
55 CellTextAttrStoreType maCellTextAttrs
;
56 CellStoreType::iterator miCellPos
;
57 CellTextAttrStoreType::iterator miAttrPos
;
60 CellValues::CellValues() :
61 mpImpl(new CellValuesImpl
) {}
63 CellValues::~CellValues()
68 void CellValues::transferFrom( ScColumn
& rCol
, SCROW nRow
, size_t nLen
)
70 mpImpl
->maCells
.resize(nLen
);
71 mpImpl
->maCellTextAttrs
.resize(nLen
);
72 rCol
.maCells
.transfer(nRow
, nRow
+nLen
-1, mpImpl
->maCells
, 0);
73 rCol
.maCellTextAttrs
.transfer(nRow
, nRow
+nLen
-1, mpImpl
->maCellTextAttrs
, 0);
76 void CellValues::transferTo( ScColumn
& rCol
, SCROW nRow
)
78 assert(mpImpl
->maCells
.size() == mpImpl
->maCellTextAttrs
.size());
80 size_t nLen
= mpImpl
->maCells
.size();
81 mpImpl
->maCells
.transfer(0, nLen
-1, rCol
.maCells
, nRow
);
82 mpImpl
->maCellTextAttrs
.transfer(0, nLen
-1, rCol
.maCellTextAttrs
, nRow
);
85 void CellValues::copyTo( ScColumn
& rCol
, SCROW nRow
) const
87 copyCellsTo(rCol
, nRow
);
88 copyCellTextAttrsTo(rCol
, nRow
);
91 void CellValues::swapNonEmpty( ScColumn
& rCol
)
93 std::vector
<BlockPos
> aBlocksToSwap
;
96 // Go through static value blocks and record their positions and sizes.
97 sc::CellStoreType::const_iterator it
= mpImpl
->maCells
.begin(), itEnd
= mpImpl
->maCells
.end();
98 for (; it
!= itEnd
; ++it
)
100 if (it
->type
== sc::element_type_empty
)
104 aPos
.mnStart
= it
->position
;
105 aPos
.mnEnd
= aPos
.mnStart
+ it
->size
- 1;
106 aBlocksToSwap
.push_back(aPos
);
110 // Do the swapping. The undo storage will store the replaced formula cells after this.
111 std::vector
<BlockPos
>::const_iterator it
= aBlocksToSwap
.begin(), itEnd
= aBlocksToSwap
.end();
112 for (; it
!= itEnd
; ++it
)
114 rCol
.maCells
.swap(it
->mnStart
, it
->mnEnd
, mpImpl
->maCells
, it
->mnStart
);
115 rCol
.maCellTextAttrs
.swap(it
->mnStart
, it
->mnEnd
, mpImpl
->maCellTextAttrs
, it
->mnStart
);
119 void CellValues::assign( const std::vector
<double>& rVals
)
121 mpImpl
->maCells
.resize(rVals
.size());
122 mpImpl
->maCells
.set(0, rVals
.begin(), rVals
.end());
124 // Set default text attributes.
125 std::vector
<CellTextAttr
> aDefaults(rVals
.size(), CellTextAttr());
126 mpImpl
->maCellTextAttrs
.resize(rVals
.size());
127 mpImpl
->maCellTextAttrs
.set(0, aDefaults
.begin(), aDefaults
.end());
130 size_t CellValues::size() const
132 assert(mpImpl
->maCells
.size() == mpImpl
->maCellTextAttrs
.size());
133 return mpImpl
->maCells
.size();
136 void CellValues::reset( size_t nSize
)
138 mpImpl
->maCells
.clear();
139 mpImpl
->maCells
.resize(nSize
);
140 mpImpl
->maCellTextAttrs
.clear();
141 mpImpl
->maCellTextAttrs
.resize(nSize
);
143 mpImpl
->miCellPos
= mpImpl
->maCells
.begin();
144 mpImpl
->miAttrPos
= mpImpl
->maCellTextAttrs
.begin();
147 void CellValues::setValue( size_t nRow
, double fVal
)
149 mpImpl
->miCellPos
= mpImpl
->maCells
.set(mpImpl
->miCellPos
, nRow
, fVal
);
150 mpImpl
->miAttrPos
= mpImpl
->maCellTextAttrs
.set(mpImpl
->miAttrPos
, nRow
, sc::CellTextAttr());
153 void CellValues::setValue( size_t nRow
, const svl::SharedString
& rStr
)
155 mpImpl
->miCellPos
= mpImpl
->maCells
.set(mpImpl
->miCellPos
, nRow
, rStr
);
156 mpImpl
->miAttrPos
= mpImpl
->maCellTextAttrs
.set(mpImpl
->miAttrPos
, nRow
, sc::CellTextAttr());
159 void CellValues::swap( CellValues
& r
)
161 std::swap(mpImpl
, r
.mpImpl
);
164 std::vector
<CellValueSpan
> CellValues::getNonEmptySpans() const
166 std::vector
<CellValueSpan
> aRet
;
167 CellStoreType::const_iterator it
= mpImpl
->maCells
.begin(), itEnd
= mpImpl
->maCells
.end();
168 for (; it
!= itEnd
; ++it
)
170 if (it
->type
!= element_type_empty
)
173 size_t nRow1
= it
->position
;
174 size_t nRow2
= nRow1
+ it
->size
- 1;
175 aRet
.push_back(CellValueSpan(nRow1
, nRow2
, toCellType(it
->type
)));
181 void CellValues::copyCellsTo( ScColumn
& rCol
, SCROW nRow
) const
183 CellStoreType
& rDest
= rCol
.maCells
;
184 const CellStoreType
& rSrc
= mpImpl
->maCells
;
186 // Caller must ensure the destination is long enough.
187 assert(rSrc
.size() + static_cast<size_t>(nRow
) < rDest
.size());
189 SCROW nCurRow
= nRow
;
190 CellStoreType::iterator itPos
= rDest
.begin();
192 CellStoreType::const_iterator itBlk
= rSrc
.begin(), itBlkEnd
= rSrc
.end();
193 for (; itBlk
!= itBlkEnd
; ++itBlk
)
197 case element_type_numeric
:
199 numeric_block::const_iterator it
= numeric_block::begin(*itBlk
->data
);
200 numeric_block::const_iterator itEnd
= numeric_block::end(*itBlk
->data
);
201 itPos
= rDest
.set(itPos
, nCurRow
, it
, itEnd
);
204 case element_type_string
:
206 string_block::const_iterator it
= string_block::begin(*itBlk
->data
);
207 string_block::const_iterator itEnd
= string_block::end(*itBlk
->data
);
208 itPos
= rDest
.set(itPos
, nCurRow
, it
, itEnd
);
211 case element_type_edittext
:
213 edittext_block::const_iterator it
= edittext_block::begin(*itBlk
->data
);
214 edittext_block::const_iterator itEnd
= edittext_block::end(*itBlk
->data
);
215 std::vector
<EditTextObject
*> aVals
;
216 aVals
.reserve(itBlk
->size
);
217 for (; it
!= itEnd
; ++it
)
219 const EditTextObject
* p
= *it
;
220 aVals
.push_back(p
->Clone());
222 itPos
= rDest
.set(itPos
, nCurRow
, aVals
.begin(), aVals
.end());
225 case element_type_formula
:
227 formula_block::const_iterator it
= formula_block::begin(*itBlk
->data
);
228 formula_block::const_iterator itEnd
= formula_block::end(*itBlk
->data
);
229 std::vector
<ScFormulaCell
*> aVals
;
230 aVals
.reserve(itBlk
->size
);
231 for (; it
!= itEnd
; ++it
)
233 const ScFormulaCell
* p
= *it
;
234 aVals
.push_back(p
->Clone());
236 itPos
= rDest
.set(itPos
, nCurRow
, aVals
.begin(), aVals
.end());
240 itPos
= rDest
.set_empty(itPos
, nCurRow
, nCurRow
+itBlk
->size
-1);
243 nCurRow
+= itBlk
->size
;
247 void CellValues::copyCellTextAttrsTo( ScColumn
& rCol
, SCROW nRow
) const
249 CellTextAttrStoreType
& rDest
= rCol
.maCellTextAttrs
;
250 const CellTextAttrStoreType
& rSrc
= mpImpl
->maCellTextAttrs
;
252 // Caller must ensure the destination is long enough.
253 assert(rSrc
.size() + static_cast<size_t>(nRow
) < rDest
.size());
255 SCROW nCurRow
= nRow
;
256 CellTextAttrStoreType::iterator itPos
= rDest
.begin();
258 CellTextAttrStoreType::const_iterator itBlk
= rSrc
.begin(), itBlkEnd
= rSrc
.end();
259 for (; itBlk
!= itBlkEnd
; ++itBlk
)
263 case element_type_celltextattr
:
265 celltextattr_block::const_iterator it
= celltextattr_block::begin(*itBlk
->data
);
266 celltextattr_block::const_iterator itEnd
= celltextattr_block::end(*itBlk
->data
);
267 itPos
= rDest
.set(itPos
, nCurRow
, it
, itEnd
);
271 itPos
= rDest
.set_empty(itPos
, nCurRow
, nCurRow
+itBlk
->size
-1);
274 nCurRow
+= itBlk
->size
;
278 typedef boost::ptr_vector
<CellValues
> TableType
;
279 typedef boost::ptr_vector
<TableType
> TablesType
;
281 struct TableValues::Impl
286 Impl( const ScRange
& rRange
) : maRange(rRange
)
288 size_t nTabs
= rRange
.aEnd
.Tab() - rRange
.aStart
.Tab() + 1;
289 size_t nCols
= rRange
.aEnd
.Col() - rRange
.aStart
.Col() + 1;
291 for (size_t nTab
= 0; nTab
< nTabs
; ++nTab
)
293 maTables
.push_back(new TableType
);
294 TableType
& rTab
= maTables
.back();
295 for (size_t nCol
= 0; nCol
< nCols
; ++nCol
)
296 rTab
.push_back(new CellValues
);
300 CellValues
* getCellValues( SCTAB nTab
, SCCOL nCol
)
302 if (nTab
< maRange
.aStart
.Tab() || maRange
.aEnd
.Tab() < nTab
)
303 // sheet index out of bound.
306 if (nCol
< maRange
.aStart
.Col() || maRange
.aEnd
.Col() < nCol
)
307 // column index out of bound.
310 size_t nTabOffset
= nTab
- maRange
.aStart
.Tab();
311 if (nTabOffset
>= maTables
.size())
314 TableType
& rTab
= maTables
[nTab
-maRange
.aStart
.Tab()];
316 size_t nColOffset
= nCol
- maRange
.aStart
.Col();
317 if (nColOffset
>= rTab
.size())
320 return &rTab
[nColOffset
];
324 TableValues::TableValues() :
325 mpImpl(new Impl(ScRange(ScAddress::INITIALIZE_INVALID
))) {}
327 TableValues::TableValues( const ScRange
& rRange
) :
328 mpImpl(new Impl(rRange
)) {}
330 TableValues::~TableValues()
335 const ScRange
& TableValues::getRange() const
337 return mpImpl
->maRange
;
340 void TableValues::swap( SCTAB nTab
, SCCOL nCol
, CellValues
& rColValue
)
342 CellValues
* pCol
= mpImpl
->getCellValues(nTab
, nCol
);
346 pCol
->swap(rColValue
);
349 void TableValues::swapNonEmpty( SCTAB nTab
, SCCOL nCol
, ScColumn
& rCol
)
351 CellValues
* pCol
= mpImpl
->getCellValues(nTab
, nCol
);
355 pCol
->swapNonEmpty(rCol
);
358 std::vector
<CellValueSpan
> TableValues::getNonEmptySpans( SCTAB nTab
, SCCOL nCol
) const
360 std::vector
<CellValueSpan
> aRet
;
361 CellValues
* pCol
= mpImpl
->getCellValues(nTab
, nCol
);
363 aRet
= pCol
->getNonEmptySpans();
368 void TableValues::swap( TableValues
& rOther
)
370 std::swap(mpImpl
, rOther
.mpImpl
);
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */