/* -*- 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 #include #include #include #include ScColumnTextWidthIterator::ScColumnTextWidthIterator(const ScDocument& rDoc, ScColumn& rCol, SCROW nStartRow, SCROW nEndRow) : mnEnd(static_cast(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(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(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(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: */