diff --git a/mozilla/content/base/src/Makefile.in b/mozilla/content/base/src/Makefile.in index 3d250879dea..821d24ea30c 100644 --- a/mozilla/content/base/src/Makefile.in +++ b/mozilla/content/base/src/Makefile.in @@ -56,6 +56,7 @@ CPPSRCS = \ nsStyleSet.cpp \ nsTextContentChangeData.cpp \ nsTextNode.cpp \ + nsTreeWalker.cpp \ nsXMLContentSerializer.cpp \ nsHTMLContentSerializer.cpp \ nsParserUtils.cpp \ diff --git a/mozilla/content/base/src/makefile.win b/mozilla/content/base/src/makefile.win index 402b775903a..1b2e5698411 100644 --- a/mozilla/content/base/src/makefile.win +++ b/mozilla/content/base/src/makefile.win @@ -53,6 +53,7 @@ CPPSRCS = \ nsRange.cpp \ nsTextContentChangeData.cpp \ nsTextNode.cpp \ + nsTreeWalker.cpp \ nsXMLContentSerializer.cpp \ nsHTMLContentSerializer.cpp \ nsParserUtils.cpp \ @@ -89,6 +90,7 @@ CPP_OBJS= \ .\$(OBJDIR)\nsRange.obj \ .\$(OBJDIR)\nsTextContentChangeData.obj \ .\$(OBJDIR)\nsTextNode.obj \ + .\$(OBJDIR)\nsTreeWalker.obj \ .\$(OBJDIR)\nsXMLContentSerializer.obj \ .\$(OBJDIR)\nsHTMLContentSerializer.obj \ .\$(OBJDIR)\nsParserUtils.obj \ diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 2c88ce58951..9b52d781f0e 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -75,6 +75,7 @@ #include "nsIDOMText.h" #include "nsIDOMComment.h" #include "nsDOMDocumentType.h" +#include "nsTreeWalker.h" #include "nsINameSpaceManager.h" #include "nsIServiceManager.h" @@ -541,6 +542,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocument) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentStyle) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentView) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentRange) + NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentTraversal) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentXBL) NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal) NS_INTERFACE_MAP_ENTRY(nsIDOMEventReceiver) @@ -2190,6 +2192,30 @@ nsDocument::CreateRange(nsIDOMRange** aReturn) return NS_NewRange(aReturn); } +NS_IMETHODIMP +nsDocument::CreateNodeIterator(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aEntityReferenceExpansion, + nsIDOMNodeIterator **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocument::CreateTreeWalker(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aEntityReferenceExpansion, + nsIDOMTreeWalker **_retval) +{ + return NS_NewTreeWalker(aRoot, + aWhatToShow, + aFilter, + aEntityReferenceExpansion, + _retval); +} + NS_IMETHODIMP nsDocument::GetDefaultView(nsIDOMAbstractView** aDefaultView) diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index f0ba5b3ca73..880ef954542 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -32,6 +32,7 @@ #include "nsIDOMNSDocument.h" #include "nsIDOMDocumentStyle.h" #include "nsIDOMDocumentRange.h" +#include "nsIDOMDocumentTraversal.h" #include "nsIDocumentObserver.h" #include "nsIDOMEventReceiver.h" #include "nsIDiskDocument.h" @@ -203,6 +204,7 @@ class nsDocument : public nsIDocument, public nsIDOMDocumentStyle, public nsIDOMDocumentView, public nsIDOMDocumentRange, + public nsIDOMDocumentTraversal, public nsIDOMDocumentXBL, public nsIDOM3Node, public nsIDiskDocument, @@ -486,6 +488,9 @@ public: // nsIDOMDocumentRange NS_DECL_NSIDOMDOCUMENTRANGE + // nsIDOMDocumentTraversal + NS_DECL_NSIDOMDOCUMENTTRAVERSAL + // nsIDOMDocumentXBL NS_DECL_NSIDOMDOCUMENTXBL diff --git a/mozilla/content/base/src/nsTreeWalker.cpp b/mozilla/content/base/src/nsTreeWalker.cpp index b409c831199..b4119b9aefc 100644 --- a/mozilla/content/base/src/nsTreeWalker.cpp +++ b/mozilla/content/base/src/nsTreeWalker.cpp @@ -42,8 +42,12 @@ #include "nsIDOMNode.h" #include "nsIDOMNodeList.h" +#include "nsIDOMEntityReference.h" #include "nsDOMError.h" +#include "nsIContent.h" +#include "nsIDocument.h" + #include "nsContentUtils.h" #include "nsMemory.h" @@ -52,39 +56,40 @@ */ nsresult -NS_NewTreeWalker(nsIDOMNode *root, - PRUint32 whatToShow, - nsIDOMNodeFilter *filter, - PRBool expandEntityReferences, +NS_NewTreeWalker(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aEntityReferenceExpansion, nsIDOMTreeWalker **aInstancePtrResult) { + NS_ENSURE_ARG_POINTER(aInstancePtrResult); - NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR); + NS_ENSURE_TRUE(aRoot, NS_ERROR_DOM_NOT_SUPPORTED_ERR); - nsTreeWalker* walker = new nsTreeWalker(root, - whatToShow, - filter, - expandEntityReferences); + nsTreeWalker* walker = new nsTreeWalker(aRoot, + aWhatToShow, + aFilter, + aEntityReferenceExpansion); NS_ENSURE_TRUE(walker, NS_ERROR_OUT_OF_MEMORY); return walker->QueryInterface(NS_GET_IID(nsIDOMTreeWalker), (void**) aInstancePtrResult); } -nsTreeWalker::nsTreeWalker(nsIDOMNode *root, - PRUint32 whatToShow, - nsIDOMNodeFilter *filter, - PRBool expandEntityReferences) : - mRoot(root), - mWhatToShow(whatToShow), - mFilter(filter), - mExpandEntityReferences(expandEntityReferences), - mCurrentNode(root) +nsTreeWalker::nsTreeWalker(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aExpandEntityReferences) : + mRoot(aRoot), + mWhatToShow(aWhatToShow), + mFilter(aFilter), + mExpandEntityReferences(aExpandEntityReferences), + mCurrentNode(aRoot), + mPossibleIndexesPos(-1) { NS_INIT_ISUPPORTS(); - /* member initializers and constructor code */ - NS_ASSERTION(root, "invalid root in call to treeWalker constructor"); + NS_ASSERTION(aRoot, "invalid root in call to nsTreeWalker constructor"); } nsTreeWalker::~nsTreeWalker() @@ -115,7 +120,7 @@ NS_IMETHODIMP nsTreeWalker::GetRoot(nsIDOMNode * *aRoot) { NS_ENSURE_ARG_POINTER(aRoot); *aRoot = mRoot; - NS_IF_ADDREF(*aRoot); + NS_ADDREF(*aRoot); return NS_OK; } @@ -136,7 +141,8 @@ NS_IMETHODIMP nsTreeWalker::GetFilter(nsIDOMNodeFilter * *aFilter) } /* readonly attribute boolean expandEntityReferences; */ -NS_IMETHODIMP nsTreeWalker::GetExpandEntityReferences(PRBool *aExpandEntityReferences) +NS_IMETHODIMP +nsTreeWalker::GetExpandEntityReferences(PRBool *aExpandEntityReferences) { *aExpandEntityReferences = mExpandEntityReferences; return NS_OK; @@ -147,13 +153,12 @@ NS_IMETHODIMP nsTreeWalker::GetCurrentNode(nsIDOMNode * *aCurrentNode) { NS_ENSURE_ARG_POINTER(aCurrentNode); *aCurrentNode = mCurrentNode; - NS_IF_ADDREF(*aCurrentNode); + NS_ADDREF(*aCurrentNode); return NS_OK; } NS_IMETHODIMP nsTreeWalker::SetCurrentNode(nsIDOMNode * aCurrentNode) { - if (!aCurrentNode) - return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + NS_ENSURE_TRUE(aCurrentNode, NS_ERROR_DOM_NOT_SUPPORTED_ERR); mCurrentNode = aCurrentNode; return NS_OK; } @@ -169,11 +174,15 @@ NS_IMETHODIMP nsTreeWalker::ParentNode(nsIDOMNode **_retval) nsCOMPtr node(mCurrentNode); nsresult rv; + + PRInt32 indexPos = mPossibleIndexesPos; while (node && node != mRoot) { nsCOMPtr tmp(node); rv = tmp->GetParentNode(getter_AddRefs(node)); NS_ENSURE_SUCCESS(rv, rv); + + indexPos--; if (node) { PRInt16 filtered; @@ -181,6 +190,7 @@ NS_IMETHODIMP nsTreeWalker::ParentNode(nsIDOMNode **_retval) NS_ENSURE_SUCCESS(rv, rv); if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) { mCurrentNode = node; + mPossibleIndexesPos = indexPos >= 0 ? indexPos : -1; *_retval = node; NS_ADDREF(*_retval); @@ -197,167 +207,110 @@ NS_IMETHODIMP nsTreeWalker::ParentNode(nsIDOMNode **_retval) NS_IMETHODIMP nsTreeWalker::FirstChild(nsIDOMNode **_retval) { NS_ENSURE_ARG_POINTER(_retval); - return FirstChildOf(mCurrentNode, PR_FALSE, _retval); + return FirstChildOf(mCurrentNode, + PR_FALSE, + mPossibleIndexesPos+1, + _retval); } /* nsIDOMNode lastChild (); */ NS_IMETHODIMP nsTreeWalker::LastChild(nsIDOMNode **_retval) { NS_ENSURE_ARG_POINTER(_retval); - return FirstChildOf(mCurrentNode, PR_TRUE, _retval); + return FirstChildOf(mCurrentNode, + PR_TRUE, + mPossibleIndexesPos+1, + _retval); } /* nsIDOMNode previousSibling (); */ NS_IMETHODIMP nsTreeWalker::PreviousSibling(nsIDOMNode **_retval) { NS_ENSURE_ARG_POINTER(_retval); - return NextSiblingOf(mCurrentNode, PR_TRUE, _retval); + return NextSiblingOf(mCurrentNode, + PR_TRUE, + mPossibleIndexesPos, + _retval); } /* nsIDOMNode nextSibling (); */ NS_IMETHODIMP nsTreeWalker::NextSibling(nsIDOMNode **_retval) { NS_ENSURE_ARG_POINTER(_retval); - return NextSiblingOf(mCurrentNode, PR_FALSE, _retval); + return NextSiblingOf(mCurrentNode, + PR_FALSE, + mPossibleIndexesPos, + _retval); } /* nsIDOMNode previousNode (); */ NS_IMETHODIMP nsTreeWalker::PreviousNode(nsIDOMNode **_retval) { NS_ENSURE_ARG_POINTER(_retval); - return NextInDocumentOrderOf(mCurrentNode, PR_TRUE, _retval); + return NextInDocumentOrderOf(mCurrentNode, + PR_TRUE, + mPossibleIndexesPos, + _retval); } /* nsIDOMNode nextNode (); */ NS_IMETHODIMP nsTreeWalker::NextNode(nsIDOMNode **_retval) { NS_ENSURE_ARG_POINTER(_retval); - return NextInDocumentOrderOf(mCurrentNode, PR_FALSE, _retval); + return NextInDocumentOrderOf(mCurrentNode, + PR_FALSE, + mPossibleIndexesPos, + _retval); } /* * nsTreeWalker helper functions */ -/* - * Tests if and how a node should be filtered. Uses mWhatToShow and - * mFilter to test the node. - * @param aNode Node to test - * @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl - */ -nsresult nsTreeWalker::TestNode(nsIDOMNode* aNode, PRInt16* _filtered) -{ - nsresult rv; - PRUint16 nodeType; - PRUint32 mask = 1; - - rv = aNode->GetNodeType(&nodeType); - NS_ENSURE_SUCCESS(rv, rv); - - if (nodeType <= 12 && !((mask << (nodeType-1)) & mWhatToShow)) { - *_filtered = nsIDOMNodeFilter::FILTER_SKIP; - - return NS_OK; - } - - if (mFilter) - return mFilter->AcceptNode(aNode, _filtered); - - *_filtered = nsIDOMNodeFilter::FILTER_ACCEPT; - return NS_OK; -} - /* * Finds the first child of aNode and returns it. If a child is * found, mCurrentNode is set to that child. * @param aNode Node to search for children. * @param aReversed Reverses search to find the last child instead * of first. + * @param aIndexPos Position of aNode in mPossibleIndexes. * @param _retval Returned node. Null if no child is found * @returns Errorcode */ nsresult nsTreeWalker::FirstChildOf(nsIDOMNode* aNode, PRBool aReversed, + PRInt32 aIndexPos, nsIDOMNode** _retval) { - nsCOMPtr children; - PRUint32 len; - PRInt16 filtered; nsresult rv; - + // Don't step into entity references if expandEntityReferences = false if (!mExpandEntityReferences) { - PRUint16 nodeType; - rv = aNode->GetNodeType(&nodeType); - NS_ENSURE_SUCCESS(rv, rv); - - if (nodeType == nsIDOMNode::ENTITY_REFERENCE_NODE) { - *_retval = nsnull; + nsCOMPtr ent(do_QueryInterface(aNode)); + if (ent) { + *_retval = nsnull; return NS_OK; } } - - // Get childlist to step through - rv = aNode->GetChildNodes(getter_AddRefs(children)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(children, "GetChildNodes returned nonexisting nodelist"); - rv = children->GetLength(&len); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr childNodes; - PRInt32 dir, start, end; + PRInt32 start; if (!aReversed) { - dir = 1; - start = 0; - end = len; + start = -1; } else { - dir = -1; - start = len-1; - end = -1; + rv = aNode->GetChildNodes(getter_AddRefs(childNodes)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(childNodes, NS_ERROR_UNEXPECTED); + + rv = childNodes->GetLength((PRUint32*)&start); + NS_ENSURE_SUCCESS(rv, rv); } - // Step through all children - PRInt32 i; - for (i = start; i != end; i += dir) { - nsCOMPtr child; - rv = children->Item((PRUint32)i, getter_AddRefs(child)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = TestNode(child, &filtered); - NS_ENSURE_SUCCESS(rv, rv); - - switch (filtered) { - case nsIDOMNodeFilter::FILTER_ACCEPT: - // Child found - mCurrentNode = child; - *_retval = child; - NS_ADDREF(*_retval); - - return NS_OK; - - case nsIDOMNodeFilter::FILTER_SKIP: - // Search children - rv = FirstChildOf(child, aReversed, _retval); - NS_ENSURE_SUCCESS(rv, rv); - - if (*_retval) - return NS_OK; - break; - - case nsIDOMNodeFilter::FILTER_REJECT: - // Keep searching - break; - - default: - return NS_ERROR_UNEXPECTED; - } - } - - *_retval = nsnull; - return NS_OK; + return ChildOf(aNode, start, aReversed, aIndexPos, _retval); } /* @@ -366,79 +319,60 @@ nsTreeWalker::FirstChildOf(nsIDOMNode* aNode, * @param aNode Node to start search at. * @param aReversed Reverses search to find the previous sibling * instead of next. + * @param aIndexPos Position of aNode in mPossibleIndexes. * @param _retval Returned node. Null if no sibling is found * @returns Errorcode */ nsresult nsTreeWalker::NextSiblingOf(nsIDOMNode* aNode, PRBool aReversed, + PRInt32 aIndexPos, nsIDOMNode** _retval) { nsresult rv; nsCOMPtr node(aNode); PRInt16 filtered; + PRInt32 childNum; + + if (node == mRoot) { + *_retval = nsnull; + return NS_OK; + } while (1) { - nsCOMPtr current(node); + nsCOMPtr parent; - // Loop siblings - if (!aReversed) - rv = current->GetNextSibling(getter_AddRefs(node)); - else - rv = current->GetPreviousSibling(getter_AddRefs(node)); + // Get our index in the parent + rv = node->GetParentNode(getter_AddRefs(parent)); NS_ENSURE_SUCCESS(rv, rv); - - while (node) { - rv = TestNode(node, &filtered); - NS_ENSURE_SUCCESS(rv, rv); - switch (filtered) { - case nsIDOMNodeFilter::FILTER_ACCEPT: - // Sibling found - mCurrentNode = node; - *_retval = node; - NS_ADDREF(*_retval); + if (!parent) + break; - return NS_OK; - - case nsIDOMNodeFilter::FILTER_SKIP: - // Search children - rv = FirstChildOf(node, aReversed, _retval); - NS_ENSURE_SUCCESS(rv, rv); - - if (*_retval) - return NS_OK; - break; - - case nsIDOMNodeFilter::FILTER_REJECT: - // Keep searching - break; - - default: - return NS_ERROR_UNEXPECTED; - } - - current = node; - if (!aReversed) - rv = current->GetNextSibling(getter_AddRefs(node)); - else - rv = current->GetPreviousSibling(getter_AddRefs(node)); - NS_ENSURE_SUCCESS(rv, rv); - } - - // Try to get parent - rv = current->GetParentNode(getter_AddRefs(node)); + rv = IndexOf(parent, node, aIndexPos, &childNum); NS_ENSURE_SUCCESS(rv, rv); - if (!node || node == mRoot) + + // Search siblings + ChildOf(parent, childNum, aReversed, aIndexPos, _retval); + NS_ENSURE_SUCCESS(rv, rv); + + if (*_retval) + return NS_OK; + + // Is parent the root? + if (parent == mRoot) break; // Is parent transparent in filtered view? - rv = TestNode(node, &filtered); + rv = TestNode(parent, &filtered); NS_ENSURE_SUCCESS(rv, rv); if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) break; + + node = parent; + aIndexPos = aIndexPos < 0 ? -1 : aIndexPos-1; } - + *_retval = nsnull; return NS_OK; } @@ -449,97 +383,316 @@ nsTreeWalker::NextSiblingOf(nsIDOMNode* aNode, * @param aNode Node to start search at. * @param aReversed Reverses search to find the preceding node * instead of next. + * @param aIndexPos Position of aNode in mPossibleIndexes. * @param _retval Returned node. Null if no node is found * @returns Errorcode */ nsresult nsTreeWalker::NextInDocumentOrderOf(nsIDOMNode* aNode, PRBool aReversed, + PRInt32 aIndexPos, nsIDOMNode** _retval) { nsresult rv; + + if (!aReversed) { + rv = FirstChildOf(aNode, aReversed, aIndexPos+1, _retval); + NS_ENSURE_SUCCESS(rv, rv); + + if (*_retval) + return NS_OK; + } + else if (aNode == mRoot){ + *_retval = nsnull; + return NS_OK; + } + nsCOMPtr node(aNode); + nsCOMPtr currentNodeBackup(mCurrentNode); PRInt16 filtered; + PRInt32 childNum; while (1) { - nsCOMPtr current(node); + nsCOMPtr parent; - // Loop siblings - if (!aReversed) - rv = current->GetNextSibling(getter_AddRefs(node)); - else - rv = current->GetPreviousSibling(getter_AddRefs(node)); + // Get our index in the parent + rv = node->GetParentNode(getter_AddRefs(parent)); NS_ENSURE_SUCCESS(rv, rv); - - while (node) { - rv = TestNode(node, &filtered); - NS_ENSURE_SUCCESS(rv, rv); - switch (filtered) { - case nsIDOMNodeFilter::FILTER_ACCEPT: - // Sibling found. - if (aReversed) { - // If reversed search we first - // check if it has a child... - rv = FirstChildOf(node, PR_TRUE, _retval); - NS_ENSURE_SUCCESS(rv, rv); + if (!parent) + break; - if (*_retval) - return NS_OK; + rv = IndexOf(parent, node, aIndexPos, &childNum); + NS_ENSURE_SUCCESS(rv, rv); + + // Search siblings + nsCOMPtr sibling; + ChildOf(parent, childNum, aReversed, aIndexPos, getter_AddRefs(sibling)); + NS_ENSURE_SUCCESS(rv, rv); + + if (sibling) { + if (aReversed) { + // in reversed walking we first test if there are + // any children. I don't like this piece of code :( + nsCOMPtr child(sibling); + while(child) { + sibling = child; + rv = FirstChildOf(sibling, + PR_TRUE, + aIndexPos, + getter_AddRefs(child)); + if (NS_FAILED(rv)) { + // ChildOf set mCurrentNode and then something + // failed. Restore the old value before returning + mCurrentNode = currentNodeBackup; + mPossibleIndexesPos = -1; + return rv; } - - // ...else we return the sibling - mCurrentNode = node; - *_retval = node; - NS_ADDREF(*_retval); - - return NS_OK; - - case nsIDOMNodeFilter::FILTER_SKIP: - // Search children - rv = FirstChildOf(node, aReversed, _retval); - NS_ENSURE_SUCCESS(rv, rv); - - if (*_retval) - return NS_OK; - break; - - case nsIDOMNodeFilter::FILTER_REJECT: - // Keep searching - break; - - default: - return NS_ERROR_UNEXPECTED; + } } - - current = node; - if (!aReversed) - rv = current->GetNextSibling(getter_AddRefs(node)); - else - rv = current->GetPreviousSibling(getter_AddRefs(node)); - NS_ENSURE_SUCCESS(rv, rv); + *_retval = sibling; + NS_ADDREF(*_retval); + return NS_OK; } - // Try to get parent - rv = current->GetParentNode(getter_AddRefs(node)); - NS_ENSURE_SUCCESS(rv, rv); - if (!node || node == mRoot) - break; + aIndexPos = aIndexPos < 0 ? -1 : aIndexPos-1; if (aReversed) { // Is parent transparent in filtered view? - rv = TestNode(node, &filtered); + rv = TestNode(parent, &filtered); NS_ENSURE_SUCCESS(rv, rv); if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) { - mCurrentNode = node; - *_retval = node; + mCurrentNode = parent; + mPossibleIndexesPos = aIndexPos; + *_retval = parent; NS_ADDREF(*_retval); - return NS_OK; } } + + // Is parent the root? + if (parent == mRoot) + break; + + node = parent; } - + *_retval = nsnull; return NS_OK; } + +/* + * Finds the first child of aNode after child N and returns it. If a + * child is found, mCurrentNode is set to that child + * @param aNode Node to search for children + * @param childNum Child number to start search from. The child with + * this number is not searched + * @param aReversed Reverses search to find the last child instead + * of first + * @param aIndexPos Position of aNode in mPossibleIndexes + * @param _retval Returned node. Null if no child is found + * @returns Errorcode + */ +nsresult +nsTreeWalker::ChildOf(nsIDOMNode* aNode, + PRInt32 childNum, + PRBool aReversed, + PRInt32 aIndexPos, + nsIDOMNode** _retval) +{ + PRInt16 filtered; + nsresult rv; + nsCOMPtr childNodes; + + rv = aNode->GetChildNodes(getter_AddRefs(childNodes)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(childNodes, NS_ERROR_UNEXPECTED); + + PRInt32 dir, end; + if (!aReversed) { + dir = 1; + rv = childNodes->GetLength((PRUint32*)&end); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + dir = -1; + end = -1; + } + + // Step through all children + PRInt32 i; + for (i = childNum+dir; i != end; i += dir) { + nsCOMPtr child; + rv = childNodes->Item(i, getter_AddRefs(child)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = TestNode(child, &filtered); + NS_ENSURE_SUCCESS(rv, rv); + + switch (filtered) { + case nsIDOMNodeFilter::FILTER_ACCEPT: + // Child found + mCurrentNode = child; + mPossibleIndexesPos = aIndexPos; + *_retval = child; + NS_ADDREF(*_retval); + + SetChildIndex(aIndexPos, i); + + return NS_OK; + + case nsIDOMNodeFilter::FILTER_SKIP: + // Search children + rv = FirstChildOf(child, aReversed, aIndexPos+1, _retval); + NS_ENSURE_SUCCESS(rv, rv); + + if (*_retval) { + SetChildIndex(aIndexPos, i); + return NS_OK; + } + break; + + case nsIDOMNodeFilter::FILTER_REJECT: + // Keep searching + break; + + default: + return NS_ERROR_UNEXPECTED; + } + } + + *_retval = nsnull; + return NS_OK; +} + +/* + * Tests if and how a node should be filtered. Uses mWhatToShow and + * mFilter to test the node. + * @param aNode Node to test + * @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl + * @returns Errorcode + */ +nsresult nsTreeWalker::TestNode(nsIDOMNode* aNode, PRInt16* _filtered) +{ + nsresult rv; + PRUint16 nodeType; + PRUint32 mask = 1; + + nsCOMPtr node(aNode); + + rv = node->GetNodeType(&nodeType); + NS_ENSURE_SUCCESS(rv, rv); + + if (nodeType <= 12 && !((mask << (nodeType-1)) & mWhatToShow)) { + *_filtered = nsIDOMNodeFilter::FILTER_SKIP; + + return NS_OK; + } + + if (mFilter) + return mFilter->AcceptNode(node, _filtered); + + *_filtered = nsIDOMNodeFilter::FILTER_ACCEPT; + return NS_OK; +} + +/* + * Gets the child index of a node within it's parent. Gets a possible index + * from mPossibleIndexes to gain speed. If the value in mPossibleIndexes + * isn't correct it'll get the index the usual way + * @param aParent in which to get the index + * @param aChild node to get the index of + * @param aIndexPos position in mPossibleIndexes that contains the possible. + * index + * @param _childNum returned index + * @returns Errorcode + */ +nsresult nsTreeWalker::IndexOf(nsIDOMNode* aParent, + nsIDOMNode* aChild, + PRInt32 aIndexPos, + PRInt32* _childNum) +{ + PRInt32 possibleIndex = -1; + if (aIndexPos >= 0) + possibleIndex = NS_PTR_TO_INT32(mPossibleIndexes[aIndexPos]); + + nsCOMPtr contParent(do_QueryInterface(aParent)); + if (contParent) { + nsCOMPtr child(do_QueryInterface(aChild)); + + if (possibleIndex >= 0) { + nsCOMPtr tmp; + contParent->ChildAt(possibleIndex, *getter_AddRefs(tmp)); + if (tmp == child) { + *_childNum = possibleIndex; + return NS_OK; + } + } + + contParent->IndexOf(child, *_childNum); + + return *_childNum >= 0 ? NS_OK : NS_ERROR_UNEXPECTED; + } + + nsCOMPtr docParent(do_QueryInterface(aParent)); + if (docParent) { + nsCOMPtr child(do_QueryInterface(aChild)); + + if (possibleIndex >= 0) { + nsCOMPtr tmp; + contParent->ChildAt(possibleIndex, *getter_AddRefs(tmp)); + if (tmp == child) { + *_childNum = possibleIndex; + return NS_OK; + } + } + + docParent->IndexOf(child, *_childNum); + + return *_childNum >= 0 ? NS_OK : NS_ERROR_UNEXPECTED; + } + + nsresult rv; + PRUint32 i, len; + nsCOMPtr childNodes; + + rv = aParent->GetChildNodes(getter_AddRefs(childNodes)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(childNodes, NS_ERROR_UNEXPECTED); + + if (possibleIndex >= 0) { + nsCOMPtr tmp; + childNodes->Item(possibleIndex, getter_AddRefs(tmp)); + if (tmp == aChild) { + *_childNum = possibleIndex; + return NS_OK; + } + } + + rv = childNodes->GetLength(&len); + NS_ENSURE_SUCCESS(rv, rv); + + for (i = 0; i < len; ++i) { + nsCOMPtr node; + rv = childNodes->Item(i, getter_AddRefs(node)); + NS_ENSURE_SUCCESS(rv, rv); + + if (node == aChild) { + *_childNum = i; + return NS_OK; + } + } + + return NS_ERROR_UNEXPECTED; +} + +/* + * Sets the child index at the specified level. It doesn't matter if this + * fails since mPossibleIndexes should only be considered a hint + * @param aIndexPos position in mPossibleIndexes to set + * @param aChildIndex child index at specified position + */ +void nsTreeWalker::SetChildIndex(PRInt32 aIndexPos, PRInt32 aChildIndex) +{ + mPossibleIndexes.ReplaceElementAt(NS_INT32_TO_PTR(aChildIndex), aIndexPos); +} diff --git a/mozilla/content/base/src/nsTreeWalker.h b/mozilla/content/base/src/nsTreeWalker.h index 69e2ff9c3fc..43de58527cf 100644 --- a/mozilla/content/base/src/nsTreeWalker.h +++ b/mozilla/content/base/src/nsTreeWalker.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file @@ -45,6 +45,7 @@ #include "nsIDOMTreeWalker.h" #include "nsIDOMNodeFilter.h" #include "nsCOMPtr.h" +#include "nsVoidArray.h" class nsTreeWalker : public nsIDOMTreeWalker { @@ -52,10 +53,10 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIDOMTREEWALKER - nsTreeWalker(nsIDOMNode *root, - PRUint32 whatToShow, - nsIDOMNodeFilter *filter, - PRBool expandEntityReferences); + nsTreeWalker(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aExpandEntityReferences); virtual ~nsTreeWalker(); /* additional members */ private: @@ -64,26 +65,32 @@ private: nsCOMPtr mFilter; PRBool mExpandEntityReferences; nsCOMPtr mCurrentNode; - + /* - * Tests if and how a node should be filtered. Uses mWhatToShow and - * mFilter to test the node. - * @param aNode Node to test - * @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl + * Array with all child indexes up the tree. This should only be + * considered a hint and the value could be wrong. + * The array contains casted PRInt32's */ - nsresult TestNode(nsIDOMNode* aNode, PRInt16* _filtered); - + nsAutoVoidArray mPossibleIndexes; + + /* + * Position of mCurrentNode in mPossibleIndexes + */ + PRInt32 mPossibleIndexesPos; + /* * Finds the first child of aNode and returns it. If a child is * found, mCurrentNode is set to that child. * @param aNode Node to search for children. * @param aReversed Reverses search to find the last child instead * of first. + * @param aIndexPos Position of aNode in mPossibleIndexes. * @param _retval Returned node. Null if no child is found * @returns Errorcode */ nsresult FirstChildOf(nsIDOMNode* aNode, PRBool aReversed, + PRInt32 aIndexPos, nsIDOMNode** _retval); /* @@ -92,31 +99,88 @@ private: * @param aNode Node to start search at. * @param aReversed Reverses search to find the previous sibling * instead of next. + * @param aIndexPos Position of aNode in mPossibleIndexes. * @param _retval Returned node. Null if no sibling is found * @returns Errorcode */ nsresult NextSiblingOf(nsIDOMNode* aNode, PRBool aReversed, + PRInt32 aIndexPos, nsIDOMNode** _retval); + /* * Finds the next node in document order of aNode and returns it. * If a node is found, mCurrentNode is set to that node. * @param aNode Node to start search at. * @param aReversed Reverses search to find the preceding node * instead of next. + * @param aIndexPos Position of aNode in mPossibleIndexes. * @param _retval Returned node. Null if no node is found * @returns Errorcode */ nsresult NextInDocumentOrderOf(nsIDOMNode* aNode, PRBool aReversed, + PRInt32 aIndexPos, nsIDOMNode** _retval); + + /* + * Finds the first child of aNode after child N and returns it. If a + * child is found, mCurrentNode is set to that child + * @param aNode Node to search for children + * @param childNum Child number to start search from. The child with + * this number is not searched + * @param aReversed Reverses search to find the last child instead + * of first + * @param aIndexPos Position of aNode in mPossibleIndexes + * @param _retval Returned node. Null if no child is found + * @returns Errorcode + */ + nsresult ChildOf(nsIDOMNode* aNode, + PRInt32 childNum, + PRBool aReversed, + PRInt32 aIndexPos, + nsIDOMNode** _retval); + + /* + * Tests if and how a node should be filtered. Uses mWhatToShow and + * mFilter to test the node. + * @param aNode Node to test + * @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl + * @returns Errorcode + */ + nsresult TestNode(nsIDOMNode* aNode, PRInt16* _filtered); + + /* + * Gets the child index of a node within it's parent. Gets a possible index + * from mPossibleIndexes to gain speed. If the value in mPossibleIndexes + * isn't correct it'll get the index the usual way. + * @param aParent in which to get the index + * @param aChild node to get the index of + * @param aIndexPos position in mPossibleIndexes that contains the possible. + * index + * @param _childNum returned index + * @returns Errorcode + */ + nsresult IndexOf(nsIDOMNode* aParent, + nsIDOMNode* aChild, + PRInt32 aIndexPos, + PRInt32* _childNum); + + /* + * Sets the child index at the specified level. It doesn't matter if this + * fails since mPossibleIndexes should only be considered a hint + * @param aIndexPos position in mPossibleIndexes to set + * @param aChildIndex child index at specified position + */ + void SetChildIndex(PRInt32 aIndexPos, PRInt32 aChildIndex); + }; // Make a new nsIDOMTreeWalker object -nsresult NS_NewTreeWalker(nsIDOMNode *root, - PRUint32 whatToShow, - nsIDOMNodeFilter *filter, - PRBool entityReferenceExpansion, +nsresult NS_NewTreeWalker(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aEntityReferenceExpansion, nsIDOMTreeWalker **aInstancePtrResult); #endif \ No newline at end of file diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index 0bce10105fc..8465c073484 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -122,6 +122,7 @@ #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" #include "nsXULCommandDispatcher.h" +#include "nsTreeWalker.h" #include "nsXULDocument.h" #include "nsXULElement.h" #include "plstr.h" @@ -581,6 +582,7 @@ NS_INTERFACE_MAP_BEGIN(nsXULDocument) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentXBL) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentStyle) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentRange) + NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentTraversal) NS_INTERFACE_MAP_ENTRY(nsIHTMLContentContainer) NS_INTERFACE_MAP_ENTRY(nsIDOMEventReceiver) NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget) @@ -2703,6 +2705,30 @@ nsXULDocument::CreateRange(nsIDOMRange** aRange) (void **)aRange); } +NS_IMETHODIMP +nsXULDocument::CreateNodeIterator(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aEntityReferenceExpansion, + nsIDOMNodeIterator **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsXULDocument::CreateTreeWalker(nsIDOMNode *aRoot, + PRUint32 aWhatToShow, + nsIDOMNodeFilter *aFilter, + PRBool aEntityReferenceExpansion, + nsIDOMTreeWalker **_retval) +{ + return NS_NewTreeWalker(aRoot, + aWhatToShow, + aFilter, + aEntityReferenceExpansion, + _retval); +} + NS_IMETHODIMP nsXULDocument::GetDefaultView(nsIDOMAbstractView** aDefaultView) { diff --git a/mozilla/content/xul/document/src/nsXULDocument.h b/mozilla/content/xul/document/src/nsXULDocument.h index 0d6a80d2aed..936a8338fe0 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.h +++ b/mozilla/content/xul/document/src/nsXULDocument.h @@ -39,6 +39,7 @@ #include "nsIDOMDocumentView.h" #include "nsIDOMDocumentXBL.h" #include "nsIDOMDocumentRange.h" +#include "nsIDOMDocumentTraversal.h" #include "nsIDOMStyleSheetList.h" #include "nsISelection.h" #include "nsIDOMXULCommandDispatcher.h" @@ -106,6 +107,7 @@ class nsXULDocument : public nsIDocument, public nsIDOMDocumentView, public nsIDOMDocumentXBL, public nsIDOMDocumentRange, + public nsIDOMDocumentTraversal, public nsIDOMNSDocument, public nsIDOM3Node, public nsIDOMDocumentStyle, @@ -376,6 +378,9 @@ public: // nsIDOMDocumentRange interface NS_DECL_NSIDOMDOCUMENTRANGE + // nsIDOMDocumentTraversal interface + NS_DECL_NSIDOMDOCUMENTTRAVERSAL + // nsIDOMNSDocument interface NS_DECL_NSIDOMNSDOCUMENT diff --git a/mozilla/dom/public/nsIDOMClassInfo.h b/mozilla/dom/public/nsIDOMClassInfo.h index 89ae4e07b5b..fe466f612f2 100644 --- a/mozilla/dom/public/nsIDOMClassInfo.h +++ b/mozilla/dom/public/nsIDOMClassInfo.h @@ -179,6 +179,9 @@ enum nsDOMClassInfoID { eDOMClassInfo_XPathProcessor_id, eDOMClassInfo_NodeSet_id, + // DOM Traversal classes + eDOMClassInfo_TreeWalker_id, + // This one better be the last one in this list eDOMClassInfoIDCount }; diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index 57ec6f19ec4..8891602d75b 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -152,6 +152,7 @@ #include "nsIDOMMutationEvent.h" #include "nsIDOMDocumentStyle.h" #include "nsIDOMDocumentRange.h" +#include "nsIDOMDocumentTraversal.h" #include "nsIDOMDocumentXBL.h" #include "nsIDOMDocumentView.h" #include "nsIDOMElementCSSInlineStyle.h" @@ -227,6 +228,7 @@ #include "nsIDOMCSSStyleSheet.h" #include "nsIDOMRange.h" #include "nsIDOMNSRange.h" +#include "nsIDOMTreeWalker.h" #include "nsIDOMXULDocument.h" #include "nsIDOMXULElement.h" #include "nsIDOMXULTreeElement.h" @@ -638,6 +640,10 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(NodeSet, nsArraySH, ARRAY_SCRIPTABLE_FLAGS) + + // DOM Traversal classes + NS_DEFINE_CLASSINFO_DATA(TreeWalker, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) }; nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull; @@ -970,6 +976,7 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentStyle) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentView) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentRange) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTraversal) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentXBL) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_END @@ -1064,6 +1071,7 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentStyle) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentView) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentRange) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTraversal) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentXBL) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_END @@ -1459,6 +1467,10 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSRange) DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(TreeWalker, nsIDOMTreeWalker) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMTreeWalker) + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(Selection, nsISelection) DOM_CLASSINFO_MAP_ENTRY(nsISelection) DOM_CLASSINFO_MAP_END @@ -1471,6 +1483,7 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentXBL) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentStyle) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentRange) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTraversal) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_END diff --git a/mozilla/embedding/config/basebrowser-unix b/mozilla/embedding/config/basebrowser-unix index d3ea56e3caa..b5394f16ea6 100644 --- a/mozilla/embedding/config/basebrowser-unix +++ b/mozilla/embedding/config/basebrowser-unix @@ -80,6 +80,7 @@ components/dom_events.xpt components/dom_html.xpt components/dom_range.xpt components/dom_stylesheets.xpt +components/dom_traversal.xpt components/dom_views.xpt components/dom_xbl.xpt components/dom_xul.xpt diff --git a/mozilla/embedding/config/basebrowser-win b/mozilla/embedding/config/basebrowser-win index f767f484f2a..a1bdd90ec2e 100644 --- a/mozilla/embedding/config/basebrowser-win +++ b/mozilla/embedding/config/basebrowser-win @@ -90,6 +90,7 @@ components\dom_events.xpt components\dom_html.xpt components\dom_range.xpt components\dom_stylesheets.xpt +components\dom_traversal.xpt components\dom_views.xpt components\dom_xbl.xpt components\dom_xul.xpt diff --git a/mozilla/xpinstall/packager/packages-mac b/mozilla/xpinstall/packager/packages-mac index 14f65e76154..3611944e735 100644 --- a/mozilla/xpinstall/packager/packages-mac +++ b/mozilla/xpinstall/packager/packages-mac @@ -94,6 +94,7 @@ viewer:Components:dom_events.xpt viewer:Components:dom_html.xpt viewer:Components:dom_range.xpt viewer:Components:dom_stylesheets.xpt +viewer:Components:dom_traversal.xpt viewer:Components:dom_views.xpt viewer:Components:dom_xbl.xpt viewer:Components:dom_xul.xpt diff --git a/mozilla/xpinstall/packager/packages-static-unix b/mozilla/xpinstall/packager/packages-static-unix index 4e6260405a1..a6acbc2780a 100644 --- a/mozilla/xpinstall/packager/packages-static-unix +++ b/mozilla/xpinstall/packager/packages-static-unix @@ -73,6 +73,7 @@ bin/components/dom_events.xpt bin/components/dom_html.xpt bin/components/dom_range.xpt bin/components/dom_stylesheets.xpt +bin/components/dom_traversal.xpt bin/components/dom_views.xpt bin/components/dom_xbl.xpt bin/components/dom_xul.xpt diff --git a/mozilla/xpinstall/packager/packages-static-win b/mozilla/xpinstall/packager/packages-static-win index f7f93ff436f..ff620623640 100644 --- a/mozilla/xpinstall/packager/packages-static-win +++ b/mozilla/xpinstall/packager/packages-static-win @@ -80,6 +80,7 @@ bin\components\dom_events.xpt bin\components\dom_html.xpt bin\components\dom_range.xpt bin\components\dom_stylesheets.xpt +bin\components\dom_traversal.xpt bin\components\dom_views.xpt bin\components\dom_xbl.xpt bin\components\dom_xul.xpt diff --git a/mozilla/xpinstall/packager/packages-unix b/mozilla/xpinstall/packager/packages-unix index 1e2688dce1e..5752efe3693 100644 --- a/mozilla/xpinstall/packager/packages-unix +++ b/mozilla/xpinstall/packager/packages-unix @@ -86,6 +86,7 @@ bin/components/dom_events.xpt bin/components/dom_html.xpt bin/components/dom_range.xpt bin/components/dom_stylesheets.xpt +bin/components/dom_traversal.xpt bin/components/dom_views.xpt bin/components/dom_xbl.xpt bin/components/dom_xul.xpt diff --git a/mozilla/xpinstall/packager/packages-win b/mozilla/xpinstall/packager/packages-win index 0d6bcfc93df..a01891e5704 100644 --- a/mozilla/xpinstall/packager/packages-win +++ b/mozilla/xpinstall/packager/packages-win @@ -102,6 +102,7 @@ bin\components\dom_events.xpt bin\components\dom_html.xpt bin\components\dom_range.xpt bin\components\dom_stylesheets.xpt +bin\components\dom_traversal.xpt bin\components\dom_views.xpt bin\components\dom_xbl.xpt bin\components\dom_xul.xpt