Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sc/source/core/data/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 11 kB image not shown  

Quelle  columnspanset.cxx   Sprache: C

 
/* -*- 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 <columnspanset.hxx>
#include <column.hxx>
#include <table.hxx>
#include <document.hxx>
#include <mtvfunctions.hxx>
#include <markdata.hxx>
#include <rangelst.hxx>
#include <fstalgorithm.hxx>

#include <algorithm>

#include <o3tl/safeint.hxx>

namespace sc {

namespace {

class ColumnNonEmptyRangesScanner
{
    ColumnSpanSet::ColumnSpansType& mrRanges;
    bool mbVal;
public:
    ColumnNonEmptyRangesScanner(ColumnSpanSet::ColumnSpansType& rRanges, bool bVal) :
        mrRanges(rRanges), mbVal(bVal) {}

    void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
    {
        if (node.type == sc::element_type_empty)
            return;

        size_t nRow = node.position + nOffset;
        size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
        mrRanges.insert_back(nRow, nEndRow, mbVal);
    }
};

}

RowSpan::RowSpan(SCROW nRow1, SCROW nRow2) : mnRow1(nRow1), mnRow2(nRow2) {}

ColRowSpan::ColRowSpan(SCCOLROW nStart, SCCOLROW nEnd) : mnStart(nStart), mnEnd(nEnd) {}

ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) :
    maSpans(nStart, nEnd+1, bInit), miPos(maSpans.begin()) {}

ColumnSpanSet::ColumnType::ColumnType(const ColumnType& rOther) :
    maSpans(rOther.maSpans), miPos(maSpans.begin()) {} // NB: copying maSpans invalidates miPos - reset it

ColumnSpanSet::Action::~Action() {}
void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}

ColumnSpanSet::ColumnAction::~ColumnAction() {}

ColumnSpanSet::ColumnSpanSet() {}

ColumnSpanSet::~ColumnSpanSet()
{
}

ColumnSpanSet::ColumnType& ColumnSpanSet::getColumn(const ScDocument& rDoc, SCTAB nTab, SCCOL nCol)
{
    if (o3tl::make_unsigned(nTab) >= maTables.size())
        maTables.resize(nTab+1);

    TableType& rTab = maTables[nTab];
    if (o3tl::make_unsigned(nCol) >= rTab.size())
        rTab.resize(nCol+1);

    if (!rTab[nCol])
        rTab[nCol].emplace(0, rDoc.MaxRow(), /*bInit*/false);

    return *rTab[nCol];
}

void ColumnSpanSet::set(const ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
{
    if (!ValidTab(nTab) || !rDoc.ValidCol(nCol) || !rDoc.ValidRow(nRow))
        return;

    ColumnType& rCol = getColumn(rDoc, nTab, nCol);
    rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow, nRow+1, bVal).first;
}

void ColumnSpanSet::set(const ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
{
    if (!ValidTab(nTab) || !rDoc.ValidCol(nCol) || !rDoc.ValidRow(nRow1) || !rDoc.ValidRow(nRow2))
        return;

    ColumnType& rCol = getColumn(rDoc, nTab, nCol);
    rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow1, nRow2+1, bVal).first;
}

void ColumnSpanSet::set(const ScDocument& rDoc, const ScRange& rRange, bool bVal)
{
    for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
    {
        for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
        {
            ColumnType& rCol = getColumn(rDoc, nTab, nCol);
            rCol.miPos = rCol.maSpans.insert(rCol.miPos, rRange.aStart.Row(), rRange.aEnd.Row()+1, bVal).first;
        }
    }
}

void ColumnSpanSet::set( const ScDocument& rDoc, SCTAB nTab, SCCOL nCol, const SingleColumnSpanSet& rSingleSet, bool bVal )
{
    SingleColumnSpanSet::SpansType aSpans;
    rSingleSet.getSpans(aSpans);
    for (const auto& rSpan : aSpans)
        set(rDoc, nTab, nCol, rSpan.mnRow1, rSpan.mnRow2, bVal);
}

void ColumnSpanSet::scan(
    const ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal)
{
    if (!rDoc.ValidColRow(nCol1, nRow1) || !rDoc.ValidColRow(nCol2, nRow2))
        return;

    if (nCol1 > nCol2 || nRow1 > nRow2)
        return;

    const ScTable* pTab = rDoc.FetchTable(nTab);
    if (!pTab)
        return;

    nCol2 = pTab->ClampToAllocatedColumns(nCol2);
    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
    {
        ColumnType& rCol = getColumn(rDoc, nTab, nCol);

        const CellStoreType& rSrcCells = pTab->aCol[nCol].maCells;

        if( nRow1 > pTab->aCol[nCol].GetLastDataPos())
            continue;

        ColumnNonEmptyRangesScanner aScanner(rCol.maSpans, bVal);
        ParseBlock(rSrcCells.begin(), rSrcCells, aScanner, nRow1, nRow2);
        rCol.miPos = rCol.maSpans.begin();
    }
}

void ColumnSpanSet::executeAction(ScDocument& rDoc, Action& ac) const
{
    for (size_t nTab = 0; nTab < maTables.size(); ++nTab)
    {
        if (maTables[nTab].empty())
            continue;

        ScTable* pTab = rDoc.FetchTable(nTab);
        if (!pTab)
            continue;

        const TableType& rTab = maTables[nTab];
        for (SCCOL nCol = 0; nCol < static_cast<SCCOL>(rTab.size()); ++nCol)
        {
            if (!rTab[nCol])
                continue;
            if (nCol >= pTab->GetAllocatedColumnsCount())
                break;

            ac.startColumn(nTab, nCol);
            const ColumnType& rCol = *rTab[nCol];
            ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
            SCROW nRow1, nRow2;
            nRow1 = it->first;
            bool bVal = it->second;
            for (++it; it != itEnd; ++it)
            {
                nRow2 = it->first-1;
                ac.execute(ScAddress(nCol, nRow1, nTab), nRow2-nRow1+1, bVal);

                nRow1 = nRow2+1; // for the next iteration.
                bVal = it->second;
            }
        }
    }
}

void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const
{
    for (size_t nTab = 0; nTab < maTables.size(); ++nTab)
    {
        if (maTables[nTab].empty())
            continue;

        ScTable* pTab = rDoc.FetchTable(nTab);
        if (!pTab)
            continue;

        const TableType& rTab = maTables[nTab];
        for (SCCOL nCol = 0; nCol < static_cast<SCCOL>(rTab.size()); ++nCol)
        {
            if (!rTab[nCol])
                continue;
            if (nCol >= pTab->GetAllocatedColumnsCount())
                break;

            ScColumn& rColumn = pTab->aCol[nCol];
            ac.startColumn(&rColumn);
            const ColumnType& rCol = *rTab[nCol];
            ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
            SCROW nRow1, nRow2;
            nRow1 = it->first;
            bool bVal = it->second;
            for (++it; it != itEnd; ++it)
            {
                nRow2 = it->first-1;
                ac.execute(nRow1, nRow2, bVal);

                nRow1 = nRow2+1; // for the next iteration.
                bVal = it->second;
            }
        }
    }
}

namespace {

class NonEmptyRangesScanner
{
    SingleColumnSpanSet::ColumnSpansType& mrRanges;
public:
    explicit NonEmptyRangesScanner(SingleColumnSpanSet::ColumnSpansType& rRanges) : mrRanges(rRanges) {}

    void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
    {
        if (node.type == sc::element_type_empty)
            return;

        size_t nRow = node.position + nOffset;
        size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1
        mrRanges.insert_back(nRow, nEndRow, true);
    }
};

}

SingleColumnSpanSet::SingleColumnSpanSet(ScSheetLimits const & rSheetLimits)
    : mrSheetLimits(rSheetLimits),
      maSpans(0, rSheetLimits.GetMaxRowCount(), false) {}

void SingleColumnSpanSet::scan(const ScColumn& rColumn)
{
    const CellStoreType& rCells = rColumn.maCells;
    SCROW nCurRow = 0;
    for (const auto& rCell : rCells)
    {
        SCROW nEndRow = nCurRow + rCell.size; // Last row of current block plus 1.
        if (rCell.type != sc::element_type_empty)
            maSpans.insert_back(nCurRow, nEndRow, true);

        nCurRow = nEndRow;
    }
}

void SingleColumnSpanSet::scan(const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
{
    if( nStart > rColumn.GetLastDataPos())
        return;
    const CellStoreType& rCells = rColumn.maCells;
    NonEmptyRangesScanner aScanner(maSpans);
    sc::ParseBlock(rCells.begin(), rCells, aScanner, nStart, nEnd);
}

void SingleColumnSpanSet::scan(
    ColumnBlockConstPosition& rBlockPos, const ScColumn& rColumn, SCROW nStart, SCROW nEnd)
{
    if( nStart > rColumn.GetLastDataPos())
        return;
    const CellStoreType& rCells = rColumn.maCells;
    NonEmptyRangesScanner aScanner(maSpans);
    rBlockPos.miCellPos = sc::ParseBlock(rBlockPos.miCellPos, rCells, aScanner, nStart, nEnd);
}

void SingleColumnSpanSet::scan(const ScMarkData& rMark, SCTAB nTab, SCCOL nCol)
{
    if (!rMark.GetTableSelect(nTab))
        // This table is not selected. Nothing to scan.
        return;

    ScRangeList aRanges = rMark.GetMarkedRangesForTab(nTab);
    scan(aRanges, nTab, nCol);
}

void SingleColumnSpanSet::scan(const ScRangeList& rRanges, SCTAB nTab, SCCOL nCol)
{
    for (size_t i = 0, n = rRanges.size(); i < n; ++i)
    {
        const ScRange & rRange = rRanges[i];
        if (nTab < rRange.aStart.Tab() || rRange.aEnd.Tab() < nTab)
            continue;

        if (nCol < rRange.aStart.Col() || rRange.aEnd.Col() < nCol)
            // This column is not in this range. Skip it.
            continue;

        maSpans.insert_back(rRange.aStart.Row(), rRange.aEnd.Row()+1, true);
    }
}

void SingleColumnSpanSet::set(SCROW nRow1, SCROW nRow2, bool bVal)
{
    maSpans.insert_back(nRow1, nRow2+1, bVal);
}

void SingleColumnSpanSet::getRows(std::vector<SCROW> &rRows) const
{
    std::vector<SCROW> aRows;

    SpansType aRanges;
    getSpans(aRanges);
    for (const auto& rRange : aRanges)
    {
        for (SCROW nRow = rRange.mnRow1; nRow <= rRange.mnRow2; ++nRow)
            aRows.push_back(nRow);
    }

    rRows.swap(aRows);
}

void SingleColumnSpanSet::getSpans(SpansType& rSpans) const
{
    SpansType aSpans = toSpanArray<SCROW,RowSpan>(maSpans);
    rSpans.swap(aSpans);
}

void SingleColumnSpanSet::swap( SingleColumnSpanSet& r )
{
    maSpans.swap(r.maSpans);
}

bool SingleColumnSpanSet::empty() const
{
    // Empty if there's only the 0..rDoc.MaxRow() span with false.
    ColumnSpansType::const_iterator it = maSpans.begin();
    return (it->first == 0) && !(it->second) && (++it != maSpans.end()) && (it->first == mrSheetLimits.GetMaxRowCount());
}


void RangeColumnSpanSet::executeColumnAction(ScDocument& rDoc, sc::ColumnSpanSet::ColumnAction& ac) const
{
    for (SCTAB nTab = range.aStart.Tab(); nTab <= range.aEnd.Tab(); ++nTab)
    {
        ScTable* pTab = rDoc.FetchTable(nTab);
        if (!pTab)
            continue;

        SCCOL nEndCol = pTab->ClampToAllocatedColumns(range.aEnd.Col());
        for (SCCOL nCol = range.aStart.Col(); nCol <= nEndCol; ++nCol)
        {
            if (!rDoc.ValidCol(nCol))
                break;

            ScColumn& rColumn = pTab->aCol[nCol];
            ac.startColumn(&rColumn);
            ac.execute( range.aStart.Row(), range.aEnd.Row(), true );
        }
    }
}

// namespace sc

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=75 H=99 G=87

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.