nisheeth%netscape.com f553d5a1c9 Checkin not part of build. New version of Transformiix from Keith Visco (kvisco@ziplink.net)
git-svn-id: svn://10.0.0.236/trunk@53489 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 07:13:17 +00:00

357 lines
9.3 KiB
C++

/*
* (C) Copyright The MITRE Corporation 1999 All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* The program provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* The Copyright owner will not be liable for any damages suffered by
* you as a result of using the Program. In no event will the Copyright
* owner be liable for any special, indirect or consequential damages or
* lost profits even if the Copyright owner has been advised of the
* possibility of their occurrence.
*
* Please see release.txt distributed with this file for more information.
*
*/
// Tom Kneeland (3/29/99)
//
// Implementation of the Document Object Model Level 1 Core
// Implementation of the NodeDefinition Class
//
// Modification History:
// Who When What
// TK 03/29/99 Created
//
#include "dom.h"
NodeDefinition::NodeDefinition(NodeType type, const DOMString& name,
const DOMString& value, Document* owner)
{
nodeName = name;
nodeValue = value;
nodeType = type;
parentNode = NULL;
previousSibling = NULL;
nextSibling = NULL;;
firstChild = NULL;
lastChild = NULL;
ownerDocument = owner;
length = 0;
}
//
// This node is being destroyed, so loop through and destroy all the children.
// Also, destroy all attributes stored in the attributes NamedNodeMap.
//
NodeDefinition::~NodeDefinition()
{
Int32 numAttributes = attributes.getLength();
Int32 killAttrLoop;
DeleteChildren();
for (killAttrLoop=0;killAttrLoop<numAttributes;killAttrLoop++)
delete attributes.removeNamedItem(attributes.item(0)->getNodeName());
}
//
//Remove and delete all children of this node
//
void NodeDefinition::DeleteChildren()
{
NodeDefinition* pCurrent = firstChild;
NodeDefinition* pDestroyer;
while (pCurrent)
{
pDestroyer = pCurrent;
pCurrent = pCurrent->nextSibling;
delete pDestroyer;
}
length = 0;
firstChild = NULL;
lastChild = NULL;
}
const DOMString& NodeDefinition::getNodeName() const
{
return nodeName;
}
const DOMString& NodeDefinition::getNodeValue() const
{
return nodeValue;
}
const DOMString& NodeDefinition::getNodeValue()
{
return nodeValue;
}
unsigned short NodeDefinition::getNodeType() const
{
return nodeType;
}
Node* NodeDefinition::getParentNode() const
{
return parentNode;
}
NodeList* NodeDefinition::getChildNodes()
{
return this;
}
Node* NodeDefinition::getFirstChild() const
{
return firstChild;
}
Node* NodeDefinition::getLastChild() const
{
return lastChild;
}
Node* NodeDefinition::getPreviousSibling() const
{
return previousSibling;
}
Node* NodeDefinition::getNextSibling() const
{
return nextSibling;
}
NamedNodeMap* NodeDefinition::getAttributes()
{
return &attributes;
}
Document* NodeDefinition::getOwnerDocument() const
{
return ownerDocument;
}
Node* NodeDefinition::item(Int32 index)
{
Int32 selectLoop;
NodeDefinition* pSelectNode = firstChild;
if (index < length)
{
for (selectLoop=0;selectLoop<index;selectLoop++)
pSelectNode = pSelectNode->nextSibling;
return pSelectNode;
}
return NULL;
}
Int32 NodeDefinition::getLength()
{
return length;
}
void NodeDefinition::setNodeValue(const DOMString& newNodeValue)
{
nodeValue = newNodeValue;
}
//
//Insert the "newChild" node before the "refChild" node. Return a pointer to
//the inserted child. If the node to insert is a document fragment, then
//insert each child of the document fragment, and return the document fragment
//which should be empty if all the inserts suceeded.
//This function's responsibility is to check for and handle document fragments
//vs. plain nodes.
// *** NOTE: Need to check the document types before inserting.
//
// The decision to return the possibly empty document fragment
// was an implementation choice. The spec did not dictate what
// whould occur.
//
Node* NodeDefinition::insertBefore(Node* newChild,
Node* refChild)
{
NodeDefinition* pCurrentNode = NULL;
NodeDefinition* pNextNode = NULL;
//Convert to a NodeDefinition Pointer
NodeDefinition* pNewChild = (NodeDefinition*)newChild;
NodeDefinition* pRefChild = (NodeDefinition*)refChild;
//Check to see if the reference node is a child of this node
if ((refChild != NULL) && (pRefChild->parentNode != this))
return NULL;
if (newChild->getNodeType() == Node::DOCUMENT_FRAGMENT_NODE)
{
pCurrentNode = pNewChild->firstChild;
while (pCurrentNode)
{
pNextNode = pCurrentNode->nextSibling;
pCurrentNode = (NodeDefinition*)pNewChild->removeChild(pCurrentNode);
implInsertBefore(pCurrentNode, pRefChild);
pCurrentNode = pNextNode;
}
return newChild;
}
else
return implInsertBefore(pNewChild, pRefChild);
}
//
//The code that actually insert one node before another.
//
Node* NodeDefinition::implInsertBefore(NodeDefinition* pNewChild,
NodeDefinition* pRefChild)
{
//Remove the "newChild" if it is already a child of this node
if (pNewChild->parentNode == this)
pNewChild = (NodeDefinition*)removeChild(pNewChild);
//The new child should not be a child of any other node
if ((pNewChild->previousSibling == NULL) &&
(pNewChild->nextSibling == NULL) &&
(pNewChild->parentNode == NULL))
{
if (pRefChild == NULL)
{
//Append
pNewChild->previousSibling = lastChild;
if (lastChild)
lastChild->nextSibling = pNewChild;
lastChild = pNewChild;
}
else
{
//Insert before the reference node
if (pRefChild->previousSibling)
pRefChild->previousSibling->nextSibling = pNewChild;
pNewChild->nextSibling = pRefChild;
pNewChild->previousSibling = pRefChild->previousSibling;
pRefChild->previousSibling = pNewChild;
}
pNewChild->parentNode = this;
if (pNewChild->previousSibling == NULL)
firstChild = pNewChild;
length++;
return pNewChild;
}
return NULL;
}
//
//Replace "oldChild" with "newChild". Return the replaced node, or NULL
//otherwise.
// *** NOTE: Need to check that the documents match ***
//
Node* NodeDefinition::replaceChild(Node* newChild,
Node* oldChild)
{
NodeDefinition* pOldChild = (NodeDefinition*)oldChild;
NodeDefinition* pNextSibling = NULL;
//If the newChild is replacing itself then we don't need to do anything
if (pOldChild == newChild)
return pOldChild;
//If "oldChild" is a child of this node, remove it from the list.
pOldChild = (NodeDefinition*)removeChild(oldChild);
//If the removal was successful... Else, return null
if (pOldChild)
{
//Try to insert the new node before the old node's next sibling. If
//successful, just returned the replaced child. If not succesful,
//reinsert the old node, and return NULL.
pNextSibling = pOldChild->nextSibling;
if (!insertBefore(newChild, pNextSibling))
{
insertBefore(pOldChild, pNextSibling);
pOldChild = NULL;
}
}
return pOldChild;
}
//
//Remove the specified "oldChild" from this node's children. First make sure
//the specified node is a child of this node. Return the removed node, NULL
//otherwise.
//
Node* NodeDefinition::removeChild(Node* oldChild)
{
NodeDefinition* pOldChild = (NodeDefinition*)oldChild;
//If "oldChild" is a child of this node, adjust pointers to remove it, and
//clear "oldChild"'s sibling and parent pointers.
if (pOldChild->parentNode == this)
{
if (pOldChild != firstChild)
pOldChild->previousSibling->nextSibling = pOldChild->nextSibling;
else
firstChild = pOldChild->nextSibling;
if (pOldChild != lastChild)
pOldChild->nextSibling->previousSibling = pOldChild->previousSibling;
else
lastChild = pOldChild->previousSibling;
pOldChild->nextSibling = NULL;
pOldChild->previousSibling = NULL;
pOldChild->parentNode = NULL;
length--;
return pOldChild;
}
return NULL;
}
//
//Append a new child node. First make sure the new child is not already a
//child of another node. Return the appended node.
// *** NOTE *** Need to eventually check to make sure the documents match ***
//
Node* NodeDefinition::appendChild(Node* newChild)
{
return insertBefore(newChild, NULL);
}
Node* NodeDefinition::cloneNode(MBool deep, Node* dest)
{
return 0;
}
MBool NodeDefinition::hasChildNodes() const
{
if (firstChild != NULL)
return MB_TRUE;
else
return MB_FALSE;
}