blob: 62183486fd397f41793c47e2df5f71676a646463 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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::const_iterator aValidateIt =
GetIterator(pNode);
if (aValidateIt != mChildren.end())
{
ASSERT((*aValidateIt)->mpParent == this, "wrong parent");
tSwNumberTreeChildren::const_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::const_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::const_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::const_iterator aRemoveIt = GetIterator(pChild);
if (aRemoveIt != mChildren.end())
{
SwNumberTreeNode * pRemove = *aRemoveIt;
pRemove->mpParent = NULL;
tSwNumberTreeChildren::const_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::const_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::const_iterator
SwNumberTreeNode::GetIterator(const SwNumberTreeNode * pChild) const
{
tSwNumberTreeChildren::const_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::const_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::const_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::const_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::const_iterator aParentChildIt =
GetParent()->GetIterator( this );
++aParentChildIt;
if ( aParentChildIt != GetParent()->mChildren.end() )
{
SwNumberTreeNode* pNextNode( *aParentChildIt );
if ( !pNextNode->IsCounted() )
{
pNextNode->InvalidateChildren();
}
}
}
// <--
}
{
if (IsContinuous())
{
tSwNumberTreeChildren::const_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::const_iterator aIt = mpParent->GetIterator(this);
mpParent->SetLastValid(aIt, bValidating);
}
}
void SwNumberTreeNode::InvalidateTree() const
{
// do not call SetInvalid, would cause loop !!!
mItLastValid = mChildren.end();
tSwNumberTreeChildren::const_iterator aIt;
for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
(*aIt)->InvalidateTree();
}
void SwNumberTreeNode::Invalidate(SwNumberTreeNode * pChild)
{
if (pChild->IsValid())
{
tSwNumberTreeChildren::const_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::const_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::const_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;
}
}
// <--