📄 dom_nodeimpl.cpp
字号:
if (rendererIsNeeded(style)) {
#endif
m_render = createRenderer(getDocument()->renderArena(), style);
m_render->setStyle(style);
parentRenderer->addChild(m_render, nextRenderer());
#ifndef KHTML_NO_XBL
} // avoid confusing the change log code parser by having two close braces to match the two open braces above
#else
}
#endif
style->deref(getDocument()->renderArena());
}
}
RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
{
return parent->style();
}
bool NodeImpl::rendererIsNeeded(RenderStyle *style)
{
return (getDocument()->documentElement() == this) || (style->display() != NONE);
}
RenderObject *NodeImpl::createRenderer(RenderArena *arena, RenderStyle *style)
{
assert(false);
return 0;
}
long NodeImpl::maxOffset() const
{
return 1;
}
long NodeImpl::caretMinOffset() const
{
return renderer() ? renderer()->caretMinOffset() : 0;
}
long NodeImpl::caretMaxOffset() const
{
return renderer() ? renderer()->caretMaxOffset() : 1;
}
unsigned long NodeImpl::caretMaxRenderedOffset() const
{
return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
}
long NodeImpl::previousOffset (long current) const
{
return renderer() ? renderer()->previousOffset(current) : current - 1;
}
long NodeImpl::nextOffset (long current) const
{
return renderer() ? renderer()->nextOffset(current) : current + 1;
}
bool NodeImpl::isBlockFlow() const
{
return renderer() && renderer()->isBlockFlow();
}
bool NodeImpl::isBlockFlowOrTable() const
{
return renderer() && (renderer()->isBlockFlow() || renderer()->isTable());
}
bool NodeImpl::isEditableBlock() const
{
return isContentEditable() && isBlockFlow();
}
ElementImpl *NodeImpl::enclosingBlockFlowOrTableElement() const
{
NodeImpl *n = const_cast<NodeImpl *>(this);
if (isBlockFlowOrTable())
return static_cast<ElementImpl *>(n);
while (1) {
n = n->parentNode();
if (!n)
break;
if (n->isBlockFlowOrTable() || n->id() == ID_BODY)
return static_cast<ElementImpl *>(n);
}
return 0;
}
ElementImpl *NodeImpl::enclosingBlockFlowElement() const
{
NodeImpl *n = const_cast<NodeImpl *>(this);
if (isBlockFlow())
return static_cast<ElementImpl *>(n);
while (1) {
n = n->parentNode();
if (!n)
break;
if (n->isBlockFlow() || n->id() == ID_BODY)
return static_cast<ElementImpl *>(n);
}
return 0;
}
ElementImpl *NodeImpl::enclosingInlineElement() const
{
NodeImpl *n = const_cast<NodeImpl *>(this);
NodeImpl *p;
while (1) {
p = n->parentNode();
if (!p || p->isBlockFlow() || p->id() == ID_BODY)
return static_cast<ElementImpl *>(n);
// Also stop if any previous sibling is a block
for (NodeImpl *sibling = n->previousSibling(); sibling; sibling = sibling->previousSibling()) {
if (sibling->isBlockFlow())
return static_cast<ElementImpl *>(n);
}
n = p;
}
ASSERT_NOT_REACHED();
return 0;
}
ElementImpl *NodeImpl::rootEditableElement() const
{
if (!isContentEditable())
return 0;
NodeImpl *n = const_cast<NodeImpl *>(this);
if (n->id() == ID_BODY)
return static_cast<ElementImpl *>(n);
NodeImpl *result = n->isEditableBlock() ? n : 0;
while (1) {
n = n->parentNode();
if (!n || !n->isContentEditable())
break;
if (n->id() == ID_BODY) {
result = n;
break;
}
if (n->isBlockFlow())
result = n;
}
return static_cast<ElementImpl *>(result);
}
bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
{
return n ? rootEditableElement() == n->rootEditableElement() : false;
}
bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
{
return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
}
#if APPLE_CHANGES
NodeImpl::Id NodeImpl::identifier() const
{
return id();
}
#endif
#ifndef NDEBUG
void NodeImpl::displayNode(const char *prefix)
{
if (!prefix)
prefix = "";
if (isTextNode())
fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().string().latin1(), this, nodeValue().string().latin1());
else
fprintf(stderr, "%s%s\t%p\n", prefix, nodeName().string().latin1(), this);
}
void NodeImpl::displayTree()
{
NodeImpl *rootNode = rootEditableElement() ? : this;
NodeImpl *node;
for (node = rootNode; node; node = node->traverseNextNode()) {
NodeImpl *tmpNode;
if (node == this)
fprintf(stderr, "*");
for (tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
fprintf(stderr, "\t");
node->displayNode(0);
}
}
void NodeImpl::formatForDebugger(char *buffer, unsigned length) const
{
DOMString result;
DOMString s;
s = nodeName();
if (s.length() == 0)
result += "<none>";
else
result += s;
strncpy(buffer, result.string().latin1(), length - 1);
}
#endif
//-------------------------------------------------------------------------
NodeBaseImpl::NodeBaseImpl(DocumentPtr *doc)
: NodeImpl(doc)
{
_first = _last = 0;
}
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);
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;
// 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->hasOneRef() && !newChild->parent()) ? 0 : 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;
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
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -