summaryrefslogtreecommitdiff
path: root/sw/source/core/SwNumberTree/SwNumberTree.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/SwNumberTree/SwNumberTree.cxx')
-rw-r--r--sw/source/core/SwNumberTree/SwNumberTree.cxx1409
1 files changed, 1409 insertions, 0 deletions
diff --git a/sw/source/core/SwNumberTree/SwNumberTree.cxx b/sw/source/core/SwNumberTree/SwNumberTree.cxx
new file mode 100644
index 000000000000..05c30aa97f5b
--- /dev/null
+++ b/sw/source/core/SwNumberTree/SwNumberTree.cxx
@@ -0,0 +1,1409 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <algorithm>
+#include <functional>
+#include <errhdl.hxx>
+#include <SwNumberTree.hxx>
+
+using std::vector;
+using std::find;
+
+#ifdef DBG_UTIL
+unsigned long SwNumberTreeNode::nInstances = 0;
+#endif
+
+SwNumberTreeNode::SwNumberTreeNode()
+ : mChildren(),
+ mpParent( 0 ),
+ mnNumber( 0 ),
+ // --> OD 2008-11-26 #158694#
+ mbContinueingPreviousSubTree( false ),
+ // <--
+ mbPhantom( false ),
+ mItLastValid()
+{
+ mItLastValid = mChildren.end();
+
+#ifdef DBG_UTIL
+ mnSerial = nInstances;
+ nInstances++;
+#endif
+}
+
+SwNumberTreeNode::~SwNumberTreeNode()
+{
+ if (GetChildCount() > 0)
+ {
+ if (HasOnlyPhantoms())
+ {
+ delete *mChildren.begin();
+
+ mChildren.clear();
+ mItLastValid = mChildren.end();
+ }
+ else
+ {
+ ASSERT(false, "lost children!");
+ }
+ }
+
+ ASSERT( IsPhantom() || mpParent == NULL, ": I'm not supposed to have a parent.");
+
+#ifdef DBG_UTIL
+ nInstances--;
+#endif
+
+ mpParent = (SwNumberTreeNode *) 0xdeadbeef;
+
+ ASSERT(mChildren.empty(), "children left!");
+}
+
+SwNumberTreeNode * SwNumberTreeNode::CreatePhantom()
+{
+ SwNumberTreeNode * pNew = NULL;
+
+ if (! mChildren.empty() &&
+ (*mChildren.begin())->IsPhantom())
+ {
+ ASSERT(false, "phantom already present");
+ }
+ else
+ {
+ pNew = Create();
+ pNew->SetPhantom(true);
+ pNew->mpParent = this;
+
+ std::pair<tSwNumberTreeChildren::iterator, bool> aInsert =
+ mChildren.insert(pNew);
+
+ if (! aInsert.second)
+ {
+ ASSERT(false, "insert of phantom failed!");
+
+ delete pNew;
+ pNew = NULL;
+ }
+ }
+
+ return pNew;
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetRoot() const
+{
+ SwNumberTreeNode * pResult = mpParent;
+
+ if (pResult)
+ while (pResult->mpParent)
+ pResult = pResult->mpParent;
+
+ return pResult;
+}
+
+void SwNumberTreeNode::ClearObsoletePhantoms()
+{
+ tSwNumberTreeChildren::iterator aIt = mChildren.begin();
+
+ if (aIt != mChildren.end() && (*aIt)->IsPhantom())
+ {
+ (*aIt)->ClearObsoletePhantoms();
+
+ if ((*aIt)->mChildren.empty())
+ {
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aIt)> could destroy the element, which
+ // is referenced by <mItLastValid>, it's needed to adjust
+ // <mItLastValid> before erasing <aIt>.
+ SetLastValid(mChildren.end());
+ // <--
+
+ delete *aIt;
+ mChildren.erase(aIt);
+ }
+ }
+}
+
+void SwNumberTreeNode::ValidateHierarchical(const SwNumberTreeNode * pNode) const
+{
+ tSwNumberTreeChildren::iterator aValidateIt =
+ GetIterator(pNode);
+
+ if (aValidateIt != mChildren.end())
+ {
+ ASSERT((*aValidateIt)->mpParent == this, "wrong parent");
+
+ tSwNumberTreeChildren::iterator aIt = mItLastValid;
+
+ // --> OD 2005-10-19 #126009#
+ // improvement:
+ // - Only one time checked for <mChildren.end()>.
+ // - Less checks for each loop run.
+ // correction:
+ // - consider case that current node isn't counted and isn't the first
+ // child of its parent. In this case the number of last counted child
+ // of the previous node determines the start value for the following
+ // children loop, if all children have to be validated and the first
+ // one doesn't restart the counting.
+// tSwNumTreeNumber nTmpNumber = 0;
+// if (aIt != mChildren.end())
+// nTmpNumber = (*aIt)->mnNumber;
+// while (aIt != aValidateIt)
+// {
+// if (aIt == mChildren.end())
+// aIt = mChildren.begin();
+// else
+// {
+// aIt++;
+// if ((*aIt)->IsCounted())
+// nTmpNumber++;
+// }
+// if ((*aIt)->IsRestart() || aIt == mChildren.begin())
+// nTmpNumber = (*aIt)->GetStart();
+// (*aIt)->mnNumber = nTmpNumber;
+// }
+ SwNumberTree::tSwNumTreeNumber nTmpNumber( 0 );
+ if (aIt != mChildren.end())
+ nTmpNumber = (*aIt)->mnNumber;
+ else
+ {
+ aIt = mChildren.begin();
+ // --> OD 2008-11-26 #158694#
+ (*aIt)->mbContinueingPreviousSubTree = false;
+ // <--
+
+ // determine default start value
+ // consider the case that the first child isn't counted.
+ nTmpNumber = (*aIt)->GetStartValue();
+ if ( !(*aIt)->IsCounted() &&
+ ( !(*aIt)->HasCountedChildren() || (*aIt)->IsPhantom() ) )
+ {
+ --nTmpNumber;
+ }
+
+ // determine special start value for the case that first child
+ // doesn't restart the numbering and the parent node isn't counted
+ // and isn't the first child.
+ // --> OD 2005-10-27 #126009#
+ const bool bParentCounted( IsCounted() &&
+ ( !IsPhantom() ||
+ HasPhantomCountedParent() ) );
+ // <--
+ if ( !(*aIt)->IsRestart() &&
+ GetParent() && !bParentCounted )
+ {
+ tSwNumberTreeChildren::iterator aParentChildIt =
+ GetParent()->GetIterator( this );
+ while ( aParentChildIt != GetParent()->mChildren.begin() )
+ {
+ --aParentChildIt;
+ SwNumberTreeNode* pPrevNode( *aParentChildIt );
+ if ( pPrevNode->GetChildCount() > 0 )
+ {
+ // --> OD 2008-11-26 #158694#
+ (*aIt)->mbContinueingPreviousSubTree = true;
+ // <--
+ nTmpNumber = (*(pPrevNode->mChildren.rbegin()))->GetNumber();
+ // --> OD 2005-10-27 #126009#
+ if ( (*aIt)->IsCounted() &&
+ ( !(*aIt)->IsPhantom() ||
+ (*aIt)->HasPhantomCountedParent() ) )
+ // <--
+ {
+ ++nTmpNumber;
+ }
+ break;
+ }
+ else if ( pPrevNode->IsCounted() )
+ {
+ break;
+ }
+ else
+ {
+ // Previous node has no children and is not counted.
+ // Thus, next turn and check for the previous node.
+ }
+ }
+ }
+
+ (*aIt)->mnNumber = nTmpNumber;
+ }
+
+ while (aIt != aValidateIt)
+ {
+ ++aIt;
+ // --> OD 2008-11-26 #158694#
+ (*aIt)->mbContinueingPreviousSubTree = false;
+ // <--
+
+ // --> OD 2005-10-19 #126009# - only for counted nodes the number
+ // has to be adjusted, compared to the previous node.
+ // this condition is hold also for nodes, which restart the numbering.
+ if ( (*aIt)->IsCounted() )
+ {
+ if ((*aIt)->IsRestart())
+ nTmpNumber = (*aIt)->GetStartValue();
+ else
+ ++nTmpNumber;
+ }
+ // <--
+
+ (*aIt)->mnNumber = nTmpNumber;
+ }
+ // <--
+
+ SetLastValid(aIt, true);
+ }
+}
+
+void SwNumberTreeNode::ValidateContinuous(const SwNumberTreeNode * pNode) const
+{
+ tSwNumberTreeChildren::iterator aIt = mItLastValid;
+
+ SwNumberTree::tSwNumTreeNumber nTmpNumber = 0;
+
+ do
+ {
+ if (aIt == mChildren.end())
+ {
+ aIt = mChildren.begin();
+
+ nTmpNumber = GetStartValue();
+ }
+ else
+ aIt++;
+
+ if (aIt != mChildren.end())
+ {
+ SwNumberTreeNode * pPred = (*aIt)->GetPred();
+
+ // --> OD 2006-04-21 #i64311#
+ // correct consideration of phantoms
+ // correct consideration of restart at a number tree node
+ if ( pPred )
+ {
+ if ( !(*aIt)->IsCounted() )
+ // --> OD 2006-05-12 #i65284#
+ nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() );
+ // <--
+ else
+ {
+ if ( (*aIt)->IsRestart() )
+ nTmpNumber = (*aIt)->GetStartValue();
+ else
+ nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() ) + 1;
+ }
+ }
+ else
+ {
+ if ( !(*aIt)->IsCounted() )
+ nTmpNumber = GetStartValue() - 1;
+ else
+ {
+ if ( (*aIt)->IsRestart() )
+ nTmpNumber = (*aIt)->GetStartValue();
+ else
+ nTmpNumber = GetStartValue();
+ }
+ }
+ // <--
+
+ (*aIt)->mnNumber = nTmpNumber;
+ }
+ }
+ while (aIt != mChildren.end() && *aIt != pNode);
+
+ // --> OD 2008-05-21 #i74748# - applied patch from garnier_romain
+ // number tree node has to be validated.
+// SetLastValid(aIt);
+ SetLastValid( aIt, true );
+ // <--
+}
+
+void SwNumberTreeNode::Validate(const SwNumberTreeNode * pNode) const
+{
+ if (! IsValid(pNode))
+ {
+ if (IsContinuous())
+ ValidateContinuous(pNode);
+ else
+ ValidateHierarchical(pNode);
+ }
+}
+
+void SwNumberTreeNode::ValidateTree()
+{
+ if (! IsContinuous())
+ {
+ {
+ tSwNumberTreeChildren::reverse_iterator aIt = mChildren.rbegin();
+
+ if (aIt != mChildren.rend())
+ Validate(*aIt);
+ }
+ {
+ tSwNumberTreeChildren::iterator aIt;
+
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
+ (*aIt)->ValidateTree();
+ }
+ }
+ else
+ {
+ SwNumberTreeNode * pNode = GetLastDescendant();
+
+ if (pNode && pNode->mpParent)
+ pNode->mpParent->Validate(pNode);
+ }
+}
+
+void SwNumberTreeNode::_GetNumberVector(vector<SwNumberTree::tSwNumTreeNumber> & rVector,
+ bool bValidate) const
+{
+ if (mpParent)
+ {
+ mpParent->_GetNumberVector(rVector, bValidate);
+ rVector.push_back(GetNumber(bValidate));
+ }
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetFirstNonPhantomChild()
+{
+ if (IsPhantom())
+ return (*mChildren.begin())->GetFirstNonPhantomChild();
+
+ return this;
+}
+
+/** Moves all children of this node that are greater than a given node
+ to the destination node.
+
+ OD 2005-10-14 #125991#
+*/
+void SwNumberTreeNode::MoveGreaterChildren( SwNumberTreeNode& _rCompareNode,
+ SwNumberTreeNode& _rDestNode )
+{
+ if ( mChildren.size() == 0 )
+ return;
+
+ // determine first child, which has to move to <_rDestNode>
+ tSwNumberTreeChildren::iterator aItUpper( mChildren.end() );
+ if ((*mChildren.begin())->IsPhantom() &&
+ _rCompareNode.LessThan(*(*mChildren.begin())->GetFirstNonPhantomChild()))
+ {
+ aItUpper = mChildren.begin();
+ }
+ else
+ {
+ aItUpper = mChildren.upper_bound(&_rCompareNode);
+ }
+
+ // move children
+ if (aItUpper != mChildren.end())
+ {
+ tSwNumberTreeChildren::iterator aIt;
+ for (aIt = aItUpper; aIt != mChildren.end(); aIt++)
+ (*aIt)->mpParent = &_rDestNode;
+
+ _rDestNode.mChildren.insert(aItUpper, mChildren.end());
+
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aItUpper, mChildren.end())> could destroy
+ // the element, which is referenced by <mItLastValid>, it's needed to
+ // adjust <mItLastValid> before erasing <aIt>.
+ SetLastValid( mChildren.end() );
+ // <--
+
+ mChildren.erase(aItUpper, mChildren.end());
+
+ // --> OD 2006-01-17 #i60652#
+ if ( !mChildren.empty() )
+ {
+ SetLastValid( --(mChildren.end()) );
+ }
+ // <--
+ }
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ if (! IsSane(false) || ! IsSane(&_rDestNode))
+ clog << __FUNCTION__ << "insanity!" << endl;
+#endif
+}
+
+void SwNumberTreeNode::MoveChildren(SwNumberTreeNode * pDest)
+{
+ if (! mChildren.empty())
+ {
+ tSwNumberTreeChildren::iterator aItBegin = mChildren.begin();
+ SwNumberTreeNode * pMyFirst = *mChildren.begin();
+
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aItBegin)> could destroy the element,
+ // which is referenced by <mItLastValid>, it's needed to adjust
+ // <mItLastValid> before erasing <aItBegin>.
+ SetLastValid(mChildren.end());
+ // <--
+
+ if (pMyFirst->IsPhantom())
+ {
+ SwNumberTreeNode * pDestLast = NULL;
+
+ if (pDest->mChildren.empty())
+ pDestLast = pDest->CreatePhantom();
+ else
+ pDestLast = *pDest->mChildren.rbegin();
+
+ pMyFirst->MoveChildren(pDestLast);
+
+ delete pMyFirst;
+ mChildren.erase(aItBegin);
+
+ aItBegin = mChildren.begin();
+ }
+
+ tSwNumberTreeChildren::iterator aIt;
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
+ (*aIt)->mpParent = pDest;
+
+ pDest->mChildren.insert(mChildren.begin(), mChildren.end());
+ mChildren.clear();
+ // --> OD 2006-03-08 #131436#
+ // <stl::set.clear()> destroys all existing iterators.
+ // Thus, <mItLastValid> is also destroyed and reset becomes necessary
+ mItLastValid = mChildren.end();
+ // <--
+ }
+
+ ASSERT (mChildren.empty(), "MoveChildren failed!");
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ ASSERT(IsSane(false) && pDest->IsSane(false), "insanity!");
+#endif
+}
+
+void SwNumberTreeNode::AddChild( SwNumberTreeNode * pChild,
+ const int nDepth )
+{
+ /*
+ Algorithm:
+
+ Search first child A that is greater than pChild,
+ A may be the end of childs.
+ If nDepth > 0 then
+ {
+ if A is first child then
+ create new phantom child B at beginning of child list
+ else
+ B is A
+
+ Add child to B with depth nDepth - 1.
+ }
+ else
+ {
+ Insert pNode before A.
+
+ if A has predecessor B then
+ remove children of B that are greater as A and insert them as
+ children of A.
+ }
+
+*/
+
+ // --> OD 2008-03-13 #refactorlists#
+ if ( nDepth < 0 )
+ {
+ ASSERT( false,
+ "<SwNumberTreeNode::AddChild(..)> - parameter <nDepth> out of valid range. Serious defect -> please inform OD." );
+ return;
+ }
+ // <--
+
+ if ( pChild->GetParent() != NULL || pChild->GetChildCount() > 0 )
+ {
+ ASSERT(false, "only orphans allowed.");
+ return;
+ }
+
+ if (nDepth > 0)
+ {
+ tSwNumberTreeChildren::iterator aInsertDeepIt =
+ mChildren.upper_bound(pChild);
+
+ ASSERT(! (aInsertDeepIt != mChildren.end() &&
+ (*aInsertDeepIt)->IsPhantom()), " unexspected phantom");
+
+
+ if (aInsertDeepIt == mChildren.begin())
+ {
+ SwNumberTreeNode * pNew = CreatePhantom();
+
+ SetLastValid(mChildren.end());
+
+ if (pNew)
+ pNew->AddChild(pChild, nDepth - 1);
+ }
+ else
+ {
+ aInsertDeepIt--;
+ (*aInsertDeepIt)->AddChild(pChild, nDepth - 1);
+ }
+
+ }
+ else
+ {
+ // --> OD 2008-02-19 #refactorlists#
+ pChild->PreAdd();
+ // <--
+ std::pair<tSwNumberTreeChildren::iterator, bool> aResult =
+ mChildren.insert(pChild);
+
+ if (aResult.second)
+ {
+ pChild->mpParent = this;
+ bool bNotification = pChild->IsNotificationEnabled();
+ tSwNumberTreeChildren::iterator aInsertedIt = aResult.first;
+
+ if (aInsertedIt != mChildren.begin())
+ {
+ tSwNumberTreeChildren::iterator aPredIt = aInsertedIt;
+ aPredIt--;
+
+ // --> OD 2005-10-14 #125991#
+ // Move greater children of previous node to new child.
+ // This has to be done recursively on the children levels.
+ // Initialize loop variables <pPrevChildNode> and <pDestNode>
+ // for loop on children levels.
+ SwNumberTreeNode* pPrevChildNode( *aPredIt );
+ SwNumberTreeNode* pDestNode( pChild );
+ while ( pDestNode && pPrevChildNode &&
+ pPrevChildNode->GetChildCount() > 0 )
+ {
+ // move children
+ pPrevChildNode->MoveGreaterChildren( *pChild, *pDestNode );
+
+ // prepare next loop:
+ // - search of last child of <pPrevChildNode
+ // - If found, determine destination node
+ if ( pPrevChildNode->GetChildCount() > 0 )
+ {
+ tSwNumberTreeChildren::reverse_iterator aIt =
+ pPrevChildNode->mChildren.rbegin();
+ pPrevChildNode = *aIt;
+ // determine new destination node
+ if ( pDestNode->GetChildCount() > 0 )
+ {
+ pDestNode = *(pDestNode->mChildren.begin());
+ if ( !pDestNode->IsPhantom() )
+ {
+ pDestNode = pDestNode->mpParent->CreatePhantom();
+ }
+ }
+ else
+ {
+ pDestNode = pDestNode->CreatePhantom();
+ }
+ }
+ else
+ {
+ // ready -> break loop.
+ break;
+ }
+ }
+ // assure that unnessary created phantoms at <pChild> are deleted.
+ pChild->ClearObsoletePhantoms();
+ // <--
+
+ if ((*aPredIt)->IsValid())
+ SetLastValid(aPredIt);
+ }
+ else
+ SetLastValid(mChildren.end());
+
+ ClearObsoletePhantoms();
+
+ if( bNotification )
+ {
+ // --> OD 2005-10-20 #126009# - invalidation of not counted parent
+ // and notification of its siblings.
+ if ( !IsCounted() )
+ {
+ InvalidateMe();
+ NotifyInvalidSiblings();
+ }
+ // <--
+ NotifyInvalidChildren();
+ }
+ }
+ }
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ if (! IsSane(false))
+ clog << __FUNCTION__ << ": insanity!" << endl;
+#endif
+}
+
+void SwNumberTreeNode::RemoveChild(SwNumberTreeNode * pChild)
+{
+ /*
+ Algorithm:
+
+ if pChild has predecessor A then
+ B is A
+ else
+ create phantom child B at beginning of child list
+
+ Move children of pChild to B.
+ */
+
+ if (pChild->IsPhantom())
+ {
+ ASSERT(false, "not applicable to phantoms!");
+
+ return;
+ }
+
+ tSwNumberTreeChildren::iterator aRemoveIt = GetIterator(pChild);
+
+ if (aRemoveIt != mChildren.end())
+ {
+ SwNumberTreeNode * pRemove = *aRemoveIt;
+
+ pRemove->mpParent = NULL;
+
+ tSwNumberTreeChildren::iterator aItPred = mChildren.end();
+
+ if (aRemoveIt == mChildren.begin())
+ {
+ if (! pRemove->mChildren.empty())
+ {
+ CreatePhantom();
+
+ aItPred = mChildren.begin();
+ }
+ }
+ else
+ {
+ aItPred = aRemoveIt;
+
+ aItPred--;
+ }
+
+ if (! pRemove->mChildren.empty())
+ {
+ pRemove->MoveChildren(*aItPred);
+ // --> OD 2008-04-04 #refactorlists#
+ (*aItPred)->InvalidateTree();
+ (*aItPred)->NotifyInvalidChildren();
+ // <--
+ }
+
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aRemoveIt)> could destroy the element,
+ // which is referenced by <mItLastValid>, it's needed to adjust
+ // <mItLastValid> before erasing <aRemoveIt>.
+ if (aItPred != mChildren.end() && (*aItPred)->IsPhantom())
+ SetLastValid(mChildren.end());
+ else
+ SetLastValid(aItPred);
+ // <--
+
+ mChildren.erase(aRemoveIt);
+
+ // --> OD 2008-04-04 #refactorlists#
+// if (aItPred != mChildren.end())
+// NotifyInvalidChildren();
+ NotifyInvalidChildren();
+ // <--
+ }
+ else
+ {
+ ASSERT(false, "RemoveChild: failed!");
+ }
+
+ // --> OD 2008-02-19 #refactorlists#
+ pChild->PostRemove();
+ // <--
+}
+
+void SwNumberTreeNode::RemoveMe()
+{
+ if (mpParent)
+ {
+ SwNumberTreeNode * pSavedParent = mpParent;
+
+ pSavedParent->RemoveChild(this);
+
+ while (pSavedParent && pSavedParent->IsPhantom() &&
+ pSavedParent->HasOnlyPhantoms())
+ pSavedParent = pSavedParent->GetParent();
+
+ if (pSavedParent)
+ pSavedParent->ClearObsoletePhantoms();
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ if (! IsSane(false))
+ clog << __FUNCTION__ << ": insanity!" << endl;
+#endif
+ }
+}
+
+bool SwNumberTreeNode::IsValid() const
+{
+ return mpParent ? mpParent->IsValid(this) : false;
+}
+
+SwNumberTree::tSwNumTreeNumber SwNumberTreeNode::GetNumber(bool bValidate)
+ const
+{
+ if (bValidate && mpParent)
+ mpParent->Validate(this);
+
+ return mnNumber;
+}
+
+// --> OD 2008-11-26 #158694#
+bool SwNumberTreeNode::IsContinueingPreviousSubTree() const
+{
+ return mbContinueingPreviousSubTree;
+}
+// <--
+
+
+vector<SwNumberTree::tSwNumTreeNumber> SwNumberTreeNode::GetNumberVector() const
+{
+ vector<SwNumberTree::tSwNumTreeNumber> aResult;
+
+ _GetNumberVector(aResult);
+
+ return aResult;
+}
+
+bool SwNumberTreeNode::IsValid(const SwNumberTreeNode * pChild) const
+{
+ bool bResult = false;
+
+ if (mItLastValid != mChildren.end())
+ {
+ if (pChild && pChild->mpParent == this)
+ {
+ bResult = ! (*mItLastValid)->LessThan(*pChild);
+ }
+ }
+
+ return bResult;
+}
+
+bool SwNumberTreeNode::IsPhantom() const
+{
+ return mbPhantom;
+}
+
+void SwNumberTreeNode::SetPhantom(bool _bPhantom)
+{
+ mbPhantom = _bPhantom;
+}
+
+bool SwNumberTreeNode::HasOnlyPhantoms() const
+{
+ bool bResult = false;
+
+ if (GetChildCount() == 1)
+ {
+ tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
+
+ bResult = (*aIt)->IsPhantom() && (*aIt)->HasOnlyPhantoms();
+ }
+ else if (GetChildCount() == 0)
+ bResult = true;
+
+ return bResult;
+}
+
+bool SwNumberTreeNode::IsCounted() const
+{
+ return !IsPhantom() ||
+ ( IsCountPhantoms() && HasCountedChildren() );
+}
+
+// --> OD 2005-10-27 #126009#
+bool SwNumberTreeNode::HasPhantomCountedParent() const
+{
+ bool bRet( false );
+
+ ASSERT( IsPhantom(),
+ "<SwNumberTreeNode::HasPhantomCountedParent()> - wrong usage of method - it's only for phantoms" );
+ if ( IsPhantom() && mpParent )
+ {
+ if ( mpParent == GetRoot() )
+ {
+ bRet = true;
+ }
+ else if ( !mpParent->IsPhantom() )
+ {
+ bRet = mpParent->IsCounted();
+ }
+ else
+ {
+ bRet = mpParent->IsCounted() && mpParent->HasPhantomCountedParent();
+ }
+ }
+
+ return bRet;
+}
+// <--
+
+bool SwNumberTreeNode::IsFirst(const SwNumberTreeNode * pNode) const
+{
+ tSwNumberTreeChildren::iterator aIt = mChildren.begin();
+
+ if ((*aIt)->IsPhantom())
+ aIt++;
+
+ return *aIt == pNode;
+}
+
+bool SwNumberTreeNode::IsFirst() const
+{
+ bool bResult = true;
+
+ if (GetParent())
+ {
+ if (GetParent()->IsFirst(this))
+ {
+ SwNumberTreeNode * pNode = GetParent();
+
+ while (pNode)
+ {
+ if (!pNode->IsPhantom() && pNode->GetParent())
+ {
+ bResult = false;
+ break;
+ }
+
+ pNode = pNode->GetParent();
+ }
+
+ // --> OD 2007-10-02 #b6600435#
+ // If node isn't the first child, it is the second child and the
+ // first child is a phanton. In this case check, if the first phantom
+ // child have only phanton childs
+ if ( bResult &&
+ this != *(GetParent()->mChildren.begin()) &&
+ !(*(GetParent()->mChildren.begin()))->HasOnlyPhantoms() )
+ {
+ bResult = false;
+ }
+ // <--
+ }
+ else
+ bResult = false;
+ }
+
+ return bResult;
+}
+
+// --> OD 2008-03-13 #refactorlists#
+void SwNumberTreeNode::SetLevelInListTree( const int nLevel )
+{
+ if ( nLevel < 0 )
+ {
+ ASSERT( false,
+ "<SwNumberTreeNode::SetLevelInListTree(..)> - parameter <nLevel> out of valid range. Serious defect -> please inform OD." );
+ return;
+ }
+
+ ASSERT( GetParent(),
+ "<SwNumberTreeNode::SetLevelInListTree(..)> - can only be called for number tree nodes in a list tree" );
+ if ( GetParent() )
+ {
+ if ( nLevel != GetLevelInListTree() )
+ {
+ SwNumberTreeNode* pRootTreeNode = GetRoot();
+ ASSERT( pRootTreeNode,
+ "<SwNumberTreeNode::SetLevelInListTree(..)> - no root tree node found. Serious defect -> please inform OD." );
+
+ RemoveMe();
+ pRootTreeNode->AddChild( this, nLevel );
+ }
+ }
+}
+// <--
+
+int SwNumberTreeNode::GetLevelInListTree() const
+{
+ if (mpParent)
+ return mpParent->GetLevelInListTree() + 1;
+
+ return -1;
+}
+
+SwNumberTreeNode::tSwNumberTreeChildren::size_type
+SwNumberTreeNode::GetChildCount() const
+{
+ return mChildren.size();
+}
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+bool SwNumberTreeNode::IsSane(bool bRecursive) const
+{
+ vector<const SwNumberTreeNode*> aParents;
+
+ return IsSane(bRecursive, aParents);
+}
+
+bool SwNumberTreeNode::IsSane(bool bRecursive,
+ vector<const SwNumberTreeNode *> rParents)
+ const
+{
+ bool bResult = true;
+
+ tSwNumberTreeChildren::const_iterator aIt;
+
+ if (find(rParents.begin(), rParents.end(), this) != rParents.end())
+ {
+ ASSERT(false, " I'm my own ancestor!");
+
+ bResult = false;
+ }
+
+ if (! rParents.empty() && rParents.back() != mpParent)
+ {
+ ASSERT(false, " I'm a bastard!");
+
+ bResult = false;
+ }
+
+ rParents.push_back(this);
+
+ bool bFirst = true;
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
+ {
+ if (*aIt)
+ {
+ if ((*aIt)->IsPhantom())
+ {
+ if ((*aIt)->HasOnlyPhantoms())
+ {
+ bResult = false;
+ }
+
+ if (! bFirst)
+ {
+ ASSERT(false, " found phantom not at first position.");
+
+ bResult = false;
+ }
+ }
+
+ if ((*aIt)->mpParent != (SwNumberTreeNode *) this)
+ {
+ ASSERT(false, "found a bastard");
+
+ bResult = false;
+ }
+
+ if (mpParent)
+ {
+ if (!(*aIt)->IsPhantom() && (*aIt)->LessThan(*this))
+ {
+ ASSERT(false, " found child less than me");
+
+ bResult = false;
+ }
+ }
+ }
+ else
+ {
+ ASSERT(false, "found child that is NULL");
+ bResult = false;
+ }
+
+ if (bRecursive)
+ bResult = (*aIt)->IsSane(bRecursive, rParents) && bResult;
+ }
+
+ rParents.pop_back();
+
+ return bResult;
+}
+#endif // __SW_NUMBER_TREE_SANITY_CHECK
+
+SwNumberTreeNode::tSwNumberTreeChildren::iterator
+SwNumberTreeNode::GetIterator(const SwNumberTreeNode * pChild) const
+{
+ tSwNumberTreeChildren::iterator aItResult =
+ mChildren.find(const_cast<SwNumberTreeNode *>(pChild));
+
+ ASSERT( aItResult != mChildren.end(),
+ "something went wrong getting the iterator for a child");
+
+ return aItResult;
+}
+
+//String SwNumberTreeNode::print(const String & rIndent,
+// const String & rMyIndent,
+// int nDepth) const
+//{
+// String aStr = rIndent;
+// aStr += ToString();
+// aStr += String("\n", RTL_TEXTENCODING_ASCII_US);
+
+// if (nDepth != 0)
+// {
+// if (nDepth < 0)
+// nDepth = -1;
+
+// tSwNumberTreeChildren::const_iterator aIt;
+// for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
+// {
+// String aTmpStr(rIndent);
+
+// aTmpStr += rMyIndent;
+// aStr += (*aIt)->print(aTmpStr, rMyIndent, nDepth - 1);
+// }
+// }
+
+// return aStr;
+//}
+
+#ifdef DBG_UTIL
+unsigned long SwNumberTreeNode::GetInstances()
+{
+ return nInstances;
+}
+
+unsigned long SwNumberTreeNode::GetSerial()
+{
+ return mnSerial;
+}
+#endif
+
+bool SwNumberTreeNodeLessThan(const SwNumberTreeNode * pA,
+ const SwNumberTreeNode * pB)
+{
+ bool bResult = false;
+
+ if (pA == NULL && pB != NULL)
+ bResult = true;
+ else if (pA != NULL && pB != NULL)
+ bResult = pA->LessThan(*pB);
+
+ return bResult;
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetLastDescendant() const
+{
+ SwNumberTreeNode * pResult = NULL;
+ tSwNumberTreeChildren::reverse_iterator aIt = mChildren.rbegin();
+
+ if (aIt != mChildren.rend())
+ {
+ pResult = (*aIt)->GetLastDescendant();
+
+ if (! pResult)
+ pResult = *aIt;
+ }
+
+ return pResult;
+}
+
+bool SwNumberTreeNode::LessThan(const SwNumberTreeNode & rTreeNode) const
+{
+ return this < &rTreeNode;
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetPred(bool bSibling) const
+{
+ SwNumberTreeNode * pResult = NULL;
+
+ if (mpParent)
+ {
+ tSwNumberTreeChildren::iterator aIt =
+ mpParent->GetIterator(this);
+
+ if ( aIt == mpParent->mChildren.begin() )
+ {
+ // --> OD 2006-04-24 #i64311#
+ // root node is no valid predecessor
+ pResult = mpParent->GetParent() ? mpParent : NULL;
+ // <--
+ }
+ else
+ {
+ aIt--;
+
+ if ( !bSibling )
+ pResult = (*aIt)->GetLastDescendant();
+ else
+ pResult = (*aIt);
+
+ if (! pResult)
+ pResult = (*aIt);
+ }
+ }
+
+ return pResult;
+}
+
+void SwNumberTreeNode::SetLastValid
+ ( SwNumberTreeNode::tSwNumberTreeChildren::iterator aItValid,
+ bool bValidating ) const
+{
+ ASSERT( (aItValid == mChildren.end() || GetIterator(*aItValid) != mChildren.end()),
+ "last-valid iterator");
+
+ if (
+ bValidating ||
+ aItValid == mChildren.end() ||
+ (mItLastValid != mChildren.end() &&
+ (*aItValid)->LessThan(**mItLastValid))
+ )
+ {
+ mItLastValid = aItValid;
+ // --> OD 2005-10-19 #126009# - invalidation of children of next not
+ // counted is needed
+ if ( GetParent() )
+ {
+ tSwNumberTreeChildren::iterator aParentChildIt =
+ GetParent()->GetIterator( this );
+ ++aParentChildIt;
+ if ( aParentChildIt != GetParent()->mChildren.end() )
+ {
+ SwNumberTreeNode* pNextNode( *aParentChildIt );
+ if ( !pNextNode->IsCounted() )
+ {
+ pNextNode->InvalidateChildren();
+ }
+ }
+ }
+ // <--
+ }
+
+ {
+ if (IsContinuous())
+ {
+ tSwNumberTreeChildren::iterator aIt = mItLastValid;
+
+ if (aIt != mChildren.end())
+ aIt++;
+ else
+ aIt = mChildren.begin();
+
+ while (aIt != mChildren.end())
+ {
+ (*aIt)->InvalidateTree();
+
+ aIt++;
+ }
+
+ SetLastValid(bValidating);
+ }
+ }
+}
+
+void SwNumberTreeNode::SetLastValid(bool bValidating) const
+{
+ if (mpParent)
+ {
+ tSwNumberTreeChildren::iterator aIt = mpParent->GetIterator(this);
+
+ mpParent->SetLastValid(aIt, bValidating);
+ }
+}
+
+void SwNumberTreeNode::InvalidateTree() const
+{
+ // do not call SetInvalid, would cause loop !!!
+ mItLastValid = mChildren.end();
+
+ tSwNumberTreeChildren::iterator aIt;
+
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
+ (*aIt)->InvalidateTree();
+}
+
+void SwNumberTreeNode::Invalidate(SwNumberTreeNode * pChild)
+{
+ if (pChild->IsValid())
+ {
+ tSwNumberTreeChildren::iterator aIt = GetIterator(pChild);
+
+ if (aIt != mChildren.begin())
+ aIt--;
+ else
+ aIt = mChildren.end();
+
+ SetLastValid(aIt);
+
+ }
+}
+
+void SwNumberTreeNode::InvalidateMe()
+{
+ if (mpParent)
+ mpParent->Invalidate(this);
+}
+
+void SwNumberTreeNode::ValidateMe()
+{
+ if (mpParent)
+ mpParent->Validate(this);
+}
+
+void SwNumberTreeNode::Notify()
+{
+ if (IsNotifiable())
+ {
+ if (! IsPhantom())
+ NotifyNode();
+
+ tSwNumberTreeChildren::iterator aIt;
+
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
+ (*aIt)->Notify();
+ }
+}
+
+void SwNumberTreeNode::NotifyInvalidChildren()
+{
+ if (IsNotifiable())
+ {
+ tSwNumberTreeChildren::iterator aIt = mItLastValid;
+
+ if (aIt == mChildren.end())
+ aIt = mChildren.begin();
+ else
+ aIt++;
+
+ while (aIt != mChildren.end())
+ {
+ (*aIt)->Notify();
+
+ aIt++;
+ }
+ // --> OD 2005-10-19 #126009# - notification of next not counted node
+ // is also needed.
+ if ( GetParent() )
+ {
+ tSwNumberTreeChildren::iterator aParentChildIt =
+ GetParent()->GetIterator( this );
+ ++aParentChildIt;
+ if ( aParentChildIt != GetParent()->mChildren.end() )
+ {
+ SwNumberTreeNode* pNextNode( *aParentChildIt );
+ if ( !pNextNode->IsCounted() )
+ {
+ pNextNode->NotifyInvalidChildren();
+ }
+ }
+ }
+
+ // <--
+ }
+
+ if (IsContinuous() && mpParent)
+ mpParent->NotifyInvalidChildren();
+}
+
+void SwNumberTreeNode::NotifyInvalidSiblings()
+{
+ if (mpParent != NULL)
+ mpParent->NotifyInvalidChildren();
+}
+
+// --> OD 2007-09-07 #i81002#
+const SwNumberTreeNode* SwNumberTreeNode::GetPrecedingNodeOf(
+ const SwNumberTreeNode& rNode ) const
+{
+ const SwNumberTreeNode* pPrecedingNode( 0 );
+
+ if ( GetChildCount() > 0 )
+ {
+ tSwNumberTreeChildren::const_iterator aUpperBoundIt =
+ mChildren.upper_bound( const_cast<SwNumberTreeNode*>(&rNode) );
+ if ( aUpperBoundIt != mChildren.begin() )
+ {
+ --aUpperBoundIt;
+ pPrecedingNode = (*aUpperBoundIt)->GetPrecedingNodeOf( rNode );
+ }
+ }
+
+ if ( pPrecedingNode == 0 && GetRoot() )
+ {
+ // <this> node has no children or the given node precedes all its children
+ // and the <this> node isn't the root node.
+ // Thus, compare the given node with the <this> node in order to check,
+ // if the <this> node precedes the given node.
+ if ( !(rNode.LessThan( *this )) )
+ {
+ pPrecedingNode = this;
+ }
+ }
+
+ return pPrecedingNode;
+}
+// <--
+
+// --> OD 2008-04-17 #refactorlists#
+void SwNumberTreeNode::NotifyNodesOnListLevel( const int nListLevel )
+{
+ if ( nListLevel < 0 )
+ {
+ ASSERT( false,
+ "<SwNumberTreeNode::NotifyNodesOnListLevel(..)> - invalid list level provided" );
+ return;
+ }
+
+ SwNumberTreeNode* pRootNode = GetParent() ? GetRoot() : this;
+
+ pRootNode->NotifyChildrenOnDepth( nListLevel );
+}
+
+void SwNumberTreeNode::NotifyChildrenOnDepth( const int nDepth )
+{
+ ASSERT( nDepth >= 0,
+ "<SwNumberTreeNode::NotifyChildrenOnDepth(..)> - misusage" );
+
+ SwNumberTreeNode::tSwNumberTreeChildren::iterator aChildIter =
+ mChildren.begin();
+ while ( aChildIter != mChildren.end() )
+ {
+ if ( nDepth == 0 )
+ {
+ (*aChildIter)->NotifyNode();
+ }
+ else
+ {
+ (*aChildIter)->NotifyChildrenOnDepth( nDepth - 1 );
+ }
+
+ ++aChildIter;
+ }
+}
+// <--