📄 dom_nodeimpl.cpp
字号:
NodeBaseImpl::~NodeBaseImpl(){ //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl; // Avoid deep recursion when destroying the node tree. static bool alreadyInsideDestructor; bool topLevel = !alreadyInsideDestructor; if (topLevel) alreadyInsideDestructor = true; // List of nodes to be deleted. static NodeImpl *head; static NodeImpl *tail; // We have to tell all children that their parent has died. NodeImpl *n; NodeImpl *next; for( n = _first; n != 0; n = next ) { next = n->nextSibling(); n->setPreviousSibling(0); n->setNextSibling(0); n->setParent(0); if ( !n->refCount() ) { // Add the node to the list of nodes to be deleted. // Reuse the nextSibling pointer for this purpose. if (tail) tail->setNextSibling(n); else head = n; tail = n; } } // Only for the top level call, do the actual deleting. if (topLevel) { while ((n = head) != 0) { next = n->nextSibling(); n->setNextSibling(0); head = next; if (next == 0) tail = 0; delete n; } alreadyInsideDestructor = false; }}NodeImpl *NodeBaseImpl::firstChild() const{ return _first;}NodeImpl *NodeBaseImpl::lastChild() const{ return _last;}NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode ){ exceptioncode = 0; // insertBefore(...,null) is equivalent to appendChild() if(!refChild) return appendChild(newChild, exceptioncode); // Make sure adding the new child is ok checkAddChild(newChild, exceptioncode); if (exceptioncode) return 0; // NOT_FOUND_ERR: Raised if refChild is not a child of this node if (refChild->parentNode() != this) { exceptioncode = DOMException::NOT_FOUND_ERR; return 0; } 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; NodeImpl *prev = refChild->previousSibling(); if ( prev == newChild || refChild == newChild ) // nothing to do return newChild; 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 if (prev) prev->setNextSibling(child); else _first = child; refChild->setPreviousSibling(child); child->setParent(this); child->setPreviousSibling(prev); child->setNextSibling(refChild); // 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; } getDocument()->setDocumentChanged(true); dispatchSubtreeModifiedEvent(); return newChild;}NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode ){ exceptioncode = 0; 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 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); // 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;}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; } // Dispatch pre-removal mutation events getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead 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; } dispatchChildRemovalEvents(oldChild,exceptioncode); if (exceptioncode) return 0; // 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); getDocument()->setDocumentChanged(true); // Dispatch post-removal mutation events dispatchSubtreeModifiedEvent(); NodeImpl *p = this; while (p->parentNode()) p = p->parentNode(); if (p->nodeType() == Node::DOCUMENT_NODE) { for (NodeImpl *c = oldChild; c; c = c->traverseNextNode(oldChild)) c->removedFromDocument(); } return oldChild;}void NodeBaseImpl::removeChildren(){ while (NodeImpl *n = _first) { NodeImpl *next = n->nextSibling(); if (n->attached()) n->detach(); if (n->inDocument()) n->removedFromDocument(); n->setPreviousSibling(0); n->setNextSibling(0); n->setParent(0); if (!n->refCount()) delete n; _first = next; } _last = 0;}NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode ){ exceptioncode = 0; // 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 child->setParent(this); if(_last) { child->setPreviousSibling(_last); _last->setNextSibling(child); _last = child; } else { _first = _last = child; } // 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 DOMvoid 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(); 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 // 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... newChild->setParent(this); if(_last) { newChild->setPreviousSibling(_last); _last->setNextSibling(newChild); _last = newChild; } else { _first = _last = newChild; } 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(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -