From ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- khtml/dom/dom_element.cpp | 409 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 khtml/dom/dom_element.cpp (limited to 'khtml/dom/dom_element.cpp') diff --git a/khtml/dom/dom_element.cpp b/khtml/dom/dom_element.cpp new file mode 100644 index 000000000..77a9b9e4b --- /dev/null +++ b/khtml/dom/dom_element.cpp @@ -0,0 +1,409 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999 Lars Knoll (knoll@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. + * + */ + +#include "dom/dom_exception.h" +#include "xml/dom_docimpl.h" +#include "xml/dom_elementimpl.h" +#include "html/html_formimpl.h" + +using namespace DOM; + +Attr::Attr() : Node() +{ +} + +Attr::Attr(const Attr &other) : Node(other) +{ +} + +Attr::Attr( AttrImpl *_impl ) +{ + impl= _impl; + if (impl) impl->ref(); +} + +Attr &Attr::operator = (const Node &other) +{ + NodeImpl* ohandle = other.handle(); + if ( impl != ohandle ) { + if (!ohandle || !ohandle->isAttributeNode()) { + if (impl) impl->deref(); + impl = 0; + } else { + Node::operator =(other); + } + } + return *this; +} + +Attr &Attr::operator = (const Attr &other) +{ + Node::operator =(other); + return *this; +} + +Attr::~Attr() +{ +} + +DOMString Attr::name() const +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + return ((AttrImpl *)impl)->name(); +} + +bool Attr::specified() const +{ + if (impl) return ((AttrImpl *)impl)->specified(); + return 0; +} + +Element Attr::ownerElement() const +{ + if (!impl) return 0; + return static_cast(impl)->ownerElement(); +} + +DOMString Attr::value() const +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + return impl->nodeValue(); +} + +void Attr::setValue( const DOMString &newValue ) +{ + if (!impl) + return; + + int exceptioncode = 0; + ((AttrImpl *)impl)->setValue(newValue,exceptioncode); + if (exceptioncode) + throw DOMException(exceptioncode); +} + +// --------------------------------------------------------------------------- + +Element::Element() : Node() +{ +} + +Element::Element(const Element &other) : Node(other) +{ +} + +Element::Element(ElementImpl *impl) : Node(impl) +{ +} + +Element &Element::operator = (const Node &other) +{ + NodeImpl* ohandle = other.handle(); + if ( impl != ohandle ) { + if (!ohandle || !ohandle->isElementNode()) { + if (impl) impl->deref(); + impl = 0; + } else { + Node::operator =(other); + } + } + return *this; +} + +Element &Element::operator = (const Element &other) +{ + Node::operator =(other); + return *this; +} + +Element::~Element() +{ +} + +DOMString Element::tagName() const +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + return static_cast(impl)->tagName(); +} + +DOMString Element::getAttribute( const DOMString &name ) +{ + // ### getAttribute() and getAttributeNS() are supposed to return the empty string if the attribute + // does not exist. However, there are a number of places around khtml that expect a null string + // for nonexistent attributes. These need to be changed to use hasAttribute() instead. + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + if (!name.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); + + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId,name.implementation(),true,true); + if (!id) return DOMString(); + + ElementImpl* e = static_cast(impl); + return e->getAttribute(id, false, name); +} + +void Element::setAttribute( const DOMString &name, const DOMString &value ) +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + int exceptioncode = 0; + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), false /* allocate */, + true, &exceptioncode); + + static_cast(impl)->setAttribute(id, value, name, exceptioncode); + if ( exceptioncode ) + throw DOMException( exceptioncode ); +} + +void Element::removeAttribute( const DOMString &name ) +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true); + if (!id) return; + + int exceptioncode = 0; + NamedNodeMapImpl *attributes = static_cast(impl)->attributes(false); + attributes->removeNamedItem(id, false, name.implementation(), exceptioncode); + // it's allowed to remove attributes that don't exist. + if ( exceptioncode && exceptioncode != DOMException::NOT_FOUND_ERR ) + throw DOMException( exceptioncode ); +} + +Attr Element::getAttributeNode( const DOMString &name ) +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + if (!name.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true); + if (!id) return 0; + + ElementImpl* e = static_cast(impl); + if (!e->attributes()) return 0; + + return static_cast(e->attributes()->getNamedItem(id, false, name.implementation())); +} + +Attr Element::setAttributeNode( const Attr &newAttr ) +{ + if (!impl || newAttr.isNull()) + throw DOMException(DOMException::NOT_FOUND_ERR); + // WRONG_DOCUMENT_ERR and INUSE_ATTRIBUTE_ERR are already tested & thrown by setNamedItem + + int exceptioncode = 0; + Attr r = static_cast(impl)->attributes(false)->setNamedItem(newAttr.handle(), false, + newAttr.handle()->nodeName().implementation(), exceptioncode); + if ( exceptioncode ) + throw DOMException( exceptioncode ); + static_cast(newAttr.handle())->setOwnerElement( static_cast(impl) ); + return r; +} + +Attr Element::removeAttributeNode( const Attr &oldAttr ) +{ + if (!impl || oldAttr.isNull() || oldAttr.ownerElement().handle() != impl) + throw DOMException(DOMException::NOT_FOUND_ERR); + + if (impl->isReadOnly()) + throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR); + + if (!static_cast(impl)->attributes(true)) + throw DOMException(DOMException::NOT_FOUND_ERR); + + NamedAttrMapImpl *attributes = static_cast(impl)->attributes(false); + return attributes->removeAttr(static_cast(static_cast(oldAttr.handle()))); +} + +NodeList Element::getElementsByTagName( const DOMString &tagName ) +{ + if (!impl) return 0; + NodeImpl::Id id; + if ( tagName == "*" ) + id = 0; + else + id = impl->getDocument()->getId(NodeImpl::ElementId, tagName.implementation(), false, true); + return new TagNodeListImpl( impl, id ); +} + +NodeList Element::getElementsByTagNameNS( const DOMString &namespaceURI, + const DOMString &localName ) +{ + if (!impl) return 0; + return new TagNodeListImpl( impl, namespaceURI, localName ); +} + +DOMString Element::getAttributeNS( const DOMString &namespaceURI, + const DOMString &localName) +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + if (!localName.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), 0/*prefix*/, localName.implementation(), true, true); + ElementImpl* e = static_cast(impl); + return e->getAttribute(id, true); +} + +void Element::setAttributeNS( const DOMString &namespaceURI, + const DOMString &qualifiedName, + const DOMString &value) +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + + int exceptioncode = 0; + static_cast(impl)->setAttributeNS(namespaceURI, qualifiedName, value, exceptioncode); + if ( exceptioncode ) + throw DOMException( exceptioncode ); +} + +void Element::removeAttributeNS( const DOMString &namespaceURI, + const DOMString &localName ) +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + + int exceptioncode = 0; + NamedNodeMapImpl *attributes = static_cast(impl)->attributes(false); + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), 0/*prefix*/, localName.implementation(), false, true); + attributes->removeNamedItem(id, true, 0, exceptioncode); + if ( exceptioncode ) + throw DOMException( exceptioncode ); +} + +Attr Element::getAttributeNodeNS( const DOMString &namespaceURI, + const DOMString &localName ) +{ + if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); + if (!localName.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), + 0/*prefix*/, localName.implementation(), true, true); + ElementImpl* e = static_cast(impl); + if (!e->attributes()) return 0; + + return static_cast(e->attributes()->getNamedItem(id, true)); +} + +Attr Element::setAttributeNodeNS( const Attr &newAttr ) +{ + if (!impl || newAttr.isNull()) + throw DOMException(DOMException::NOT_FOUND_ERR); + // WRONG_DOCUMENT_ERR and INUSE_ATTRIBUTE_ERR are already tested & thrown by setNamedItem + + int exceptioncode = 0; + Attr r = static_cast(impl)->attributes(false)->setNamedItem(newAttr.handle(), true, 0, exceptioncode); + if ( exceptioncode ) + throw DOMException( exceptioncode ); + static_cast(newAttr.handle())->setOwnerElement( static_cast(impl) ); + return r; +} + + +bool Element::hasAttribute( const DOMString& name ) +{ + if (!impl || !static_cast(impl)->attributes()) return false; // ### throw ? + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true); + if (!id) return false; + + if (!static_cast(impl)->attributes(true /*readonly*/)) return false; + return static_cast(impl)->attributes(true)->getValue(id, false, name.implementation()) != 0; +} + +bool Element::hasAttributeNS( const DOMString &namespaceURI, + const DOMString &localName ) +{ + if (!impl || !static_cast(impl)->attributes()) return false; // ### throw ? + if (!static_cast(impl)->attributes(true /*readonly*/)) return false; + NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId,namespaceURI.implementation(), + 0/*prefix*/, localName.implementation(), true, true); + return static_cast(impl)->attributes(true)->getValue(id, true) != 0; +} + +bool Element::isHTMLElement() const +{ + if(!impl) return false; + return ((ElementImpl *)impl)->isHTMLElement(); +} + +Element Element::form() const +{ + if (!impl || !impl->isGenericFormElement()) return 0; + return static_cast(impl)->form(); + ElementImpl* f = static_cast( impl )->form(); + + if( f && f->implicitNode() ) + return 0; + return f; +} + +CSSStyleDeclaration Element::style() +{ + if (impl) return ((ElementImpl *)impl)->styleRules(); + return 0; +} + +bool Element::contentEditable() const { + if(!impl) return false; + return static_cast(impl)->contentEditable(); +} + +void Element::setContentEditable(bool enabled) { + if(!impl) + throw DOMException(DOMException::INVALID_STATE_ERR); + + static_cast(impl)->setContentEditable(enabled); +} + +bool Element::khtmlValidAttrName(const DOMString &name) +{ + // Check if name is valid + // http://www.w3.org/TR/2000/REC-xml-20001006#NT-Name + DOMStringImpl* _name = name.implementation(); + QChar ch = _name->s[0]; + if ( !ch.isLetter() && ch != '_' && ch != ':' ) + return false; // first char isn't valid + for ( uint i = 0; i < _name->l; ++i ) + { + ch = _name->s[i]; + if ( !ch.isLetter() && !ch.isDigit() && ch != '.' + && ch != '-' && ch != '_' && ch != ':' + && ch.category() != QChar::Mark_SpacingCombining + /* no idea what "extender is" */ ) + return false; + } + return true; +} + +bool Element::khtmlValidPrefix(const DOMString &name) +{ + // Null prefix is ok. If not null, reuse code from khtmlValidAttrName + return !name.implementation() || khtmlValidAttrName(name); +} + +bool Element::khtmlValidQualifiedName(const DOMString &name) +{ + return khtmlValidAttrName(name); +} + +bool Element::khtmlMalformedQualifiedName(const DOMString &name) +{ + // #### Not clearly defined in the DOM spec... + // But we know for sure that a null qualified name is malformed + return name.isNull(); +} + +bool Element::khtmlMalformedPrefix(const DOMString &/*name*/) +{ + // #### + return false; +} -- cgit v1.2.3