dom_nodeimpl.cpp
来自「最新Nokia手机浏览器全套源代码完美版。」· C++ 代码 · 共 2,194 行 · 第 1/5 页
CPP
2,194 行
NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
{
if (previousSibling()) {
NodeImpl *n = previousSibling();
while (!n->isAtomicNode() && n->lastChild())
n = n->lastChild();
return n;
}
else if (parentNode()) {
return parentNode();
}
else {
return 0;
}
}
NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
{
if (!isAtomicNode() && firstChild())
return firstChild();
if (nextSibling())
return nextSibling();
const NodeImpl *n = this;
while (n && !n->nextSibling())
n = n->parentNode();
if (n)
return n->nextSibling();
return 0;
}
NodeImpl *NodeImpl::previousLeafNode() const
{
NodeImpl *node = previousNodeConsideringAtomicNodes();
while (node) {
if (node->isAtomicNode())
return node;
node = node->previousNodeConsideringAtomicNodes();
}
return 0;
}
NodeImpl *NodeImpl::nextLeafNode() const
{
NodeImpl *node = nextNodeConsideringAtomicNodes();
while (node) {
if (node->isAtomicNode())
return node;
node = node->nextNodeConsideringAtomicNodes();
}
return 0;
}
void NodeImpl::createRendererIfNeeded()
{
#if APPLE_CHANGES
if (!getDocument()->shouldCreateRenderers())
return;
#endif
assert(!attached());
assert(!m_render);
NodeImpl *parent = parentNode();
assert(parent);
RenderObject *parentRenderer = parent->renderer();
if (parentRenderer && parentRenderer->canHaveChildren()) {
RenderStyle *style = styleForRenderer(parentRenderer);
style->ref();
#ifndef KHTML_NO_XBL
bool resolveStyle = false;
if (getDocument()->bindingManager()->loadBindings(this, style->bindingURIs(), true, &resolveStyle) &&
rendererIsNeeded(style)) {
if (resolveStyle) {
style->deref();
style = styleForRenderer(parentRenderer);
}
#else
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;
}
// method for editing madness, which allows BR,1 as a position, though that is incorrect
long NodeImpl::maxDeepOffset() const
{
if (isTextNode())
return static_cast<const TextImpl*>(this)->length();
if (id() == ID_BR || (renderer() && renderer()->isReplaced()))
return 1;
return childNodeCount();
}
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() ? 0 : 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
forbidEventDispatch();
if (prev)
prev->setNextSibling(child);
else
_first = child;
refChild->setPreviousSibling(child);
child->setParent(this);
child->setPreviousSibling(prev);
child->setNextSibling(refChild);
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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?