📄 dom_nodeimpl.cpp
字号:
}
void NodeImpl::defaultEventHandler(EventImpl *evt)
{
}
unsigned long NodeImpl::childNodeCount() const
{
return 0;
}
NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
{
return 0;
}
NodeImpl *NodeImpl::traverseNextNode(const NodeImpl *stayWithin) const
{
if (firstChild()) {
assert(!stayWithin || firstChild()->isAncestor(stayWithin));
return firstChild();
}
if (this == stayWithin)
return 0;
if (nextSibling()) {
assert(!stayWithin || nextSibling()->isAncestor(stayWithin));
return nextSibling();
}
const NodeImpl *n = this;
while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
n = n->parentNode();
if (n) {
assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isAncestor(stayWithin));
return n->nextSibling();
}
return 0;
}
NodeImpl *NodeImpl::traverseNextSibling(const NodeImpl *stayWithin) const
{
if (this == stayWithin)
return 0;
if (nextSibling()) {
assert(!stayWithin || nextSibling()->isAncestor(stayWithin));
return nextSibling();
}
const NodeImpl *n = this;
while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
n = n->parentNode();
if (n) {
assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isAncestor(stayWithin));
return n->nextSibling();
}
return 0;
}
NodeImpl *NodeImpl::traversePreviousNode() const
{
if (previousSibling()) {
NodeImpl *n = previousSibling();
while (n->lastChild())
n = n->lastChild();
return n;
}
else if (parentNode()) {
return parentNode();
}
else {
return 0;
}
}
NodeImpl *NodeImpl::traversePreviousNodePostOrder(const NodeImpl *stayWithin) const
{
if (lastChild()) {
assert(!stayWithin || lastChild()->isAncestor(stayWithin));
return lastChild();
}
if (this == stayWithin)
return 0;
if (previousSibling()) {
assert(!stayWithin || previousSibling()->isAncestor(stayWithin));
return previousSibling();
}
const NodeImpl *n = this;
while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
n = n->parentNode();
if (n) {
assert(!stayWithin || !n->previousSibling() || n->previousSibling()->isAncestor(stayWithin));
return n->previousSibling();
}
return 0;
}
void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
{
// Perform error checking as required by spec for setting Node.prefix. Used by
// ElementImpl::setPrefix() and AttrImpl::setPrefix()
// INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
if (!Element::khtmlValidPrefix(_prefix)) {
exceptioncode = DOMException::INVALID_CHARACTER_ERR;
return;
}
// NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
if (isReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
// NAMESPACE_ERR: - Raised if the specified prefix is malformed
// - if the namespaceURI of this node is null,
// - if the specified prefix is "xml" and the namespaceURI of this node is different from
// "http://www.w3.org/XML/1998/namespace",
// - if this node is an attribute and the specified prefix is "xmlns" and
// the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
// - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
if (Element::khtmlMalformedPrefix(_prefix) || (namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
(_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
exceptioncode = DOMException::NAMESPACE_ERR;
return;
}
}
void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
{
// Perform error checking as required by spec for adding a new child. Used by
// appendChild(), replaceChild() and insertBefore()
// Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
if (!newChild) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return;
}
// NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
if (isReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
bool shouldAdoptChild = false;
// WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
// created this node.
// We assume that if newChild is a DocumentFragment, all children are created from the same document
// as the fragment itself (otherwise they could not have been added as children)
if (newChild->getDocument() != getDocument()) {
// but if the child is not in a document yet then loosen the
// restriction, so that e.g. creating an element with the Option()
// constructor and then adding it to a different document works,
// as it does in Mozilla and Mac IE.
if (!newChild->inDocument()) {
shouldAdoptChild = true;
} else {
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return;
}
}
// HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
// newChild node, or if the node to append is one of this node's ancestors.
// check for ancestor/same node
if (newChild == this || isAncestor(newChild)) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
// only do this once we know there won't be an exception
if (shouldAdoptChild) {
KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
newChild->setDocument(getDocument()->docPtr());
}
}
bool NodeImpl::isAncestor(const NodeImpl *other) const
{
// Return true if other is an ancestor of this, otherwise false
for (const NodeImpl *n = parentNode(); n; n = n->parentNode()) {
if (n == other)
return true;
}
return false;
}
bool NodeImpl::childAllowed( NodeImpl *newChild )
{
return childTypeAllowed(newChild->nodeType());
}
NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
{
// FIXME: The behavior of this function is just totally wrong. It doesn't handle
// explicit inheritance of non-inherited properties and so you end up not re-resolving
// style in cases where you need to.
StyleChange ch = NoInherit;
EDisplay display1 = s1 ? s1->display() : NONE;
bool fl1 = s1 ? s1->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
EDisplay display2 = s2 ? s2->display() : NONE;
bool fl2 = s2 ? s2->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
if (display1 != display2 || fl1 != fl2)
ch = Detach;
else if ( !s1 || !s2 )
ch = Inherit;
else if ( *s1 == *s2 )
ch = NoChange;
else if ( s1->inheritedNotEqual( s2 ) )
ch = Inherit;
return ch;
}
#ifndef NDEBUG
void NodeImpl::dump(QTextStream *stream, QString ind) const
{
// ### implement dump() for all appropriate subclasses
if (m_hasId) { *stream << " hasId"; }
if (m_hasClass) { *stream << " hasClass"; }
if (m_hasStyle) { *stream << " hasStyle"; }
if (m_specified) { *stream << " specified"; }
if (m_focused) { *stream << " focused"; }
if (m_active) { *stream << " active"; }
if (m_styleElement) { *stream << " styleElement"; }
if (m_implicit) { *stream << " implicit"; }
*stream << " tabIndex=" << m_tabIndex;
if (m_regdListeners)
*stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
*stream << endl;
NodeImpl *child = firstChild();
while( child != 0 )
{
*stream << ind << child->nodeName().string().ascii() << ": ";
child->dump(stream,ind+" ");
child = child->nextSibling();
}
}
#endif
void NodeImpl::attach()
{
assert(!attached());
assert(!m_render || (m_render->style() && m_render->parent()));
getDocument()->incDOMTreeVersion();
m_attached = true;
}
void NodeImpl::detach()
{
// assert(m_attached);
if (m_render)
m_render->detach();
m_render = 0;
DocumentImpl *doc = getDocument();
if (doc)
doc->incDOMTreeVersion();
m_attached = false;
}
bool NodeImpl::maintainsState()
{
return false;
}
QString NodeImpl::state()
{
return QString::null;
}
void NodeImpl::restoreState(QStringList &/*states*/)
{
}
void NodeImpl::insertedIntoDocument()
{
if (m_regdListeners && !m_regdListeners->isEmpty() && getDocument())
getDocument()->unregisterDisconnectedNodeWithEventListeners(this);
setInDocument(true);
}
void NodeImpl::removedFromDocument()
{
if (m_regdListeners && !m_regdListeners->isEmpty() && getDocument())
getDocument()->registerDisconnectedNodeWithEventListeners(this);
setInDocument(false);
}
void NodeImpl::childrenChanged()
{
}
bool NodeImpl::disabled() const
{
return false;
}
bool NodeImpl::isReadOnly()
{
// Entity & Entity Reference nodes and their descendants are read-only
NodeImpl *n = this;
while (n) {
if (n->nodeType() == Node::ENTITY_NODE ||
n->nodeType() == Node::ENTITY_REFERENCE_NODE)
return true;
n = n->parentNode();
}
return false;
}
NodeImpl *NodeImpl::previousEditable() const
{
NodeImpl *node = previousLeafNode();
while (node) {
if (node->isContentEditable())
return node;
node = node->previousLeafNode();
}
return 0;
}
NodeImpl *NodeImpl::nextEditable() const
{
NodeImpl *node = nextLeafNode();
while (node) {
if (node->isContentEditable())
return node;
node = node->nextLeafNode();
}
return 0;
}
RenderObject * NodeImpl::previousRenderer()
{
for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
if (n->renderer())
return n->renderer();
}
return 0;
}
RenderObject * NodeImpl::nextRenderer()
{
// Avoid an O(n^2) problem with this function by not checking for nextRenderer() when the parent element hasn't even
// been attached yet.
if (parent() && !parent()->attached())
return 0;
for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
if (n->renderer())
return n->renderer();
}
return 0;
}
bool NodeImpl::isAtomicNode() const
{
return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
}
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -