nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / SwNumberTree / SwNumberTree.cxx
blobba15af2c0f90c47b8a00e9231da18eca720b0c11
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 <algorithm>
21 #include <SwNumberTree.hxx>
22 #include <osl/diagnose.h>
23 #include <sal/log.hxx>
25 #include <cassert>
27 using std::vector;
28 using std::find;
30 SwNumberTreeNode::SwNumberTreeNode()
31 : mChildren(),
32 mpParent( nullptr ),
33 mnNumber( 0 ),
34 mbContinueingPreviousSubTree( false ),
35 mbPhantom( false ),
36 mItLastValid()
38 mItLastValid = mChildren.end();
41 SwNumberTreeNode::~SwNumberTreeNode()
43 if (GetChildCount() > 0)
45 if (HasOnlyPhantoms())
47 delete *mChildren.begin();
49 mChildren.clear();
50 mItLastValid = mChildren.end();
52 else
54 OSL_FAIL("lost children!");
58 OSL_ENSURE( IsPhantom() || mpParent == nullptr, ": I'm not supposed to have a parent.");
60 mpParent = reinterpret_cast<SwNumberTreeNode *>(0xdeadbeef);
62 OSL_ENSURE(mChildren.empty(), "children left!");
65 SwNumberTreeNode * SwNumberTreeNode::CreatePhantom()
67 SwNumberTreeNode * pNew = nullptr;
69 if (! mChildren.empty() &&
70 (*mChildren.begin())->IsPhantom())
72 OSL_FAIL("phantom already present");
74 else
76 pNew = Create();
77 pNew->mbPhantom = true;
78 pNew->mpParent = this;
80 std::pair<tSwNumberTreeChildren::iterator, bool> aInsert =
81 mChildren.insert(pNew);
83 if (! aInsert.second)
85 OSL_FAIL("insert of phantom failed!");
87 delete pNew;
88 pNew = nullptr;
92 return pNew;
95 SwNumberTreeNode * SwNumberTreeNode::GetRoot() const
97 SwNumberTreeNode * pResult = mpParent;
99 if (pResult)
100 while (pResult->mpParent)
101 pResult = pResult->mpParent;
103 return pResult;
106 void SwNumberTreeNode::ClearObsoletePhantoms()
108 tSwNumberTreeChildren::iterator aIt = mChildren.begin();
110 if (!(aIt != mChildren.end() && (*aIt)->IsPhantom()))
111 return;
113 (*aIt)->ClearObsoletePhantoms();
115 if ((*aIt)->mChildren.empty())
117 // #i60652#
118 // Because <mChildren.erase(aIt)> could destroy the element, which
119 // is referenced by <mItLastValid>, it's needed to adjust
120 // <mItLastValid> before erasing <aIt>.
121 SetLastValid(mChildren.end());
123 delete *aIt;
124 mChildren.erase(aIt);
128 void SwNumberTreeNode::ValidateHierarchical(const SwNumberTreeNode * pNode) const
130 tSwNumberTreeChildren::const_iterator aValidateIt =
131 GetIterator(pNode);
133 if (aValidateIt == mChildren.end())
134 return;
136 OSL_ENSURE((*aValidateIt)->mpParent == this, "wrong parent");
138 tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
140 // -->
141 // improvement:
142 // - Only one time checked for <mChildren.end()>.
143 // - Less checks for each loop run.
144 // correction:
145 // - consider case that current node isn't counted and isn't the first
146 // child of its parent. In this case the number of last counted child
147 // of the previous node determines the start value for the following
148 // children loop, if all children have to be validated and the first
149 // one doesn't restart the counting.
150 SwNumberTree::tSwNumTreeNumber nTmpNumber( 0 );
151 if (aIt != mChildren.end())
152 nTmpNumber = (*aIt)->mnNumber;
153 else
155 aIt = mChildren.begin();
156 (*aIt)->mbContinueingPreviousSubTree = false;
158 // determine default start value
159 // consider the case that the first child isn't counted.
160 nTmpNumber = (*aIt)->GetStartValue();
161 if ( !(*aIt)->IsCounted() &&
162 ( !(*aIt)->HasCountedChildren() || (*aIt)->IsPhantom() ) )
164 --nTmpNumber;
167 // determine special start value for the case that first child
168 // doesn't restart the numbering and the parent node isn't counted
169 // and isn't the first child.
170 const bool bParentCounted( IsCounted() &&
171 ( !IsPhantom() ||
172 HasPhantomCountedParent() ) );
173 if ( !(*aIt)->IsRestart() &&
174 GetParent() && !bParentCounted )
176 tSwNumberTreeChildren::const_iterator aParentChildIt =
177 GetParent()->GetIterator( this );
178 while ( aParentChildIt != GetParent()->mChildren.begin() )
180 --aParentChildIt;
181 SwNumberTreeNode* pPrevNode( *aParentChildIt );
182 if ( pPrevNode->GetChildCount() > 0 )
184 (*aIt)->mbContinueingPreviousSubTree = true;
185 nTmpNumber = (*(pPrevNode->mChildren.rbegin()))->GetNumber();
186 if ( (*aIt)->IsCounted() &&
187 ( !(*aIt)->IsPhantom() ||
188 (*aIt)->HasPhantomCountedParent() ) )
190 ++nTmpNumber;
192 break;
194 else if ( pPrevNode->IsCounted() )
196 break;
198 else
200 // Previous node has no children and is not counted.
201 // Thus, next turn and check for the previous node.
206 (*aIt)->mnNumber = nTmpNumber;
209 while (aIt != aValidateIt)
211 ++aIt;
212 (*aIt)->mbContinueingPreviousSubTree = false;
214 // --> only for counted nodes the number
215 // has to be adjusted, compared to the previous node.
216 // this condition is hold also for nodes, which restart the numbering.
217 if ( (*aIt)->IsCounted() )
219 if ((*aIt)->IsRestart())
220 nTmpNumber = (*aIt)->GetStartValue();
221 else
222 ++nTmpNumber;
225 (*aIt)->mnNumber = nTmpNumber;
228 SetLastValid(aIt, true);
231 void SwNumberTreeNode::ValidateContinuous(const SwNumberTreeNode * pNode) const
233 tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
237 if (aIt == mChildren.end())
239 aIt = mChildren.begin();
241 else
242 ++aIt;
244 if (aIt != mChildren.end())
246 SwNumberTree::tSwNumTreeNumber nTmpNumber = 0;
247 SwNumberTreeNode * pPred = (*aIt)->GetPred();
249 // #i64311#
250 // correct consideration of phantoms
251 // correct consideration of restart at a number tree node
252 if ( pPred )
254 if ( !(*aIt)->IsCounted() )
255 // #i65284#
256 nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() );
257 else
259 if ( (*aIt)->IsRestart() )
260 nTmpNumber = (*aIt)->GetStartValue();
261 else
262 nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() ) + 1;
265 else
267 if ( !(*aIt)->IsCounted() )
268 nTmpNumber = GetStartValue() - 1;
269 else
271 if ( (*aIt)->IsRestart() )
272 nTmpNumber = (*aIt)->GetStartValue();
273 else
274 nTmpNumber = GetStartValue();
278 (*aIt)->mnNumber = nTmpNumber;
281 while (aIt != mChildren.end() && *aIt != pNode);
283 // #i74748# - applied patch from garnier_romain
284 // number tree node has to be validated.
285 SetLastValid( aIt, true );
288 void SwNumberTreeNode::Validate(const SwNumberTreeNode * pNode) const
290 if (! IsValid(pNode))
292 if (IsContinuous())
293 ValidateContinuous(pNode);
294 else
295 ValidateHierarchical(pNode);
299 void SwNumberTreeNode::GetNumberVector_(SwNumberTree::tNumberVector & rVector,
300 bool bValidate) const
302 if (mpParent)
304 mpParent->GetNumberVector_(rVector, bValidate);
305 rVector.push_back(GetNumber(bValidate));
309 SwNumberTreeNode * SwNumberTreeNode::GetFirstNonPhantomChild()
311 if (IsPhantom())
312 return (*mChildren.begin())->GetFirstNonPhantomChild();
314 return this;
317 /** Moves all children of this node that are greater than a given node
318 to the destination node.
320 void SwNumberTreeNode::MoveGreaterChildren( SwNumberTreeNode& _rCompareNode,
321 SwNumberTreeNode& _rDestNode )
323 if ( mChildren.empty() )
324 return;
326 // determine first child, which has to move to <_rDestNode>
327 tSwNumberTreeChildren::iterator aItUpper( mChildren.end() );
328 if ((*mChildren.begin())->IsPhantom() &&
329 _rCompareNode.LessThan(*(*mChildren.begin())->GetFirstNonPhantomChild()))
331 aItUpper = mChildren.begin();
333 else
335 aItUpper = mChildren.upper_bound(&_rCompareNode);
338 // move children
339 if (aItUpper != mChildren.end())
341 tSwNumberTreeChildren::iterator aIt;
342 for (aIt = aItUpper; aIt != mChildren.end(); ++aIt)
343 (*aIt)->mpParent = &_rDestNode;
345 _rDestNode.mChildren.insert(aItUpper, mChildren.end());
347 // #i60652#
348 // Because <mChildren.erase(aItUpper, mChildren.end())> could destroy
349 // the element, which is referenced by <mItLastValid>, it's needed to
350 // adjust <mItLastValid> before erasing <aIt>.
351 SetLastValid( mChildren.end() );
353 mChildren.erase(aItUpper, mChildren.end());
355 // #i60652#
356 if ( !mChildren.empty() )
358 SetLastValid( --(mChildren.end()) );
362 #ifdef DBG_UTIL
363 IsSane(false);
364 _rDestNode.IsSane(true);
365 #endif
368 void SwNumberTreeNode::MoveChildren(SwNumberTreeNode * pDest)
370 if (! mChildren.empty())
372 tSwNumberTreeChildren::iterator aItBegin = mChildren.begin();
373 SwNumberTreeNode * pMyFirst = *mChildren.begin();
375 // #i60652#
376 // Because <mChildren.erase(aItBegin)> could destroy the element,
377 // which is referenced by <mItLastValid>, it's needed to adjust
378 // <mItLastValid> before erasing <aItBegin>.
379 SetLastValid(mChildren.end());
381 if (pMyFirst->IsPhantom())
383 SwNumberTreeNode * pDestLast = nullptr;
385 if (pDest->mChildren.empty())
386 pDestLast = pDest->CreatePhantom();
387 else
388 pDestLast = *pDest->mChildren.rbegin();
390 pMyFirst->MoveChildren(pDestLast);
392 delete pMyFirst;
393 mChildren.erase(aItBegin);
395 aItBegin = mChildren.begin();
398 for (auto& rpChild : mChildren)
399 rpChild->mpParent = pDest;
401 pDest->mChildren.insert(mChildren.begin(), mChildren.end());
402 mChildren.clear();
403 // <stl::set.clear()> destroys all existing iterators.
404 // Thus, <mItLastValid> is also destroyed and reset becomes necessary
405 mItLastValid = mChildren.end();
408 OSL_ENSURE(mChildren.empty(), "MoveChildren failed!");
410 #ifdef DBG_UTIL
411 IsSane(false);
412 pDest->IsSane(false);
413 #endif
416 void SwNumberTreeNode::AddChild( SwNumberTreeNode * pChild,
417 const int nDepth )
420 Algorithm:
422 Search first child A that is greater than pChild,
423 A may be the end of children.
424 If nDepth > 0 then
426 if A is first child then
427 create new phantom child B at beginning of child list
428 else
429 B is A
431 Add child to B with depth nDepth - 1.
433 else
435 Insert pNode before A.
437 if A has predecessor B then
438 remove children of B that are greater as A and insert them as
439 children of A.
444 if ( nDepth < 0 )
446 OSL_FAIL( "<SwNumberTreeNode::AddChild(..)> - parameter <nDepth> out of valid range. Serious defect." );
447 return;
450 if ( pChild->GetParent() != nullptr || pChild->GetChildCount() > 0 )
452 OSL_FAIL("only orphans allowed.");
453 return;
456 if (nDepth > 0)
458 tSwNumberTreeChildren::iterator aInsertDeepIt =
459 mChildren.upper_bound(pChild);
461 OSL_ENSURE(! (aInsertDeepIt != mChildren.end() &&
462 (*aInsertDeepIt)->IsPhantom()), " unexpected phantom");
464 if (aInsertDeepIt == mChildren.begin())
466 SwNumberTreeNode * pNew = CreatePhantom();
468 SetLastValid(mChildren.end());
470 if (pNew)
471 pNew->AddChild(pChild, nDepth - 1);
473 else
475 --aInsertDeepIt;
476 (*aInsertDeepIt)->AddChild(pChild, nDepth - 1);
480 else
482 pChild->PreAdd();
483 std::pair<tSwNumberTreeChildren::iterator, bool> aResult =
484 mChildren.insert(pChild);
486 if (aResult.second)
488 pChild->mpParent = this;
489 bool bNotification = pChild->IsNotificationEnabled();
490 tSwNumberTreeChildren::iterator aInsertedIt = aResult.first;
492 if (aInsertedIt != mChildren.begin())
494 tSwNumberTreeChildren::iterator aPredIt = aInsertedIt;
495 --aPredIt;
497 // -->
498 // Move greater children of previous node to new child.
499 // This has to be done recursively on the children levels.
500 // Initialize loop variables <pPrevChildNode> and <pDestNode>
501 // for loop on children levels.
502 SwNumberTreeNode* pPrevChildNode( *aPredIt );
503 SwNumberTreeNode* pDestNode( pChild );
504 while ( pDestNode && pPrevChildNode &&
505 pPrevChildNode->GetChildCount() > 0 )
507 // move children
508 pPrevChildNode->MoveGreaterChildren( *pChild, *pDestNode );
510 // prepare next loop:
511 // - search of last child of <pPrevChildNode
512 // - If found, determine destination node
513 if ( pPrevChildNode->GetChildCount() > 0 )
515 tSwNumberTreeChildren::reverse_iterator aIt =
516 pPrevChildNode->mChildren.rbegin();
517 pPrevChildNode = *aIt;
518 // determine new destination node
519 if ( pDestNode->GetChildCount() > 0 )
521 pDestNode = *(pDestNode->mChildren.begin());
522 if ( !pDestNode->IsPhantom() )
524 pDestNode = pDestNode->mpParent->CreatePhantom();
527 else
529 pDestNode = pDestNode->CreatePhantom();
532 else
534 // ready -> break loop.
535 break;
538 // assure that unnecessary created phantoms at <pChild> are deleted.
539 pChild->ClearObsoletePhantoms();
541 if ((*aPredIt)->IsValid())
542 SetLastValid(aPredIt);
544 else
545 SetLastValid(mChildren.end());
547 ClearObsoletePhantoms();
549 if( bNotification )
551 // invalidation of not counted parent
552 // and notification of its siblings.
553 if ( !IsCounted() )
555 InvalidateMe();
556 NotifyInvalidSiblings();
558 NotifyInvalidChildren();
563 #ifdef DBG_UTIL
564 IsSane(false);
565 #endif
568 void SwNumberTreeNode::RemoveChild(SwNumberTreeNode * pChild)
571 Algorithm:
573 if pChild has predecessor A then
574 B is A
575 else
576 create phantom child B at beginning of child list
578 Move children of pChild to B.
581 if (pChild->IsPhantom())
583 OSL_FAIL("not applicable to phantoms!");
585 return;
588 tSwNumberTreeChildren::const_iterator aRemoveIt = GetIterator(pChild);
590 if (aRemoveIt != mChildren.end())
592 SwNumberTreeNode * pRemove = *aRemoveIt;
594 pRemove->mpParent = nullptr;
596 tSwNumberTreeChildren::const_iterator aItPred = mChildren.end();
598 if (aRemoveIt == mChildren.begin())
600 if (! pRemove->mChildren.empty())
602 CreatePhantom();
604 aItPred = mChildren.begin();
607 else
609 aItPred = aRemoveIt;
610 --aItPred;
613 if (! pRemove->mChildren.empty())
615 pRemove->MoveChildren(*aItPred);
616 (*aItPred)->InvalidateTree();
617 (*aItPred)->NotifyInvalidChildren();
620 // #i60652#
621 // Because <mChildren.erase(aRemoveIt)> could destroy the element,
622 // which is referenced by <mItLastValid>, it's needed to adjust
623 // <mItLastValid> before erasing <aRemoveIt>.
624 if (aItPred != mChildren.end() && (*aItPred)->IsPhantom())
625 SetLastValid(mChildren.end());
626 else
627 SetLastValid(aItPred);
629 mChildren.erase(aRemoveIt);
631 NotifyInvalidChildren();
633 else
635 OSL_FAIL("RemoveChild: failed!");
638 pChild->PostRemove();
641 void SwNumberTreeNode::RemoveMe()
643 if (!mpParent)
644 return;
646 SwNumberTreeNode * pSavedParent = mpParent;
648 pSavedParent->RemoveChild(this);
650 while (pSavedParent && pSavedParent->IsPhantom() &&
651 pSavedParent->HasOnlyPhantoms())
652 pSavedParent = pSavedParent->GetParent();
654 if (pSavedParent)
655 pSavedParent->ClearObsoletePhantoms();
657 #ifdef DBG_UTIL
658 IsSane(false);
659 #endif
662 bool SwNumberTreeNode::IsValid() const
664 return mpParent && mpParent->IsValid(this);
667 SwNumberTree::tSwNumTreeNumber SwNumberTreeNode::GetNumber(bool bValidate)
668 const
670 if (bValidate && mpParent)
671 mpParent->Validate(this);
673 return mnNumber;
677 SwNumberTree::tNumberVector SwNumberTreeNode::GetNumberVector() const
679 vector<SwNumberTree::tSwNumTreeNumber> aResult;
681 GetNumberVector_(aResult);
683 return aResult;
686 bool SwNumberTreeNode::IsValid(const SwNumberTreeNode * pChild) const
688 bool bResult = false;
690 if (mItLastValid != mChildren.end())
692 if (pChild && pChild->mpParent == this)
694 bResult = ! (*mItLastValid)->LessThan(*pChild);
698 return bResult;
702 bool SwNumberTreeNode::HasOnlyPhantoms() const
704 bool bResult = false;
706 if (GetChildCount() == 1)
708 tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
710 bResult = (*aIt)->IsPhantom() && (*aIt)->HasOnlyPhantoms();
712 else if (GetChildCount() == 0)
713 bResult = true;
715 return bResult;
718 bool SwNumberTreeNode::IsCounted() const
720 return !IsPhantom() ||
721 ( IsCountPhantoms() && HasCountedChildren() );
724 bool SwNumberTreeNode::HasPhantomCountedParent() const
726 bool bRet( false );
728 OSL_ENSURE( IsPhantom(),
729 "<SwNumberTreeNode::HasPhantomCountedParent()> - wrong usage of method - it's only for phantoms" );
730 if ( IsPhantom() && mpParent )
732 if ( mpParent == GetRoot() )
734 bRet = true;
736 else if ( !mpParent->IsPhantom() )
738 bRet = mpParent->IsCounted();
740 else
742 bRet = mpParent->IsCounted() && mpParent->HasPhantomCountedParent();
746 return bRet;
749 bool SwNumberTreeNode::IsFirst(const SwNumberTreeNode * pNode) const
751 tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
753 if ((*aIt)->IsPhantom())
754 ++aIt;
756 return *aIt == pNode;
759 bool SwNumberTreeNode::IsFirst() const
761 bool bResult = true;
763 if (GetParent())
765 if (GetParent()->IsFirst(this))
767 SwNumberTreeNode * pNode = GetParent();
769 while (pNode)
771 if (!pNode->IsPhantom() && pNode->GetParent())
773 bResult = false;
774 break;
777 pNode = pNode->GetParent();
780 // If node isn't the first child, it is the second child and the
781 // first child is a phantom. In this case check, if the first phantom
782 // child have only phantom children
783 if ( bResult &&
784 this != *(GetParent()->mChildren.begin()) &&
785 !(*(GetParent()->mChildren.begin()))->HasOnlyPhantoms() )
787 bResult = false;
790 else
791 bResult = false;
794 return bResult;
797 void SwNumberTreeNode::SetLevelInListTree( const int nLevel )
799 if ( nLevel < 0 )
801 OSL_FAIL( "<SwNumberTreeNode::SetLevelInListTree(..)> - parameter <nLevel> out of valid range. Serious defect." );
802 return;
805 OSL_ENSURE( GetParent(),
806 "<SwNumberTreeNode::SetLevelInListTree(..)> - can only be called for number tree nodes in a list tree" );
807 if ( GetParent() )
809 if ( nLevel != GetLevelInListTree() )
811 SwNumberTreeNode* pRootTreeNode = GetRoot();
812 OSL_ENSURE( pRootTreeNode,
813 "<SwNumberTreeNode::SetLevelInListTree(..)> - no root tree node found. Serious defect." );
815 RemoveMe();
816 pRootTreeNode->AddChild( this, nLevel );
821 int SwNumberTreeNode::GetLevelInListTree() const
823 if (mpParent)
824 return mpParent->GetLevelInListTree() + 1;
826 return -1;
829 SwNumberTreeNode::tSwNumberTreeChildren::size_type
830 SwNumberTreeNode::GetChildCount() const
832 return mChildren.size();
835 #ifdef DBG_UTIL
836 void SwNumberTreeNode::IsSane(bool bRecursive) const
838 vector<const SwNumberTreeNode*> aParents;
840 return IsSane(bRecursive, aParents);
843 void SwNumberTreeNode::IsSane(bool bRecursive,
844 vector<const SwNumberTreeNode *> rParents)
845 const
847 assert(find(rParents.begin(), rParents.end(), this) == rParents.end());
849 assert(rParents.empty() || rParents.back() == mpParent);
851 rParents.push_back(this);
853 bool bFirst = true;
854 for (const auto& rpChild : mChildren)
856 if (rpChild)
858 if (rpChild->IsPhantom())
860 SAL_WARN_IF(rpChild->HasOnlyPhantoms(), "sw.core",
861 "HasOnlyPhantoms: is this an error?");
863 assert(bFirst && "found phantom not at first position.");
866 assert(rpChild->mpParent == this);
868 if (mpParent)
870 assert(rpChild->IsPhantom() || !rpChild->LessThan(*this));
873 else
875 assert(!"found child that is NULL");
878 if (bRecursive)
880 rpChild->IsSane(bRecursive, rParents);
883 bFirst = false;
886 rParents.pop_back();
888 #endif // DBG_UTIL
890 SwNumberTreeNode::tSwNumberTreeChildren::const_iterator
891 SwNumberTreeNode::GetIterator(const SwNumberTreeNode * pChild) const
893 tSwNumberTreeChildren::const_iterator aItResult =
894 mChildren.find(const_cast<SwNumberTreeNode *>(pChild));
896 OSL_ENSURE( aItResult != mChildren.end(),
897 "something went wrong getting the iterator for a child");
899 return aItResult;
902 bool SwNumberTreeNodeLessThan(const SwNumberTreeNode * pA,
903 const SwNumberTreeNode * pB)
905 bool bResult = false;
907 if (pA == nullptr && pB != nullptr)
908 bResult = true;
909 else if (pA != nullptr && pB != nullptr)
910 bResult = pA->LessThan(*pB);
912 return bResult;
915 SwNumberTreeNode * SwNumberTreeNode::GetLastDescendant() const
917 SwNumberTreeNode * pResult = nullptr;
918 tSwNumberTreeChildren::const_reverse_iterator aIt = mChildren.rbegin();
920 if (aIt != mChildren.rend())
922 pResult = (*aIt)->GetLastDescendant();
924 if (! pResult)
925 pResult = *aIt;
928 return pResult;
931 bool SwNumberTreeNode::LessThan(const SwNumberTreeNode & rTreeNode) const
933 return this < &rTreeNode;
936 SwNumberTreeNode * SwNumberTreeNode::GetPred(bool bSibling) const
938 SwNumberTreeNode * pResult = nullptr;
940 if (mpParent)
942 tSwNumberTreeChildren::const_iterator aIt =
943 mpParent->GetIterator(this);
945 if ( aIt == mpParent->mChildren.begin() )
947 // #i64311#
948 // root node is no valid predecessor
949 pResult = mpParent->GetParent() ? mpParent : nullptr;
951 else
953 --aIt;
955 if ( !bSibling )
956 pResult = (*aIt)->GetLastDescendant();
957 else
958 pResult = (*aIt);
960 if (! pResult)
961 pResult = (*aIt);
965 return pResult;
968 void SwNumberTreeNode::SetLastValid
969 ( const SwNumberTreeNode::tSwNumberTreeChildren::const_iterator& aItValid,
970 bool bValidating ) const
972 OSL_ENSURE( (aItValid == mChildren.end() || GetIterator(*aItValid) != mChildren.end()),
973 "last-valid iterator");
975 if (
976 bValidating ||
977 aItValid == mChildren.end() ||
978 (mItLastValid != mChildren.end() &&
979 (*aItValid)->LessThan(**mItLastValid))
982 mItLastValid = aItValid;
983 // invalidation of children of next not counted is needed
984 if ( GetParent() )
986 tSwNumberTreeChildren::const_iterator aParentChildIt =
987 GetParent()->GetIterator( this );
988 ++aParentChildIt;
989 if ( aParentChildIt != GetParent()->mChildren.end() )
991 SwNumberTreeNode* pNextNode( *aParentChildIt );
992 if ( !pNextNode->IsCounted() )
994 pNextNode->InvalidateChildren();
1001 if (IsContinuous())
1003 tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
1005 if (aIt != mChildren.end())
1006 ++aIt;
1007 else
1008 aIt = mChildren.begin();
1010 while (aIt != mChildren.end())
1012 (*aIt)->InvalidateTree();
1014 ++aIt;
1017 if (mpParent)
1019 mpParent->SetLastValid(mpParent->GetIterator(this), bValidating);
1025 void SwNumberTreeNode::InvalidateTree() const
1027 // do not call SetInvalid, would cause loop !!!
1028 mItLastValid = mChildren.end();
1030 for (const auto& rpChild : mChildren)
1031 rpChild->InvalidateTree();
1034 void SwNumberTreeNode::Invalidate(SwNumberTreeNode const * pChild)
1036 if (pChild->IsValid())
1038 tSwNumberTreeChildren::const_iterator aIt = GetIterator(pChild);
1040 if (aIt != mChildren.begin())
1041 --aIt;
1042 else
1043 aIt = mChildren.end();
1045 SetLastValid(aIt);
1050 void SwNumberTreeNode::InvalidateMe()
1052 if (mpParent)
1053 mpParent->Invalidate(this);
1056 void SwNumberTreeNode::ValidateMe()
1058 if (mpParent)
1059 mpParent->Validate(this);
1062 void SwNumberTreeNode::Notify()
1064 if (IsNotifiable())
1066 if (! IsPhantom())
1067 NotifyNode();
1069 for (auto& rpChild : mChildren)
1070 rpChild->Notify();
1074 void SwNumberTreeNode::NotifyInvalidChildren()
1076 if (IsNotifiable())
1078 tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
1080 if (aIt == mChildren.end())
1081 aIt = mChildren.begin();
1082 else
1083 ++aIt;
1085 while (aIt != mChildren.end())
1087 (*aIt)->Notify();
1089 ++aIt;
1091 // notification of next not counted node is also needed.
1092 if ( GetParent() )
1094 tSwNumberTreeChildren::const_iterator aParentChildIt =
1095 GetParent()->GetIterator( this );
1096 ++aParentChildIt;
1097 if ( aParentChildIt != GetParent()->mChildren.end() )
1099 SwNumberTreeNode* pNextNode( *aParentChildIt );
1100 if ( !pNextNode->IsCounted() )
1102 pNextNode->NotifyInvalidChildren();
1109 if (IsContinuous() && mpParent)
1110 mpParent->NotifyInvalidChildren();
1113 void SwNumberTreeNode::NotifyInvalidSiblings()
1115 if (mpParent != nullptr)
1116 mpParent->NotifyInvalidChildren();
1119 // #i81002#
1120 const SwNumberTreeNode* SwNumberTreeNode::GetPrecedingNodeOf(
1121 const SwNumberTreeNode& rNode ) const
1123 const SwNumberTreeNode* pPrecedingNode( nullptr );
1125 if ( GetChildCount() > 0 )
1127 tSwNumberTreeChildren::const_iterator aUpperBoundIt =
1128 mChildren.upper_bound( const_cast<SwNumberTreeNode*>(&rNode) );
1129 if ( aUpperBoundIt != mChildren.begin() )
1131 --aUpperBoundIt;
1132 pPrecedingNode = (*aUpperBoundIt)->GetPrecedingNodeOf( rNode );
1136 if ( pPrecedingNode == nullptr && GetRoot() )
1138 // <this> node has no children or the given node precedes all its children
1139 // and the <this> node isn't the root node.
1140 // Thus, compare the given node with the <this> node in order to check,
1141 // if the <this> node precedes the given node.
1142 if ( !(rNode.LessThan( *this )) )
1144 pPrecedingNode = this;
1148 return pPrecedingNode;
1151 void SwNumberTreeNode::NotifyNodesOnListLevel( const int nListLevel )
1153 if ( nListLevel < 0 )
1155 OSL_FAIL( "<SwNumberTreeNode::NotifyNodesOnListLevel(..)> - invalid list level provided" );
1156 return;
1159 SwNumberTreeNode* pRootNode = GetParent() ? GetRoot() : this;
1161 pRootNode->NotifyChildrenOnDepth( nListLevel );
1164 void SwNumberTreeNode::NotifyChildrenOnDepth( const int nDepth )
1166 OSL_ENSURE( nDepth >= 0,
1167 "<SwNumberTreeNode::NotifyChildrenOnDepth(..)> - misusage" );
1169 for ( const auto& rpChild : mChildren )
1171 if ( nDepth == 0 )
1173 rpChild->NotifyNode();
1175 else
1177 rpChild->NotifyChildrenOnDepth( nDepth - 1 );
1182 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */