diff options
Diffstat (limited to 'khtml/xml/dom_elementimpl.h')
-rw-r--r-- | khtml/xml/dom_elementimpl.h | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/khtml/xml/dom_elementimpl.h b/khtml/xml/dom_elementimpl.h new file mode 100644 index 000000000..1bc5148d5 --- /dev/null +++ b/khtml/xml/dom_elementimpl.h @@ -0,0 +1,392 @@ +/* + * 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) + * (C) 2003 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef _DOM_ELEMENTImpl_h_ +#define _DOM_ELEMENTImpl_h_ + +#include "dom_nodeimpl.h" +#include "dom/dom_exception.h" +#include "dom/dom_element.h" +#include "xml/dom_stringimpl.h" +#include "misc/shared.h" + +namespace khtml { + class CSSStyleSelector; +} + +namespace DOM { + +class ElementImpl; +class DocumentImpl; +class NamedAttrMapImpl; + +// Attr can have Text and EntityReference children +// therefore it has to be a fullblown Node. The plan +// is to dynamically allocate a textchild and store the +// resulting nodevalue in the AttributeImpl upon +// destruction. however, this is not yet implemented. +class AttrImpl : public NodeBaseImpl +{ + friend class ElementImpl; + friend class NamedAttrMapImpl; + +public: + AttrImpl(ElementImpl* element, DocumentImpl* docPtr, NodeImpl::Id attrId, + DOMStringImpl *value, DOMStringImpl *prefix = 0); + ~AttrImpl(); + +private: + AttrImpl(const AttrImpl &other); + AttrImpl &operator = (const AttrImpl &other); +public: + + // DOM methods & attributes for Attr + bool specified() const { return m_specified; } + ElementImpl* ownerElement() const { return m_element; } + void setOwnerElement( ElementImpl* impl ) { m_element = impl; } + DOMString name() const; + + //DOMString value() const; + void setValue( const DOMString &v, int &exceptioncode ); + + // DOM methods overridden from parent classes + virtual DOMString nodeName() const; + virtual unsigned short nodeType() const; + virtual DOMString prefix() const; + virtual void setPrefix(const DOMString &_prefix, int &exceptioncode ); + virtual DOMString namespaceURI() const; + virtual DOMString localName() const; + + virtual DOMString nodeValue() const; + virtual void setNodeValue( const DOMString &, int &exceptioncode ); + virtual NodeImpl *cloneNode ( bool deep ); + + virtual DOMStringImpl* textContent() const; + virtual void setTextContent( const DOMString &text, int& exceptioncode ); + + + // Other methods (not part of DOM) + virtual bool isAttributeNode() const { return true; } + virtual bool childAllowed( NodeImpl *newChild ); + virtual bool childTypeAllowed( unsigned short type ); + virtual NodeImpl::Id id() const { return m_attrId; } + + virtual DOMString toString() const; + + void setElement(ElementImpl *element); + DOMStringImpl *val() { return m_value; } + +protected: + ElementImpl *m_element; + NodeImpl::Id m_attrId; + DOMStringImpl *m_value; + DOMStringImpl *m_prefix; + DOMStringImpl *m_localName; +}; + +// Mini version of AttrImpl internal to NamedAttrMapImpl. +// Stores either the id and value of an attribute +// (in the case of m_attrId != 0), or a pointer to an AttrImpl (if m_attrId == 0) +// The latter case only happens when the Attr node is requested by some DOM +// code or is an XML attribute. +// In most cases the id and value is all we need to store, which is more +// memory efficient. +struct AttributeImpl +{ + NodeImpl::Id id() const { return m_attrId ? m_attrId : m_data.attr->id(); } + DOMStringImpl *val() const { return m_attrId ? m_data.value : m_data.attr->val(); } + DOMString value() const { return val(); } + AttrImpl *attr() const { return m_attrId ? 0 : m_data.attr; } + DOMString namespaceURI() { return m_attrId ? DOMString() : m_data.attr->namespaceURI(); } + DOMString prefix() { return m_attrId ? DOMString() : m_data.attr->prefix(); } + DOMString localName() { return m_attrId ? DOMString() : m_data.attr->localName(); } + DOMString name() { return m_attrId ? DOMString() : m_data.attr->name(); } + + void setValue(DOMStringImpl *value, ElementImpl *element); + AttrImpl *createAttr(ElementImpl *element, DocumentImpl *docPtr); + void free(); + + NodeImpl::Id m_attrId; + union { + DOMStringImpl *value; + AttrImpl *attr; + } m_data; +}; + +class ElementImpl : public NodeBaseImpl +{ + friend class DocumentImpl; + friend class NamedAttrMapImpl; + friend class AttrImpl; + friend class NodeImpl; + friend class khtml::CSSStyleSelector; +public: + ElementImpl(DocumentImpl *doc); + ~ElementImpl(); + + DOMString getAttribute( NodeImpl::Id id, bool nsAware = 0, const DOMString& qName = DOMString() ) const; + DOMStringImpl* getAttributeImpl( NodeImpl::Id id, bool nsAware = 0, DOMStringImpl* qName = 0 ) const; + void setAttribute( NodeImpl::Id id, const DOMString &value, const DOMString &qName, + int &exceptioncode ); + void setAttributeNS( const DOMString &namespaceURI, const DOMString &qualifiedName, + const DOMString& value, int &exceptioncode ); + virtual DOMString prefix() const; + void setPrefix(const DOMString &_prefix, int &exceptioncode ); + virtual DOMString namespaceURI() const; + + // DOM methods overridden from parent classes + virtual DOMString tagName() const = 0; + virtual unsigned short nodeType() const; + virtual NodeImpl *cloneNode ( bool deep ); + virtual DOMString nodeName() const; + virtual NodeImpl::Id id() const = 0; + virtual bool isElementNode() const { return true; } + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + + // convenience methods which ignore exceptions + void setAttribute (NodeImpl::Id id, const DOMString &value); + + NamedAttrMapImpl* attributes(bool readonly = false) const + { + if (!readonly && !namedAttrMap) createAttributeMap(); + return namedAttrMap; + } + + //This is always called, whenever an attribute changed + virtual void parseAttribute(AttributeImpl *) {} + void parseAttribute(NodeImpl::Id attrId, DOMStringImpl *value) { + AttributeImpl aimpl; + aimpl.m_attrId = attrId; + aimpl.m_data.value = value; + parseAttribute(&aimpl); + } + + // not part of the DOM + void setAttributeMap ( NamedAttrMapImpl* list ); + + // State of the element. + virtual QString state() { return QString::null; } + + virtual void attach(); + virtual void close(); + virtual void detach(); + virtual void structureChanged(); + virtual void backwardsStructureChanged(); + virtual void attributeChanged(NodeImpl::Id attrId); + + virtual khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent); + virtual khtml::RenderObject *createRenderer(khtml::RenderArena *, khtml::RenderStyle *); + virtual void recalcStyle( StyleChange = NoChange ); + + virtual void mouseEventHandler( MouseEvent* /*ev*/, bool /*inside*/ ) {} + virtual bool isFocusable() const; + virtual bool childAllowed( NodeImpl *newChild ); + virtual bool childTypeAllowed( unsigned short type ); + + DOM::CSSStyleDeclarationImpl *styleRules() { + if (!m_styleDecls) createDecl(); + return m_styleDecls; + } + + void dispatchAttrRemovalEvent(NodeImpl::Id id, DOMStringImpl *value); + void dispatchAttrAdditionEvent(NodeImpl::Id id, DOMStringImpl *value); + + virtual DOMString toString() const; + virtual DOMString selectionToString(NodeImpl *selectionStart, NodeImpl *selectionEnd, int startOffset, int endOffset, bool &found) const; + + virtual bool contentEditable() const; + void setContentEditable(bool enabled); + + void scrollIntoView(bool alignToTop); + + /** Returns the opening tag and properties. + * Examples: '<b', '<img alt="hello" src="image.png" + * + * For security reasons, passwords are stripped out of all src= and + * href= tags if expandurls is turned on. + * + * @param expandurls If this is set then in the above example, it would give + * src="http://website.com/image.png". Note that the password + * is stripped out of the url. + * + * DOM::RangeImpl uses this which is why it is public. + */ + DOMString openTagStartToString(bool expandurls = false) const; + + void updateId(DOMStringImpl* oldId, DOMStringImpl* newId); + //Called when mapping from id to this node in document should be removed + virtual void removeId(const QString& id); + //Called when mapping from id to this node in document should be added + virtual void addId (const QString& id); + +protected: + void createAttributeMap() const; + void createDecl(); + void finishCloneNode( ElementImpl *clone, bool deep ); + +private: + // map of default attributes. derived element classes are responsible + // for setting this according to the corresponding element description + // in the DTD + virtual NamedAttrMapImpl* defaultMap() const; + +protected: // member variables + mutable NamedAttrMapImpl *namedAttrMap; + + DOM::CSSStyleDeclarationImpl *m_styleDecls; + DOMStringImpl *m_prefix; +}; + + +class XMLElementImpl : public ElementImpl +{ + +public: + XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id); + XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id, DOMStringImpl *_qualifiedName); + ~XMLElementImpl(); + + // DOM methods overridden from parent classes + virtual DOMString tagName() const; + virtual DOMString localName() const; + virtual NodeImpl *cloneNode ( bool deep ); + + // Other methods (not part of DOM) + virtual bool isXMLElementNode() const { return true; } + virtual Id id() const { return m_id; } + +protected: + Id m_id; +}; + +// the map of attributes of an element +class NamedAttrMapImpl : public NamedNodeMapImpl +{ + friend class ElementImpl; +public: + NamedAttrMapImpl(ElementImpl *element); + virtual ~NamedAttrMapImpl(); + + // DOM methods & attributes for NamedNodeMap + virtual NodeImpl *getNamedItem ( NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0 ) const; + virtual Node removeNamedItem ( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName, int &exceptioncode ); + virtual Node setNamedItem ( NodeImpl* arg, bool nsAware, DOMStringImpl* qName, int &exceptioncode ); + + virtual NodeImpl *item ( unsigned long index ) const; + virtual unsigned long length( ) const; + + // Other methods (not part of DOM) + virtual bool isReadOnly() { return false; } + + AttributeImpl *attrAt(unsigned long index) const { return &m_attrs[index]; } + // ### replace idAt and getValueAt with attrAt + NodeImpl::Id idAt(unsigned long index) const; + DOMStringImpl *valueAt(unsigned long index) const; + DOMStringImpl *getValue(NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0) const; + void setValue(NodeImpl::Id id, DOMStringImpl *value, DOMStringImpl* qName = 0, + DOMStringImpl *prefix = 0, bool nsAware = false, bool hasNS = false); + Attr removeAttr(AttrImpl *attr); + NodeImpl::Id mapId(DOMStringImpl* namespaceURI, DOMStringImpl* localName, bool readonly); + void copyAttributes(NamedAttrMapImpl *other); + void setElement(ElementImpl *element); + void detachFromElement(); + +protected: + ElementImpl *m_element; + AttributeImpl *m_attrs; + unsigned long m_attrCount; +}; + +// ------------ inline DOM helper functions --------------- + +inline bool checkQualifiedName(const DOMString &qualifiedName, const DOMString &namespaceURI, int *colonPos, + bool nameCanBeNull, bool nameCanBeEmpty, int *pExceptioncode) +{ + + // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied + if (!nameCanBeNull && qualifiedName.isNull()) { + if (pExceptioncode) + *pExceptioncode = DOMException::NAMESPACE_ERR; + return false; + } + + // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character. + if (!qualifiedName.isNull() && !Element::khtmlValidQualifiedName(qualifiedName) + && ( !qualifiedName.isEmpty() || !nameCanBeEmpty ) ) { + if (pExceptioncode) + *pExceptioncode = DOMException::INVALID_CHARACTER_ERR; + return false; + } + + // NAMESPACE_ERR: + // - Raised if the qualifiedName is malformed, + // - if the qualifiedName has a prefix and the namespaceURI is null, or + // - if the qualifiedName is null and the namespaceURI is different from null + // - if the qualifiedName has a prefix that is "xml" and the namespaceURI is different + // from "http://www.w3.org/XML/1998/namespace" [Namespaces]. + int colonpos = -1; + uint i; + DOMStringImpl *qname = qualifiedName.implementation(); + for (i = 0 ; i < qname->l ; i++) { + if ((*qname)[i] == ':') { + colonpos = i; + break; + } + } + + if (!qualifiedName.isNull() && Element::khtmlMalformedQualifiedName(qualifiedName) || + (colonpos >= 0 && namespaceURI.isNull()) || + (qualifiedName.isNull() && !namespaceURI.isNull()) || + (colonpos == 3 && qualifiedName[0] == 'x' && qualifiedName[1] == 'm' && qualifiedName[2] == 'l' && + namespaceURI != "http://www.w3.org/XML/1998/namespace")) { + if (pExceptioncode) + *pExceptioncode = DOMException::NAMESPACE_ERR; + return false; + } + if(colonPos) + *colonPos = colonpos; + return true; +} + +inline void splitPrefixLocalName(DOMStringImpl *qualifiedName, DOMString &prefix, DOMString &localName, int colonPos = -2) +{ + if (colonPos == -2) + for (uint i = 0 ; i < qualifiedName->l ; ++i) + if (qualifiedName->s[i] == ':') { + colonPos = i; + break; + } + if (colonPos >= 0) { + prefix = qualifiedName->copy(); + localName = prefix.split(colonPos+1); + prefix.implementation()->truncate(colonPos); + } else + localName = qualifiedName->copy(); +} + +} //namespace + +#endif |