📄 dom_docimpl.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) * (C) 2001 Dirk Mueller (mueller@kde.org) * (C) 2002-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. */#include "dom/dom_exception.h"#include "xml/dom_textimpl.h"#include "xml/dom_xmlimpl.h"#include "xml/dom2_rangeimpl.h"#include "xml/dom2_eventsimpl.h"#include "xml/xml_tokenizer.h"#include "html/htmltokenizer.h"#include "css/csshelper.h"#include "css/cssstyleselector.h"#include "css/css_stylesheetimpl.h"#include "misc/htmlhashes.h"#include "misc/helper.h"#include "misc/seed.h"#include "misc/loader.h"#include "ecma/kjs_proxy.h"#include "ecma/kjs_binding.h"#include <qptrstack.h>#include <qpaintdevicemetrics.h>#include <kdebug.h>#include <klocale.h>#include <kstaticdeleter.h>#include "rendering/counter_tree.h"#include "rendering/render_canvas.h"#include "rendering/render_replaced.h"#include "rendering/render_arena.h"#include "rendering/render_layer.h"#include "rendering/render_frames.h"#include "rendering/render_image.h"#include "khtmlview.h"#include "khtml_part.h"#include <kglobalsettings.h>#include <kstringhandler.h>#include <krfcdate.h>#include "khtml_settings.h"#include "khtmlpart_p.h"#include "html/html_baseimpl.h"#include "html/html_blockimpl.h"#include "html/html_documentimpl.h"#include "html/html_formimpl.h"#include "html/html_headimpl.h"#include "html/html_imageimpl.h"#include "html/html_listimpl.h"#include "html/html_miscimpl.h"#include "html/html_tableimpl.h"#include "html/html_objectimpl.h"#include <kapplication.h>#include <kio/job.h>#include <stdlib.h>#include "dom_docimpl.h"using namespace DOM;using namespace khtml;// ------------------------------------------------------------------------DOMImplementationImpl *DOMImplementationImpl::m_instance = 0;DOMImplementationImpl::DOMImplementationImpl(){}DOMImplementationImpl::~DOMImplementationImpl(){}bool DOMImplementationImpl::hasFeature ( const DOMString &feature, const DOMString &version ){ // ### update when we (fully) support the relevant features QString lower = feature.string().lower(); if ((lower == "html" || lower == "xml") && (version.isEmpty() || version == "1.0" || version == "2.0" || version == "null")) return true; // ## Do we support Core Level 3 ? if ((lower == "core" ) && (version.isEmpty() || version == "2.0" || version == "null")) return true; if ((lower == "events" || lower == "uievents" || lower == "mouseevents" || lower == "mutationevents" || lower == "htmlevents" || lower == "textevents" ) && (version.isEmpty() || version == "2.0" || version == "3.0" || version == "null")) return true; return false;}DocumentTypeImpl *DOMImplementationImpl::createDocumentType( const DOMString &qualifiedName, const DOMString &publicId, const DOMString &systemId, int &exceptioncode ){ // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied if (qualifiedName.isNull()) { exceptioncode = DOMException::NAMESPACE_ERR; return 0; } // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character. if (!Element::khtmlValidQualifiedName(qualifiedName)) { exceptioncode = DOMException::INVALID_CHARACTER_ERR; return 0; } // NAMESPACE_ERR: Raised if the qualifiedName is malformed. // Added special case for the empty string, which seems to be a common pre-DOM2 misuse if (!qualifiedName.isEmpty() && Element::khtmlMalformedQualifiedName(qualifiedName)) { exceptioncode = DOMException::NAMESPACE_ERR; return 0; } return new DocumentTypeImpl(this,0,qualifiedName,publicId,systemId);}DOMImplementationImpl* DOMImplementationImpl::getInterface(const DOMString& /*feature*/) const{ // ### return 0;}DocumentImpl *DOMImplementationImpl::createDocument( const DOMString &namespaceURI, const DOMString &qualifiedName, const DocumentType &doctype, int &exceptioncode ){ exceptioncode = 0; if (!checkQualifiedName(qualifiedName, namespaceURI, 0, true/*nameCanBeNull*/, true /*nameCanBeEmpty, see #61650*/, &exceptioncode) ) return 0; DocumentTypeImpl *dtype = static_cast<DocumentTypeImpl*>(doctype.handle()); // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was // created from a different implementation. if (dtype && (dtype->getDocument() || dtype->implementation() != this)) { exceptioncode = DOMException::WRONG_DOCUMENT_ERR; return 0; } // ### this is completely broken.. without a view it will not work (Dirk) DocumentImpl *doc = new DocumentImpl(this, 0); // now get the interesting parts of the doctype // ### create new one if not there (currently always there) if (doc->doctype() && dtype) doc->doctype()->copyFrom(*dtype); // the document must be created empty if all parameters are null // (or empty for qName/nsURI as a tolerance) - see DOM 3 Core. if (dtype || !qualifiedName.isEmpty() || !namespaceURI.isEmpty()) { ElementImpl *element = doc->createElementNS(namespaceURI,qualifiedName); doc->appendChild(element,exceptioncode); if (exceptioncode) { delete element; delete doc; return 0; } } return doc;}CSSStyleSheetImpl *DOMImplementationImpl::createCSSStyleSheet(DOMStringImpl* /*title*/, DOMStringImpl *media, int &/*exceptioncode*/){ // ### TODO : title should be set, and media could have wrong syntax, in which case we should // generate an exception. CSSStyleSheetImpl *parent = 0L; CSSStyleSheetImpl *sheet = new CSSStyleSheetImpl(parent, DOMString()); sheet->setMedia(new MediaListImpl(sheet, media)); return sheet;}DocumentImpl *DOMImplementationImpl::createDocument( KHTMLView *v ){ return new DocumentImpl(this, v);}HTMLDocumentImpl *DOMImplementationImpl::createHTMLDocument( KHTMLView *v ){ return new HTMLDocumentImpl(this, v);}DOMImplementationImpl *DOMImplementationImpl::instance(){ if (!m_instance) { m_instance = new DOMImplementationImpl(); m_instance->ref(); } return m_instance;}// ------------------------------------------------------------------------ElementMappingCache::ElementMappingCache():m_dict(257){}void ElementMappingCache::add(const QString& id, ElementImpl* nd){ if (id.isEmpty()) return; ItemInfo* info = m_dict.find(id); if (info) { info->ref++; info->nd = 0; //Now ambigous } else { ItemInfo* info = new ItemInfo(); info->ref = 1; info->nd = nd; m_dict.insert(id, info); }}void ElementMappingCache::set(const QString& id, ElementImpl* nd){ if (id.isEmpty()) return; ItemInfo* info = m_dict.find(id); info->nd = nd;}void ElementMappingCache::remove(const QString& id, ElementImpl* nd){ if (id.isEmpty()) return; ItemInfo* info = m_dict.find(id); info->ref--; if (info->ref == 0) { m_dict.take(id); delete info; } else { if (info->nd == nd) info->nd = 0; }}bool ElementMappingCache::contains(const QString& id){ if (id.isEmpty()) return false; return m_dict.find(id);}ElementMappingCache::ItemInfo* ElementMappingCache::get(const QString& id){ if (id.isEmpty()) return 0; return m_dict.find(id);}static KStaticDeleter< QPtrList<DocumentImpl> > s_changedDocumentsDeleter;QPtrList<DocumentImpl> * DocumentImpl::changedDocuments;// KHTMLView might be 0DocumentImpl::DocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v) : NodeBaseImpl( new DocumentPtr() ), m_domtree_version(0), m_counterDict(257), m_imageLoadEventTimer(0){ document->doc = this; m_paintDeviceMetrics = 0; m_paintDevice = 0; m_decoderMibEnum = 0; m_textColor = Qt::black; m_view = v; m_renderArena = 0; KHTMLFactory::ref(); if ( v ) { m_docLoader = new DocLoader(v->part(), this ); setPaintDevice( m_view ); } else m_docLoader = new DocLoader( 0, this ); visuallyOrdered = false; m_bParsing = false; m_docChanged = false; m_elemSheet = 0; m_tokenizer = 0; // ### this should be created during parsing a <!DOCTYPE> // not during construction. Not sure who added that and why (Dirk) m_doctype = new DocumentTypeImpl(_implementation, document, DOMString() /* qualifiedName */, DOMString() /* publicId */, DOMString() /* systemId */); m_doctype->ref(); m_implementation = _implementation; m_implementation->ref(); pMode = Strict; hMode = XHtml; m_textColor = "#000000"; m_attrMap = new IdNameMapping(ATTR_LAST_ATTR+1); m_elementMap = new IdNameMapping(ID_LAST_TAG+1); m_namespaceMap = new IdNameMapping(2); QString xhtml(XHTML_NAMESPACE); m_namespaceMap->names.insert(noNamespace, new DOMStringImpl("")); m_namespaceMap->names.insert(xhtmlNamespace, new DOMStringImpl(xhtml.unicode(), xhtml.length())); m_namespaceMap->names[noNamespace]->ref(); m_namespaceMap->names[xhtmlNamespace]->ref(); m_namespaceMap->count+=2; m_focusNode = 0; m_hoverNode = 0; m_defaultView = new AbstractViewImpl(this); m_defaultView->ref(); m_listenerTypes = 0; m_styleSheets = new StyleSheetListImpl; m_styleSheets->ref(); m_addedStyleSheets = 0; m_inDocument = true; m_styleSelectorDirty = false; m_styleSelector = 0; m_counterDict.setAutoDelete(true); m_inStyleRecalc = false; m_pendingStylesheets = 0; m_ignorePendingStylesheets = false; m_usesDescendantRules = false; m_async = true; m_hadLoadError = false; m_docLoading = false; m_inSyncLoad = false; m_loadingXMLDoc = 0; m_cssTarget = 0;}DocumentImpl::~DocumentImpl(){ assert( !m_render ); QIntDictIterator<NodeListImpl::Cache> it(m_nodeListCache); for (; it.current(); ++it) it.current()->deref(); if (m_loadingXMLDoc) m_loadingXMLDoc->deref(this); if (changedDocuments && m_docChanged) changedDocuments->remove(this); delete m_tokenizer; document->doc = 0; delete m_styleSelector; delete m_docLoader; if (m_elemSheet ) m_elemSheet->deref(); if (m_doctype) m_doctype->deref(); m_implementation->deref(); delete m_paintDeviceMetrics; delete m_elementMap; delete m_attrMap; delete m_namespaceMap; m_defaultView->deref(); m_styleSheets->deref(); if (m_addedStyleSheets) m_addedStyleSheets->deref(); if (m_focusNode) m_focusNode->deref(); if ( m_hoverNode ) m_hoverNode->deref(); if (m_renderArena){ delete m_renderArena; m_renderArena = 0; } KHTMLFactory::deref();}DocumentTypeImpl *DocumentImpl::doctype() const{ return m_doctype;}DOMImplementationImpl *DocumentImpl::implementation() const{ return m_implementation;}ElementImpl *DocumentImpl::documentElement() const{ NodeImpl *n = firstChild(); while (n && n->nodeType() != Node::ELEMENT_NODE) n = n->nextSibling(); return static_cast<ElementImpl*>(n);}ElementImpl *DocumentImpl::createElement( const DOMString &name, int* pExceptioncode ){ Id id = getId( NodeImpl::ElementId, name.implementation(), false /* allocate */, false /*HTMLDocumentImpl::createElement looked for HTML elements already*/, pExceptioncode); if ( pExceptioncode && *pExceptioncode ) return 0; XMLElementImpl* e = new XMLElementImpl( document, id ); e->setHTMLCompat( htmlMode() != XHtml ); // Not a real HTML element, but inside an html-compat doc all tags are uppercase. return e;}AttrImpl *DocumentImpl::createAttribute( const DOMString &tagName, int* pExceptioncode )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -