diff --git a/mozilla/htmlparser/src/nsAVLTree.cpp b/mozilla/htmlparser/src/nsAVLTree.cpp
new file mode 100644
index 00000000000..36ccda7c4ff
--- /dev/null
+++ b/mozilla/htmlparser/src/nsAVLTree.cpp
@@ -0,0 +1,605 @@
+/* -*- 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) 1999 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "nsAVLTree.h"
+
+
+enum eLean {eLeft,eNeutral,eRight};
+
+struct NS_COM nsAVLNode {
+public:
+
+ nsAVLNode(void* aValue) {
+ mLeft=0;
+ mRight=0;
+ mSkew=eNeutral;
+ mValue=aValue;
+ }
+
+ nsAVLNode* mLeft;
+ nsAVLNode* mRight;
+ eLean mSkew;
+ void* mValue;
+};
+
+
+/************************************************************
+ Now begin the tree class. Don't forget that the comparison
+ between nodes must occur via the comparitor function,
+ otherwise all you're testing is pointer addresses.
+ ************************************************************/
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
+ nsAVLNodeFunctor* aDeallocator) :
+ mComparitor(aComparitor), mDeallocator(aDeallocator) {
+ mRoot=0;
+ mCount=0;
+}
+
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+nsAVLTree::~nsAVLTree(){
+ if (mDeallocator) {
+ ForEachDepthFirst(*mDeallocator);
+ }
+}
+
+
+class CDoesntExist: public nsAVLNodeFunctor {
+public:
+ CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
+ }
+ virtual void* operator()(void* anItem) {
+ void* result=mOtherTree.FindItem(anItem);
+ if(result)
+ return nsnull;
+ return anItem;
+ }
+protected:
+ const nsAVLTree& mOtherTree;
+};
+
+/**
+ * This method compares two trees (members by identity).
+ * @update gess12/27/98
+ * @param tree to compare against
+ * @return true if they are identical (contain same stuff).
+ */
+PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
+ void* theItem=FirstThat(CDoesntExist(aCopy));
+ PRBool result=PRBool(!theItem);
+ return result;
+}
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+static void
+avlRotateRight(nsAVLNode*& aRootNode){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+
+ ptr2=aRootNode->mRight;
+ if(ptr2->mSkew==eRight) {
+ aRootNode->mRight=ptr2->mLeft;
+ ptr2->mLeft=aRootNode;
+ aRootNode->mSkew=eNeutral;
+ aRootNode=ptr2;
+ }
+ else {
+ ptr3=ptr2->mLeft;
+ ptr2->mLeft=ptr3->mRight;
+ ptr3->mRight=ptr2;
+ aRootNode->mRight=ptr3->mLeft;
+ ptr3->mLeft=aRootNode;
+ if(ptr3->mSkew==eLeft)
+ ptr2->mSkew=eRight;
+ else ptr2->mSkew=eNeutral;
+ if(ptr3->mSkew==eRight)
+ aRootNode->mSkew=eLeft;
+ else aRootNode->mSkew=eNeutral;
+ aRootNode=ptr3;
+ }
+ aRootNode->mSkew=eNeutral;
+ return;
+}
+
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+static void
+avlRotateLeft(nsAVLNode*& aRootNode){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+
+ ptr2=aRootNode->mLeft;
+ if(ptr2->mSkew==eLeft) {
+ aRootNode->mLeft=ptr2->mRight;
+ ptr2->mRight=aRootNode;
+ aRootNode->mSkew=eNeutral;
+ aRootNode=ptr2;
+ }
+ else {
+ ptr3=ptr2->mRight;
+ ptr2->mRight=ptr3->mLeft;
+ ptr3->mLeft=ptr2;
+ aRootNode->mLeft=ptr3->mRight;
+ ptr3->mRight=aRootNode;
+ if(ptr3->mSkew==eRight)
+ ptr2->mSkew=eLeft;
+ else ptr2->mSkew=eNeutral;
+ if(ptr3->mSkew==eLeft)
+ aRootNode->mSkew=eRight;
+ else aRootNode->mSkew=eNeutral;
+ aRootNode=ptr3;
+ }
+ aRootNode->mSkew=eNeutral;
+ return;
+}
+
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
+ nsAVLNodeComparitor& aComparitor) {
+ eAVLStatus result=eAVL_unknown;
+
+ if(!aRootNode) {
+ aRootNode = aNewNode;
+ return eAVL_ok;
+ }
+
+ if(aNewNode==aRootNode->mValue) {
+ return eAVL_duplicate;
+ }
+
+ PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
+ if(0 < theCompareResult) { //if(anItemmValue)
+ result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
+ if(eAVL_ok==result) {
+ switch(aRootNode->mSkew){
+ case eLeft:
+ avlRotateLeft(aRootNode);
+ result=eAVL_fail;
+ break;
+ case eRight:
+ aRootNode->mSkew=eNeutral;
+ result=eAVL_fail;
+ break;
+ case eNeutral:
+ aRootNode->mSkew=eLeft;
+ break;
+ } //switch
+ }//if
+ } //if
+ else {
+ result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
+ if(eAVL_ok==result) {
+ switch(aRootNode->mSkew){
+ case eLeft:
+ aRootNode->mSkew=eNeutral;
+ result=eAVL_fail;
+ break;
+ case eRight:
+ avlRotateRight(aRootNode);
+ result=eAVL_fail;
+ break;
+ case eNeutral:
+ aRootNode->mSkew=eRight;
+ break;
+ } //switch
+ }
+ } //if
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static void
+avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+ eLean balnc2;
+ eLean balnc3;
+
+ switch(aRootNode->mSkew){
+ case eLeft:
+ ptr2=aRootNode->mLeft;
+ balnc2=ptr2->mSkew;
+ if(balnc2!=eRight) {
+ aRootNode->mLeft=ptr2->mRight;
+ ptr2->mRight=aRootNode;
+ if(balnc2==eNeutral){
+ aRootNode->mSkew=eLeft;
+ ptr2->mSkew=eRight;
+ delOk=PR_FALSE;
+ }
+ else{
+ aRootNode->mSkew=eNeutral;
+ ptr2->mSkew=eNeutral;
+ }
+ aRootNode=ptr2;
+ }
+ else{
+ ptr3=ptr2->mRight;
+ balnc3=ptr3->mSkew;
+ ptr2->mRight=ptr3->mLeft;
+ ptr3->mLeft=ptr2;
+ aRootNode->mLeft=ptr3->mRight;
+ ptr3->mRight=aRootNode;
+ if(balnc3==eRight) {
+ ptr2->mSkew=eLeft;
+ }
+ else {
+ ptr2->mSkew=eNeutral;
+ }
+ if(balnc3==eLeft) {
+ aRootNode->mSkew=eRight;
+ }
+ else {
+ aRootNode->mSkew=eNeutral;
+ }
+ aRootNode=ptr3;
+ ptr3->mSkew=eNeutral;
+ }
+ break;
+
+ case eRight:
+ aRootNode->mSkew=eNeutral;
+ break;
+
+ case eNeutral:
+ aRootNode->mSkew=eLeft;
+ delOk=PR_FALSE;
+ break;
+ }//switch
+ return;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static void
+avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+ eLean balnc2;
+ eLean balnc3;
+
+ switch(aRootNode->mSkew){
+ case eLeft:
+ aRootNode->mSkew=eNeutral;
+ break;
+
+ case eRight:
+ ptr2=aRootNode->mRight;
+ balnc2=ptr2->mSkew;
+ if(balnc2!=eLeft) {
+ aRootNode->mRight=ptr2->mLeft;
+ ptr2->mLeft=aRootNode;
+ if(balnc2==eNeutral){
+ aRootNode->mSkew=eRight;
+ ptr2->mSkew=eLeft;
+ delOk=PR_FALSE;
+ }
+ else{
+ aRootNode->mSkew=eNeutral;
+ ptr2->mSkew=eNeutral;
+ }
+ aRootNode=ptr2;
+ }
+ else{
+ ptr3=ptr2->mLeft;
+ balnc3=ptr3->mSkew;
+ ptr2->mLeft=ptr3->mRight;
+ ptr3->mRight=ptr2;
+ aRootNode->mRight=ptr3->mLeft;
+ ptr3->mLeft=aRootNode;
+ if(balnc3==eLeft) {
+ ptr2->mSkew=eRight;
+ }
+ else {
+ ptr2->mSkew=eNeutral;
+ }
+ if(balnc3==eRight) {
+ aRootNode->mSkew=eLeft;
+ }
+ else {
+ aRootNode->mSkew=eNeutral;
+ }
+ aRootNode=ptr3;
+ ptr3->mSkew=eNeutral;
+ }
+ break;
+
+ case eNeutral:
+ aRootNode->mSkew=eRight;
+ delOk=PR_FALSE;
+ break;
+ }//switch
+ return;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
+ eAVLStatus result=eAVL_ok;
+
+ if(!anotherNode->mRight){
+ aRootNode->mValue=anotherNode->mValue; //swap
+ anotherNode=anotherNode->mLeft;
+ delOk=PR_TRUE;
+ }
+ else{
+ avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
+ if(delOk)
+ avlBalanceLeft(anotherNode,delOk);
+ }
+
+ return result;
+}
+
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
+ nsAVLNodeComparitor& aComparitor){
+ eAVLStatus result=eAVL_ok;
+
+ if(!aRootNode)
+ delOk=PR_FALSE;
+ else {
+ PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
+ if(cmp<0){
+ avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
+ if(delOk)
+ avlBalanceRight(aRootNode,delOk);
+ }
+ else if(cmp>0){
+ avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
+ if(delOk)
+ avlBalanceLeft(aRootNode,delOk);
+ }
+ else{ //they match...
+ nsAVLNode* temp=aRootNode;
+ if(!aRootNode->mRight) {
+ aRootNode=aRootNode->mLeft;
+ delOk=PR_TRUE;
+ delete temp;
+ }
+ else if(!aRootNode->mLeft) {
+ aRootNode=aRootNode->mRight;
+ delOk=PR_TRUE;
+ delete temp;
+ }
+ else {
+ avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
+ if(delOk)
+ avlBalanceRight(aRootNode,delOk);
+ }
+ }
+ }
+
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+eAVLStatus
+nsAVLTree::AddItem(void* anItem){
+ eAVLStatus result=eAVL_ok;
+
+ nsAVLNode* theNewNode=new nsAVLNode(anItem);
+ result=avlInsert(mRoot,theNewNode,mComparitor);
+ if(eAVL_duplicate!=result)
+ mCount++;
+ else {
+ delete theNewNode;
+ }
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+void* nsAVLTree::FindItem(void* aValue) const{
+ nsAVLNode* result=mRoot;
+ PRInt32 count=0;
+ while(result) {
+ count++;
+ PRInt32 cmp=mComparitor(aValue,result->mValue);
+ if(0==cmp) {
+ //we matched...
+ break;
+ }
+ else if(0>cmp){
+ //theNode was greater...
+ result=result->mLeft;
+ }
+ else {
+ //aValue is greater...
+ result=result->mRight;
+ }
+ }
+ if(result) {
+ return result->mValue;
+ }
+ return nsnull;
+}
+
+
+/**
+ *
+ * @update gess12/30/98
+ * @param
+ * @return
+ */
+eAVLStatus
+nsAVLTree::RemoveItem(void* aValue){
+ PRBool delOk=PR_TRUE;
+ eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
+ if(eAVL_ok==result)
+ mCount--;
+ return result;
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void
+avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
+ if(aNode) {
+ avlForEachDepthFirst(aNode->mLeft,aFunctor);
+ avlForEachDepthFirst(aNode->mRight,aFunctor);
+ aFunctor(aNode->mValue);
+ }
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void
+nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
+ ::avlForEachDepthFirst(mRoot,aFunctor);
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void
+avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
+ if(aNode) {
+ avlForEach(aNode->mLeft,aFunctor);
+ aFunctor(aNode->mValue);
+ avlForEach(aNode->mRight,aFunctor);
+ }
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void
+nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
+ ::avlForEach(mRoot,aFunctor);
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void*
+avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
+ void* result=nsnull;
+ if(aNode) {
+ if (result = avlFirstThat(aNode->mLeft,aFunctor)) {
+ return result;
+ }
+ if (result = aFunctor(aNode->mValue)) {
+ return result;
+ }
+ result = avlFirstThat(aNode->mRight,aFunctor);
+ }
+ return result;
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void*
+nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
+ return ::avlFirstThat(mRoot,aFunctor);
+}
+
diff --git a/mozilla/htmlparser/src/nsAVLTree.h b/mozilla/htmlparser/src/nsAVLTree.h
new file mode 100644
index 00000000000..2d01851dd25
--- /dev/null
+++ b/mozilla/htmlparser/src/nsAVLTree.h
@@ -0,0 +1,74 @@
+/* -*- 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) 1999 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef nsAVLTree_h___
+#define nsAVLTree_h___
+
+
+#include "nscore.h"
+
+
+enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
+
+
+struct nsAVLNode;
+
+/**
+ *
+ * @update gess12/26/98
+ * @param anObject1 is the first object to be compared
+ * @param anObject2 is the second object to be compared
+ * @return -1,0,1 if object1 is less, equal, greater than object2
+ */
+class NS_COM nsAVLNodeComparitor {
+public:
+ virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
+};
+
+class NS_COM nsAVLNodeFunctor {
+public:
+ virtual void* operator()(void* anItem)=0;
+};
+
+class NS_COM nsAVLTree {
+public:
+ nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
+ ~nsAVLTree(void);
+
+ PRBool operator==(const nsAVLTree& aOther) const;
+ PRInt32 GetCount(void) const {return mCount;}
+
+ //main functions...
+ eAVLStatus AddItem(void* anItem);
+ eAVLStatus RemoveItem(void* anItem);
+ void* FindItem(void* anItem) const;
+ void ForEach(nsAVLNodeFunctor& aFunctor) const;
+ void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
+ void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
+
+protected:
+
+ nsAVLNode* mRoot;
+ PRInt32 mCount;
+ nsAVLNodeComparitor& mComparitor;
+ nsAVLNodeFunctor* mDeallocator;
+};
+
+
+#endif /* nsAVLTree_h___ */
+
diff --git a/mozilla/parser/htmlparser/src/nsAVLTree.cpp b/mozilla/parser/htmlparser/src/nsAVLTree.cpp
new file mode 100644
index 00000000000..36ccda7c4ff
--- /dev/null
+++ b/mozilla/parser/htmlparser/src/nsAVLTree.cpp
@@ -0,0 +1,605 @@
+/* -*- 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) 1999 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "nsAVLTree.h"
+
+
+enum eLean {eLeft,eNeutral,eRight};
+
+struct NS_COM nsAVLNode {
+public:
+
+ nsAVLNode(void* aValue) {
+ mLeft=0;
+ mRight=0;
+ mSkew=eNeutral;
+ mValue=aValue;
+ }
+
+ nsAVLNode* mLeft;
+ nsAVLNode* mRight;
+ eLean mSkew;
+ void* mValue;
+};
+
+
+/************************************************************
+ Now begin the tree class. Don't forget that the comparison
+ between nodes must occur via the comparitor function,
+ otherwise all you're testing is pointer addresses.
+ ************************************************************/
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
+ nsAVLNodeFunctor* aDeallocator) :
+ mComparitor(aComparitor), mDeallocator(aDeallocator) {
+ mRoot=0;
+ mCount=0;
+}
+
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+nsAVLTree::~nsAVLTree(){
+ if (mDeallocator) {
+ ForEachDepthFirst(*mDeallocator);
+ }
+}
+
+
+class CDoesntExist: public nsAVLNodeFunctor {
+public:
+ CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
+ }
+ virtual void* operator()(void* anItem) {
+ void* result=mOtherTree.FindItem(anItem);
+ if(result)
+ return nsnull;
+ return anItem;
+ }
+protected:
+ const nsAVLTree& mOtherTree;
+};
+
+/**
+ * This method compares two trees (members by identity).
+ * @update gess12/27/98
+ * @param tree to compare against
+ * @return true if they are identical (contain same stuff).
+ */
+PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
+ void* theItem=FirstThat(CDoesntExist(aCopy));
+ PRBool result=PRBool(!theItem);
+ return result;
+}
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+static void
+avlRotateRight(nsAVLNode*& aRootNode){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+
+ ptr2=aRootNode->mRight;
+ if(ptr2->mSkew==eRight) {
+ aRootNode->mRight=ptr2->mLeft;
+ ptr2->mLeft=aRootNode;
+ aRootNode->mSkew=eNeutral;
+ aRootNode=ptr2;
+ }
+ else {
+ ptr3=ptr2->mLeft;
+ ptr2->mLeft=ptr3->mRight;
+ ptr3->mRight=ptr2;
+ aRootNode->mRight=ptr3->mLeft;
+ ptr3->mLeft=aRootNode;
+ if(ptr3->mSkew==eLeft)
+ ptr2->mSkew=eRight;
+ else ptr2->mSkew=eNeutral;
+ if(ptr3->mSkew==eRight)
+ aRootNode->mSkew=eLeft;
+ else aRootNode->mSkew=eNeutral;
+ aRootNode=ptr3;
+ }
+ aRootNode->mSkew=eNeutral;
+ return;
+}
+
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+static void
+avlRotateLeft(nsAVLNode*& aRootNode){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+
+ ptr2=aRootNode->mLeft;
+ if(ptr2->mSkew==eLeft) {
+ aRootNode->mLeft=ptr2->mRight;
+ ptr2->mRight=aRootNode;
+ aRootNode->mSkew=eNeutral;
+ aRootNode=ptr2;
+ }
+ else {
+ ptr3=ptr2->mRight;
+ ptr2->mRight=ptr3->mLeft;
+ ptr3->mLeft=ptr2;
+ aRootNode->mLeft=ptr3->mRight;
+ ptr3->mRight=aRootNode;
+ if(ptr3->mSkew==eRight)
+ ptr2->mSkew=eLeft;
+ else ptr2->mSkew=eNeutral;
+ if(ptr3->mSkew==eLeft)
+ aRootNode->mSkew=eRight;
+ else aRootNode->mSkew=eNeutral;
+ aRootNode=ptr3;
+ }
+ aRootNode->mSkew=eNeutral;
+ return;
+}
+
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
+ nsAVLNodeComparitor& aComparitor) {
+ eAVLStatus result=eAVL_unknown;
+
+ if(!aRootNode) {
+ aRootNode = aNewNode;
+ return eAVL_ok;
+ }
+
+ if(aNewNode==aRootNode->mValue) {
+ return eAVL_duplicate;
+ }
+
+ PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
+ if(0 < theCompareResult) { //if(anItemmValue)
+ result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
+ if(eAVL_ok==result) {
+ switch(aRootNode->mSkew){
+ case eLeft:
+ avlRotateLeft(aRootNode);
+ result=eAVL_fail;
+ break;
+ case eRight:
+ aRootNode->mSkew=eNeutral;
+ result=eAVL_fail;
+ break;
+ case eNeutral:
+ aRootNode->mSkew=eLeft;
+ break;
+ } //switch
+ }//if
+ } //if
+ else {
+ result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
+ if(eAVL_ok==result) {
+ switch(aRootNode->mSkew){
+ case eLeft:
+ aRootNode->mSkew=eNeutral;
+ result=eAVL_fail;
+ break;
+ case eRight:
+ avlRotateRight(aRootNode);
+ result=eAVL_fail;
+ break;
+ case eNeutral:
+ aRootNode->mSkew=eRight;
+ break;
+ } //switch
+ }
+ } //if
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static void
+avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+ eLean balnc2;
+ eLean balnc3;
+
+ switch(aRootNode->mSkew){
+ case eLeft:
+ ptr2=aRootNode->mLeft;
+ balnc2=ptr2->mSkew;
+ if(balnc2!=eRight) {
+ aRootNode->mLeft=ptr2->mRight;
+ ptr2->mRight=aRootNode;
+ if(balnc2==eNeutral){
+ aRootNode->mSkew=eLeft;
+ ptr2->mSkew=eRight;
+ delOk=PR_FALSE;
+ }
+ else{
+ aRootNode->mSkew=eNeutral;
+ ptr2->mSkew=eNeutral;
+ }
+ aRootNode=ptr2;
+ }
+ else{
+ ptr3=ptr2->mRight;
+ balnc3=ptr3->mSkew;
+ ptr2->mRight=ptr3->mLeft;
+ ptr3->mLeft=ptr2;
+ aRootNode->mLeft=ptr3->mRight;
+ ptr3->mRight=aRootNode;
+ if(balnc3==eRight) {
+ ptr2->mSkew=eLeft;
+ }
+ else {
+ ptr2->mSkew=eNeutral;
+ }
+ if(balnc3==eLeft) {
+ aRootNode->mSkew=eRight;
+ }
+ else {
+ aRootNode->mSkew=eNeutral;
+ }
+ aRootNode=ptr3;
+ ptr3->mSkew=eNeutral;
+ }
+ break;
+
+ case eRight:
+ aRootNode->mSkew=eNeutral;
+ break;
+
+ case eNeutral:
+ aRootNode->mSkew=eLeft;
+ delOk=PR_FALSE;
+ break;
+ }//switch
+ return;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static void
+avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+ eLean balnc2;
+ eLean balnc3;
+
+ switch(aRootNode->mSkew){
+ case eLeft:
+ aRootNode->mSkew=eNeutral;
+ break;
+
+ case eRight:
+ ptr2=aRootNode->mRight;
+ balnc2=ptr2->mSkew;
+ if(balnc2!=eLeft) {
+ aRootNode->mRight=ptr2->mLeft;
+ ptr2->mLeft=aRootNode;
+ if(balnc2==eNeutral){
+ aRootNode->mSkew=eRight;
+ ptr2->mSkew=eLeft;
+ delOk=PR_FALSE;
+ }
+ else{
+ aRootNode->mSkew=eNeutral;
+ ptr2->mSkew=eNeutral;
+ }
+ aRootNode=ptr2;
+ }
+ else{
+ ptr3=ptr2->mLeft;
+ balnc3=ptr3->mSkew;
+ ptr2->mLeft=ptr3->mRight;
+ ptr3->mRight=ptr2;
+ aRootNode->mRight=ptr3->mLeft;
+ ptr3->mLeft=aRootNode;
+ if(balnc3==eLeft) {
+ ptr2->mSkew=eRight;
+ }
+ else {
+ ptr2->mSkew=eNeutral;
+ }
+ if(balnc3==eRight) {
+ aRootNode->mSkew=eLeft;
+ }
+ else {
+ aRootNode->mSkew=eNeutral;
+ }
+ aRootNode=ptr3;
+ ptr3->mSkew=eNeutral;
+ }
+ break;
+
+ case eNeutral:
+ aRootNode->mSkew=eRight;
+ delOk=PR_FALSE;
+ break;
+ }//switch
+ return;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
+ eAVLStatus result=eAVL_ok;
+
+ if(!anotherNode->mRight){
+ aRootNode->mValue=anotherNode->mValue; //swap
+ anotherNode=anotherNode->mLeft;
+ delOk=PR_TRUE;
+ }
+ else{
+ avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
+ if(delOk)
+ avlBalanceLeft(anotherNode,delOk);
+ }
+
+ return result;
+}
+
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
+ nsAVLNodeComparitor& aComparitor){
+ eAVLStatus result=eAVL_ok;
+
+ if(!aRootNode)
+ delOk=PR_FALSE;
+ else {
+ PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
+ if(cmp<0){
+ avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
+ if(delOk)
+ avlBalanceRight(aRootNode,delOk);
+ }
+ else if(cmp>0){
+ avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
+ if(delOk)
+ avlBalanceLeft(aRootNode,delOk);
+ }
+ else{ //they match...
+ nsAVLNode* temp=aRootNode;
+ if(!aRootNode->mRight) {
+ aRootNode=aRootNode->mLeft;
+ delOk=PR_TRUE;
+ delete temp;
+ }
+ else if(!aRootNode->mLeft) {
+ aRootNode=aRootNode->mRight;
+ delOk=PR_TRUE;
+ delete temp;
+ }
+ else {
+ avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
+ if(delOk)
+ avlBalanceRight(aRootNode,delOk);
+ }
+ }
+ }
+
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+eAVLStatus
+nsAVLTree::AddItem(void* anItem){
+ eAVLStatus result=eAVL_ok;
+
+ nsAVLNode* theNewNode=new nsAVLNode(anItem);
+ result=avlInsert(mRoot,theNewNode,mComparitor);
+ if(eAVL_duplicate!=result)
+ mCount++;
+ else {
+ delete theNewNode;
+ }
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+void* nsAVLTree::FindItem(void* aValue) const{
+ nsAVLNode* result=mRoot;
+ PRInt32 count=0;
+ while(result) {
+ count++;
+ PRInt32 cmp=mComparitor(aValue,result->mValue);
+ if(0==cmp) {
+ //we matched...
+ break;
+ }
+ else if(0>cmp){
+ //theNode was greater...
+ result=result->mLeft;
+ }
+ else {
+ //aValue is greater...
+ result=result->mRight;
+ }
+ }
+ if(result) {
+ return result->mValue;
+ }
+ return nsnull;
+}
+
+
+/**
+ *
+ * @update gess12/30/98
+ * @param
+ * @return
+ */
+eAVLStatus
+nsAVLTree::RemoveItem(void* aValue){
+ PRBool delOk=PR_TRUE;
+ eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
+ if(eAVL_ok==result)
+ mCount--;
+ return result;
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void
+avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
+ if(aNode) {
+ avlForEachDepthFirst(aNode->mLeft,aFunctor);
+ avlForEachDepthFirst(aNode->mRight,aFunctor);
+ aFunctor(aNode->mValue);
+ }
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void
+nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
+ ::avlForEachDepthFirst(mRoot,aFunctor);
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void
+avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
+ if(aNode) {
+ avlForEach(aNode->mLeft,aFunctor);
+ aFunctor(aNode->mValue);
+ avlForEach(aNode->mRight,aFunctor);
+ }
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void
+nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
+ ::avlForEach(mRoot,aFunctor);
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void*
+avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
+ void* result=nsnull;
+ if(aNode) {
+ if (result = avlFirstThat(aNode->mLeft,aFunctor)) {
+ return result;
+ }
+ if (result = aFunctor(aNode->mValue)) {
+ return result;
+ }
+ result = avlFirstThat(aNode->mRight,aFunctor);
+ }
+ return result;
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void*
+nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
+ return ::avlFirstThat(mRoot,aFunctor);
+}
+
diff --git a/mozilla/parser/htmlparser/src/nsAVLTree.h b/mozilla/parser/htmlparser/src/nsAVLTree.h
new file mode 100644
index 00000000000..2d01851dd25
--- /dev/null
+++ b/mozilla/parser/htmlparser/src/nsAVLTree.h
@@ -0,0 +1,74 @@
+/* -*- 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) 1999 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef nsAVLTree_h___
+#define nsAVLTree_h___
+
+
+#include "nscore.h"
+
+
+enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
+
+
+struct nsAVLNode;
+
+/**
+ *
+ * @update gess12/26/98
+ * @param anObject1 is the first object to be compared
+ * @param anObject2 is the second object to be compared
+ * @return -1,0,1 if object1 is less, equal, greater than object2
+ */
+class NS_COM nsAVLNodeComparitor {
+public:
+ virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
+};
+
+class NS_COM nsAVLNodeFunctor {
+public:
+ virtual void* operator()(void* anItem)=0;
+};
+
+class NS_COM nsAVLTree {
+public:
+ nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
+ ~nsAVLTree(void);
+
+ PRBool operator==(const nsAVLTree& aOther) const;
+ PRInt32 GetCount(void) const {return mCount;}
+
+ //main functions...
+ eAVLStatus AddItem(void* anItem);
+ eAVLStatus RemoveItem(void* anItem);
+ void* FindItem(void* anItem) const;
+ void ForEach(nsAVLNodeFunctor& aFunctor) const;
+ void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
+ void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
+
+protected:
+
+ nsAVLNode* mRoot;
+ PRInt32 mCount;
+ nsAVLNodeComparitor& mComparitor;
+ nsAVLNodeFunctor* mDeallocator;
+};
+
+
+#endif /* nsAVLTree_h___ */
+
diff --git a/mozilla/xpcom/ds/nsAVLTree.cpp b/mozilla/xpcom/ds/nsAVLTree.cpp
new file mode 100644
index 00000000000..36ccda7c4ff
--- /dev/null
+++ b/mozilla/xpcom/ds/nsAVLTree.cpp
@@ -0,0 +1,605 @@
+/* -*- 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) 1999 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "nsAVLTree.h"
+
+
+enum eLean {eLeft,eNeutral,eRight};
+
+struct NS_COM nsAVLNode {
+public:
+
+ nsAVLNode(void* aValue) {
+ mLeft=0;
+ mRight=0;
+ mSkew=eNeutral;
+ mValue=aValue;
+ }
+
+ nsAVLNode* mLeft;
+ nsAVLNode* mRight;
+ eLean mSkew;
+ void* mValue;
+};
+
+
+/************************************************************
+ Now begin the tree class. Don't forget that the comparison
+ between nodes must occur via the comparitor function,
+ otherwise all you're testing is pointer addresses.
+ ************************************************************/
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
+ nsAVLNodeFunctor* aDeallocator) :
+ mComparitor(aComparitor), mDeallocator(aDeallocator) {
+ mRoot=0;
+ mCount=0;
+}
+
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+nsAVLTree::~nsAVLTree(){
+ if (mDeallocator) {
+ ForEachDepthFirst(*mDeallocator);
+ }
+}
+
+
+class CDoesntExist: public nsAVLNodeFunctor {
+public:
+ CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
+ }
+ virtual void* operator()(void* anItem) {
+ void* result=mOtherTree.FindItem(anItem);
+ if(result)
+ return nsnull;
+ return anItem;
+ }
+protected:
+ const nsAVLTree& mOtherTree;
+};
+
+/**
+ * This method compares two trees (members by identity).
+ * @update gess12/27/98
+ * @param tree to compare against
+ * @return true if they are identical (contain same stuff).
+ */
+PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
+ void* theItem=FirstThat(CDoesntExist(aCopy));
+ PRBool result=PRBool(!theItem);
+ return result;
+}
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+static void
+avlRotateRight(nsAVLNode*& aRootNode){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+
+ ptr2=aRootNode->mRight;
+ if(ptr2->mSkew==eRight) {
+ aRootNode->mRight=ptr2->mLeft;
+ ptr2->mLeft=aRootNode;
+ aRootNode->mSkew=eNeutral;
+ aRootNode=ptr2;
+ }
+ else {
+ ptr3=ptr2->mLeft;
+ ptr2->mLeft=ptr3->mRight;
+ ptr3->mRight=ptr2;
+ aRootNode->mRight=ptr3->mLeft;
+ ptr3->mLeft=aRootNode;
+ if(ptr3->mSkew==eLeft)
+ ptr2->mSkew=eRight;
+ else ptr2->mSkew=eNeutral;
+ if(ptr3->mSkew==eRight)
+ aRootNode->mSkew=eLeft;
+ else aRootNode->mSkew=eNeutral;
+ aRootNode=ptr3;
+ }
+ aRootNode->mSkew=eNeutral;
+ return;
+}
+
+
+
+/**
+ *
+ * @update gess12/27/98
+ * @param
+ * @return
+ */
+static void
+avlRotateLeft(nsAVLNode*& aRootNode){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+
+ ptr2=aRootNode->mLeft;
+ if(ptr2->mSkew==eLeft) {
+ aRootNode->mLeft=ptr2->mRight;
+ ptr2->mRight=aRootNode;
+ aRootNode->mSkew=eNeutral;
+ aRootNode=ptr2;
+ }
+ else {
+ ptr3=ptr2->mRight;
+ ptr2->mRight=ptr3->mLeft;
+ ptr3->mLeft=ptr2;
+ aRootNode->mLeft=ptr3->mRight;
+ ptr3->mRight=aRootNode;
+ if(ptr3->mSkew==eRight)
+ ptr2->mSkew=eLeft;
+ else ptr2->mSkew=eNeutral;
+ if(ptr3->mSkew==eLeft)
+ aRootNode->mSkew=eRight;
+ else aRootNode->mSkew=eNeutral;
+ aRootNode=ptr3;
+ }
+ aRootNode->mSkew=eNeutral;
+ return;
+}
+
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
+ nsAVLNodeComparitor& aComparitor) {
+ eAVLStatus result=eAVL_unknown;
+
+ if(!aRootNode) {
+ aRootNode = aNewNode;
+ return eAVL_ok;
+ }
+
+ if(aNewNode==aRootNode->mValue) {
+ return eAVL_duplicate;
+ }
+
+ PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
+ if(0 < theCompareResult) { //if(anItemmValue)
+ result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
+ if(eAVL_ok==result) {
+ switch(aRootNode->mSkew){
+ case eLeft:
+ avlRotateLeft(aRootNode);
+ result=eAVL_fail;
+ break;
+ case eRight:
+ aRootNode->mSkew=eNeutral;
+ result=eAVL_fail;
+ break;
+ case eNeutral:
+ aRootNode->mSkew=eLeft;
+ break;
+ } //switch
+ }//if
+ } //if
+ else {
+ result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
+ if(eAVL_ok==result) {
+ switch(aRootNode->mSkew){
+ case eLeft:
+ aRootNode->mSkew=eNeutral;
+ result=eAVL_fail;
+ break;
+ case eRight:
+ avlRotateRight(aRootNode);
+ result=eAVL_fail;
+ break;
+ case eNeutral:
+ aRootNode->mSkew=eRight;
+ break;
+ } //switch
+ }
+ } //if
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static void
+avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+ eLean balnc2;
+ eLean balnc3;
+
+ switch(aRootNode->mSkew){
+ case eLeft:
+ ptr2=aRootNode->mLeft;
+ balnc2=ptr2->mSkew;
+ if(balnc2!=eRight) {
+ aRootNode->mLeft=ptr2->mRight;
+ ptr2->mRight=aRootNode;
+ if(balnc2==eNeutral){
+ aRootNode->mSkew=eLeft;
+ ptr2->mSkew=eRight;
+ delOk=PR_FALSE;
+ }
+ else{
+ aRootNode->mSkew=eNeutral;
+ ptr2->mSkew=eNeutral;
+ }
+ aRootNode=ptr2;
+ }
+ else{
+ ptr3=ptr2->mRight;
+ balnc3=ptr3->mSkew;
+ ptr2->mRight=ptr3->mLeft;
+ ptr3->mLeft=ptr2;
+ aRootNode->mLeft=ptr3->mRight;
+ ptr3->mRight=aRootNode;
+ if(balnc3==eRight) {
+ ptr2->mSkew=eLeft;
+ }
+ else {
+ ptr2->mSkew=eNeutral;
+ }
+ if(balnc3==eLeft) {
+ aRootNode->mSkew=eRight;
+ }
+ else {
+ aRootNode->mSkew=eNeutral;
+ }
+ aRootNode=ptr3;
+ ptr3->mSkew=eNeutral;
+ }
+ break;
+
+ case eRight:
+ aRootNode->mSkew=eNeutral;
+ break;
+
+ case eNeutral:
+ aRootNode->mSkew=eLeft;
+ delOk=PR_FALSE;
+ break;
+ }//switch
+ return;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static void
+avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
+ nsAVLNode* ptr2;
+ nsAVLNode* ptr3;
+ eLean balnc2;
+ eLean balnc3;
+
+ switch(aRootNode->mSkew){
+ case eLeft:
+ aRootNode->mSkew=eNeutral;
+ break;
+
+ case eRight:
+ ptr2=aRootNode->mRight;
+ balnc2=ptr2->mSkew;
+ if(balnc2!=eLeft) {
+ aRootNode->mRight=ptr2->mLeft;
+ ptr2->mLeft=aRootNode;
+ if(balnc2==eNeutral){
+ aRootNode->mSkew=eRight;
+ ptr2->mSkew=eLeft;
+ delOk=PR_FALSE;
+ }
+ else{
+ aRootNode->mSkew=eNeutral;
+ ptr2->mSkew=eNeutral;
+ }
+ aRootNode=ptr2;
+ }
+ else{
+ ptr3=ptr2->mLeft;
+ balnc3=ptr3->mSkew;
+ ptr2->mLeft=ptr3->mRight;
+ ptr3->mRight=ptr2;
+ aRootNode->mRight=ptr3->mLeft;
+ ptr3->mLeft=aRootNode;
+ if(balnc3==eLeft) {
+ ptr2->mSkew=eRight;
+ }
+ else {
+ ptr2->mSkew=eNeutral;
+ }
+ if(balnc3==eRight) {
+ aRootNode->mSkew=eLeft;
+ }
+ else {
+ aRootNode->mSkew=eNeutral;
+ }
+ aRootNode=ptr3;
+ ptr3->mSkew=eNeutral;
+ }
+ break;
+
+ case eNeutral:
+ aRootNode->mSkew=eRight;
+ delOk=PR_FALSE;
+ break;
+ }//switch
+ return;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
+ eAVLStatus result=eAVL_ok;
+
+ if(!anotherNode->mRight){
+ aRootNode->mValue=anotherNode->mValue; //swap
+ anotherNode=anotherNode->mLeft;
+ delOk=PR_TRUE;
+ }
+ else{
+ avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
+ if(delOk)
+ avlBalanceLeft(anotherNode,delOk);
+ }
+
+ return result;
+}
+
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+static eAVLStatus
+avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
+ nsAVLNodeComparitor& aComparitor){
+ eAVLStatus result=eAVL_ok;
+
+ if(!aRootNode)
+ delOk=PR_FALSE;
+ else {
+ PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
+ if(cmp<0){
+ avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
+ if(delOk)
+ avlBalanceRight(aRootNode,delOk);
+ }
+ else if(cmp>0){
+ avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
+ if(delOk)
+ avlBalanceLeft(aRootNode,delOk);
+ }
+ else{ //they match...
+ nsAVLNode* temp=aRootNode;
+ if(!aRootNode->mRight) {
+ aRootNode=aRootNode->mLeft;
+ delOk=PR_TRUE;
+ delete temp;
+ }
+ else if(!aRootNode->mLeft) {
+ aRootNode=aRootNode->mRight;
+ delOk=PR_TRUE;
+ delete temp;
+ }
+ else {
+ avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
+ if(delOk)
+ avlBalanceRight(aRootNode,delOk);
+ }
+ }
+ }
+
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+eAVLStatus
+nsAVLTree::AddItem(void* anItem){
+ eAVLStatus result=eAVL_ok;
+
+ nsAVLNode* theNewNode=new nsAVLNode(anItem);
+ result=avlInsert(mRoot,theNewNode,mComparitor);
+ if(eAVL_duplicate!=result)
+ mCount++;
+ else {
+ delete theNewNode;
+ }
+ return result;
+}
+
+/** ------------------------------------------------
+ *
+ *
+ * @update gess 4/22/98
+ * @param
+ * @return
+ */ //----------------------------------------------
+void* nsAVLTree::FindItem(void* aValue) const{
+ nsAVLNode* result=mRoot;
+ PRInt32 count=0;
+ while(result) {
+ count++;
+ PRInt32 cmp=mComparitor(aValue,result->mValue);
+ if(0==cmp) {
+ //we matched...
+ break;
+ }
+ else if(0>cmp){
+ //theNode was greater...
+ result=result->mLeft;
+ }
+ else {
+ //aValue is greater...
+ result=result->mRight;
+ }
+ }
+ if(result) {
+ return result->mValue;
+ }
+ return nsnull;
+}
+
+
+/**
+ *
+ * @update gess12/30/98
+ * @param
+ * @return
+ */
+eAVLStatus
+nsAVLTree::RemoveItem(void* aValue){
+ PRBool delOk=PR_TRUE;
+ eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
+ if(eAVL_ok==result)
+ mCount--;
+ return result;
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void
+avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
+ if(aNode) {
+ avlForEachDepthFirst(aNode->mLeft,aFunctor);
+ avlForEachDepthFirst(aNode->mRight,aFunctor);
+ aFunctor(aNode->mValue);
+ }
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void
+nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
+ ::avlForEachDepthFirst(mRoot,aFunctor);
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void
+avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
+ if(aNode) {
+ avlForEach(aNode->mLeft,aFunctor);
+ aFunctor(aNode->mValue);
+ avlForEach(aNode->mRight,aFunctor);
+ }
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void
+nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
+ ::avlForEach(mRoot,aFunctor);
+}
+
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+static void*
+avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
+ void* result=nsnull;
+ if(aNode) {
+ if (result = avlFirstThat(aNode->mLeft,aFunctor)) {
+ return result;
+ }
+ if (result = aFunctor(aNode->mValue)) {
+ return result;
+ }
+ result = avlFirstThat(aNode->mRight,aFunctor);
+ }
+ return result;
+}
+
+/**
+ *
+ * @update gess9/11/98
+ * @param
+ * @return
+ */
+void*
+nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
+ return ::avlFirstThat(mRoot,aFunctor);
+}
+
diff --git a/mozilla/xpcom/ds/nsAVLTree.h b/mozilla/xpcom/ds/nsAVLTree.h
new file mode 100644
index 00000000000..2d01851dd25
--- /dev/null
+++ b/mozilla/xpcom/ds/nsAVLTree.h
@@ -0,0 +1,74 @@
+/* -*- 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) 1999 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef nsAVLTree_h___
+#define nsAVLTree_h___
+
+
+#include "nscore.h"
+
+
+enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
+
+
+struct nsAVLNode;
+
+/**
+ *
+ * @update gess12/26/98
+ * @param anObject1 is the first object to be compared
+ * @param anObject2 is the second object to be compared
+ * @return -1,0,1 if object1 is less, equal, greater than object2
+ */
+class NS_COM nsAVLNodeComparitor {
+public:
+ virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
+};
+
+class NS_COM nsAVLNodeFunctor {
+public:
+ virtual void* operator()(void* anItem)=0;
+};
+
+class NS_COM nsAVLTree {
+public:
+ nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
+ ~nsAVLTree(void);
+
+ PRBool operator==(const nsAVLTree& aOther) const;
+ PRInt32 GetCount(void) const {return mCount;}
+
+ //main functions...
+ eAVLStatus AddItem(void* anItem);
+ eAVLStatus RemoveItem(void* anItem);
+ void* FindItem(void* anItem) const;
+ void ForEach(nsAVLNodeFunctor& aFunctor) const;
+ void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
+ void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
+
+protected:
+
+ nsAVLNode* mRoot;
+ PRInt32 mCount;
+ nsAVLNodeComparitor& mComparitor;
+ nsAVLNodeFunctor* mDeallocator;
+};
+
+
+#endif /* nsAVLTree_h___ */
+