summaryrefslogtreecommitdiffstats
path: root/sc/source/core/data/olinetab.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/data/olinetab.cxx')
-rw-r--r--sc/source/core/data/olinetab.cxx873
1 files changed, 873 insertions, 0 deletions
diff --git a/sc/source/core/data/olinetab.cxx b/sc/source/core/data/olinetab.cxx
new file mode 100644
index 000000000..13fc17a7b
--- /dev/null
+++ b/sc/source/core/data/olinetab.cxx
@@ -0,0 +1,873 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <olinetab.hxx>
+#include <address.hxx>
+#include <table.hxx>
+
+#include <osl/diagnose.h>
+
+ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, bool bNewHidden ) :
+ nStart ( nNewStart ),
+ nSize ( nNewSize ),
+ bHidden ( bNewHidden ),
+ bVisible( true )
+{
+}
+
+ScOutlineEntry::ScOutlineEntry( const ScOutlineEntry& rEntry ) :
+ nStart ( rEntry.nStart ),
+ nSize ( rEntry.nSize ),
+ bHidden ( rEntry.bHidden ),
+ bVisible( rEntry.bVisible )
+{
+}
+
+SCCOLROW ScOutlineEntry::GetEnd() const
+{
+ return nStart+nSize-1;
+}
+
+void ScOutlineEntry::Move( SCCOLROW nDelta )
+{
+ SCCOLROW nNewPos = nStart + nDelta;
+ if (nNewPos<0)
+ {
+ OSL_FAIL("OutlineEntry < 0");
+ nNewPos = 0;
+ }
+ nStart = nNewPos;
+}
+
+void ScOutlineEntry::SetSize( SCSIZE nNewSize )
+{
+ if (nNewSize>0)
+ nSize = nNewSize;
+ else
+ {
+ OSL_FAIL("ScOutlineEntry Size == 0");
+ }
+}
+
+void ScOutlineEntry::SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize )
+{
+ nStart = nNewPos;
+ SetSize( nNewSize );
+}
+
+void ScOutlineEntry::SetHidden( bool bNewHidden )
+{
+ bHidden = bNewHidden;
+}
+
+void ScOutlineEntry::SetVisible( bool bNewVisible )
+{
+ bVisible = bNewVisible;
+}
+
+OString ScOutlineEntry::dumpAsString() const
+{
+ const char* const pSep = ":";
+ return OString::number(nStart) + pSep + OString::number(nSize) +
+ pSep + (bHidden ? "1" : "0") + pSep + (bVisible ? "1" : "0");
+}
+
+ScOutlineCollection::ScOutlineCollection() {}
+
+size_t ScOutlineCollection::size() const
+{
+ return m_Entries.size();
+}
+
+void ScOutlineCollection::clear()
+{
+ m_Entries.clear();
+}
+
+void ScOutlineCollection::insert(ScOutlineEntry const& rEntry)
+{
+ SCCOLROW nStart = rEntry.GetStart();
+ m_Entries.insert(std::make_pair(nStart, rEntry));
+}
+
+ScOutlineCollection::iterator ScOutlineCollection::begin()
+{
+ return m_Entries.begin();
+}
+
+ScOutlineCollection::iterator ScOutlineCollection::end()
+{
+ return m_Entries.end();
+}
+
+ScOutlineCollection::const_iterator ScOutlineCollection::begin() const
+{
+ return m_Entries.begin();
+}
+
+ScOutlineCollection::const_iterator ScOutlineCollection::end() const
+{
+ return m_Entries.end();
+}
+
+ScOutlineCollection::iterator ScOutlineCollection::erase(const iterator& pos)
+{
+ return m_Entries.erase(pos);
+}
+
+bool ScOutlineCollection::empty() const
+{
+ return m_Entries.empty();
+}
+
+ScOutlineCollection::iterator ScOutlineCollection::FindStart(SCCOLROW nMinStart)
+{
+ return m_Entries.lower_bound(nMinStart);
+}
+
+OString ScOutlineCollection::dumpAsString() const
+{
+ OString aOutput;
+ const char* const pGroupEntrySep = ",";
+ for (const auto& rKeyValuePair : m_Entries)
+ aOutput += rKeyValuePair.second.dumpAsString() + pGroupEntrySep;
+
+ return aOutput;
+}
+
+ScOutlineArray::ScOutlineArray() :
+ nDepth(0) {}
+
+ScOutlineArray::ScOutlineArray( const ScOutlineArray& rArray ) :
+ nDepth( rArray.nDepth )
+{
+ for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
+ {
+ const ScOutlineCollection& rColl = rArray.aCollections[nLevel];
+ for (const auto& rEntry : rColl)
+ {
+ const ScOutlineEntry *const pEntry = &rEntry.second;
+ aCollections[nLevel].insert(*pEntry);
+ }
+ }
+}
+
+void ScOutlineArray::FindEntry(
+ SCCOLROW nSearchPos, size_t& rFindLevel, size_t& rFindIndex,
+ size_t nMaxLevel )
+{
+ rFindLevel = rFindIndex = 0;
+
+ if (nMaxLevel > nDepth)
+ nMaxLevel = nDepth;
+
+ for (size_t nLevel = 0; nLevel < nMaxLevel; ++nLevel) //TODO: Search backwards?
+ {
+ ScOutlineCollection* pCollect = &aCollections[nLevel];
+ size_t nIndex = 0;
+ for (auto& rEntry : *pCollect)
+ {
+ ScOutlineEntry *const pEntry = &rEntry.second;
+ if (pEntry->GetStart() <= nSearchPos && pEntry->GetEnd() >= nSearchPos)
+ {
+ rFindLevel = nLevel + 1; // Next Level (for insertion)
+ rFindIndex = nIndex;
+ }
+ ++nIndex;
+ }
+ }
+}
+
+bool ScOutlineArray::Insert(
+ SCCOLROW nStartCol, SCCOLROW nEndCol, bool& rSizeChanged, bool bHidden )
+{
+ rSizeChanged = false;
+
+ size_t nStartLevel, nEndLevel, nStartIndex, nEndIndex;
+ bool bFound = false;
+
+ bool bCont;
+ sal_uInt16 nFindMax;
+ FindEntry( nStartCol, nStartLevel, nStartIndex ); // nLevel = new Level (old+1)
+ FindEntry( nEndCol, nEndLevel, nEndIndex );
+ nFindMax = std::max(nStartLevel,nEndLevel);
+ do
+ {
+ bCont = false;
+
+ if (nStartLevel == nEndLevel && nStartIndex == nEndIndex && nStartLevel < SC_OL_MAXDEPTH)
+ bFound = true;
+
+ if (!bFound && nFindMax>0)
+ {
+ --nFindMax;
+ if (nStartLevel)
+ {
+ ScOutlineCollection::const_iterator it = aCollections[nStartLevel-1].begin();
+ std::advance(it, nStartIndex);
+ if (it->second.GetStart() == nStartCol)
+ FindEntry(nStartCol, nStartLevel, nStartIndex, nFindMax);
+ }
+
+ if (nEndLevel)
+ {
+ ScOutlineCollection::const_iterator it = aCollections[nEndLevel-1].begin();
+ std::advance(it, nEndIndex);
+ if (it->second.GetEnd() == nEndCol)
+ FindEntry(nEndCol, nEndLevel, nEndIndex, nFindMax);
+ }
+ bCont = true;
+ }
+ }
+ while ( !bFound && bCont );
+
+ if (!bFound)
+ return false;
+
+ size_t nLevel = nStartLevel;
+
+ // Move the ones underneath
+ bool bNeedSize = false;
+ if (nDepth > 0)
+ {
+ for (size_t nMoveLevel = nDepth-1; nMoveLevel >= nLevel; --nMoveLevel)
+ {
+ ScOutlineCollection& rColl = aCollections[nMoveLevel];
+ ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
+ while (it != itEnd)
+ {
+ ScOutlineEntry *const pEntry = &it->second;
+ SCCOLROW nEntryStart = pEntry->GetStart();
+ if (nEntryStart >= nStartCol && nEntryStart <= nEndCol)
+ {
+ if (nMoveLevel >= SC_OL_MAXDEPTH - 1)
+ {
+ rSizeChanged = false; // No more room
+ return false;
+ }
+ aCollections[nMoveLevel+1].insert(*pEntry);
+ it = rColl.erase(it);
+ if (nMoveLevel == nDepth - 1)
+ bNeedSize = true;
+ }
+ else
+ ++it;
+ }
+ if (nMoveLevel == 0)
+ break;
+ }
+ }
+
+ if (bNeedSize)
+ {
+ ++nDepth;
+ rSizeChanged = true;
+ }
+
+ if (nDepth <= nLevel)
+ {
+ nDepth = nLevel+1;
+ rSizeChanged = true;
+ }
+
+ ScOutlineEntry aNewEntry(nStartCol, nEndCol+1-nStartCol, bHidden);
+ aNewEntry.SetVisible( true );
+ aCollections[nLevel].insert(aNewEntry);
+
+ return true;
+}
+
+bool ScOutlineArray::FindTouchedLevel(
+ SCCOLROW nBlockStart, SCCOLROW nBlockEnd, size_t& rFindLevel) const
+{
+ bool bFound = false;
+ rFindLevel = 0;
+
+ for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
+ {
+ const ScOutlineCollection* pCollect = &aCollections[nLevel];
+ for (const auto& rEntry : *pCollect)
+ {
+ const ScOutlineEntry *const pEntry = &rEntry.second;
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+
+ if ( ( nBlockStart>=nStart && nBlockStart<=nEnd ) ||
+ ( nBlockEnd >=nStart && nBlockEnd <=nEnd ) )
+ {
+ rFindLevel = nLevel; // Actual Level
+ bFound = true;
+ }
+ }
+ }
+
+ return bFound;
+}
+
+void ScOutlineArray::PromoteSub(SCCOLROW nStartPos, SCCOLROW nEndPos, size_t nStartLevel)
+{
+ if (nStartLevel==0)
+ {
+ OSL_FAIL("PromoteSub with Level 0");
+ return;
+ }
+
+ for (size_t nLevel = nStartLevel; nLevel < nDepth; ++nLevel)
+ {
+ ScOutlineCollection& rColl = aCollections[nLevel];
+ ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
+ while (it != itEnd)
+ {
+ ScOutlineEntry *const pEntry = &it->second;
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+ if (nStart >= nStartPos && nEnd <= nEndPos)
+ {
+ aCollections[nLevel-1].insert(*pEntry);
+
+ it = rColl.erase(it);
+ }
+ else
+ ++it;
+ }
+
+ it = rColl.begin();
+ itEnd = rColl.end();
+
+ while (it != itEnd)
+ {
+ ScOutlineEntry *const pEntry = &it->second;
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+ if (nStart >= nStartPos && nEnd <= nEndPos)
+ {
+ aCollections[nLevel-1].insert(*pEntry);
+
+ it = rColl.erase(it);
+ }
+ else
+ ++it;
+ }
+ }
+}
+
+/**
+ * Adapt nDepth for empty Levels
+ */
+bool ScOutlineArray::DecDepth()
+{
+ bool bChanged = false;
+ bool bCont;
+ do
+ {
+ bCont = false;
+ if (nDepth)
+ {
+ if (aCollections[nDepth-1].empty())
+ {
+ --nDepth;
+ bChanged = true;
+ bCont = true;
+ }
+ }
+ }
+ while (bCont);
+
+ return bChanged;
+}
+
+bool ScOutlineArray::Remove( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, bool& rSizeChanged )
+{
+ size_t nLevel;
+ FindTouchedLevel( nBlockStart, nBlockEnd, nLevel );
+
+ ScOutlineCollection* pCollect = &aCollections[nLevel];
+ ScOutlineCollection::iterator it = pCollect->begin(), itEnd = pCollect->end();
+ bool bAny = false;
+ while (it != itEnd)
+ {
+ ScOutlineEntry *const pEntry = &it->second;
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+ if (nBlockStart <= nEnd && nBlockEnd >= nStart)
+ {
+ // Overlaps
+ pCollect->erase(it);
+ PromoteSub( nStart, nEnd, nLevel+1 );
+ itEnd = pCollect->end();
+ it = pCollect->FindStart( nEnd+1 );
+ bAny = true;
+ }
+ else
+ ++it;
+ }
+
+ if (bAny) // Adapt Depth
+ if (DecDepth())
+ rSizeChanged = true;
+
+ return bAny;
+}
+
+ScOutlineEntry* ScOutlineArray::GetEntry(size_t nLevel, size_t nIndex)
+{
+ if (nLevel >= nDepth)
+ return nullptr;
+
+ ScOutlineCollection& rColl = aCollections[nLevel];
+ if (nIndex >= rColl.size())
+ return nullptr;
+
+ ScOutlineCollection::iterator it = rColl.begin();
+ std::advance(it, nIndex);
+ return &it->second;
+}
+
+const ScOutlineEntry* ScOutlineArray::GetEntry(size_t nLevel, size_t nIndex) const
+{
+ if (nLevel >= nDepth)
+ return nullptr;
+
+ const ScOutlineCollection& rColl = aCollections[nLevel];
+ if (nIndex >= rColl.size())
+ return nullptr;
+
+ ScOutlineCollection::const_iterator it = rColl.begin();
+ std::advance(it, nIndex);
+ return &it->second;
+}
+
+size_t ScOutlineArray::GetCount(size_t nLevel) const
+{
+ if (nLevel >= nDepth)
+ return 0;
+
+ return aCollections[nLevel].size();
+}
+
+const ScOutlineEntry* ScOutlineArray::GetEntryByPos(size_t nLevel, SCCOLROW nPos) const
+{
+ if (nLevel >= nDepth)
+ return nullptr;
+
+ const ScOutlineCollection& rColl = aCollections[nLevel];
+ ScOutlineCollection::const_iterator it = std::find_if(rColl.begin(), rColl.end(),
+ [&nPos](const auto& rEntry) {
+ const ScOutlineEntry *const pEntry = &rEntry.second;
+ return pEntry->GetStart() <= nPos && nPos <= pEntry->GetEnd();
+ });
+ if (it != rColl.end())
+ return &it->second;
+
+ return nullptr;
+}
+
+bool ScOutlineArray::GetEntryIndex(size_t nLevel, SCCOLROW nPos, size_t& rnIndex) const
+{
+ if (nLevel >= nDepth)
+ return false;
+
+ // Found entry contains passed position
+ const ScOutlineCollection& rColl = aCollections[nLevel];
+ ScOutlineCollection::const_iterator it = std::find_if(rColl.begin(), rColl.end(),
+ [&nPos](const auto& rEntry) {
+ const ScOutlineEntry *const p = &rEntry.second;
+ return p->GetStart() <= nPos && nPos <= p->GetEnd();
+ });
+ if (it != rColl.end())
+ {
+ rnIndex = std::distance(rColl.begin(), it);
+ return true;
+ }
+ return false;
+}
+
+bool ScOutlineArray::GetEntryIndexInRange(
+ size_t nLevel, SCCOLROW nBlockStart, SCCOLROW nBlockEnd, size_t& rnIndex) const
+{
+ if (nLevel >= nDepth)
+ return false;
+
+ // Found entry will be completely inside of passed range
+ const ScOutlineCollection& rColl = aCollections[nLevel];
+ ScOutlineCollection::const_iterator it = std::find_if(rColl.begin(), rColl.end(),
+ [&nBlockStart, &nBlockEnd](const auto& rEntry) {
+ const ScOutlineEntry *const p = &rEntry.second;
+ return nBlockStart <= p->GetStart() && p->GetEnd() <= nBlockEnd;
+ });
+ if (it != rColl.end())
+ {
+ rnIndex = std::distance(rColl.begin(), it);
+ return true;
+ }
+ return false;
+}
+
+void ScOutlineArray::SetVisibleBelow(
+ size_t nLevel, size_t nEntry, bool bValue, bool bSkipHidden)
+{
+ const ScOutlineEntry* pEntry = GetEntry( nLevel, nEntry );
+ if (!pEntry)
+ return;
+
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+
+ for (size_t nSubLevel = nLevel+1; nSubLevel < nDepth; ++nSubLevel)
+ {
+ ScOutlineCollection& rColl = aCollections[nSubLevel];
+ size_t nPos = 0;
+ for (auto& rEntry : rColl)
+ {
+ ScOutlineEntry *const p = &rEntry.second;
+ if (p->GetStart() >= nStart && p->GetEnd() <= nEnd)
+ {
+ p->SetVisible(bValue);
+ if (bSkipHidden && !p->IsHidden())
+ {
+ SetVisibleBelow(nSubLevel, nPos, bValue, true);
+ }
+ }
+ ++nPos;
+ }
+
+ if (bSkipHidden)
+ nSubLevel = nDepth; // Bail out
+ }
+}
+
+void ScOutlineArray::GetRange(SCCOLROW& rStart, SCCOLROW& rEnd) const
+{
+ const ScOutlineCollection& rColl = aCollections[0];
+ if (!rColl.empty())
+ {
+ ScOutlineCollection::const_iterator it = rColl.begin();
+ rStart = it->second.GetStart();
+ std::advance(it, rColl.size()-1);
+ rEnd = it->second.GetEnd();
+ }
+ else
+ rStart = rEnd = 0;
+}
+
+void ScOutlineArray::ExtendBlock(size_t nLevel, SCCOLROW& rBlkStart, SCCOLROW& rBlkEnd)
+{
+ if (nLevel >= nDepth)
+ return;
+
+ const ScOutlineCollection& rColl = aCollections[nLevel];
+ for (const auto& rEntry : rColl)
+ {
+ const ScOutlineEntry *const pEntry = &rEntry.second;
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+
+ if (rBlkStart <= nEnd && rBlkEnd >= nStart)
+ {
+ if (nStart < rBlkStart)
+ rBlkStart = nStart;
+ if (nEnd > rBlkEnd)
+ rBlkEnd = nEnd;
+ }
+ }
+}
+
+bool ScOutlineArray::TestInsertSpace(SCSIZE nSize, SCCOLROW nMaxVal) const
+{
+ const ScOutlineCollection& rColl = aCollections[0];
+ if (rColl.empty())
+ return true;
+
+ ScOutlineCollection::const_iterator it = rColl.begin();
+ std::advance(it, rColl.size()-1);
+ SCCOLROW nEnd = it->second.GetEnd();
+ return sal::static_int_cast<SCCOLROW>(nEnd+nSize) <= nMaxVal;
+}
+
+void ScOutlineArray::InsertSpace(SCCOLROW nStartPos, SCSIZE nSize)
+{
+ ScSubOutlineIterator aIter( this );
+ ScOutlineEntry* pEntry;
+ while ((pEntry = aIter.GetNext()) != nullptr)
+ {
+ if ( pEntry->GetStart() >= nStartPos )
+ pEntry->Move(static_cast<SCCOLROW>(nSize));
+ else
+ {
+ SCCOLROW nEnd = pEntry->GetEnd();
+ // Always expand if inserted within the group
+ // When inserting at the end, only if the group is not hidden
+ if ( nEnd >= nStartPos || ( nEnd+1 >= nStartPos && !pEntry->IsHidden() ) )
+ {
+ SCSIZE nEntrySize = pEntry->GetSize();
+ nEntrySize += nSize;
+ pEntry->SetSize( nEntrySize );
+ }
+ }
+ }
+}
+
+bool ScOutlineArray::DeleteSpace(SCCOLROW nStartPos, SCSIZE nSize)
+{
+ SCCOLROW nEndPos = nStartPos + nSize - 1;
+ bool bNeedSave = false; // Do we need the original one for Undo?
+ bool bChanged = false; // For Level test
+
+ ScSubOutlineIterator aIter( this );
+ ScOutlineEntry* pEntry;
+ while((pEntry=aIter.GetNext())!=nullptr)
+ {
+ SCCOLROW nEntryStart = pEntry->GetStart();
+ SCCOLROW nEntryEnd = pEntry->GetEnd();
+ SCSIZE nEntrySize = pEntry->GetSize();
+
+ if ( nEntryEnd >= nStartPos )
+ {
+ if ( nEntryStart > nEndPos ) // Right
+ pEntry->Move(-static_cast<SCCOLROW>(nSize));
+ else if ( nEntryStart < nStartPos && nEntryEnd >= nEndPos ) // Outside
+ pEntry->SetSize( nEntrySize-nSize );
+ else
+ {
+ bNeedSave = true;
+ if ( nEntryStart >= nStartPos && nEntryEnd <= nEndPos ) // Inside
+ {
+ aIter.DeleteLast();
+ bChanged = true;
+ }
+ else if ( nEntryStart >= nStartPos ) // Top right
+ pEntry->SetPosSize( nStartPos, static_cast<SCSIZE>(nEntryEnd-nEndPos) );
+ else // Top left
+ pEntry->SetSize( static_cast<SCSIZE>(nStartPos-nEntryStart) );
+ }
+ }
+ }
+
+ if (bChanged)
+ DecDepth();
+
+ return bNeedSave;
+}
+
+bool ScOutlineArray::ManualAction(
+ SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, const ScTable& rTable, bool bCol)
+{
+ bool bModified = false;
+ ScSubOutlineIterator aIter( this );
+ ScOutlineEntry* pEntry;
+ while((pEntry=aIter.GetNext())!=nullptr)
+ {
+ SCCOLROW nEntryStart = pEntry->GetStart();
+ SCCOLROW nEntryEnd = pEntry->GetEnd();
+
+ if (nEntryEnd>=nStartPos && nEntryStart<=nEndPos)
+ {
+ if ( pEntry->IsHidden() == bShow )
+ {
+ // #i12341# hide if all columns/rows are hidden, show if at least one
+ // is visible
+ SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol);
+ bool bAllHidden = (nEntryEnd <= nEnd && nEnd <
+ ::std::numeric_limits<SCCOLROW>::max());
+
+ bool bToggle = ( bShow != bAllHidden );
+ if ( bToggle )
+ {
+ pEntry->SetHidden( !bShow );
+ SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow );
+ bModified = true;
+ }
+ }
+ }
+ }
+ return bModified;
+}
+
+void ScOutlineArray::RemoveAll()
+{
+ for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
+ aCollections[nLevel].clear();
+
+ nDepth = 0;
+}
+
+void ScOutlineArray::finalizeImport(const ScTable& rTable)
+{
+ ScSubOutlineIterator aIter( this );
+ ScOutlineEntry* pEntry;
+ while((pEntry=aIter.GetNext())!=nullptr)
+ {
+
+ if (!pEntry->IsHidden())
+ continue;
+
+ SCCOLROW nEntryStart = pEntry->GetStart();
+ SCCOLROW nEntryEnd = pEntry->GetEnd();
+ SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, false/*bCol*/);
+ bool bAllHidden = (nEntryEnd <= nEnd && nEnd <
+ ::std::numeric_limits<SCCOLROW>::max());
+
+ pEntry->SetHidden(bAllHidden);
+ SetVisibleBelow(aIter.LastLevel(), aIter.LastEntry(), !bAllHidden, !bAllHidden);
+ }
+}
+
+OString ScOutlineArray::dumpAsString() const
+{
+ OString aOutput;
+ const char* const pLevelSep = " ";
+ for (const auto& rCollection : aCollections)
+ {
+ if (rCollection.empty())
+ continue;
+ aOutput += rCollection.dumpAsString() + pLevelSep;
+ }
+
+ return aOutput;
+}
+
+ScOutlineTable::ScOutlineTable()
+{
+}
+
+ScOutlineTable::ScOutlineTable( const ScOutlineTable& rOutline ) :
+ aColOutline( rOutline.aColOutline ),
+ aRowOutline( rOutline.aRowOutline )
+{
+}
+
+bool ScOutlineTable::TestInsertCol( SCSIZE nSize )
+{
+ return aColOutline.TestInsertSpace( nSize, MAXCOL );
+}
+
+void ScOutlineTable::InsertCol( SCCOL nStartCol, SCSIZE nSize )
+{
+ aColOutline.InsertSpace( nStartCol, nSize );
+}
+
+bool ScOutlineTable::DeleteCol( SCCOL nStartCol, SCSIZE nSize )
+{
+ return aColOutline.DeleteSpace( nStartCol, nSize );
+}
+
+bool ScOutlineTable::TestInsertRow( SCSIZE nSize )
+{
+ return aRowOutline.TestInsertSpace( nSize, MAXROW );
+}
+
+void ScOutlineTable::InsertRow( SCROW nStartRow, SCSIZE nSize )
+{
+ aRowOutline.InsertSpace( nStartRow, nSize );
+}
+
+bool ScOutlineTable::DeleteRow( SCROW nStartRow, SCSIZE nSize )
+{
+ return aRowOutline.DeleteSpace( nStartRow, nSize );
+}
+
+ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray ) :
+ pArray( pOutlineArray ),
+ nStart( 0 ),
+ nEnd( SCCOLROW_MAX ), // Iterate over all of them
+ nSubLevel( 0 ),
+ nSubEntry( 0 )
+{
+ nDepth = pArray->nDepth;
+}
+
+ScSubOutlineIterator::ScSubOutlineIterator(
+ ScOutlineArray* pOutlineArray, size_t nLevel, size_t nEntry ) :
+ pArray( pOutlineArray )
+{
+ const ScOutlineCollection& rColl = pArray->aCollections[nLevel];
+ ScOutlineCollection::const_iterator it = rColl.begin();
+ std::advance(it, nEntry);
+ const ScOutlineEntry* pEntry = &it->second;
+ nStart = pEntry->GetStart();
+ nEnd = pEntry->GetEnd();
+ nSubLevel = nLevel + 1;
+ nSubEntry = 0;
+ nDepth = pArray->nDepth;
+}
+
+ScOutlineEntry* ScSubOutlineIterator::GetNext()
+{
+ ScOutlineEntry* pEntry = nullptr;
+ bool bFound = false;
+ do
+ {
+ if (nSubLevel >= nDepth)
+ return nullptr;
+
+ ScOutlineCollection& rColl = pArray->aCollections[nSubLevel];
+ if (nSubEntry < rColl.size())
+ {
+ ScOutlineCollection::iterator it = rColl.begin();
+ std::advance(it, nSubEntry);
+ pEntry = &it->second;
+
+ if (pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd)
+ bFound = true;
+
+ ++nSubEntry;
+ }
+ else
+ {
+ // Go to the next sub-level
+ nSubEntry = 0;
+ ++nSubLevel;
+ }
+ }
+ while (!bFound);
+ return pEntry; // nSubLevel valid, if pEntry != 0
+}
+
+size_t ScSubOutlineIterator::LastEntry() const
+{
+ if (nSubEntry == 0)
+ {
+ OSL_FAIL("ScSubOutlineIterator::LastEntry before GetNext");
+ return 0;
+ }
+ return nSubEntry-1;
+}
+
+void ScSubOutlineIterator::DeleteLast()
+{
+ if (nSubLevel >= nDepth)
+ {
+ OSL_FAIL("ScSubOutlineIterator::DeleteLast after End");
+ return;
+ }
+ if (nSubEntry == 0)
+ {
+ OSL_FAIL("ScSubOutlineIterator::DeleteLast before GetNext");
+ return;
+ }
+
+ --nSubEntry;
+ ScOutlineCollection& rColl = pArray->aCollections[nSubLevel];
+ assert(nSubEntry < rColl.size());
+ ScOutlineCollection::iterator it = rColl.begin();
+ std::advance(it, nSubEntry);
+ rColl.erase(it);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */