diff options
Diffstat (limited to 'sc/source/core/data/columniterator.cxx')
-rw-r--r-- | sc/source/core/data/columniterator.cxx | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/sc/source/core/data/columniterator.cxx b/sc/source/core/data/columniterator.cxx new file mode 100644 index 000000000..cec8f7a20 --- /dev/null +++ b/sc/source/core/data/columniterator.cxx @@ -0,0 +1,209 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <columniterator.hxx> +#include <column.hxx> +#include <document.hxx> +#include <table.hxx> + +#include <osl/diagnose.h> + +ScColumnTextWidthIterator::ScColumnTextWidthIterator(const ScDocument& rDoc, ScColumn& rCol, SCROW nStartRow, SCROW nEndRow) : + mnEnd(static_cast<size_t>(nEndRow)), + mnCurPos(0) +{ + miBlockCur = rCol.maCellTextAttrs.begin(); + miBlockEnd = rCol.maCellTextAttrs.end(); + init(rDoc, nStartRow, nEndRow); +} + +ScColumnTextWidthIterator::ScColumnTextWidthIterator(const ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow) : + mnEnd(static_cast<size_t>(nEndRow)), + mnCurPos(0) +{ + auto & rCellTextAttrs = rDoc.maTabs[rStartPos.Tab()]->aCol[rStartPos.Col()].maCellTextAttrs; + miBlockCur = rCellTextAttrs.begin(); + miBlockEnd = rCellTextAttrs.end(); + init(rDoc, rStartPos.Row(), nEndRow); +} + +void ScColumnTextWidthIterator::next() +{ + ++miDataCur; + ++mnCurPos; + + if (miDataCur != miDataEnd) + { + // Still in the same block. We're good. + checkEndRow(); + return; + } + + // Move to the next block. + for (++miBlockCur; miBlockCur != miBlockEnd; ++miBlockCur) + { + if (miBlockCur->type != sc::element_type_celltextattr) + { + // We don't iterator over this block. + mnCurPos += miBlockCur->size; + continue; + } + + getDataIterators(0); + checkEndRow(); + return; + } + + // Reached the end. + assert(miBlockCur == miBlockEnd); +} + +bool ScColumnTextWidthIterator::hasCell() const +{ + return miBlockCur != miBlockEnd; +} + +SCROW ScColumnTextWidthIterator::getPos() const +{ + assert(miBlockCur != miBlockEnd && miDataCur != miDataEnd); + return static_cast<SCROW>(mnCurPos); +} + +sal_uInt16 ScColumnTextWidthIterator::getValue() const +{ + assert(miBlockCur != miBlockEnd && miDataCur != miDataEnd); + return miDataCur->mnTextWidth; +} + +void ScColumnTextWidthIterator::setValue(sal_uInt16 nVal) +{ + assert(miBlockCur != miBlockEnd && miDataCur != miDataEnd); + miDataCur->mnTextWidth = nVal; +} + +void ScColumnTextWidthIterator::init(const ScDocument& rDoc, SCROW nStartRow, SCROW nEndRow) +{ + if (!rDoc.ValidRow(nStartRow) || !rDoc.ValidRow(nEndRow)) + miBlockCur = miBlockEnd; + + size_t nStart = static_cast<size_t>(nStartRow); + + // Locate the start row position. + size_t nBlockStart = 0, nBlockEnd = 0; + for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd) + { + nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point. + if (nBlockStart <= nStart && nStart < nBlockEnd) + { + // Initial block is found! + break; + } + } + + if (miBlockCur == miBlockEnd) + // Initial block not found for whatever reason... Bail out. + return; + + // Locate the initial row position within this block. + if (miBlockCur->type == sc::element_type_celltextattr) + { + // This block stores text widths for non-empty cells. + size_t nOffsetInBlock = nStart - nBlockStart; + mnCurPos = nStart; + getDataIterators(nOffsetInBlock); + checkEndRow(); + return; + } + + // Current block is not of ushort type. Skip to the next block. + nBlockStart = nBlockEnd; + ++miBlockCur; + + // Look for the first ushort block. + for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd) + { + nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point. + if (miBlockCur->type != sc::element_type_celltextattr) + continue; + + // Found! + mnCurPos = nBlockStart; + getDataIterators(0); + checkEndRow(); + return; + } + + // Not found. + assert(miBlockCur == miBlockEnd); +} + +void ScColumnTextWidthIterator::getDataIterators(size_t nOffsetInBlock) +{ + OSL_ENSURE(miBlockCur != miBlockEnd, "block is at end position"); +#if 0 + // Does not compile + OSL_ENSURE(miBlockCur->type == sc::celltextattr_block, + "wrong block type - unsigned short block expected."); +#endif + miDataCur = sc::celltextattr_block::begin(*miBlockCur->data); + miDataEnd = sc::celltextattr_block::end(*miBlockCur->data); + + std::advance(miDataCur, nOffsetInBlock); +} + +void ScColumnTextWidthIterator::checkEndRow() +{ + if (mnCurPos <= mnEnd) + // We're still good. + return; + + // We're below the end position. End the iteration. + miBlockCur = miBlockEnd; +} + +namespace sc { + +ColumnIterator::ColumnIterator( const CellStoreType& rCells, SCROW nRow1, SCROW nRow2 ) : + maPos(rCells.position(nRow1)), + maPosEnd(rCells.position(maPos.first, nRow2)), + mbComplete(false) +{ +} + +void ColumnIterator::next() +{ + if ( maPos == maPosEnd) + mbComplete = true; + else + maPos = CellStoreType::next_position(maPos); +} + +SCROW ColumnIterator::getRow() const +{ + return CellStoreType::logical_position(maPos); +} + +bool ColumnIterator::hasCell() const +{ + return !mbComplete; +} + +mdds::mtv::element_t ColumnIterator::getType() const +{ + return maPos.first->type; +} + +ScRefCellValue ColumnIterator::getCell() const +{ + return toRefCell(maPos.first, maPos.second); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |