diff options
Diffstat (limited to 'tdehtml/xml/dom_xmlimpl.cpp')
-rw-r--r-- | tdehtml/xml/dom_xmlimpl.cpp | 498 |
1 files changed, 498 insertions, 0 deletions
diff --git a/tdehtml/xml/dom_xmlimpl.cpp b/tdehtml/xml/dom_xmlimpl.cpp new file mode 100644 index 000000000..121ad436a --- /dev/null +++ b/tdehtml/xml/dom_xmlimpl.cpp @@ -0,0 +1,498 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 2000 Peter Kelly (pmk@post.com) + * + * 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_xmlimpl.h" +#include "xml/dom_docimpl.h" +#include "xml/dom_stringimpl.h" +#include "css/css_stylesheetimpl.h" +#include "misc/loader.h" + +using namespace DOM; + +EntityImpl::EntityImpl(DocumentImpl *doc) : NodeBaseImpl(doc) +{ + m_publicId = 0; + m_systemId = 0; + m_notationName = 0; + m_name = 0; +} + +EntityImpl::EntityImpl(DocumentImpl *doc, DOMString _name) : NodeBaseImpl(doc) +{ + m_publicId = 0; + m_systemId = 0; + m_notationName = 0; + m_name = _name.implementation(); + if (m_name) + m_name->ref(); +} + +EntityImpl::EntityImpl(DocumentImpl *doc, DOMString _publicId, DOMString _systemId, DOMString _notationName) : NodeBaseImpl(doc) +{ + m_publicId = _publicId.implementation(); + if (m_publicId) + m_publicId->ref(); + m_systemId = _systemId.implementation(); + if (m_systemId) + m_systemId->ref(); + m_notationName = _notationName.implementation(); + if (m_notationName) + m_notationName->ref(); + m_name = 0; +} + + +EntityImpl::~EntityImpl() +{ + if (m_publicId) + m_publicId->deref(); + if (m_systemId) + m_systemId->deref(); + if (m_notationName) + m_notationName->deref(); + if (m_name) + m_name->deref(); +} + +DOMString EntityImpl::publicId() const +{ + return m_publicId; +} + +DOMString EntityImpl::systemId() const +{ + return m_systemId; +} + +DOMString EntityImpl::notationName() const +{ + return m_notationName; +} + +DOMString EntityImpl::nodeName() const +{ + return m_name; +} + +unsigned short EntityImpl::nodeType() const +{ + return Node::ENTITY_NODE; +} + +NodeImpl *EntityImpl::cloneNode ( bool /*deep*/) +{ + // Spec says cloning Document nodes is "implementation dependent" + // so we do not support it... + return 0; +} + +// DOM Section 1.1.1 +bool EntityImpl::childTypeAllowed( unsigned short type ) +{ + switch (type) { + case Node::ELEMENT_NODE: + case Node::PROCESSING_INSTRUCTION_NODE: + case Node::COMMENT_NODE: + case Node::TEXT_NODE: + case Node::CDATA_SECTION_NODE: + case Node::ENTITY_REFERENCE_NODE: + return true; + break; + default: + return false; + } +} + +DOMString EntityImpl::toString() const +{ + DOMString result = "<!ENTITY' "; + + if (m_name && m_name->l != 0) { + result += " "; + result += m_name; + } + + if (m_publicId && m_publicId->l != 0) { + result += " PUBLIC \""; + result += m_publicId; + result += "\" \""; + result += m_systemId; + result += "\""; + } else if (m_systemId && m_systemId->l != 0) { + result += " SYSTEM \""; + result += m_systemId; + result += "\""; + } + + if (m_notationName && m_notationName->l != 0) { + result += " NDATA "; + result += m_notationName; + } + + result += ">"; + + return result; +} + +// ------------------------------------------------------------------------- + +EntityReferenceImpl::EntityReferenceImpl(DocumentImpl *doc) : NodeBaseImpl(doc) +{ + m_entityName = 0; +} + +EntityReferenceImpl::EntityReferenceImpl(DocumentImpl *doc, DOMStringImpl *_entityName) : NodeBaseImpl(doc) +{ + m_entityName = _entityName; + if (m_entityName) + m_entityName->ref(); +} + +EntityReferenceImpl::~EntityReferenceImpl() +{ + if (m_entityName) + m_entityName->deref(); +} + +DOMString EntityReferenceImpl::nodeName() const +{ + return m_entityName; +} + +unsigned short EntityReferenceImpl::nodeType() const +{ + return Node::ENTITY_REFERENCE_NODE; +} + +NodeImpl *EntityReferenceImpl::cloneNode ( bool deep ) +{ + EntityReferenceImpl *clone = new EntityReferenceImpl(docPtr(),m_entityName); + // ### make sure children are readonly + // ### since we are a reference, should we clone children anyway (even if not deep?) + if (deep) + cloneChildNodes(clone); + return clone; +} + +// DOM Section 1.1.1 +bool EntityReferenceImpl::childTypeAllowed( unsigned short type ) +{ + switch (type) { + case Node::ELEMENT_NODE: + case Node::PROCESSING_INSTRUCTION_NODE: + case Node::COMMENT_NODE: + case Node::TEXT_NODE: + case Node::CDATA_SECTION_NODE: + case Node::ENTITY_REFERENCE_NODE: + return true; + break; + default: + return false; + } +} + +DOMString EntityReferenceImpl::toString() const +{ + DOMString result = "&"; + result += m_entityName; + result += ";"; + + return result; +} + +// ------------------------------------------------------------------------- + +NotationImpl::NotationImpl(DocumentImpl *doc) : NodeBaseImpl(doc) +{ + m_publicId = 0; + m_systemId = 0; + m_name = 0; +} + +NotationImpl::NotationImpl(DocumentImpl *doc, DOMString _name, DOMString _publicId, DOMString _systemId) : NodeBaseImpl(doc) +{ + m_name = _name.implementation(); + if (m_name) + m_name->ref(); + m_publicId = _publicId.implementation(); + if (m_publicId) + m_publicId->ref(); + m_systemId = _systemId.implementation(); + if (m_systemId) + m_systemId->ref(); +} + +NotationImpl::~NotationImpl() +{ + if (m_name) + m_name->deref(); + if (m_publicId) + m_publicId->deref(); + if (m_systemId) + m_systemId->deref(); +} + +DOMString NotationImpl::publicId() const +{ + return m_publicId; +} + +DOMString NotationImpl::systemId() const +{ + return m_systemId; +} + +DOMString NotationImpl::nodeName() const +{ + return m_name; +} + +unsigned short NotationImpl::nodeType() const +{ + return Node::NOTATION_NODE; +} + +NodeImpl *NotationImpl::cloneNode ( bool /*deep*/) +{ + // Spec says cloning Document nodes is "implementation dependent" + // so we do not support it... + return 0; +} + +// DOM Section 1.1.1 +bool NotationImpl::childTypeAllowed( unsigned short /*type*/ ) +{ + return false; +} + +// ------------------------------------------------------------------------- + +// ### need a way of updating these properly whenever child nodes of the processing instruction +// change or are added/removed + +ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentImpl *doc) : NodeBaseImpl(doc) +{ + m_target = 0; + m_data = 0; + m_localHref = 0; + m_sheet = 0; + m_cachedSheet = 0; +} + +ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentImpl *doc, DOMString _target, DOMString _data) : NodeBaseImpl(doc) +{ + m_target = _target.implementation(); + if (m_target) + m_target->ref(); + m_data = _data.implementation(); + if (m_data) + m_data->ref(); + m_sheet = 0; + m_cachedSheet = 0; + m_localHref = 0; +} + +ProcessingInstructionImpl::~ProcessingInstructionImpl() +{ + if (m_target) + m_target->deref(); + if (m_data) + m_data->deref(); + if (m_cachedSheet) + m_cachedSheet->deref(this); + if (m_sheet) + m_sheet->deref(); +} + +DOMString ProcessingInstructionImpl::target() const +{ + return m_target; +} + +void ProcessingInstructionImpl::setData( const DOMString &_data, int &exceptioncode ) +{ + // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. + if (isReadOnly()) { + exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; + return; + } + + if (m_data) + m_data->deref(); + m_data = _data.implementation(); + if (m_data) + m_data->ref(); +} + +DOMString ProcessingInstructionImpl::nodeName() const +{ + return m_target; +} + +unsigned short ProcessingInstructionImpl::nodeType() const +{ + return Node::PROCESSING_INSTRUCTION_NODE; +} + +DOMString ProcessingInstructionImpl::nodeValue() const +{ + return m_data; +} + +void ProcessingInstructionImpl::setNodeValue( const DOMString &_nodeValue, int &exceptioncode ) +{ + // NO_MODIFICATION_ALLOWED_ERR: taken care of by setData() + setData(_nodeValue, exceptioncode); +} + +NodeImpl *ProcessingInstructionImpl::cloneNode ( bool /*deep*/) +{ + // ### copy m_localHref + return new ProcessingInstructionImpl(docPtr(),m_target,m_data); +} + +DOMString ProcessingInstructionImpl::localHref() const +{ + return m_localHref; +} + +// DOM Section 1.1.1 +bool ProcessingInstructionImpl::childTypeAllowed( unsigned short /*type*/ ) +{ + return false; +} + +void ProcessingInstructionImpl::checkStyleSheet() +{ + if (m_target && DOMString(m_target) == "xml-stylesheet") { + // see http://www.w3.org/TR/xml-stylesheet/ + // ### check that this occurs only in the prolog + // ### support stylesheet included in a fragment of this (or another) document + // ### make sure this gets called when adding from javascript + XMLAttributeReader attrReader(DOMString(m_data).string()); + bool attrsOk; + TQXmlAttributes attrs = attrReader.readAttrs(attrsOk); + if (!attrsOk) + return; + if (attrs.value("type") != "text/css" && !attrs.value("type").isEmpty()) + return; + + DOMString href = attrs.value("href"); + + if (href.length()>1) + { + if (href[0]=='#') + { + if (m_localHref) + m_localHref->deref(); + m_localHref=href.implementation()->split(1); + if (m_localHref) + m_localHref->ref(); + } + else + { + // ### some validation on the URL? + // ### FIXME charset + if (m_cachedSheet) m_cachedSheet->deref(this); + m_cachedSheet = getDocument()->docLoader()->requestStyleSheet(getDocument()->completeURL(href.string()), TQString::null); + if (m_cachedSheet) { + getDocument()->addPendingSheet(); //before ref, because during the ref it might load! + m_cachedSheet->ref( this ); + } + } + + } + } +} + +StyleSheetImpl *ProcessingInstructionImpl::sheet() const +{ + return m_sheet; +} + +void ProcessingInstructionImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset) +{ + if (m_sheet) + m_sheet->deref(); + m_sheet = new CSSStyleSheetImpl(getDocument(), url); + m_sheet->ref(); + m_sheet->setCharset(charset); + m_sheet->parseString(sheet); + if (m_cachedSheet) + m_cachedSheet->deref(this); + m_cachedSheet = 0; + + getDocument()->styleSheetLoaded(); +} + +void ProcessingInstructionImpl::setStyleSheet(CSSStyleSheetImpl* sheet) +{ + if (m_sheet) + m_sheet->deref(); + m_sheet = sheet; + if (m_sheet) + m_sheet->ref(); +} + +DOMString ProcessingInstructionImpl::toString() const +{ + DOMString result = "<?"; + result += m_target; + result += " "; + result += m_data; + result += ">"; + return result; +} + +// ------------------------------------------------------------------------- + +XMLAttributeReader::XMLAttributeReader(const TQString& _attrString) +{ + m_attrString = _attrString; +} + +XMLAttributeReader::~XMLAttributeReader() +{ +} + +TQXmlAttributes XMLAttributeReader::readAttrs(bool &ok) +{ + // parse xml file + TQXmlInputSource source; + source.setData("<?xml version=\"1.0\"?><attrs "+m_attrString+" />"); + TQXmlSimpleReader reader; + reader.setContentHandler( this ); + ok = reader.parse( source ); + return attrs; +} + +bool XMLAttributeReader::startElement(const TQString& /*namespaceURI*/, const TQString& localName, + const TQString& /*qName*/, const TQXmlAttributes& atts) +{ + if (localName == "attrs") { + attrs = atts; + return true; + } + else + return false; // we shouldn't have any other elements +} |