dom_nodeimpl.cpp
来自「最新Nokia手机浏览器全套源代码完美版。」· C++ 代码 · 共 2,194 行 · 第 1/5 页
CPP
2,194 行
child = nextChild;
}
getDocument()->setDocumentChanged(true);
dispatchSubtreeModifiedEvent();
return newChild;
}
NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
{
exceptioncode = 0;
Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
if ( oldChild == newChild ) // nothing to do
return oldChild;
// Make sure adding the new child is ok
checkAddChild(newChild, exceptioncode);
if (exceptioncode)
return 0;
// NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
if (!oldChild || oldChild->parentNode() != this) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return 0;
}
bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
NodeImpl *nextChild;
NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
// Remove the old child
NodeImpl *prev = oldChild->previousSibling();
NodeImpl *next = oldChild->nextSibling();
removeChild(oldChild, exceptioncode);
if (exceptioncode)
return 0;
// Add the new child(ren)
while (child) {
nextChild = isFragment ? child->nextSibling() : 0;
// If child is already present in the tree, first remove it
NodeImpl *newParent = child->parentNode();
if (newParent)
newParent->removeChild( child, exceptioncode );
if (exceptioncode)
return 0;
// Add child in the correct position
forbidEventDispatch();
if (prev) prev->setNextSibling(child);
if (next) next->setPreviousSibling(child);
if(!prev) _first = child;
if(!next) _last = child;
child->setParent(this);
child->setPreviousSibling(prev);
child->setNextSibling(next);
allowEventDispatch();
// Add child to the rendering tree
// ### should we detach() it first if it's already attached?
if (attached() && !child->attached())
child->attach();
// Dispatch the mutation events
dispatchChildInsertedEvents(child,exceptioncode);
prev = child;
child = nextChild;
}
// ### set style in case it's attached
getDocument()->setDocumentChanged(true);
dispatchSubtreeModifiedEvent();
return oldChild;
}
void NodeBaseImpl::willRemove()
{
for (NodeImpl *n = _first; n != 0; n = n->nextSibling()) {
n->willRemove();
}
}
int NodeBaseImpl::willRemoveChild(NodeImpl *child)
{
int exceptionCode = 0;
// fire removed from document mutation events.
dispatchChildRemovalEvents(child, exceptionCode);
if (exceptionCode)
return exceptionCode;
if (child->attached())
child->willRemove();
return 0;
}
NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
{
exceptioncode = 0;
// NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
if (isReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return 0;
}
// NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
if (!oldChild || oldChild->parentNode() != this) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return 0;
}
// update auxiliary doc info (e.g. iterators) to note that node is being removed
// FIX: This looks redundant with same call from dispatchChildRemovalEvents in willRemoveChild
// getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
// dispatch pre-removal mutation events
if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
if (exceptioncode)
return 0;
}
exceptioncode = willRemoveChild(oldChild);
if (exceptioncode)
return 0;
forbidEventDispatch();
// Remove from rendering tree
if (oldChild->attached())
oldChild->detach();
// Remove the child
NodeImpl *prev, *next;
prev = oldChild->previousSibling();
next = oldChild->nextSibling();
if(next) next->setPreviousSibling(prev);
if(prev) prev->setNextSibling(next);
if(_first == oldChild) _first = next;
if(_last == oldChild) _last = prev;
oldChild->setPreviousSibling(0);
oldChild->setNextSibling(0);
oldChild->setParent(0);
allowEventDispatch();
getDocument()->setDocumentChanged(true);
// Dispatch post-removal mutation events
dispatchSubtreeModifiedEvent();
if (oldChild->inDocument())
oldChild->removedFromDocument();
return oldChild;
}
// this differs from other remove functions because it forcibly removes all the children,
// regardless of read-only status or event exceptions, e.g.
void NodeBaseImpl::removeChildren()
{
NodeImpl *n;
if (!_first)
return;
// do any prep work needed before actually starting to detach
// and remove... e.g. stop loading frames, fire unload events
for (n = _first; n != 0; n = n->nextSibling())
willRemoveChild(n);
forbidEventDispatch();
while ((n = _first) != 0) {
NodeImpl *next = n->nextSibling();
n->ref();
if (n->attached())
n->detach();
n->setPreviousSibling(0);
n->setNextSibling(0);
n->setParent(0);
if (n->inDocument())
n->removedFromDocument();
n->deref();
_first = next;
}
_last = 0;
allowEventDispatch();
// Dispatch a single post-removal mutation event denoting a modified subtree.
dispatchSubtreeModifiedEvent();
}
NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
{
exceptioncode = 0;
Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
// Make sure adding the new child is ok
checkAddChild(newChild, exceptioncode);
if (exceptioncode)
return 0;
if ( newChild == _last ) // nothing to do
return newChild;
bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
// If newChild is a DocumentFragment with no children.... there's nothing to do.
// Just return the document fragment
if (isFragment && !newChild->firstChild())
return newChild;
// Now actually add the child(ren)
NodeImpl *nextChild;
NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
while (child) {
nextChild = isFragment ? child->nextSibling() : 0;
// If child is already present in the tree, first remove it
NodeImpl *oldParent = child->parentNode();
if(oldParent) {
oldParent->removeChild( child, exceptioncode );
if (exceptioncode)
return 0;
}
// Append child to the end of the list
forbidEventDispatch();
child->setParent(this);
if (_last) {
child->setPreviousSibling(_last);
_last->setNextSibling(child);
_last = child;
} else
_first = _last = child;
allowEventDispatch();
// Add child to the rendering tree
// ### should we detach() it first if it's already attached?
if (attached() && !child->attached())
child->attach();
// Dispatch the mutation events
dispatchChildInsertedEvents(child,exceptioncode);
child = nextChild;
}
getDocument()->setDocumentChanged(true);
// ### set style in case it's attached
dispatchSubtreeModifiedEvent();
return newChild;
}
bool NodeBaseImpl::hasChildNodes ( ) const
{
return _first != 0;
}
// not part of the DOM
void NodeBaseImpl::setFirstChild(NodeImpl *child)
{
_first = child;
}
void NodeBaseImpl::setLastChild(NodeImpl *child)
{
_last = child;
}
// check for same source document:
bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
{
exceptioncode = 0;
DocumentImpl *ownerDocThis = getDocument();
// FIXME: Doh! This next line isn't getting newChild, so it's never going to work!
DocumentImpl *ownerDocNew = getDocument();
if(ownerDocThis != ownerDocNew) {
kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return true;
}
return false;
}
// check for being (grand-..)father:
// ### remove in favor or isAncestor()
bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
{
//check if newChild is parent of this...
NodeImpl *n;
for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
if(n == newChild) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return true;
}
return false;
}
// check for being child:
bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
{
if(!oldChild || oldChild->parentNode() != this) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return true;
}
return false;
}
NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
{
// do not add applyChanges here! This function is only used during parsing
Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
// short check for consistency with DTD
if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
{
//kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
return 0;
}
// just add it...
forbidEventDispatch();
newChild->setParent(this);
if(_last) {
newChild->setPreviousSibling(_last);
_last->setNextSibling(newChild);
_last = newChild;
} else
_first = _last = newChild;
allowEventDispatch();
if (inDocument())
newChild->insertedIntoDocument();
childrenChanged();
if(newChild->nodeType() == Node::ELEMENT_NODE)
return newChild;
return this;
}
void NodeBaseImpl::attach()
{
NodeImpl *child = _first;
while(child != 0)
{
child->attach();
child = child->nextSibling();
}
NodeImpl::attach();
}
void NodeBaseImpl::detach()
{
NodeImpl *child = _first;
while(child != 0)
{
NodeImpl* prev = child;
child = child->nextSibling();
prev->detach();
}
NodeImpl::detach();
}
void NodeBaseImpl::insertedIntoDocument()
{
NodeImpl::insertedIntoDocument();
for (NodeImpl *child = _first; child; child = child->nextSibling())
child->insertedIntoDocument();
}
void NodeBaseImpl::removedFromDocument()
{
NodeImpl::removedFromDocument();
for (NodeImpl *child = _first; child; child = child->nextSibling())
child->removedFromDocument();
}
void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
{
int exceptioncode = 0;
NodeImpl *n;
for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
{
clone->appendChild(n->cloneNode(true),exceptioncode);
}
}
NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
DOMStringImpl* localName )
{
if (!localName) return 0;
NodeImpl::Id idMask = namespaceMask | localNameMask;
if (localName->l && localName->s[0] == '*')
idMask &= ~localNameMask;
if (!namespaceURI || (namespaceURI->l && namespaceURI->s[0] == '*'))
idMask &= ~namespaceMask;
Id id = 0; // 0 means "all items"
if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
{
id = getDocument()->tagId( namespaceURI, localName, true);
if ( !id ) // not found -> we want to return an empty list, not "all items"
id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
}
return new TagNodeListImpl( this, id, idMask );
}
// I don't like this way of implementing the method, but I didn't find any
// other way. Lars
bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
{
if (!m_render)
return false;
RenderObject *o = m_render;
xPos = yPos = 0;
if ( !o
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?