1998-12-14 23:16:31 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* nsContentIterator.cpp: Implementation of the nsContentIterator object.
|
1999-02-12 05:28:12 +00:00
|
|
|
* This ite
|
1998-12-14 23:16:31 +00:00
|
|
|
*/
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
#include "nsISupports.h"
|
1999-02-12 08:20:40 +00:00
|
|
|
//#include "nsIEnumerator.h"
|
1999-02-12 05:28:12 +00:00
|
|
|
#include "nsIContentIterator.h"
|
1999-02-16 15:48:13 +00:00
|
|
|
#include "nsRange.h"
|
1998-12-14 23:16:31 +00:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIDOMText.h"
|
1999-03-01 08:17:18 +00:00
|
|
|
#include "nsISupportsArray.h"
|
1998-12-14 23:16:31 +00:00
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
#include "nsCOMPtr.h"
|
1998-12-14 23:16:31 +00:00
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A simple iterator class for traversing the content in "close tag" order
|
|
|
|
*/
|
1999-02-12 08:20:40 +00:00
|
|
|
class nsContentIterator : public nsIContentIterator //, public nsIEnumerator
|
1998-12-14 23:16:31 +00:00
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
nsContentIterator();
|
|
|
|
virtual ~nsContentIterator();
|
|
|
|
|
|
|
|
// nsIContentIterator interface methods ------------------------------
|
|
|
|
|
|
|
|
NS_IMETHOD Init(nsIContent* aRoot);
|
|
|
|
|
|
|
|
NS_IMETHOD Init(nsIDOMRange* aRange);
|
|
|
|
|
|
|
|
NS_IMETHOD First();
|
|
|
|
|
|
|
|
NS_IMETHOD Last();
|
|
|
|
|
|
|
|
NS_IMETHOD Next();
|
|
|
|
|
|
|
|
NS_IMETHOD Prev();
|
|
|
|
|
|
|
|
NS_IMETHOD CurrentNode(nsIContent **aNode);
|
|
|
|
|
|
|
|
NS_IMETHOD IsDone();
|
|
|
|
|
|
|
|
// nsIEnumertor interface methods ------------------------------
|
|
|
|
|
1999-02-12 08:20:40 +00:00
|
|
|
//NS_IMETHOD CurrentItem(nsISupports **aItem);
|
1999-02-12 05:28:12 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
static nsCOMPtr<nsIContent> GetDeepFirstChild(nsCOMPtr<nsIContent> aRoot);
|
1999-03-01 08:17:18 +00:00
|
|
|
static nsCOMPtr<nsIContent> GetDeepLastChild(nsCOMPtr<nsIContent> aRoot);
|
|
|
|
|
|
|
|
nsresult GetNextSibling(nsCOMPtr<nsIContent> aNode, nsCOMPtr<nsIContent> *aSibling);
|
|
|
|
nsresult GetPrevSibling(nsCOMPtr<nsIContent> aNode, nsCOMPtr<nsIContent> *aSibling);
|
|
|
|
|
|
|
|
nsresult NextNode(nsCOMPtr<nsIContent> *ioNextNode);
|
|
|
|
nsresult PrevNode(nsCOMPtr<nsIContent> *ioPrevNode);
|
1999-02-12 05:28:12 +00:00
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
void MakeEmpty();
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
nsCOMPtr<nsIContent> mCurNode;
|
|
|
|
nsCOMPtr<nsIContent> mFirst;
|
|
|
|
nsCOMPtr<nsIContent> mLast;
|
1999-03-01 08:17:18 +00:00
|
|
|
nsCOMPtr<nsIContent> mCommonParent;
|
1999-02-12 05:28:12 +00:00
|
|
|
|
|
|
|
PRBool mIsDone;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
// no copy's or assigns FIX ME
|
|
|
|
nsContentIterator(const nsContentIterator&);
|
|
|
|
nsContentIterator& operator=(const nsContentIterator&);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
|
|
|
|
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
/******************************************************
|
|
|
|
* repository cruft
|
|
|
|
******************************************************/
|
|
|
|
|
|
|
|
nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult)
|
|
|
|
{
|
|
|
|
nsContentIterator * iter = new nsContentIterator();
|
1999-03-03 19:48:57 +00:00
|
|
|
return iter->QueryInterface(nsIContentIterator::GetIID(), (void**) aInstancePtrResult);
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
/******************************************************
|
|
|
|
* XPCOM cruft
|
|
|
|
******************************************************/
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(nsContentIterator)
|
|
|
|
NS_IMPL_RELEASE(nsContentIterator)
|
|
|
|
|
|
|
|
nsresult nsContentIterator::QueryInterface(const nsIID& aIID,
|
|
|
|
void** aInstancePtrResult)
|
1998-12-14 23:16:31 +00:00
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
|
1999-02-14 09:15:13 +00:00
|
|
|
if (nsnull == aInstancePtrResult)
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
1999-02-14 09:15:13 +00:00
|
|
|
if (aIID.Equals(kISupportsIID))
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
*aInstancePtrResult = (void*)(nsISupports*)(nsIContentIterator*)this;
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-03-03 19:48:57 +00:00
|
|
|
/* if (aIID.Equals(nsIEnumerator::GetIID()))
|
1999-02-14 09:15:13 +00:00
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
*aInstancePtrResult = (void*)(nsIEnumerator*)this;
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
return NS_OK;
|
1999-02-12 08:20:40 +00:00
|
|
|
} */
|
1999-03-03 19:48:57 +00:00
|
|
|
if (aIID.Equals(nsIContentIterator::GetIID()))
|
1999-02-14 09:15:13 +00:00
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
*aInstancePtrResult = (void*)(nsIContentIterator*)this;
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return !NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************
|
|
|
|
* constructor/destructor
|
|
|
|
******************************************************/
|
|
|
|
|
|
|
|
nsContentIterator::nsContentIterator() :
|
1999-02-18 23:55:10 +00:00
|
|
|
// don't need to explicitly initialize |nsCOMPtr|s, they will automatically be NULL
|
1999-02-12 05:28:12 +00:00
|
|
|
mIsDone(PR_FALSE)
|
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsContentIterator::~nsContentIterator()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************
|
|
|
|
* Init routines
|
|
|
|
******************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
nsresult nsContentIterator::Init(nsIContent* aRoot)
|
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!aRoot)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1998-12-14 23:16:31 +00:00
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
nsCOMPtr<nsIContent> root( do_QueryInterface(aRoot) );
|
1999-02-14 09:15:13 +00:00
|
|
|
mFirst = GetDeepFirstChild(root);
|
1999-02-18 23:55:10 +00:00
|
|
|
mLast = root;
|
1999-03-01 08:17:18 +00:00
|
|
|
mCommonParent = root;
|
1998-12-14 23:16:31 +00:00
|
|
|
mCurNode = mFirst;
|
1999-02-12 05:28:12 +00:00
|
|
|
return NS_OK;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
nsresult nsContentIterator::Init(nsIDOMRange* aRange)
|
1998-12-14 23:16:31 +00:00
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!aRange)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1998-12-14 23:16:31 +00:00
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
nsCOMPtr<nsIContent> cN;
|
|
|
|
nsCOMPtr<nsIDOMNode> dN;
|
1999-03-01 08:17:18 +00:00
|
|
|
// get common content parent
|
|
|
|
if (!NS_SUCCEEDED(aRange->GetCommonParent(getter_AddRefs(dN))) || !dN)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
mCommonParent = do_QueryInterface(dN);
|
|
|
|
|
|
|
|
// get the start node and offset, convert to nsIContent
|
1999-02-12 05:28:12 +00:00
|
|
|
aRange->GetStartParent(getter_AddRefs(dN));
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!dN)
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
1999-02-17 02:08:00 +00:00
|
|
|
cN = do_QueryInterface(dN);
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!cN)
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-02-12 05:28:12 +00:00
|
|
|
|
1998-12-14 23:16:31 +00:00
|
|
|
PRInt32 indx;
|
|
|
|
aRange->GetStartOffset(&indx);
|
|
|
|
|
|
|
|
// find first node in range
|
1999-02-12 05:28:12 +00:00
|
|
|
nsCOMPtr<nsIContent> cChild;
|
|
|
|
cN->ChildAt(0,*getter_AddRefs(cChild));
|
1999-02-14 09:15:13 +00:00
|
|
|
|
1998-12-14 23:16:31 +00:00
|
|
|
if (!cChild) // no children, must be a text node
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
mFirst = cN;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
cN->ChildAt(indx,*getter_AddRefs(cChild));
|
1998-12-14 23:16:31 +00:00
|
|
|
if (!cChild) // offset after last child, parent is first node
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
mFirst = cN;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
mFirst = GetDeepFirstChild(cChild);
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
1999-02-16 15:48:13 +00:00
|
|
|
// Does that first node really intersect the range?
|
|
|
|
// the range could be collapsed, or the range could be
|
|
|
|
// 'degenerate', ie not collapsed but still containing
|
|
|
|
// no content. In this case, we want the iterator to
|
1999-03-01 08:17:18 +00:00
|
|
|
// be empty
|
1998-12-14 23:16:31 +00:00
|
|
|
|
1999-02-16 15:48:13 +00:00
|
|
|
if (!IsNodeIntersectsRange(mFirst, aRange))
|
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
MakeEmpty();
|
1999-02-16 15:48:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
1999-02-14 09:15:13 +00:00
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
aRange->GetEndParent(getter_AddRefs(dN));
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!dN)
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
1999-02-17 02:08:00 +00:00
|
|
|
cN = do_QueryInterface(dN);
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!cN)
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-02-12 05:28:12 +00:00
|
|
|
|
1998-12-14 23:16:31 +00:00
|
|
|
aRange->GetEndOffset(&indx);
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
// find last node in range
|
1999-02-12 05:28:12 +00:00
|
|
|
cN->ChildAt(0,*getter_AddRefs(cChild));
|
1999-02-14 09:15:13 +00:00
|
|
|
|
1998-12-14 23:16:31 +00:00
|
|
|
if (!cChild) // no children, must be a text node
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
mLast = cN;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
else if (indx == 0) // before first child, parent is last node
|
|
|
|
{
|
1999-02-12 05:28:12 +00:00
|
|
|
mLast = cN;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
cN->ChildAt(--indx,*getter_AddRefs(cChild));
|
1998-12-14 23:16:31 +00:00
|
|
|
if (!cChild) // offset after last child, last child is last node
|
|
|
|
{
|
|
|
|
cN->ChildCount(indx);
|
1999-02-14 09:15:13 +00:00
|
|
|
cN->ChildAt(--indx,*getter_AddRefs(cChild));
|
1998-12-14 23:16:31 +00:00
|
|
|
if (!cChild)
|
|
|
|
{
|
|
|
|
NS_NOTREACHED("nsContentIterator::nsContentIterator");
|
1999-02-12 05:28:12 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
}
|
1999-02-14 09:15:13 +00:00
|
|
|
mLast = cChild;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mCurNode = mFirst;
|
1999-02-12 05:28:12 +00:00
|
|
|
return NS_OK;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
/******************************************************
|
1999-02-14 09:15:13 +00:00
|
|
|
* Helper routines
|
1999-02-12 05:28:12 +00:00
|
|
|
******************************************************/
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
void nsContentIterator::MakeEmpty()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> noNode;
|
|
|
|
mCurNode = noNode;
|
|
|
|
mFirst = noNode;
|
|
|
|
mLast = noNode;
|
|
|
|
mCommonParent = noNode;
|
|
|
|
mIsDone = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
nsCOMPtr<nsIContent> nsContentIterator::GetDeepFirstChild(nsCOMPtr<nsIContent> aRoot)
|
1998-12-14 23:16:31 +00:00
|
|
|
{
|
1999-03-09 19:21:30 +00:00
|
|
|
nsCOMPtr<nsIContent> deepFirstChild;
|
|
|
|
|
|
|
|
if (aRoot)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> cN = aRoot;
|
|
|
|
nsCOMPtr<nsIContent> cChild;
|
1999-02-14 09:15:13 +00:00
|
|
|
cN->ChildAt(0,*getter_AddRefs(cChild));
|
1999-03-09 19:21:30 +00:00
|
|
|
while ( cChild )
|
|
|
|
{
|
|
|
|
cN = cChild;
|
|
|
|
cN->ChildAt(0,*getter_AddRefs(cChild));
|
|
|
|
}
|
|
|
|
deepFirstChild = cN;
|
1999-02-12 05:28:12 +00:00
|
|
|
}
|
1999-03-09 19:21:30 +00:00
|
|
|
|
|
|
|
return deepFirstChild;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
nsCOMPtr<nsIContent> nsContentIterator::GetDeepLastChild(nsCOMPtr<nsIContent> aRoot)
|
|
|
|
{
|
1999-03-09 19:21:30 +00:00
|
|
|
nsCOMPtr<nsIContent> deepFirstChild;
|
1999-03-01 08:17:18 +00:00
|
|
|
|
1999-03-09 19:21:30 +00:00
|
|
|
if (aRoot)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> cN = aRoot;
|
|
|
|
nsCOMPtr<nsIContent> cChild;
|
|
|
|
PRInt32 numChildren;
|
|
|
|
|
|
|
|
cN->ChildCount(numChildren);
|
1999-03-01 08:17:18 +00:00
|
|
|
|
1999-03-09 19:21:30 +00:00
|
|
|
while ( numChildren )
|
1999-03-01 08:17:18 +00:00
|
|
|
{
|
1999-03-09 19:21:30 +00:00
|
|
|
cN->ChildAt(--numChildren,*getter_AddRefs(cChild));
|
|
|
|
if (cChild)
|
|
|
|
{
|
|
|
|
cChild->ChildCount(numChildren);
|
|
|
|
cN = cChild;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
1999-03-01 08:17:18 +00:00
|
|
|
}
|
1999-03-09 19:21:30 +00:00
|
|
|
deepFirstChild = cN;
|
1999-03-01 08:17:18 +00:00
|
|
|
}
|
1999-03-09 19:21:30 +00:00
|
|
|
|
|
|
|
return deepFirstChild;
|
1999-03-01 08:17:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get the next sibling, or parents next sibling, or grandpa's next sibling...
|
|
|
|
nsresult nsContentIterator::GetNextSibling(nsCOMPtr<nsIContent> aNode, nsCOMPtr<nsIContent> *aSibling)
|
|
|
|
{
|
|
|
|
if (!aNode)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (!aSibling)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> sib;
|
|
|
|
nsCOMPtr<nsIContent> parent;
|
|
|
|
PRInt32 indx;
|
|
|
|
|
|
|
|
if (!NS_SUCCEEDED(aNode->GetParent(*getter_AddRefs(parent))))
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-03-08 01:20:02 +00:00
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
if (!NS_SUCCEEDED(parent->IndexOf(aNode, indx)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(parent->ChildAt(++indx, *getter_AddRefs(sib))) && sib)
|
|
|
|
{
|
|
|
|
*aSibling = sib;
|
|
|
|
}
|
|
|
|
else if (parent != mCommonParent)
|
|
|
|
{
|
1999-03-08 01:20:02 +00:00
|
|
|
return GetNextSibling(parent, aSibling);
|
1999-03-01 08:17:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*aSibling = nsCOMPtr<nsIContent>();
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the prev sibling, or parents prev sibling, or grandpa's prev sibling...
|
|
|
|
nsresult nsContentIterator::GetPrevSibling(nsCOMPtr<nsIContent> aNode, nsCOMPtr<nsIContent> *aSibling)
|
|
|
|
{
|
|
|
|
if (!aNode)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (!aSibling)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> sib;
|
|
|
|
nsCOMPtr<nsIContent> parent;
|
|
|
|
PRInt32 indx;
|
|
|
|
|
|
|
|
if (!NS_SUCCEEDED(aNode->GetParent(*getter_AddRefs(parent))))
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-03-08 01:20:02 +00:00
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
if (!NS_SUCCEEDED(parent->IndexOf(aNode, indx)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
if (indx && NS_SUCCEEDED(parent->ChildAt(--indx, *getter_AddRefs(sib))) && sib)
|
|
|
|
{
|
|
|
|
*aSibling = sib;
|
|
|
|
}
|
|
|
|
else if (parent != mCommonParent)
|
|
|
|
{
|
1999-03-08 01:20:02 +00:00
|
|
|
return GetPrevSibling(parent, aSibling);
|
1999-03-01 08:17:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*aSibling = nsCOMPtr<nsIContent>();
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-02-16 15:48:13 +00:00
|
|
|
nsresult nsContentIterator::NextNode(nsCOMPtr<nsIContent> *ioNextNode)
|
|
|
|
{
|
|
|
|
if (!ioNextNode)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> cN = *ioNextNode;
|
|
|
|
nsCOMPtr<nsIContent> cSibling;
|
1999-03-01 08:17:18 +00:00
|
|
|
nsCOMPtr<nsIContent> parent;
|
|
|
|
PRInt32 indx;
|
|
|
|
|
|
|
|
// get next sibling if there is one
|
|
|
|
if (!NS_SUCCEEDED(cN->GetParent(*getter_AddRefs(parent))))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (!NS_SUCCEEDED(parent->IndexOf(cN, indx)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (NS_SUCCEEDED(parent->ChildAt(++indx,*getter_AddRefs(cSibling))) && cSibling)
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
// next node is siblings "deep left" child
|
|
|
|
*ioNextNode = GetDeepFirstChild(cSibling);
|
1999-02-16 15:48:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
// else it's the parent
|
|
|
|
*ioNextNode = parent;
|
1999-02-16 15:48:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsContentIterator::PrevNode(nsCOMPtr<nsIContent> *ioNextNode)
|
|
|
|
{
|
|
|
|
if (!ioNextNode)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-03-01 08:17:18 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> cN = *ioNextNode;
|
|
|
|
nsCOMPtr<nsIContent> cLastChild;
|
1999-02-16 15:48:13 +00:00
|
|
|
PRInt32 numChildren;
|
1999-03-01 08:17:18 +00:00
|
|
|
|
|
|
|
cN->ChildCount(numChildren);
|
|
|
|
|
|
|
|
// if it has children then prev node is last child
|
1999-02-16 15:48:13 +00:00
|
|
|
if (numChildren)
|
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
cN->ChildAt(--numChildren,*getter_AddRefs(cLastChild));
|
|
|
|
if (!cLastChild)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
*ioNextNode = cLastChild;
|
1999-02-16 15:48:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
// else prev sibling is previous
|
|
|
|
return GetPrevSibling(cN, ioNextNode);
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
/******************************************************
|
|
|
|
* ContentIterator routines
|
|
|
|
******************************************************/
|
1998-12-14 23:16:31 +00:00
|
|
|
|
|
|
|
nsresult nsContentIterator::First()
|
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!mFirst)
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-02-19 01:41:03 +00:00
|
|
|
mIsDone = PR_FALSE;
|
1999-02-14 09:15:13 +00:00
|
|
|
if (mFirst == mCurNode)
|
|
|
|
return NS_OK;
|
1998-12-14 23:16:31 +00:00
|
|
|
mCurNode = mFirst;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult nsContentIterator::Last()
|
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!mLast)
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-02-19 01:41:03 +00:00
|
|
|
mIsDone = PR_FALSE;
|
1999-02-14 09:15:13 +00:00
|
|
|
if (mLast == mCurNode)
|
|
|
|
return NS_OK;
|
1998-12-14 23:16:31 +00:00
|
|
|
mCurNode = mLast;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult nsContentIterator::Next()
|
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
if (mIsDone)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (!mCurNode)
|
|
|
|
return NS_OK;
|
1999-01-28 23:55:53 +00:00
|
|
|
if (mCurNode == mLast)
|
|
|
|
{
|
1999-02-19 01:41:03 +00:00
|
|
|
mIsDone = PR_TRUE;
|
1999-01-28 23:55:53 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1998-12-14 23:16:31 +00:00
|
|
|
|
1999-02-16 15:48:13 +00:00
|
|
|
return NextNode(&mCurNode);
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult nsContentIterator::Prev()
|
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
if (mIsDone)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (!mCurNode)
|
|
|
|
return NS_OK;
|
|
|
|
if (mCurNode == mFirst)
|
|
|
|
{
|
|
|
|
mIsDone = PR_TRUE;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PrevNode(&mCurNode);
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
nsresult nsContentIterator::IsDone()
|
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
if (mIsDone)
|
|
|
|
return NS_OK;
|
|
|
|
else
|
|
|
|
return NS_COMFALSE;
|
1999-02-12 05:28:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-14 23:16:31 +00:00
|
|
|
nsresult nsContentIterator::CurrentNode(nsIContent **aNode)
|
|
|
|
{
|
1999-02-14 09:15:13 +00:00
|
|
|
if (!mCurNode)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (mIsDone)
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-03-03 19:48:57 +00:00
|
|
|
return mCurNode->QueryInterface(nsIContent::GetIID(), (void**) aNode);
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*====================================================================================*/
|
|
|
|
/*====================================================================================*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************
|
|
|
|
* nsContentSubtreeIterator
|
|
|
|
******************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A simple iterator class for traversing the content in "top subtree" order
|
|
|
|
*/
|
|
|
|
class nsContentSubtreeIterator : public nsContentIterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
nsContentSubtreeIterator() {};
|
|
|
|
virtual ~nsContentSubtreeIterator() {};
|
|
|
|
|
|
|
|
// nsContentIterator overrides ------------------------------
|
|
|
|
|
|
|
|
NS_IMETHOD Init(nsIContent* aRoot);
|
|
|
|
|
|
|
|
NS_IMETHOD Init(nsIDOMRange* aRange);
|
|
|
|
|
|
|
|
NS_IMETHOD Next();
|
|
|
|
|
|
|
|
NS_IMETHOD Prev();
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
protected:
|
1999-02-14 09:15:13 +00:00
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
nsresult GetTopAncestorInRange( nsCOMPtr<nsIContent> aNode,
|
|
|
|
nsCOMPtr<nsIContent> *outAnestor);
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
// no copy's or assigns FIX ME
|
|
|
|
nsContentSubtreeIterator(const nsContentSubtreeIterator&);
|
|
|
|
nsContentSubtreeIterator& operator=(const nsContentSubtreeIterator&);
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
nsCOMPtr<nsIDOMRange> mRange;
|
1999-02-14 09:15:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult);
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
/******************************************************
|
|
|
|
* repository cruft
|
|
|
|
******************************************************/
|
|
|
|
|
|
|
|
nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult)
|
|
|
|
{
|
|
|
|
nsContentIterator * iter = new nsContentSubtreeIterator();
|
1999-03-03 19:48:57 +00:00
|
|
|
return iter->QueryInterface(nsIContentIterator::GetIID(), (void**) aInstancePtrResult);
|
1999-02-14 09:15:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-02-12 05:28:12 +00:00
|
|
|
/******************************************************
|
1999-02-14 09:15:13 +00:00
|
|
|
* Init routines
|
1999-02-12 05:28:12 +00:00
|
|
|
******************************************************/
|
|
|
|
|
1999-02-14 09:15:13 +00:00
|
|
|
|
|
|
|
nsresult nsContentSubtreeIterator::Init(nsIContent* aRoot)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult nsContentSubtreeIterator::Init(nsIDOMRange* aRange)
|
1998-12-14 23:16:31 +00:00
|
|
|
{
|
1999-02-16 15:48:13 +00:00
|
|
|
if (!aRange)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
mRange = do_QueryInterface(aRange);
|
1999-03-01 08:17:18 +00:00
|
|
|
|
1999-02-16 15:48:13 +00:00
|
|
|
// get the start node and offset, convert to nsIContent
|
1999-03-01 08:17:18 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> commonParent;
|
|
|
|
nsCOMPtr<nsIDOMNode> startParent;
|
|
|
|
nsCOMPtr<nsIDOMNode> endParent;
|
|
|
|
nsCOMPtr<nsIContent> cStartP;
|
|
|
|
nsCOMPtr<nsIContent> cEndP;
|
1999-02-16 15:48:13 +00:00
|
|
|
nsCOMPtr<nsIContent> cN;
|
1999-03-08 01:20:02 +00:00
|
|
|
nsCOMPtr<nsIContent> firstCandidate;
|
|
|
|
nsCOMPtr<nsIContent> lastCandidate;
|
1999-03-01 08:17:18 +00:00
|
|
|
|
|
|
|
// get common content parent
|
|
|
|
if (!NS_SUCCEEDED(aRange->GetCommonParent(getter_AddRefs(commonParent))) || !commonParent)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
mCommonParent = do_QueryInterface(commonParent);
|
|
|
|
|
|
|
|
// get start content parent
|
|
|
|
if (!NS_SUCCEEDED(aRange->GetStartParent(getter_AddRefs(startParent))) || !startParent)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
cStartP = do_QueryInterface(startParent);
|
|
|
|
|
|
|
|
// get end content parent
|
|
|
|
if (!NS_SUCCEEDED(aRange->GetEndParent(getter_AddRefs(endParent))) || !endParent)
|
1999-02-16 15:48:13 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
1999-03-01 08:17:18 +00:00
|
|
|
cEndP = do_QueryInterface(endParent);
|
|
|
|
|
1999-02-16 15:48:13 +00:00
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
// find first node in range
|
1999-02-16 15:48:13 +00:00
|
|
|
PRInt32 indx;
|
|
|
|
aRange->GetStartOffset(&indx);
|
|
|
|
nsCOMPtr<nsIContent> cChild;
|
1999-03-01 08:17:18 +00:00
|
|
|
PRInt32 numChildren;
|
|
|
|
cStartP->ChildCount(numChildren);
|
1999-02-16 15:48:13 +00:00
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!numChildren) // no children, must be a text node
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
cN = cStartP;
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
cStartP->ChildAt(indx,*getter_AddRefs(cChild));
|
|
|
|
if (!cChild) // offset after last child
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
cN = cStartP;
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-03-08 01:20:02 +00:00
|
|
|
firstCandidate = cChild;
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!firstCandidate)
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-08 01:20:02 +00:00
|
|
|
// then firstCandidate is next node after cN
|
|
|
|
if (!NS_SUCCEEDED(GetNextSibling(cN, &firstCandidate)))
|
1999-03-01 08:17:18 +00:00
|
|
|
{
|
|
|
|
MakeEmpty();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
1999-03-01 08:17:18 +00:00
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
firstCandidate = GetDeepFirstChild(firstCandidate);
|
1999-03-01 08:17:18 +00:00
|
|
|
|
|
|
|
// confirm that this first possible contained node
|
|
|
|
// is indeed contained. Else we have a range that
|
|
|
|
// does not fully contain any node.
|
|
|
|
|
|
|
|
PRBool nodeBefore, nodeAfter;
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!NS_SUCCEEDED(CompareNodeToRange(firstCandidate, aRange, &nodeBefore, &nodeAfter)))
|
1999-03-01 08:17:18 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (nodeBefore || nodeAfter)
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
MakeEmpty();
|
1999-02-16 15:48:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
// cool, we have the first node in the range. Now we walk
|
|
|
|
// up it's ancestors to find the most senior that is still
|
|
|
|
// in the range. That's the real first node.
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!NS_SUCCEEDED(GetTopAncestorInRange(firstCandidate, &mFirst)))
|
1999-03-01 08:17:18 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
1999-02-16 15:48:13 +00:00
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
// now to find the last node
|
|
|
|
aRange->GetEndOffset(&indx);
|
|
|
|
if (!indx)
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
cN = cEndP;
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
cEndP->ChildCount(numChildren);
|
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!numChildren) // no children, must be a text node
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
cN = cEndP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cEndP->ChildAt(--indx,*getter_AddRefs(cChild));
|
|
|
|
if (!cChild) // shouldn't happen
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
NS_ASSERTION(0,"tree traversal trouble in nsContentSubtreeIterator::Init");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-03-08 01:20:02 +00:00
|
|
|
lastCandidate = cChild;
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!lastCandidate)
|
1999-02-16 15:48:13 +00:00
|
|
|
{
|
1999-03-08 01:20:02 +00:00
|
|
|
// then lastCandidate is prev node before cN
|
|
|
|
if (!NS_SUCCEEDED(GetPrevSibling(cN, &lastCandidate)))
|
1999-03-01 08:17:18 +00:00
|
|
|
{
|
|
|
|
MakeEmpty();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
lastCandidate = GetDeepLastChild(lastCandidate);
|
1999-03-01 08:17:18 +00:00
|
|
|
|
|
|
|
// confirm that this first possible contained node
|
|
|
|
// is indeed contained. Else we have a range that
|
|
|
|
// does not fully contain any node.
|
|
|
|
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!NS_SUCCEEDED(CompareNodeToRange(lastCandidate, aRange, &nodeBefore, &nodeAfter)))
|
1999-03-01 08:17:18 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (nodeBefore || nodeAfter)
|
|
|
|
{
|
|
|
|
MakeEmpty();
|
|
|
|
return NS_OK;
|
1999-02-16 15:48:13 +00:00
|
|
|
}
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
// cool, we have the last node in the range. Now we walk
|
|
|
|
// up it's ancestors to find the most senior that is still
|
|
|
|
// in the range. That's the real first node.
|
1999-03-08 01:20:02 +00:00
|
|
|
if (!NS_SUCCEEDED(GetTopAncestorInRange(lastCandidate, &mLast)))
|
1999-03-01 08:17:18 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
1999-02-16 15:48:13 +00:00
|
|
|
mCurNode = mFirst;
|
1999-03-01 08:17:18 +00:00
|
|
|
|
1999-02-16 15:48:13 +00:00
|
|
|
return NS_OK;
|
1998-12-14 23:16:31 +00:00
|
|
|
}
|
1999-02-14 09:15:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************
|
|
|
|
* nsContentSubtreeIterator overrides of ContentIterator routines
|
|
|
|
****************************************************************/
|
|
|
|
|
|
|
|
nsresult nsContentSubtreeIterator::Next()
|
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
if (mIsDone)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (!mCurNode)
|
|
|
|
return NS_OK;
|
|
|
|
if (mCurNode == mLast)
|
|
|
|
{
|
|
|
|
mIsDone = PR_TRUE;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> nextNode;
|
|
|
|
if (!NS_SUCCEEDED(GetNextSibling(mCurNode, &nextNode)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nextNode = GetDeepFirstChild(nextNode);
|
|
|
|
return GetTopAncestorInRange(nextNode, &mCurNode);
|
1999-02-14 09:15:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult nsContentSubtreeIterator::Prev()
|
|
|
|
{
|
1999-03-01 08:17:18 +00:00
|
|
|
if (mIsDone)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (!mCurNode)
|
|
|
|
return NS_OK;
|
|
|
|
if (mCurNode == mFirst)
|
|
|
|
{
|
|
|
|
mIsDone = PR_TRUE;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> prevNode;
|
|
|
|
prevNode = GetDeepFirstChild(mCurNode);
|
|
|
|
if (!NS_SUCCEEDED(PrevNode(&prevNode)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
prevNode = GetDeepLastChild(prevNode);
|
|
|
|
return GetTopAncestorInRange(prevNode, &mCurNode);
|
1999-02-14 09:15:13 +00:00
|
|
|
}
|
|
|
|
|
1999-03-01 08:17:18 +00:00
|
|
|
/****************************************************************
|
|
|
|
* nsContentSubtreeIterator helper routines
|
|
|
|
****************************************************************/
|
|
|
|
|
|
|
|
nsresult nsContentSubtreeIterator::GetTopAncestorInRange(
|
|
|
|
nsCOMPtr<nsIContent> aNode,
|
|
|
|
nsCOMPtr<nsIContent> *outAnestor)
|
|
|
|
{
|
|
|
|
if (!aNode)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (!outAnestor)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
|
|
|
|
// sanity check: aNode is itself in the range
|
|
|
|
PRBool nodeBefore, nodeAfter;
|
|
|
|
if (!NS_SUCCEEDED(CompareNodeToRange(aNode, mRange, &nodeBefore, &nodeAfter)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (nodeBefore || nodeAfter)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> parent;
|
|
|
|
while (aNode)
|
|
|
|
{
|
|
|
|
if (!NS_SUCCEEDED(aNode->GetParent(*getter_AddRefs(parent))))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (!NS_SUCCEEDED(CompareNodeToRange(parent, mRange, &nodeBefore, &nodeAfter)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (nodeBefore || nodeAfter)
|
|
|
|
{
|
|
|
|
*outAnestor = aNode;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
aNode = parent;
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|