Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / sc / source / core / data / olinetab.cxx
blob13fc17a7b35f00a40a69dc78bc20e5290b1feb90
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <olinetab.hxx>
21 #include <address.hxx>
22 #include <table.hxx>
24 #include <osl/diagnose.h>
26 ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, bool bNewHidden ) :
27 nStart ( nNewStart ),
28 nSize ( nNewSize ),
29 bHidden ( bNewHidden ),
30 bVisible( true )
34 ScOutlineEntry::ScOutlineEntry( const ScOutlineEntry& rEntry ) :
35 nStart ( rEntry.nStart ),
36 nSize ( rEntry.nSize ),
37 bHidden ( rEntry.bHidden ),
38 bVisible( rEntry.bVisible )
42 SCCOLROW ScOutlineEntry::GetEnd() const
44 return nStart+nSize-1;
47 void ScOutlineEntry::Move( SCCOLROW nDelta )
49 SCCOLROW nNewPos = nStart + nDelta;
50 if (nNewPos<0)
52 OSL_FAIL("OutlineEntry < 0");
53 nNewPos = 0;
55 nStart = nNewPos;
58 void ScOutlineEntry::SetSize( SCSIZE nNewSize )
60 if (nNewSize>0)
61 nSize = nNewSize;
62 else
64 OSL_FAIL("ScOutlineEntry Size == 0");
68 void ScOutlineEntry::SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize )
70 nStart = nNewPos;
71 SetSize( nNewSize );
74 void ScOutlineEntry::SetHidden( bool bNewHidden )
76 bHidden = bNewHidden;
79 void ScOutlineEntry::SetVisible( bool bNewVisible )
81 bVisible = bNewVisible;
84 OString ScOutlineEntry::dumpAsString() const
86 const char* const pSep = ":";
87 return OString::number(nStart) + pSep + OString::number(nSize) +
88 pSep + (bHidden ? "1" : "0") + pSep + (bVisible ? "1" : "0");
91 ScOutlineCollection::ScOutlineCollection() {}
93 size_t ScOutlineCollection::size() const
95 return m_Entries.size();
98 void ScOutlineCollection::clear()
100 m_Entries.clear();
103 void ScOutlineCollection::insert(ScOutlineEntry const& rEntry)
105 SCCOLROW nStart = rEntry.GetStart();
106 m_Entries.insert(std::make_pair(nStart, rEntry));
109 ScOutlineCollection::iterator ScOutlineCollection::begin()
111 return m_Entries.begin();
114 ScOutlineCollection::iterator ScOutlineCollection::end()
116 return m_Entries.end();
119 ScOutlineCollection::const_iterator ScOutlineCollection::begin() const
121 return m_Entries.begin();
124 ScOutlineCollection::const_iterator ScOutlineCollection::end() const
126 return m_Entries.end();
129 ScOutlineCollection::iterator ScOutlineCollection::erase(const iterator& pos)
131 return m_Entries.erase(pos);
134 bool ScOutlineCollection::empty() const
136 return m_Entries.empty();
139 ScOutlineCollection::iterator ScOutlineCollection::FindStart(SCCOLROW nMinStart)
141 return m_Entries.lower_bound(nMinStart);
144 OString ScOutlineCollection::dumpAsString() const
146 OString aOutput;
147 const char* const pGroupEntrySep = ",";
148 for (const auto& rKeyValuePair : m_Entries)
149 aOutput += rKeyValuePair.second.dumpAsString() + pGroupEntrySep;
151 return aOutput;
154 ScOutlineArray::ScOutlineArray() :
155 nDepth(0) {}
157 ScOutlineArray::ScOutlineArray( const ScOutlineArray& rArray ) :
158 nDepth( rArray.nDepth )
160 for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
162 const ScOutlineCollection& rColl = rArray.aCollections[nLevel];
163 for (const auto& rEntry : rColl)
165 const ScOutlineEntry *const pEntry = &rEntry.second;
166 aCollections[nLevel].insert(*pEntry);
171 void ScOutlineArray::FindEntry(
172 SCCOLROW nSearchPos, size_t& rFindLevel, size_t& rFindIndex,
173 size_t nMaxLevel )
175 rFindLevel = rFindIndex = 0;
177 if (nMaxLevel > nDepth)
178 nMaxLevel = nDepth;
180 for (size_t nLevel = 0; nLevel < nMaxLevel; ++nLevel) //TODO: Search backwards?
182 ScOutlineCollection* pCollect = &aCollections[nLevel];
183 size_t nIndex = 0;
184 for (auto& rEntry : *pCollect)
186 ScOutlineEntry *const pEntry = &rEntry.second;
187 if (pEntry->GetStart() <= nSearchPos && pEntry->GetEnd() >= nSearchPos)
189 rFindLevel = nLevel + 1; // Next Level (for insertion)
190 rFindIndex = nIndex;
192 ++nIndex;
197 bool ScOutlineArray::Insert(
198 SCCOLROW nStartCol, SCCOLROW nEndCol, bool& rSizeChanged, bool bHidden )
200 rSizeChanged = false;
202 size_t nStartLevel, nEndLevel, nStartIndex, nEndIndex;
203 bool bFound = false;
205 bool bCont;
206 sal_uInt16 nFindMax;
207 FindEntry( nStartCol, nStartLevel, nStartIndex ); // nLevel = new Level (old+1)
208 FindEntry( nEndCol, nEndLevel, nEndIndex );
209 nFindMax = std::max(nStartLevel,nEndLevel);
212 bCont = false;
214 if (nStartLevel == nEndLevel && nStartIndex == nEndIndex && nStartLevel < SC_OL_MAXDEPTH)
215 bFound = true;
217 if (!bFound && nFindMax>0)
219 --nFindMax;
220 if (nStartLevel)
222 ScOutlineCollection::const_iterator it = aCollections[nStartLevel-1].begin();
223 std::advance(it, nStartIndex);
224 if (it->second.GetStart() == nStartCol)
225 FindEntry(nStartCol, nStartLevel, nStartIndex, nFindMax);
228 if (nEndLevel)
230 ScOutlineCollection::const_iterator it = aCollections[nEndLevel-1].begin();
231 std::advance(it, nEndIndex);
232 if (it->second.GetEnd() == nEndCol)
233 FindEntry(nEndCol, nEndLevel, nEndIndex, nFindMax);
235 bCont = true;
238 while ( !bFound && bCont );
240 if (!bFound)
241 return false;
243 size_t nLevel = nStartLevel;
245 // Move the ones underneath
246 bool bNeedSize = false;
247 if (nDepth > 0)
249 for (size_t nMoveLevel = nDepth-1; nMoveLevel >= nLevel; --nMoveLevel)
251 ScOutlineCollection& rColl = aCollections[nMoveLevel];
252 ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
253 while (it != itEnd)
255 ScOutlineEntry *const pEntry = &it->second;
256 SCCOLROW nEntryStart = pEntry->GetStart();
257 if (nEntryStart >= nStartCol && nEntryStart <= nEndCol)
259 if (nMoveLevel >= SC_OL_MAXDEPTH - 1)
261 rSizeChanged = false; // No more room
262 return false;
264 aCollections[nMoveLevel+1].insert(*pEntry);
265 it = rColl.erase(it);
266 if (nMoveLevel == nDepth - 1)
267 bNeedSize = true;
269 else
270 ++it;
272 if (nMoveLevel == 0)
273 break;
277 if (bNeedSize)
279 ++nDepth;
280 rSizeChanged = true;
283 if (nDepth <= nLevel)
285 nDepth = nLevel+1;
286 rSizeChanged = true;
289 ScOutlineEntry aNewEntry(nStartCol, nEndCol+1-nStartCol, bHidden);
290 aNewEntry.SetVisible( true );
291 aCollections[nLevel].insert(aNewEntry);
293 return true;
296 bool ScOutlineArray::FindTouchedLevel(
297 SCCOLROW nBlockStart, SCCOLROW nBlockEnd, size_t& rFindLevel) const
299 bool bFound = false;
300 rFindLevel = 0;
302 for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
304 const ScOutlineCollection* pCollect = &aCollections[nLevel];
305 for (const auto& rEntry : *pCollect)
307 const ScOutlineEntry *const pEntry = &rEntry.second;
308 SCCOLROW nStart = pEntry->GetStart();
309 SCCOLROW nEnd = pEntry->GetEnd();
311 if ( ( nBlockStart>=nStart && nBlockStart<=nEnd ) ||
312 ( nBlockEnd >=nStart && nBlockEnd <=nEnd ) )
314 rFindLevel = nLevel; // Actual Level
315 bFound = true;
320 return bFound;
323 void ScOutlineArray::PromoteSub(SCCOLROW nStartPos, SCCOLROW nEndPos, size_t nStartLevel)
325 if (nStartLevel==0)
327 OSL_FAIL("PromoteSub with Level 0");
328 return;
331 for (size_t nLevel = nStartLevel; nLevel < nDepth; ++nLevel)
333 ScOutlineCollection& rColl = aCollections[nLevel];
334 ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
335 while (it != itEnd)
337 ScOutlineEntry *const pEntry = &it->second;
338 SCCOLROW nStart = pEntry->GetStart();
339 SCCOLROW nEnd = pEntry->GetEnd();
340 if (nStart >= nStartPos && nEnd <= nEndPos)
342 aCollections[nLevel-1].insert(*pEntry);
344 it = rColl.erase(it);
346 else
347 ++it;
350 it = rColl.begin();
351 itEnd = rColl.end();
353 while (it != itEnd)
355 ScOutlineEntry *const pEntry = &it->second;
356 SCCOLROW nStart = pEntry->GetStart();
357 SCCOLROW nEnd = pEntry->GetEnd();
358 if (nStart >= nStartPos && nEnd <= nEndPos)
360 aCollections[nLevel-1].insert(*pEntry);
362 it = rColl.erase(it);
364 else
365 ++it;
371 * Adapt nDepth for empty Levels
373 bool ScOutlineArray::DecDepth()
375 bool bChanged = false;
376 bool bCont;
379 bCont = false;
380 if (nDepth)
382 if (aCollections[nDepth-1].empty())
384 --nDepth;
385 bChanged = true;
386 bCont = true;
390 while (bCont);
392 return bChanged;
395 bool ScOutlineArray::Remove( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, bool& rSizeChanged )
397 size_t nLevel;
398 FindTouchedLevel( nBlockStart, nBlockEnd, nLevel );
400 ScOutlineCollection* pCollect = &aCollections[nLevel];
401 ScOutlineCollection::iterator it = pCollect->begin(), itEnd = pCollect->end();
402 bool bAny = false;
403 while (it != itEnd)
405 ScOutlineEntry *const pEntry = &it->second;
406 SCCOLROW nStart = pEntry->GetStart();
407 SCCOLROW nEnd = pEntry->GetEnd();
408 if (nBlockStart <= nEnd && nBlockEnd >= nStart)
410 // Overlaps
411 pCollect->erase(it);
412 PromoteSub( nStart, nEnd, nLevel+1 );
413 itEnd = pCollect->end();
414 it = pCollect->FindStart( nEnd+1 );
415 bAny = true;
417 else
418 ++it;
421 if (bAny) // Adapt Depth
422 if (DecDepth())
423 rSizeChanged = true;
425 return bAny;
428 ScOutlineEntry* ScOutlineArray::GetEntry(size_t nLevel, size_t nIndex)
430 if (nLevel >= nDepth)
431 return nullptr;
433 ScOutlineCollection& rColl = aCollections[nLevel];
434 if (nIndex >= rColl.size())
435 return nullptr;
437 ScOutlineCollection::iterator it = rColl.begin();
438 std::advance(it, nIndex);
439 return &it->second;
442 const ScOutlineEntry* ScOutlineArray::GetEntry(size_t nLevel, size_t nIndex) const
444 if (nLevel >= nDepth)
445 return nullptr;
447 const ScOutlineCollection& rColl = aCollections[nLevel];
448 if (nIndex >= rColl.size())
449 return nullptr;
451 ScOutlineCollection::const_iterator it = rColl.begin();
452 std::advance(it, nIndex);
453 return &it->second;
456 size_t ScOutlineArray::GetCount(size_t nLevel) const
458 if (nLevel >= nDepth)
459 return 0;
461 return aCollections[nLevel].size();
464 const ScOutlineEntry* ScOutlineArray::GetEntryByPos(size_t nLevel, SCCOLROW nPos) const
466 if (nLevel >= nDepth)
467 return nullptr;
469 const ScOutlineCollection& rColl = aCollections[nLevel];
470 ScOutlineCollection::const_iterator it = std::find_if(rColl.begin(), rColl.end(),
471 [&nPos](const auto& rEntry) {
472 const ScOutlineEntry *const pEntry = &rEntry.second;
473 return pEntry->GetStart() <= nPos && nPos <= pEntry->GetEnd();
475 if (it != rColl.end())
476 return &it->second;
478 return nullptr;
481 bool ScOutlineArray::GetEntryIndex(size_t nLevel, SCCOLROW nPos, size_t& rnIndex) const
483 if (nLevel >= nDepth)
484 return false;
486 // Found entry contains passed position
487 const ScOutlineCollection& rColl = aCollections[nLevel];
488 ScOutlineCollection::const_iterator it = std::find_if(rColl.begin(), rColl.end(),
489 [&nPos](const auto& rEntry) {
490 const ScOutlineEntry *const p = &rEntry.second;
491 return p->GetStart() <= nPos && nPos <= p->GetEnd();
493 if (it != rColl.end())
495 rnIndex = std::distance(rColl.begin(), it);
496 return true;
498 return false;
501 bool ScOutlineArray::GetEntryIndexInRange(
502 size_t nLevel, SCCOLROW nBlockStart, SCCOLROW nBlockEnd, size_t& rnIndex) const
504 if (nLevel >= nDepth)
505 return false;
507 // Found entry will be completely inside of passed range
508 const ScOutlineCollection& rColl = aCollections[nLevel];
509 ScOutlineCollection::const_iterator it = std::find_if(rColl.begin(), rColl.end(),
510 [&nBlockStart, &nBlockEnd](const auto& rEntry) {
511 const ScOutlineEntry *const p = &rEntry.second;
512 return nBlockStart <= p->GetStart() && p->GetEnd() <= nBlockEnd;
514 if (it != rColl.end())
516 rnIndex = std::distance(rColl.begin(), it);
517 return true;
519 return false;
522 void ScOutlineArray::SetVisibleBelow(
523 size_t nLevel, size_t nEntry, bool bValue, bool bSkipHidden)
525 const ScOutlineEntry* pEntry = GetEntry( nLevel, nEntry );
526 if (!pEntry)
527 return;
529 SCCOLROW nStart = pEntry->GetStart();
530 SCCOLROW nEnd = pEntry->GetEnd();
532 for (size_t nSubLevel = nLevel+1; nSubLevel < nDepth; ++nSubLevel)
534 ScOutlineCollection& rColl = aCollections[nSubLevel];
535 size_t nPos = 0;
536 for (auto& rEntry : rColl)
538 ScOutlineEntry *const p = &rEntry.second;
539 if (p->GetStart() >= nStart && p->GetEnd() <= nEnd)
541 p->SetVisible(bValue);
542 if (bSkipHidden && !p->IsHidden())
544 SetVisibleBelow(nSubLevel, nPos, bValue, true);
547 ++nPos;
550 if (bSkipHidden)
551 nSubLevel = nDepth; // Bail out
555 void ScOutlineArray::GetRange(SCCOLROW& rStart, SCCOLROW& rEnd) const
557 const ScOutlineCollection& rColl = aCollections[0];
558 if (!rColl.empty())
560 ScOutlineCollection::const_iterator it = rColl.begin();
561 rStart = it->second.GetStart();
562 std::advance(it, rColl.size()-1);
563 rEnd = it->second.GetEnd();
565 else
566 rStart = rEnd = 0;
569 void ScOutlineArray::ExtendBlock(size_t nLevel, SCCOLROW& rBlkStart, SCCOLROW& rBlkEnd)
571 if (nLevel >= nDepth)
572 return;
574 const ScOutlineCollection& rColl = aCollections[nLevel];
575 for (const auto& rEntry : rColl)
577 const ScOutlineEntry *const pEntry = &rEntry.second;
578 SCCOLROW nStart = pEntry->GetStart();
579 SCCOLROW nEnd = pEntry->GetEnd();
581 if (rBlkStart <= nEnd && rBlkEnd >= nStart)
583 if (nStart < rBlkStart)
584 rBlkStart = nStart;
585 if (nEnd > rBlkEnd)
586 rBlkEnd = nEnd;
591 bool ScOutlineArray::TestInsertSpace(SCSIZE nSize, SCCOLROW nMaxVal) const
593 const ScOutlineCollection& rColl = aCollections[0];
594 if (rColl.empty())
595 return true;
597 ScOutlineCollection::const_iterator it = rColl.begin();
598 std::advance(it, rColl.size()-1);
599 SCCOLROW nEnd = it->second.GetEnd();
600 return sal::static_int_cast<SCCOLROW>(nEnd+nSize) <= nMaxVal;
603 void ScOutlineArray::InsertSpace(SCCOLROW nStartPos, SCSIZE nSize)
605 ScSubOutlineIterator aIter( this );
606 ScOutlineEntry* pEntry;
607 while ((pEntry = aIter.GetNext()) != nullptr)
609 if ( pEntry->GetStart() >= nStartPos )
610 pEntry->Move(static_cast<SCCOLROW>(nSize));
611 else
613 SCCOLROW nEnd = pEntry->GetEnd();
614 // Always expand if inserted within the group
615 // When inserting at the end, only if the group is not hidden
616 if ( nEnd >= nStartPos || ( nEnd+1 >= nStartPos && !pEntry->IsHidden() ) )
618 SCSIZE nEntrySize = pEntry->GetSize();
619 nEntrySize += nSize;
620 pEntry->SetSize( nEntrySize );
626 bool ScOutlineArray::DeleteSpace(SCCOLROW nStartPos, SCSIZE nSize)
628 SCCOLROW nEndPos = nStartPos + nSize - 1;
629 bool bNeedSave = false; // Do we need the original one for Undo?
630 bool bChanged = false; // For Level test
632 ScSubOutlineIterator aIter( this );
633 ScOutlineEntry* pEntry;
634 while((pEntry=aIter.GetNext())!=nullptr)
636 SCCOLROW nEntryStart = pEntry->GetStart();
637 SCCOLROW nEntryEnd = pEntry->GetEnd();
638 SCSIZE nEntrySize = pEntry->GetSize();
640 if ( nEntryEnd >= nStartPos )
642 if ( nEntryStart > nEndPos ) // Right
643 pEntry->Move(-static_cast<SCCOLROW>(nSize));
644 else if ( nEntryStart < nStartPos && nEntryEnd >= nEndPos ) // Outside
645 pEntry->SetSize( nEntrySize-nSize );
646 else
648 bNeedSave = true;
649 if ( nEntryStart >= nStartPos && nEntryEnd <= nEndPos ) // Inside
651 aIter.DeleteLast();
652 bChanged = true;
654 else if ( nEntryStart >= nStartPos ) // Top right
655 pEntry->SetPosSize( nStartPos, static_cast<SCSIZE>(nEntryEnd-nEndPos) );
656 else // Top left
657 pEntry->SetSize( static_cast<SCSIZE>(nStartPos-nEntryStart) );
662 if (bChanged)
663 DecDepth();
665 return bNeedSave;
668 bool ScOutlineArray::ManualAction(
669 SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, const ScTable& rTable, bool bCol)
671 bool bModified = false;
672 ScSubOutlineIterator aIter( this );
673 ScOutlineEntry* pEntry;
674 while((pEntry=aIter.GetNext())!=nullptr)
676 SCCOLROW nEntryStart = pEntry->GetStart();
677 SCCOLROW nEntryEnd = pEntry->GetEnd();
679 if (nEntryEnd>=nStartPos && nEntryStart<=nEndPos)
681 if ( pEntry->IsHidden() == bShow )
683 // #i12341# hide if all columns/rows are hidden, show if at least one
684 // is visible
685 SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol);
686 bool bAllHidden = (nEntryEnd <= nEnd && nEnd <
687 ::std::numeric_limits<SCCOLROW>::max());
689 bool bToggle = ( bShow != bAllHidden );
690 if ( bToggle )
692 pEntry->SetHidden( !bShow );
693 SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow );
694 bModified = true;
699 return bModified;
702 void ScOutlineArray::RemoveAll()
704 for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
705 aCollections[nLevel].clear();
707 nDepth = 0;
710 void ScOutlineArray::finalizeImport(const ScTable& rTable)
712 ScSubOutlineIterator aIter( this );
713 ScOutlineEntry* pEntry;
714 while((pEntry=aIter.GetNext())!=nullptr)
717 if (!pEntry->IsHidden())
718 continue;
720 SCCOLROW nEntryStart = pEntry->GetStart();
721 SCCOLROW nEntryEnd = pEntry->GetEnd();
722 SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, false/*bCol*/);
723 bool bAllHidden = (nEntryEnd <= nEnd && nEnd <
724 ::std::numeric_limits<SCCOLROW>::max());
726 pEntry->SetHidden(bAllHidden);
727 SetVisibleBelow(aIter.LastLevel(), aIter.LastEntry(), !bAllHidden, !bAllHidden);
731 OString ScOutlineArray::dumpAsString() const
733 OString aOutput;
734 const char* const pLevelSep = " ";
735 for (const auto& rCollection : aCollections)
737 if (rCollection.empty())
738 continue;
739 aOutput += rCollection.dumpAsString() + pLevelSep;
742 return aOutput;
745 ScOutlineTable::ScOutlineTable()
749 ScOutlineTable::ScOutlineTable( const ScOutlineTable& rOutline ) :
750 aColOutline( rOutline.aColOutline ),
751 aRowOutline( rOutline.aRowOutline )
755 bool ScOutlineTable::TestInsertCol( SCSIZE nSize )
757 return aColOutline.TestInsertSpace( nSize, MAXCOL );
760 void ScOutlineTable::InsertCol( SCCOL nStartCol, SCSIZE nSize )
762 aColOutline.InsertSpace( nStartCol, nSize );
765 bool ScOutlineTable::DeleteCol( SCCOL nStartCol, SCSIZE nSize )
767 return aColOutline.DeleteSpace( nStartCol, nSize );
770 bool ScOutlineTable::TestInsertRow( SCSIZE nSize )
772 return aRowOutline.TestInsertSpace( nSize, MAXROW );
775 void ScOutlineTable::InsertRow( SCROW nStartRow, SCSIZE nSize )
777 aRowOutline.InsertSpace( nStartRow, nSize );
780 bool ScOutlineTable::DeleteRow( SCROW nStartRow, SCSIZE nSize )
782 return aRowOutline.DeleteSpace( nStartRow, nSize );
785 ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray ) :
786 pArray( pOutlineArray ),
787 nStart( 0 ),
788 nEnd( SCCOLROW_MAX ), // Iterate over all of them
789 nSubLevel( 0 ),
790 nSubEntry( 0 )
792 nDepth = pArray->nDepth;
795 ScSubOutlineIterator::ScSubOutlineIterator(
796 ScOutlineArray* pOutlineArray, size_t nLevel, size_t nEntry ) :
797 pArray( pOutlineArray )
799 const ScOutlineCollection& rColl = pArray->aCollections[nLevel];
800 ScOutlineCollection::const_iterator it = rColl.begin();
801 std::advance(it, nEntry);
802 const ScOutlineEntry* pEntry = &it->second;
803 nStart = pEntry->GetStart();
804 nEnd = pEntry->GetEnd();
805 nSubLevel = nLevel + 1;
806 nSubEntry = 0;
807 nDepth = pArray->nDepth;
810 ScOutlineEntry* ScSubOutlineIterator::GetNext()
812 ScOutlineEntry* pEntry = nullptr;
813 bool bFound = false;
816 if (nSubLevel >= nDepth)
817 return nullptr;
819 ScOutlineCollection& rColl = pArray->aCollections[nSubLevel];
820 if (nSubEntry < rColl.size())
822 ScOutlineCollection::iterator it = rColl.begin();
823 std::advance(it, nSubEntry);
824 pEntry = &it->second;
826 if (pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd)
827 bFound = true;
829 ++nSubEntry;
831 else
833 // Go to the next sub-level
834 nSubEntry = 0;
835 ++nSubLevel;
838 while (!bFound);
839 return pEntry; // nSubLevel valid, if pEntry != 0
842 size_t ScSubOutlineIterator::LastEntry() const
844 if (nSubEntry == 0)
846 OSL_FAIL("ScSubOutlineIterator::LastEntry before GetNext");
847 return 0;
849 return nSubEntry-1;
852 void ScSubOutlineIterator::DeleteLast()
854 if (nSubLevel >= nDepth)
856 OSL_FAIL("ScSubOutlineIterator::DeleteLast after End");
857 return;
859 if (nSubEntry == 0)
861 OSL_FAIL("ScSubOutlineIterator::DeleteLast before GetNext");
862 return;
865 --nSubEntry;
866 ScOutlineCollection& rColl = pArray->aCollections[nSubLevel];
867 assert(nSubEntry < rColl.size());
868 ScOutlineCollection::iterator it = rColl.begin();
869 std::advance(it, nSubEntry);
870 rColl.erase(it);
873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */