📄 dom_elementimpl.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 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. *///#define EVENT_DEBUG#include "dom/dom_exception.h"#include "dom/dom_node.h"#include "dom/html_image.h"#include "xml/dom_textimpl.h"#include "xml/dom_docimpl.h"#include "xml/dom2_eventsimpl.h"#include "xml/dom_elementimpl.h"#include "html/dtd.h"#include "html/htmlparser.h"#include "html/html_imageimpl.h"#include "rendering/render_canvas.h"#include "misc/htmlhashes.h"#include "css/css_valueimpl.h"#include "css/css_stylesheetimpl.h"#include "css/cssstyleselector.h"#include "css/cssvalues.h"#include "css/cssproperties.h"#include "xml/dom_xmlimpl.h"#include <qtextstream.h>#include <kdebug.h>#include <stdlib.h>// ### support default attributes// ### dispatch mutation events// ### check for INVALID_CHARACTER_ERR where appropriateusing namespace DOM;using namespace khtml;AttrImpl::AttrImpl(ElementImpl* element, DocumentPtr* docPtr, NodeImpl::Id attrId, DOMStringImpl *value, DOMStringImpl *prefix) : NodeBaseImpl(docPtr), m_element(element), m_attrId(attrId){ m_value = value; m_value->ref(); m_prefix = prefix; if (m_prefix) m_prefix->ref(); m_specified = true; // we don't yet support default attributes}AttrImpl::~AttrImpl(){ m_value->deref(); if (m_prefix) m_prefix->deref();}DOMString AttrImpl::nodeName() const{ return name();}unsigned short AttrImpl::nodeType() const{ return Node::ATTRIBUTE_NODE;}DOMString AttrImpl::prefix() const{ return m_prefix;}void AttrImpl::setPrefix(const DOMString &_prefix, int &exceptioncode ){ checkSetPrefix(_prefix, exceptioncode); if (exceptioncode) return; if (m_prefix == _prefix.implementation()) return; if (m_prefix) m_prefix->deref(); m_prefix = _prefix.implementation(); if (m_prefix) m_prefix->ref();}DOMString AttrImpl::namespaceURI() const{ if (m_htmlCompat) return DOMString(); return getDocument()->getName(NamespaceId, m_attrId >> 16);}DOMString AttrImpl::localName() const{ if (m_htmlCompat) return DOMString(); return getDocument()->getName(AttributeId, m_attrId);}DOMString AttrImpl::nodeValue() const{ return m_value;}DOMString AttrImpl::name() const{ DOMString n = getDocument()->getName(AttributeId, m_attrId); // compat mode always return attribute names in lowercase. // that's not formally in the specification, but common // practice - a w3c erratum to DOM L2 is pending. if (m_htmlCompat) n = n.lower(); if (m_prefix && m_prefix->l) return DOMString(m_prefix) + ":" + n; return n;}void AttrImpl::setValue( const DOMString &v, int &exceptioncode ){ exceptioncode = 0; // ### according to the DOM docs, we should create an unparsed Text child // node here // do not interprete entities in the string, its literal! // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly if (isReadOnly()) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return; } // ### what to do on 0 ? if (v.isNull()) { exceptioncode = DOMException::DOMSTRING_SIZE_ERR; return; } if (m_value == v.implementation()) return; if (m_element && m_attrId == ATTR_ID) m_element->updateId(m_value, v.implementation()); m_value->deref(); m_value = v.implementation(); m_value->ref(); if (m_element) m_element->parseAttribute(m_attrId,m_value);}void AttrImpl::setNodeValue( const DOMString &v, int &exceptioncode ){ exceptioncode = 0; // NO_MODIFICATION_ALLOWED_ERR: taken care of by setValue() setValue(v, exceptioncode);}NodeImpl *AttrImpl::cloneNode ( bool /*deep*/){ AttrImpl* attr = new AttrImpl(0, docPtr(), m_attrId, m_value, m_prefix); attr->setHTMLCompat(m_htmlCompat); return attr;}// DOM Section 1.1.1bool AttrImpl::childAllowed( NodeImpl *newChild ){ if(!newChild) return false; return childTypeAllowed(newChild->nodeType());}bool AttrImpl::childTypeAllowed( unsigned short type ){ switch (type) { case Node::TEXT_NODE: case Node::ENTITY_REFERENCE_NODE: return true; break; default: return false; }}DOMString AttrImpl::toString() const{ DOMString result; result += nodeName(); // FIXME: substitute entities for any instances of " or ' -- // maybe easier to just use text value and ignore existing // entity refs? if ( firstChild() ) { result += "=\""; for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) { result += child->toString(); } result += "\""; } else if ( !nodeValue().isEmpty() ){ //remove the else once the AttributeImpl changes are merged result += "=\""; result += nodeValue(); result += "\""; } return result;}void AttrImpl::setElement(ElementImpl *element){ m_element = element;}// -------------------------------------------------------------------------void AttributeImpl::setValue(DOMStringImpl *value, ElementImpl *element){ assert(value); if (m_attrId) { if (m_data.value == value) return; if (element && m_attrId == ATTR_ID) element->updateId(m_data.value, value); m_data.value->deref(); m_data.value = value; m_data.value->ref(); if (element) element->parseAttribute(this); } else { int exceptioncode = 0; m_data.attr->setValue(value,exceptioncode); // AttrImpl::setValue() calls parseAttribute() }}AttrImpl *AttributeImpl::createAttr(ElementImpl *element, DocumentPtr *docPtr){ if (m_attrId) { AttrImpl *attr = new AttrImpl(element,docPtr,m_attrId,m_data.value); if (!attr) return 0; attr->setHTMLCompat( docPtr->document()->htmlMode() != DocumentImpl::XHtml ); m_data.value->deref(); m_data.attr = attr; m_data.attr->ref(); m_attrId = 0; /* "has implementation" flag */ } return m_data.attr;}void AttributeImpl::free(){ if (m_attrId) { m_data.value->deref(); } else { m_data.attr->setElement(0); m_data.attr->deref(); }}// -------------------------------------------------------------------------ElementImpl::ElementImpl(DocumentPtr *doc) : NodeBaseImpl(doc){ namedAttrMap = 0; m_styleDecls = 0; m_prefix = 0; m_restyleLate = false; m_restyleSelfLate = false; m_restyleChildrenLate = false;}ElementImpl::~ElementImpl(){ if(namedAttrMap) { namedAttrMap->detachFromElement(); namedAttrMap->deref(); } if (m_styleDecls) { m_styleDecls->setNode(0); m_styleDecls->setParent(0); m_styleDecls->deref(); } if (m_prefix) m_prefix->deref();}unsigned short ElementImpl::nodeType() const{ return Node::ELEMENT_NODE;}DOMString ElementImpl::getAttribute( NodeImpl::Id id, bool nsAware, const DOMString& qName) const{ if (!namedAttrMap) return DOMString(); DOMStringImpl *value = namedAttrMap->getValue(id, nsAware, (qName.isEmpty() ? 0: qName.implementation())); if (value) return value; // then search in default attr in case it is not yet set NamedAttrMapImpl* dm = defaultMap(); value = dm ? dm->getValue(id, nsAware, (qName.isEmpty() ? 0: qName.implementation())) : 0; if (value) return value; return DOMString();}void ElementImpl::setAttribute(NodeImpl::Id id, const DOMString &value, const DOMString& qName, int &exceptioncode){ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly if (isReadOnly()) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return; } attributes()->setValue(id, value.implementation(), (qName.isEmpty() ? 0: qName.implementation()));}void ElementImpl::setAttributeNS( const DOMString &namespaceURI, const DOMString &qualifiedName, const DOMString &value, int &exceptioncode ){ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly if (isReadOnly()) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return; } int colonPos; if (!DOM::checkQualifiedName(qualifiedName, namespaceURI, &colonPos, false/*nameCanBeNull*/, false/*nameCanBeEmpty*/, &exceptioncode)) return; DOMString prefix, localName; splitPrefixLocalName(qualifiedName.implementation(), prefix, localName, colonPos); NodeImpl::Id id = getDocument()->getId(AttributeId, namespaceURI.implementation(), prefix.implementation(), localName.implementation(), false, true /*lookupHTML*/); attributes()->setValue(id, value.implementation(), 0, prefix.implementation(), true /*nsAware*/, !namespaceURI.isNull() /*hasNS*/);}void ElementImpl::setAttribute(NodeImpl::Id id, const DOMString &value){ int exceptioncode = 0; setAttribute(id,value,DOMString(),exceptioncode);}void ElementImpl::setAttributeMap( NamedAttrMapImpl* list ){ // If setting the whole map changes the id attribute, we need to // call updateId. DOMStringImpl *oldId = namedAttrMap ? namedAttrMap->getValue(ATTR_ID) : 0; DOMStringImpl *newId = list ? list->getValue(ATTR_ID) : 0; if (oldId || newId) { updateId(oldId, newId); } if (namedAttrMap) { namedAttrMap->detachFromElement(); namedAttrMap->deref(); } namedAttrMap = list; if (namedAttrMap) { namedAttrMap->ref(); assert(namedAttrMap->m_element == 0); namedAttrMap->setElement(this); unsigned long len = namedAttrMap->length();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -