📄 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) * * 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. * * $Id: dom_elementimpl.cpp,v 1.1.1.1 2002/01/16 10:39:55 ymwei Exp $ */#include <stdio.h>#include "dom_elementimpl.h"#include "dom_exception.h"#include "dom_node.h"#include "dom_textimpl.h"#include "dom_docimpl.h"#include "cssstyleselector.h"#include "render_interface.h"#include "mghtmlview.h"#include "render_object.h"#include "htmlhashes.h"using namespace DOM;using namespace khtml;/* * NOTE: * According to the DOM docs, an Attr stores the value directly in it's parsed * form, but for values containing entities, creates a subtree with nodes * containing the unexpanded form (for XML). On read, the value is always * returned entity-free, so we decided for HTML we could only store a * parsed DOMString and have no child-nodes. */AttrImpl::AttrImpl() : NodeImpl(0), _name( 0 ), _value( 0 ), _element(0), attrId(0){}AttrImpl::AttrImpl(DocumentImpl *doc, const DOMString &name) : NodeImpl(doc), _name( 0 ), _value( 0 ), _element(0), attrId(0){ setName(name);}AttrImpl::AttrImpl(DocumentImpl *doc, int id) : NodeImpl(doc), _name( 0 ), _value( 0 ), _element(0), attrId(id){}AttrImpl::AttrImpl(const AttrImpl &other) : NodeImpl(other.ownerDocument()){ m_specified = other.specified(); _element = other._element; _name = other._name; if (_name) _name->ref(); _value = other._value; if (_value) _value->ref(); attrId = other.attrId;}AttrImpl &AttrImpl::operator = (const AttrImpl &other){ m_specified = other.specified(); document = other.ownerDocument(); _element = other._element; if (_name) _name->deref(); _name = other._name; if (_name) _name->ref(); if (_value) _value->deref(); _value = other._value; if (_value) _value->ref(); attrId = other.attrId; return *this;}AttrImpl::~AttrImpl(){ if(_name) _name->deref(); if(_value) _value->deref();}const DOMString AttrImpl::nodeName() const{ return name();}unsigned short AttrImpl::nodeType() const{ return Node::ATTRIBUTE_NODE;}DOMString AttrImpl::name() const{ if(attrId) return getAttrName(attrId); else if (_name) return _name; else return DOMString();}void AttrImpl::setName(const DOMString &n){ if(_name) _name->deref(); _name = n.implementation(); attrId = khtml::getAttrID(QConstString(_name->s, _name->l).string().lower().ascii(), _name->l); if (attrId) _name = 0; else _name->ref();}DOMString AttrImpl::value() const { return _value;}void AttrImpl::setValue( const DOMString &v ){ // according to the DOM docs, we should create an unparsed Text child // node here; we decided this was not necessary for HTML // TODO: parse value string, interprete entities if (_element) _element->checkReadOnly(); if (_value) _value->deref(); _value = v.implementation(); if (_value) _value->ref(); m_specified = true; if (_element) { _element->parseAttribute(this); _element->setChanged(true); }}void AttrImpl::setNodeValue( const DOMString &v ){ setValue(v);}// ### is this still needed?AttrImpl::AttrImpl(const DOMString &name, const DOMString &value, DocumentImpl *doc, bool specified) : NodeImpl(doc){ _element = 0; m_specified = specified; attrId = 0; _name = 0; setName(name); _value = value.implementation(); if (_value) _value->ref();}AttrImpl::AttrImpl(const khtml::Attribute *attr, DocumentImpl *doc, ElementImpl *element) : NodeImpl(doc){ _name = attr->n; if (_name) _name->ref(); _value = attr->v; if (_value) _value->ref(); attrId = attr->id; _element = element; m_specified = 1;}AttrImpl::AttrImpl(const DOMString &name, const DOMString &value, DocumentImpl *doc) : NodeImpl(doc){ attrId = 0; _name = 0; setName(name); _value = value.implementation(); if (_value) _value->ref(); _element = 0; m_specified = 1;}AttrImpl::AttrImpl(int _id, const DOMString &value, DocumentImpl *doc) : NodeImpl(doc){ attrId = _id; _name = 0; _value = value.implementation(); if (_value) _value->ref(); _element = 0; m_specified = false;}NodeImpl *AttrImpl::parentNode() const{ return 0;}NodeImpl *AttrImpl::previousSibling() const{ return 0;}NodeImpl *AttrImpl::nextSibling() const{ return 0;}NodeImpl *AttrImpl::cloneNode ( bool /*deep*/ ){ AttrImpl *newImpl = new AttrImpl(*this); newImpl->_element = 0; // can't have two attributes with the same name/id attached to an element return newImpl;}bool AttrImpl::deleteMe(){ if(!_element && _ref <= 0) return true; return false;}// -------------------------------------------------------------------------ElementImpl::ElementImpl(DocumentImpl *doc) : NodeBaseImpl(doc){ m_style = 0; namedAttrMap = new NamedAttrMapImpl(this); namedAttrMap->ref();}ElementImpl::~ElementImpl(){ if (m_render) detach(); delete m_style; namedAttrMap->detachFromElement(); namedAttrMap->deref();}bool ElementImpl::isInline(){ if(!m_style) return false; return (m_style->display() == khtml::INLINE);}unsigned short ElementImpl::nodeType() const{ return Node::ELEMENT_NODE;}DOMString ElementImpl::tagName() const{ return nodeName();}DOMString ElementImpl::getAttribute( const DOMString &name ) const{ // search in already set attributes first AttrImpl *attr = static_cast<AttrImpl*>(namedAttrMap->getNamedItem(name)); if (attr) return attr->value(); if(!defaultMap()) return 0; // then search in default attr in case it is not yet set int index = defaultMap()->find(name); if (index != -1) return defaultMap()->value(index); return 0;}DOMString ElementImpl::getAttribute( int id ){ // search in already set attributes first AttrImpl *attr = static_cast<AttrImpl*>(namedAttrMap->getIdItem(id)); if (attr) return attr->value(); if(!defaultMap()) return 0; // then search in default attr in case it is not yet set int index = defaultMap()->find(id); if (index != -1) return defaultMap()->value(index); return 0;}AttrImpl *ElementImpl::getAttributeNode ( int index ) const{ return namedAttrMap->getIdItem(index);}int ElementImpl::getAttributeCount() const{ return namedAttrMap->length();}void ElementImpl::setAttribute( const DOMString &name, const DOMString &value ){ // TODO: check for invalid characters in value -> throw exception AttrImpl *oldAttr; if (value.isNull()) oldAttr = static_cast<AttrImpl*>(namedAttrMap->removeNamedItem(name)); else oldAttr = static_cast<AttrImpl*>(namedAttrMap->setNamedItem(new AttrImpl(name,value,document))); if (oldAttr && oldAttr->deleteMe()) delete oldAttr;}void ElementImpl::setAttribute( int id, const DOMString &value ){ AttrImpl *oldAttr; if (value.isNull()) oldAttr = namedAttrMap->removeIdItem(id); else oldAttr = namedAttrMap->setIdItem(new AttrImpl(id,value,document)); if (oldAttr && oldAttr->deleteMe()) delete oldAttr;}void ElementImpl::setAttribute( AttributeList list ){ namedAttrMap->fromAttributeList(list);}void ElementImpl::removeAttribute( const DOMString &name ){ AttrImpl *oldAttr = static_cast<AttrImpl*>(namedAttrMap->removeNamedItem(name)); if (oldAttr && oldAttr->deleteMe()) delete oldAttr;}NodeImpl *ElementImpl::cloneNode ( bool deep ){ ElementImpl *newImpl = document->createElement(tagName()); if (!newImpl) return 0; newImpl->setParent(0); newImpl->setFirstChild(0); newImpl->setLastChild(0); newImpl->namedAttrMap->fromNamedAttrMapImpl(namedAttrMap); if(deep) { NodeImpl *n; for(n = firstChild(); n; n = n->nextSibling()) { newImpl->appendChild(n->cloneNode(deep)); } } return newImpl;}NamedNodeMapImpl *ElementImpl::attributes() const{ return namedAttrMap;}AttrImpl *ElementImpl::getAttributeNode( const DOMString &name ){ // ### do we return attribute node if it is in the default map but not specified? return static_cast<AttrImpl*>(namedAttrMap->getNamedItem(name));}AttrImpl *ElementImpl::setAttributeNode( AttrImpl *newAttr ){ if (!newAttr) throw DOMException(DOMException::NOT_FOUND_ERR); if (newAttr->attrId) return static_cast<AttrImpl*>(namedAttrMap->setIdItem(newAttr)); else return static_cast<AttrImpl*>(namedAttrMap->setNamedItem(newAttr));}AttrImpl *ElementImpl::removeAttributeNode( AttrImpl *oldAttr ){ if (!oldAttr) throw DOMException(DOMException::NOT_FOUND_ERR); checkReadOnly(); // ### should we replace with default in map? currently default attrs don't exist in map return namedAttrMap->removeAttr(oldAttr);}NodeListImpl *ElementImpl::getElementsByTagName( const DOMString &name ){ return new TagNodeListImpl( this, name );}NodeListImpl *ElementImpl::getElementsByNameAttr( const DOMString &name ){ return new NameNodeListImpl( this, name);}void ElementImpl::normalize(){ NodeImpl *child = _first; while(1) { NodeImpl *nextChild = child->nextSibling(); if(!nextChild) return; if ( (child->nodeType() == Node::TEXT_NODE) && (nextChild->nodeType() == Node::TEXT_NODE)) { (static_cast<TextImpl *>(child))->appendData( (static_cast<TextImpl *>(nextChild))->data() ); removeChild(nextChild); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -