You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
14 KiB
393 lines
14 KiB
/*
|
|
* 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 TQString state() { return TQString::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 TQString& id);
|
|
//Called when mapping from id to this node in document should be added
|
|
virtual void addId (const TQString& 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
|