📄 dom_nodeimpl.cpp
字号:
/** * This file is part of the DOM implementation for KDE. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include "xml/dom_nodeimpl.h"#include "dom/dom_exception.h"#include "misc/htmlattrs.h"#include "misc/htmltags.h"#include "xml/dom_elementimpl.h"#include "xml/dom_textimpl.h"#include "xml/dom2_eventsimpl.h"#include "xml/dom_docimpl.h"#include "xml/dom_position.h"#include "xml/dom_selection.h"#include "xml/dom2_rangeimpl.h"#include "css/csshelper.h"#include "css/cssstyleselector.h"#include <kglobal.h>#include <kdebug.h>#include "rendering/render_object.h"#include "rendering/render_text.h"#include "ecma/kjs_binding.h"#include "ecma/kjs_proxy.h"#include "khtmlview.h"#include "khtml_part.h"#include "html/dtd.h"#ifndef KHTML_NO_XBL#include "xbl/xbl_binding_manager.h"#endifusing namespace DOM;using namespace khtml;NodeImpl::NodeImpl(DocumentPtr *doc) : document(doc), m_previous(0), m_next(0), m_render(0), m_regdListeners( 0 ), m_tabIndex( 0 ), m_hasId( false ), m_hasClass( false ), m_hasStyle( false ), m_attached(false), m_changed( false ), m_hasChangedChild( false ), m_inDocument( false ), m_hasAnchor( false ), m_specified( false ), m_focused( false ), m_active( false ), m_styleElement( false ), m_implicit( false ), m_rendererNeedsClose( false ){ if (document) document->ref();}void NodeImpl::setDocument(DocumentPtr *doc){ if (inDocument()) return; if (doc) doc->ref(); if (document) document->deref(); document = doc;}NodeImpl::~NodeImpl(){ if (m_render) detach(); delete m_regdListeners; if (document) document->deref(); if (m_previous) m_previous->setNextSibling(0); if (m_next) m_next->setPreviousSibling(0);}DOMString NodeImpl::nodeValue() const{ return DOMString();}void NodeImpl::setNodeValue( const DOMString &/*_nodeValue*/, int &exceptioncode ){ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly if (isReadOnly()) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return; } // be default nodeValue is null, so setting it has no effect}DOMString NodeImpl::nodeName() const{ return DOMString();}unsigned short NodeImpl::nodeType() const{ return 0;}NodeListImpl *NodeImpl::childNodes(){ return new ChildNodeListImpl(this);}NodeImpl *NodeImpl::firstChild() const{ return 0;}NodeImpl *NodeImpl::lastChild() const{ return 0;}NodeImpl *NodeImpl::insertBefore( NodeImpl *, NodeImpl *, int &exceptioncode ){ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return 0;}NodeImpl *NodeImpl::replaceChild( NodeImpl *, NodeImpl *, int &exceptioncode ){ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return 0;}NodeImpl *NodeImpl::removeChild( NodeImpl *, int &exceptioncode ){ exceptioncode = DOMException::NOT_FOUND_ERR; return 0;}NodeImpl *NodeImpl::appendChild( NodeImpl *, int &exceptioncode ){ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return 0;}void NodeImpl::remove(int &exceptioncode){ exceptioncode = 0; if (!parentNode()) { exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return; } parentNode()->removeChild(this, exceptioncode);}bool NodeImpl::hasChildNodes( ) const{ return false;}void NodeImpl::normalize (){ // ### normalize attributes? (when we store attributes using child nodes) int exceptioncode = 0; NodeImpl *child = firstChild(); // Recursively go through the subtree beneath us, normalizing all nodes. In the case // where there are two adjacent text nodes, they are merged together while (child) { NodeImpl *nextChild = child->nextSibling(); if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) { // Current child and the next one are both text nodes... merge them TextImpl *currentText = static_cast<TextImpl*>(child); TextImpl *nextText = static_cast<TextImpl*>(nextChild); currentText->appendData(nextText->data(),exceptioncode); if (exceptioncode) return; removeChild(nextChild,exceptioncode); if (exceptioncode) return; } else { child->normalize(); child = nextChild; } }}DOMString NodeImpl::prefix() const{ // For nodes other than elements and attributes, the prefix is always null return DOMString();}void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode ){ // The spec says that for nodes other than elements and attributes, prefix is always null. // It does not say what to do when the user tries to set the prefix on another type of // node, however mozilla throws a NAMESPACE_ERR exception exceptioncode = DOMException::NAMESPACE_ERR;}DOMString NodeImpl::localName() const{ return DOMString();}void NodeImpl::setFirstChild(NodeImpl *){}void NodeImpl::setLastChild(NodeImpl *){}NodeImpl *NodeImpl::addChild(NodeImpl *){ return 0;}QString NodeImpl::toHTML() const{ NodeImpl* fc = firstChild(); if ( fc ) return fc->recursive_toHTML(true); return "";}static QString escapeHTML( const QString& in ){ QString s; for ( unsigned int i = 0; i < in.length(); ++i ) { switch( in[i].latin1() ) { case '&': s += "&"; break; case '<': s += "<"; break; case '>': s += ">"; break; default: s += in[i]; } } return s;}QString NodeImpl::recursive_toHTMLWithOptions(bool start, const DOM::RangeImpl *range, QPtrList<NodeImpl> *nodes) const{ QString me = ""; int exceptionCode; NodeImpl *startContainer = range ? range->startContainer(exceptionCode) : NULL; NodeImpl *endContainer = range ? range->endContainer(exceptionCode) : NULL; NodeImpl *n = startContainer; bool isNodeIncluded = range ? false : true; Id ident = id(); // Determine if the HTML string of this node should be part of the end result. if (range && (!start || (start && (ident == ID_TABLE || ident == ID_OL || ident == ID_UL)))) { // Check if this node is in the range or is an ancestor of a node in the range. while (n) { NodeImpl *ancestor = n; while (ancestor) { if (this == ancestor) { isNodeIncluded = true; break; } ancestor = ancestor->parentNode(); } if (isNodeIncluded) { break; } if (n == endContainer) { break; } NodeImpl *next = n->firstChild(); if (!next) { next = n->nextSibling(); } while (!next && n->parentNode()) { n = n->parentNode(); next = n->nextSibling(); } n = next; } } if (isNodeIncluded) { if (nodes) { nodes->append(this); } // Copy who I am into the me string if (nodeType() == Node::TEXT_NODE) { DOMString str = nodeValue().copy(); if (range) { if (this == endContainer) { str.truncate(range->endOffset(exceptionCode)); } if (this == startContainer) { str.remove(0, range->startOffset(exceptionCode)); } } Id parentID = parentNode()->id(); bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE); me += dontEscape ? str.string() : escapeHTML(str.string()); } else if (nodeType() != Node::DOCUMENT_NODE) { // If I am an element, not a text me += QChar('<') + nodeName().string(); if (nodeType() == Node::ELEMENT_NODE) { const ElementImpl *el = static_cast<const ElementImpl *>(this); NamedAttrMapImpl *attrs = el->attributes(); unsigned long length = attrs->length(); for (unsigned int i=0; i<length; i++) { AttributeImpl *attr = attrs->attributeItem(i); me += " " + getDocument()->attrName(attr->id()).string() + "=\"" + attr->value().string() + "\""; } } me += isHTMLElement() ? ">" : "/>"; } } if (!isHTMLElement() || endTag[ident] != FORBIDDEN) { // print firstChild if ((n = firstChild())) { me += n->recursive_toHTMLWithOptions(false, range, nodes); } // Print my ending tag if (isNodeIncluded && nodeType() != Node::TEXT_NODE && nodeType() != Node::DOCUMENT_NODE) { me += "</" + nodeName().string() + ">"; } } // print next sibling if ((n = nextSibling())) { me += n->recursive_toHTMLWithOptions(false, range, nodes); } return me;}QString NodeImpl::recursive_toHTML(bool start) const{ return recursive_toHTMLWithOptions(start);}void NodeImpl::recursive_completeURLs(QString baseURL){ if (nodeType() == Node::ELEMENT_NODE) { ElementImpl *el = static_cast<ElementImpl *>(this); NamedAttrMapImpl *attrs = el->attributes(); unsigned long length = attrs->length(); for (unsigned int i=0; i<length; i++) { AttributeImpl *attr = attrs->attributeItem(i); if (el->isURLAttribute(attr)) { el->setAttribute(attr->id(), KURL(baseURL, attr->value().string()).url()); } } } NodeImpl *n; if ((n = firstChild())) { n->recursive_completeURLs(baseURL); } if ((n = nextSibling())) { n->recursive_completeURLs(baseURL); }}bool NodeImpl::isContentEditable() const{ return m_parent ? m_parent->isContentEditable() : false;}QRect NodeImpl::getRect() const{ int _x, _y; if(m_render && m_render->absolutePosition(_x, _y)) return QRect( _x, _y, m_render->width(), m_render->height() ); return QRect();}void NodeImpl::setChanged(bool b){ if (b && !attached()) // changed compared to what? return; m_changed = b; if ( b ) { NodeImpl *p = parentNode(); while ( p ) { p->setHasChangedChild( true ); p = p->parentNode(); } getDocument()->setDocumentChanged(true); }}bool NodeImpl::isInline() const{ if (m_render) return m_render->style()->display() == khtml::INLINE; return !isElementNode();}bool NodeImpl::isFocusable() const{ return false;}bool NodeImpl::isKeyboardFocusable() const{ return isFocusable();}bool NodeImpl::isMouseFocusable() const{ return isFocusable();}unsigned long NodeImpl::nodeIndex() const{ NodeImpl *_tempNode = previousSibling(); unsigned long count=0; for( count=0; _tempNode; count++ ) _tempNode = _tempNode->previousSibling();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -