khtml Library API Documentation

dom_docimpl.cpp

00001 
00024 #include "dom/dom_exception.h"
00025 
00026 #include "xml/dom_textimpl.h"
00027 #include "xml/dom_xmlimpl.h"
00028 #include "xml/dom2_rangeimpl.h"
00029 #include "xml/dom2_eventsimpl.h"
00030 #include "xml/xml_tokenizer.h"
00031 
00032 #include "css/csshelper.h"
00033 #include "css/cssstyleselector.h"
00034 #include "css/css_stylesheetimpl.h"
00035 #include "misc/htmlhashes.h"
00036 #include "misc/helper.h"
00037 #include "ecma/kjs_proxy.h"
00038 
00039 #include <qptrstack.h>
00040 #include <qpaintdevicemetrics.h>
00041 #include <kdebug.h>
00042 #include <kstaticdeleter.h>
00043 
00044 #include "rendering/render_root.h"
00045 #include "rendering/render_replaced.h"
00046 
00047 #include "khtmlview.h"
00048 #include "khtml_part.h"
00049 
00050 #include <kglobalsettings.h>
00051 #include <kstringhandler.h>
00052 #include <krfcdate.h>
00053 #include "khtml_settings.h"
00054 #include "khtmlpart_p.h"
00055 
00056 #include "html/html_baseimpl.h"
00057 #include "html/html_blockimpl.h"
00058 #include "html/html_documentimpl.h"
00059 #include "html/html_formimpl.h"
00060 #include "html/html_headimpl.h"
00061 #include "html/html_imageimpl.h"
00062 #include "html/html_listimpl.h"
00063 #include "html/html_miscimpl.h"
00064 #include "html/html_tableimpl.h"
00065 #include "html/html_objectimpl.h"
00066 
00067 #include <kio/job.h>
00068 #include <kapplication.h>
00069 
00070 using namespace DOM;
00071 using namespace khtml;
00072 
00073 DOMImplementationImpl *DOMImplementationImpl::m_instance = 0;
00074 
00075 DOMImplementationImpl::DOMImplementationImpl()
00076 {
00077 }
00078 
00079 DOMImplementationImpl::~DOMImplementationImpl()
00080 {
00081 }
00082 
00083 bool DOMImplementationImpl::hasFeature ( const DOMString &feature, const DOMString &version )
00084 {
00085     // ### update when we (fully) support the relevant features
00086     QString lower = feature.string().lower();
00087     if ((lower == "html" || lower == "xml") &&
00088         (version == "1.0" || version == "null" || version == "" || version.isNull()))
00089         return true;
00090     else
00091         return false;
00092 }
00093 
00094 DocumentTypeImpl *DOMImplementationImpl::createDocumentType( const DOMString &qualifiedName, const DOMString &publicId,
00095                                                              const DOMString &systemId, int &exceptioncode )
00096 {
00097     // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied
00098     if (qualifiedName.isNull()) {
00099         exceptioncode = DOMException::NAMESPACE_ERR;
00100         return 0;
00101     }
00102 
00103     // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
00104     if (!Element::khtmlValidQualifiedName(qualifiedName)) {
00105         exceptioncode = DOMException::INVALID_CHARACTER_ERR;
00106         return 0;
00107     }
00108 
00109     // NAMESPACE_ERR: Raised if the qualifiedName is malformed.
00110     if (Element::khtmlMalformedQualifiedName(qualifiedName)) {
00111         exceptioncode = DOMException::NAMESPACE_ERR;
00112         return 0;
00113     }
00114 
00115     return new DocumentTypeImpl(this,0,qualifiedName,publicId,systemId);
00116 }
00117 
00118 DOMImplementationImpl* DOMImplementationImpl::getInterface(const DOMString& /*feature*/) const
00119 {
00120     // ###
00121     return 0;
00122 }
00123 
00124 DocumentImpl *DOMImplementationImpl::createDocument( const DOMString &namespaceURI, const DOMString &qualifiedName,
00125                                                      const DocumentType &doctype, int &exceptioncode )
00126 {
00127     exceptioncode = 0;
00128 
00129     DocumentTypeImpl *dtype = static_cast<DocumentTypeImpl*>(doctype.handle());
00130     // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was
00131     // created from a different implementation.
00132     if (dtype && (dtype->getDocument() || dtype->implementation() != this)) {
00133         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
00134         return 0;
00135     }
00136 
00137     // ### this is completely broken.. without a view it will not work (Dirk)
00138     DocumentImpl *doc = new DocumentImpl(this, 0);
00139 
00140     // now get the interesting parts of the doctype
00141     // ### create new one if not there (currently always there)
00142     if (doc->doctype() && dtype)
00143         doc->doctype()->copyFrom(*dtype);
00144 
00145     ElementImpl *element = doc->createElementNS(namespaceURI, qualifiedName, &exceptioncode);
00146     if (!exceptioncode)
00147         doc->appendChild(element,exceptioncode);
00148 
00149     if (exceptioncode) {
00150         delete element;
00151         delete doc;
00152         return 0;
00153     }
00154 
00155     return doc;
00156 }
00157 
00158 CSSStyleSheetImpl *DOMImplementationImpl::createCSSStyleSheet(DOMStringImpl */*title*/, DOMStringImpl *media,
00159                                                               int &/*exceptioncode*/)
00160 {
00161     // ### TODO : title should be set, and media could have wrong syntax, in which case we should
00162     // generate an exception.
00163     CSSStyleSheetImpl *parent = 0L;
00164     CSSStyleSheetImpl *sheet = new CSSStyleSheetImpl(parent, DOMString());
00165     sheet->setMedia(new MediaListImpl(sheet, media));
00166     return sheet;
00167 }
00168 
00169 DocumentImpl *DOMImplementationImpl::createDocument( KHTMLView *v )
00170 {
00171     return new DocumentImpl(this, v);
00172 }
00173 
00174 HTMLDocumentImpl *DOMImplementationImpl::createHTMLDocument( KHTMLView *v )
00175 {
00176     return new HTMLDocumentImpl(this, v);
00177 }
00178 
00179 DOMImplementationImpl *DOMImplementationImpl::instance()
00180 {
00181     if (!m_instance) {
00182         m_instance = new DOMImplementationImpl();
00183         m_instance->ref();
00184     }
00185 
00186     return m_instance;
00187 }
00188 
00189 // ------------------------------------------------------------------------
00190 
00191 static KStaticDeleter< QPtrList<DocumentImpl> > s_changedDocumentsDeleter;
00192 QPtrList<DocumentImpl> * DocumentImpl::changedDocuments;
00193 
00194 // KHTMLView might be 0
00195 DocumentImpl::DocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
00196     : NodeBaseImpl( new DocumentPtr() )
00197 {
00198     document->doc = this;
00199     m_paintDeviceMetrics = 0;
00200     m_decoderMibEnum = 0;
00201     m_textColor = Qt::black;
00202 
00203     m_view = v;
00204 
00205     if ( v ) {
00206         m_docLoader = new DocLoader(v->part(), this );
00207         setPaintDevice( m_view );
00208     }
00209     else
00210         m_docLoader = new DocLoader( 0, this );
00211 
00212     visuallyOrdered = false;
00213     m_loadingSheet = false;
00214     m_bParsing = false;
00215     m_docChanged = false;
00216     m_sheet = 0;
00217     m_elemSheet = 0;
00218     m_tokenizer = 0;
00219 
00220     // ### this should be created during parsing a <!DOCTYPE>
00221     // not during construction. Not sure who added that and why (Dirk)
00222     m_doctype = new DocumentTypeImpl(_implementation, document,
00223                                      DOMString() /* qualifiedName */,
00224                                      DOMString() /* publicId */,
00225                                      DOMString() /* systemId */);
00226     m_doctype->ref();
00227 
00228     m_implementation = _implementation;
00229     m_implementation->ref();
00230     pMode = Strict;
00231     hMode = XHtml;
00232     m_textColor = "#000000";
00233     m_elementNames = 0;
00234     m_elementNameAlloc = 0;
00235     m_elementNameCount = 0;
00236     m_attrNames = 0;
00237     m_attrNameAlloc = 0;
00238     m_attrNameCount = 0;
00239     m_namespaceURIAlloc = 4;
00240     m_namespaceURICount = 1;
00241     QString xhtml(XHTML_NAMESPACE);
00242     m_namespaceURIs = new DOMStringImpl* [m_namespaceURIAlloc];
00243     m_namespaceURIs[0] = new DOMStringImpl(xhtml.unicode(), xhtml.length());
00244     m_namespaceURIs[0]->ref();
00245     m_focusNode = 0;
00246     m_defaultView = new AbstractViewImpl(this);
00247     m_defaultView->ref();
00248     m_listenerTypes = 0;
00249     m_styleSheets = new StyleSheetListImpl;
00250     m_styleSheets->ref();
00251     m_inDocument = true;
00252     m_styleSelectorDirty = false;
00253     m_styleSelector = 0;
00254     m_windowEventListeners.setAutoDelete(true);
00255 
00256     m_inStyleRecalc = false;
00257 }
00258 
00259 DocumentImpl::~DocumentImpl()
00260 {
00261     assert( !m_render );
00262 
00263     if (changedDocuments && m_docChanged)
00264         changedDocuments->remove(this);
00265     delete m_tokenizer;
00266     document->doc = 0;
00267     delete m_sheet;
00268     delete m_styleSelector;
00269     delete m_docLoader;
00270     if (m_elemSheet )  m_elemSheet->deref();
00271     if (m_doctype)
00272         m_doctype->deref();
00273     m_implementation->deref();
00274     delete m_paintDeviceMetrics;
00275 
00276     if (m_elementNames) {
00277         for (unsigned short id = 0; id < m_elementNameCount; id++)
00278             m_elementNames[id]->deref();
00279         delete [] m_elementNames;
00280     }
00281     if (m_attrNames) {
00282         for (unsigned short id = 0; id < m_attrNameCount; id++)
00283             m_attrNames[id]->deref();
00284         delete [] m_attrNames;
00285     }
00286     for (unsigned short id = 0; id < m_namespaceURICount; ++id)
00287         m_namespaceURIs[id]->deref();
00288     delete [] m_namespaceURIs;
00289     m_defaultView->deref();
00290     m_styleSheets->deref();
00291     if (m_focusNode)
00292         m_focusNode->deref();
00293 }
00294 
00295 
00296 DocumentTypeImpl *DocumentImpl::doctype() const
00297 {
00298     return m_doctype;
00299 }
00300 
00301 DOMImplementationImpl *DocumentImpl::implementation() const
00302 {
00303     return m_implementation;
00304 }
00305 
00306 ElementImpl *DocumentImpl::documentElement() const
00307 {
00308     NodeImpl *n = firstChild();
00309     while (n && n->nodeType() != Node::ELEMENT_NODE)
00310       n = n->nextSibling();
00311     return static_cast<ElementImpl*>(n);
00312 }
00313 
00314 ElementImpl *DocumentImpl::createElement( const DOMString &name, int *pExceptioncode )
00315 {
00316     Id id = tagId(0 /* no namespace */, name.implementation(),
00317                   false /* allocate */, pExceptioncode);
00318     if ( pExceptioncode && *pExceptioncode )
00319         return 0;
00320     return new XMLElementImpl( document, id );
00321 }
00322 
00323 DocumentFragmentImpl *DocumentImpl::createDocumentFragment(  )
00324 {
00325     return new DocumentFragmentImpl( docPtr() );
00326 }
00327 
00328 CommentImpl *DocumentImpl::createComment ( DOMStringImpl* data )
00329 {
00330     return new CommentImpl( docPtr(), data );
00331 }
00332 
00333 CDATASectionImpl *DocumentImpl::createCDATASection ( DOMStringImpl* data )
00334 {
00335     return new CDATASectionImpl( docPtr(), data );
00336 }
00337 
00338 ProcessingInstructionImpl *DocumentImpl::createProcessingInstruction ( const DOMString &target, DOMStringImpl* data )
00339 {
00340     return new ProcessingInstructionImpl( docPtr(),target,data);
00341 }
00342 
00343 Attr DocumentImpl::createAttribute( NodeImpl::Id id )
00344 {
00345     return new AttrImpl(0, docPtr(), new AttributeImpl(id, DOMString("").implementation()));
00346 }
00347 
00348 EntityReferenceImpl *DocumentImpl::createEntityReference ( const DOMString &name )
00349 {
00350     return new EntityReferenceImpl(docPtr(), name.implementation());
00351 }
00352 
00353 NodeImpl *DocumentImpl::importNode(NodeImpl *importedNode, bool deep, int &exceptioncode)
00354 {
00355     NodeImpl *result = 0;
00356 
00357     // Not mentioned in spec: throw NOT_FOUND_ERR if evt is null
00358     if (!importedNode) {
00359         exceptioncode = DOMException::NOT_FOUND_ERR;
00360         return 0;
00361     }
00362 
00363 
00364     if(importedNode->nodeType() == Node::ELEMENT_NODE)
00365     {
00366         ElementImpl *tempElementImpl = createElementNS(getDocument()->namespaceURI(id()), importedNode->nodeName(), 0);
00367         result = tempElementImpl;
00368 
00369         if(static_cast<ElementImpl *>(importedNode)->attributes(true) && static_cast<ElementImpl *>(importedNode)->attributes(true)->length())
00370         {
00371             NamedNodeMapImpl *attr = static_cast<ElementImpl *>(importedNode)->attributes();
00372 
00373             for(unsigned int i = 0; i < attr->length(); i++)
00374             {
00375                 DOM::DOMString qualifiedName = attr->item(i)->nodeName();
00376                 DOM::DOMString value = attr->item(i)->nodeValue();
00377 
00378                 int colonpos = qualifiedName.find(':');
00379                 DOMString localName = qualifiedName;
00380                 if(colonpos >= 0)
00381                 {
00382                     localName.remove(0, colonpos + 1);
00383                     // ### extract and set new prefix
00384                 }
00385 
00386                 NodeImpl::Id nodeId = getDocument()->attrId(getDocument()->namespaceURI(id()), localName.implementation(), false /* allocate */, 0);
00387                 tempElementImpl->setAttribute(nodeId, value.implementation(), exceptioncode);
00388 
00389                 if(exceptioncode != 0)
00390                     break;
00391             }
00392         }
00393     }
00394     else if(importedNode->nodeType() == Node::TEXT_NODE)
00395     {
00396         result = createTextNode(static_cast<TextImpl*>(importedNode)->string());
00397         deep = false;
00398     }
00399     else if(importedNode->nodeType() == Node::CDATA_SECTION_NODE)
00400     {
00401         result = createCDATASection(static_cast<CDATASectionImpl*>(importedNode)->string());
00402         deep = false;
00403     }
00404     else if(importedNode->nodeType() == Node::ENTITY_REFERENCE_NODE)
00405         result = createEntityReference(importedNode->nodeName());
00406     else if(importedNode->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
00407     {
00408         result = createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue().implementation());
00409         deep = false;
00410     }
00411     else if(importedNode->nodeType() == Node::COMMENT_NODE)
00412     {
00413         result = createComment(static_cast<CommentImpl*>(importedNode)->string());
00414         deep = false;
00415     }
00416     else
00417         exceptioncode = DOMException::NOT_SUPPORTED_ERR;
00418 
00419     if(deep)
00420     {
00421         for(Node n = importedNode->firstChild(); !n.isNull(); n = n.nextSibling())
00422             result->appendChild(importNode(n.handle(), true, exceptioncode), exceptioncode);
00423     }
00424 
00425     return result;
00426 }
00427 
00428 ElementImpl *DocumentImpl::createElementNS( const DOMString &_namespaceURI, const DOMString &_qualifiedName, int* pExceptioncode )
00429 {
00430     QString qName = _qualifiedName.string();
00431     int colonPos = qName.find(':',0);
00432 
00433     if ( pExceptioncode ) // skip those checks during parsing
00434     {
00435         // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
00436         if (!Element::khtmlValidQualifiedName(_qualifiedName)) {
00437             *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
00438             return 0;
00439         }
00440 
00441         // NAMESPACE_ERR:
00442         // - Raised if the qualifiedName is malformed,
00443         // - if the qualifiedName has a prefix and the namespaceURI is null, or
00444         // - if the qualifiedName has a prefix that is "xml" and the namespaceURI is different
00445         //   from "http://www.w3.org/XML/1998/namespace" [Namespaces].
00446         if (Element::khtmlMalformedQualifiedName(_qualifiedName) ||
00447             (colonPos >= 0 && _namespaceURI.isNull()) ||
00448             (colonPos == 3 && _qualifiedName[0] == 'x' && _qualifiedName[1] == 'm' && _qualifiedName[2] == 'l' &&
00449              _namespaceURI != "http://www.w3.org/XML/1998/namespace")) {
00450 
00451             *pExceptioncode = DOMException::NAMESPACE_ERR;
00452             return 0;
00453         }
00454     }
00455 
00456     ElementImpl *e = 0;
00457     if ((_namespaceURI.isNull() && colonPos < 0) ||
00458         _namespaceURI == XHTML_NAMESPACE) {
00459         // User requested an element in the XHTML namespace - this means we create a HTML element
00460         // (elements not in this namespace are treated as normal XML elements)
00461         e = createHTMLElement(qName.mid(colonPos+1));
00462         if ( e )
00463         {
00464             int _exceptioncode = 0;
00465             if (colonPos >= 0)
00466                 e->setPrefix(qName.left(colonPos), _exceptioncode);
00467             if ( _exceptioncode ) {
00468                 if ( pExceptioncode ) *pExceptioncode = _exceptioncode;
00469                 return 0;
00470             }
00471         }
00472     }
00473     if (!e)
00474         e = new XMLElementImpl( document, _qualifiedName.implementation(), _namespaceURI.implementation() );
00475 
00476     return e;
00477 }
00478 
00479 ElementImpl *DocumentImpl::getElementById( const DOMString &elementId ) const
00480 {
00481     QPtrStack<NodeImpl> nodeStack;
00482     NodeImpl *current = _first;
00483 
00484     while(1)
00485     {
00486         if(!current)
00487         {
00488             if(nodeStack.isEmpty()) break;
00489             current = nodeStack.pop();
00490             current = current->nextSibling();
00491         }
00492         else
00493         {
00494             if(current->isElementNode())
00495             {
00496                 ElementImpl *e = static_cast<ElementImpl *>(current);
00497                 if(e->getAttribute(ATTR_ID) == elementId)
00498                     return e;
00499             }
00500 
00501             NodeImpl *child = current->firstChild();
00502             if(child)
00503             {
00504                 nodeStack.push(current);
00505                 current = child;
00506             }
00507             else
00508             {
00509                 current = current->nextSibling();
00510             }
00511         }
00512     }
00513 
00514     //kdDebug() << "WARNING: *DocumentImpl::getElementById not found " << elementId.string() << endl;
00515     return 0;
00516 }
00517 
00518 void DocumentImpl::setTitle(DOMString _title)
00519 {
00520     m_title = _title;
00521 
00522     QString titleStr = m_title.string();
00523     for (unsigned int i = 0; i < titleStr.length(); ++i)
00524         if (titleStr[i] < ' ')
00525             titleStr[i] = ' ';
00526     titleStr = titleStr.simplifyWhiteSpace();
00527     titleStr.compose();
00528     if ( !view()->part()->parentPart() ) {
00529     if (titleStr.isNull() || titleStr.isEmpty()) {
00530         // empty title... set window caption as the URL
00531         KURL url = m_url;
00532         url.setRef(QString::null);
00533         url.setQuery(QString::null);
00534         titleStr = url.url();
00535     }
00536 
00537     emit view()->part()->setWindowCaption( KStringHandler::csqueeze( titleStr, 128 ) );
00538     }
00539 }
00540 
00541 DOMString DocumentImpl::nodeName() const
00542 {
00543     return "#document";
00544 }
00545 
00546 unsigned short DocumentImpl::nodeType() const
00547 {
00548     return Node::DOCUMENT_NODE;
00549 }
00550 
00551 ElementImpl *DocumentImpl::createHTMLElement( const DOMString &name )
00552 {
00553     QString qstr = name.string().lower();
00554     uint id = khtml::getTagID( qstr.latin1(), qstr.length() );
00555 
00556     ElementImpl *n = 0;
00557     switch(id)
00558     {
00559     case ID_HTML:
00560         n = new HTMLHtmlElementImpl(docPtr());
00561         break;
00562     case ID_HEAD:
00563         n = new HTMLHeadElementImpl(docPtr());
00564         break;
00565     case ID_BODY:
00566         n = new HTMLBodyElementImpl(docPtr());
00567         break;
00568 
00569 // head elements
00570     case ID_BASE:
00571         n = new HTMLBaseElementImpl(docPtr());
00572         break;
00573     case ID_LINK:
00574         n = new HTMLLinkElementImpl(docPtr());
00575         break;
00576     case ID_META:
00577         n = new HTMLMetaElementImpl(docPtr());
00578         break;
00579     case ID_STYLE:
00580         n = new HTMLStyleElementImpl(docPtr());
00581         break;
00582     case ID_TITLE:
00583         n = new HTMLTitleElementImpl(docPtr());
00584         break;
00585 
00586 // frames
00587     case ID_FRAME:
00588         n = new HTMLFrameElementImpl(docPtr());
00589         break;
00590     case ID_FRAMESET:
00591         n = new HTMLFrameSetElementImpl(docPtr());
00592         break;
00593     case ID_IFRAME:
00594         n = new HTMLIFrameElementImpl(docPtr());
00595         break;
00596 
00597 // form elements
00598 // ### FIXME: we need a way to set form dependency after we have made the form elements
00599     case ID_FORM:
00600             n = new HTMLFormElementImpl(docPtr(), false);
00601         break;
00602     case ID_BUTTON:
00603             n = new HTMLButtonElementImpl(docPtr());
00604         break;
00605     case ID_FIELDSET:
00606             n = new HTMLFieldSetElementImpl(docPtr());
00607         break;
00608     case ID_INPUT:
00609             n = new HTMLInputElementImpl(docPtr());
00610         break;
00611     case ID_ISINDEX:
00612             n = new HTMLIsIndexElementImpl(docPtr());
00613         break;
00614     case ID_LABEL:
00615             n = new HTMLLabelElementImpl(docPtr());
00616         break;
00617     case ID_LEGEND:
00618             n = new HTMLLegendElementImpl(docPtr());
00619         break;
00620     case ID_OPTGROUP:
00621             n = new HTMLOptGroupElementImpl(docPtr());
00622         break;
00623     case ID_OPTION:
00624             n = new HTMLOptionElementImpl(docPtr());
00625         break;
00626     case ID_SELECT:
00627             n = new HTMLSelectElementImpl(docPtr());
00628         break;
00629     case ID_TEXTAREA:
00630             n = new HTMLTextAreaElementImpl(docPtr());
00631         break;
00632 
00633 // lists
00634     case ID_DL:
00635         n = new HTMLDListElementImpl(docPtr());
00636         break;
00637     case ID_DD:
00638         n = new HTMLGenericElementImpl(docPtr(), id);
00639         break;
00640     case ID_DT:
00641         n = new HTMLGenericElementImpl(docPtr(), id);
00642         break;
00643     case ID_UL:
00644         n = new HTMLUListElementImpl(docPtr());
00645         break;
00646     case ID_OL:
00647         n = new HTMLOListElementImpl(docPtr());
00648         break;
00649     case ID_DIR:
00650         n = new HTMLDirectoryElementImpl(docPtr());
00651         break;
00652     case ID_MENU:
00653         n = new HTMLMenuElementImpl(docPtr());
00654         break;
00655     case ID_LI:
00656         n = new HTMLLIElementImpl(docPtr());
00657         break;
00658 
00659 // formatting elements (block)
00660     case ID_DIV:
00661     case ID_P:
00662         n = new HTMLDivElementImpl(docPtr(), id);
00663         break;
00664     case ID_BLOCKQUOTE:
00665     case ID_H1:
00666     case ID_H2:
00667     case ID_H3:
00668     case ID_H4:
00669     case ID_H5:
00670     case ID_H6:
00671         n = new HTMLGenericElementImpl(docPtr(), id);
00672         break;
00673     case ID_HR:
00674         n = new HTMLHRElementImpl(docPtr());
00675         break;
00676     case ID_PRE:
00677         n = new HTMLPreElementImpl(docPtr(), id);
00678         break;
00679 
00680 // font stuff
00681     case ID_BASEFONT:
00682         n = new HTMLBaseFontElementImpl(docPtr());
00683         break;
00684     case ID_FONT:
00685         n = new HTMLFontElementImpl(docPtr());
00686         break;
00687 
00688 // ins/del
00689     case ID_DEL:
00690     case ID_INS:
00691         n = new HTMLGenericElementImpl(docPtr(), id);
00692         break;
00693 
00694 // anchor
00695     case ID_A:
00696         n = new HTMLAnchorElementImpl(docPtr());
00697         break;
00698 
00699 // images
00700     case ID_IMG:
00701         n = new HTMLImageElementImpl(docPtr());
00702         break;
00703     case ID_MAP:
00704         n = new HTMLMapElementImpl(docPtr());
00705         /*n = map;*/
00706         break;
00707     case ID_AREA:
00708         n = new HTMLAreaElementImpl(docPtr());
00709         break;
00710 
00711 // objects, applets and scripts
00712     case ID_APPLET:
00713         n = new HTMLAppletElementImpl(docPtr());
00714         break;
00715     case ID_OBJECT:
00716         n = new HTMLObjectElementImpl(docPtr());
00717         break;
00718     case ID_PARAM:
00719         n = new HTMLParamElementImpl(docPtr());
00720         break;
00721     case ID_SCRIPT:
00722         n = new HTMLScriptElementImpl(docPtr());
00723         break;
00724 
00725 // tables
00726     case ID_TABLE:
00727         n = new HTMLTableElementImpl(docPtr());
00728         break;
00729     case ID_CAPTION:
00730         n = new HTMLTableCaptionElementImpl(docPtr());
00731         break;
00732     case ID_COLGROUP:
00733     case ID_COL:
00734         n = new HTMLTableColElementImpl(docPtr(), id);
00735         break;
00736     case ID_TR:
00737         n = new HTMLTableRowElementImpl(docPtr());
00738         break;
00739     case ID_TD:
00740     case ID_TH:
00741         n = new HTMLTableCellElementImpl(docPtr(), id);
00742         break;
00743     case ID_THEAD:
00744     case ID_TBODY:
00745     case ID_TFOOT:
00746         n = new HTMLTableSectionElementImpl(docPtr(), id, false);
00747         break;
00748 
00749 // inline elements
00750     case ID_BR:
00751         n = new HTMLBRElementImpl(docPtr());
00752         break;
00753     case ID_Q:
00754         n = new HTMLGenericElementImpl(docPtr(), id);
00755         break;
00756 
00757 // elements with no special representation in the DOM
00758 
00759 // block:
00760     case ID_ADDRESS:
00761     case ID_CENTER:
00762         n = new HTMLGenericElementImpl(docPtr(), id);
00763         break;
00764 // inline
00765         // %fontstyle
00766     case ID_TT:
00767     case ID_U:
00768     case ID_B:
00769     case ID_I:
00770     case ID_S:
00771     case ID_STRIKE:
00772     case ID_BIG:
00773     case ID_SMALL:
00774 
00775         // %phrase
00776     case ID_EM:
00777     case ID_STRONG:
00778     case ID_DFN:
00779     case ID_CODE:
00780     case ID_SAMP:
00781     case ID_KBD:
00782     case ID_VAR:
00783     case ID_CITE:
00784     case ID_ABBR:
00785     case ID_ACRONYM:
00786 
00787         // %special
00788     case ID_SUB:
00789     case ID_SUP:
00790     case ID_SPAN:
00791     case ID_NOBR:
00792     case ID_WBR:
00793         n = new HTMLGenericElementImpl(docPtr(), id);
00794         break;
00795 
00796     case ID_BDO:
00797         break;
00798 
00799 // text
00800     case ID_TEXT:
00801         kdDebug( 6020 ) << "Use document->createTextNode()" << endl;
00802         break;
00803 
00804     default:
00805         if ( id )  // known tag but missing in this list
00806             kdDebug( 6020 ) << "Unsupported tag " << qstr << " id=" << id << endl;
00807         break;
00808     }
00809     return n;
00810 }
00811 
00812 QString DocumentImpl::nextState()
00813 {
00814    QString state;
00815    if (!m_state.isEmpty())
00816    {
00817       state = m_state.first();
00818       m_state.remove(m_state.begin());
00819    }
00820    return state;
00821 }
00822 
00823 QStringList DocumentImpl::docState()
00824 {
00825     QStringList s;
00826     for (QPtrListIterator<NodeImpl> it(m_maintainsState); it.current(); ++it)
00827         s.append(it.current()->state());
00828 
00829     return s;
00830 }
00831 
00832 RangeImpl *DocumentImpl::createRange()
00833 {
00834     return new RangeImpl( docPtr() );
00835 }
00836 
00837 NodeIteratorImpl *DocumentImpl::createNodeIterator(NodeImpl *root, unsigned long whatToShow,
00838                                                    NodeFilter &filter, bool entityReferenceExpansion,
00839                                                    int &exceptioncode)
00840 {
00841     if (!root) {
00842         exceptioncode = DOMException::NOT_SUPPORTED_ERR;
00843         return 0;
00844     }
00845 
00846     return new NodeIteratorImpl(root,whatToShow,filter,entityReferenceExpansion);
00847 }
00848 
00849 TreeWalkerImpl *DocumentImpl::createTreeWalker(Node /*root*/, unsigned long /*whatToShow*/, NodeFilter &/*filter*/,
00850                                 bool /*entityReferenceExpansion*/)
00851 {
00852     // ###
00853     return new TreeWalkerImpl;
00854 }
00855 
00856 void DocumentImpl::setDocumentChanged(bool b)
00857 {
00858     if (!changedDocuments)
00859         changedDocuments = s_changedDocumentsDeleter.setObject( new QPtrList<DocumentImpl>() );
00860 
00861     if (b && !m_docChanged)
00862         changedDocuments->append(this);
00863     else if (!b && m_docChanged)
00864         changedDocuments->remove(this);
00865     m_docChanged = b;
00866 }
00867 
00868 void DocumentImpl::recalcStyle( StyleChange change )
00869 {
00870 //     qDebug("recalcStyle(%p)", this);
00871 //     QTime qt;
00872 //     qt.start();
00873     if (m_inStyleRecalc)
00874         return; // Guard against re-entrancy. -dwh
00875 
00876     m_inStyleRecalc = true;
00877 
00878     if( !m_render ) goto bail_out;
00879 
00880     if ( change == Force ) {
00881         RenderStyle* oldStyle = m_render->style();
00882         if ( oldStyle ) oldStyle->ref();
00883         RenderStyle* _style = new RenderStyle();
00884         _style->setDisplay(BLOCK);
00885         _style->setVisuallyOrdered( visuallyOrdered );
00886         // ### make the font stuff _really_ work!!!!
00887 
00888     khtml::FontDef fontDef;
00889     QFont f = KGlobalSettings::generalFont();
00890     fontDef.family = f.family();
00891     fontDef.italic = f.italic();
00892     fontDef.weight = f.weight();
00893         if (m_view) {
00894             const KHTMLSettings *settings = m_view->part()->settings();
00895         QString stdfont = settings->stdFontName();
00896         if ( !stdfont.isEmpty() )
00897         fontDef.family = stdfont;
00898 
00899             fontDef.size = m_styleSelector->fontSizes()[3];
00900         }
00901 
00902         //kdDebug() << "DocumentImpl::attach: setting to charset " << settings->charset() << endl;
00903         _style->setFontDef(fontDef);
00904     _style->htmlFont().update( paintDeviceMetrics() );
00905         if ( parseMode() != Strict )
00906             _style->setHtmlHacks(true); // enable html specific rendering tricks
00907 
00908         StyleChange ch = diff( _style, oldStyle );
00909         if(m_render && ch != NoChange)
00910             m_render->setStyle(_style);
00911     else
00912         delete _style;
00913         if ( change != Force )
00914             change = ch;
00915 
00916         if (oldStyle)
00917             oldStyle->deref();
00918     }
00919 
00920     NodeImpl *n;
00921     for (n = _first; n; n = n->nextSibling())
00922         if ( change>= Inherit || n->hasChangedChild() || n->changed() )
00923             n->recalcStyle( change );
00924     //kdDebug( 6020 ) << "TIME: recalcStyle() dt=" << qt.elapsed() << endl;
00925 
00926     // ### should be done by the rendering tree itself,
00927     // this way is rather crude and CPU intensive
00928     if ( changed() ) {
00929     renderer()->setLayouted( false );
00930     renderer()->setMinMaxKnown( false );
00931     }
00932 
00933 bail_out:
00934     setChanged( false );
00935     setHasChangedChild( false );
00936     setDocumentChanged( false );
00937 
00938     m_inStyleRecalc = false;
00939 }
00940 
00941 void DocumentImpl::updateRendering()
00942 {
00943     if (!hasChangedChild()) return;
00944 
00945 //     QTime time;
00946 //     time.start();
00947 //     kdDebug() << "UPDATERENDERING: "<<endl;
00948 
00949     StyleChange change = NoChange;
00950 #if 0
00951     if ( m_styleSelectorDirty ) {
00952     recalcStyleSelector();
00953     change = Force;
00954     }
00955 #endif
00956     recalcStyle( change );
00957 
00958 //    kdDebug() << "UPDATERENDERING time used="<<time.elapsed()<<endl;
00959 }
00960 
00961 void DocumentImpl::updateDocumentsRendering()
00962 {
00963     if (!changedDocuments)
00964         return;
00965 
00966     while ( !changedDocuments->isEmpty() ) {
00967         changedDocuments->first();
00968         DocumentImpl* it = changedDocuments->take();
00969         if (it->isDocumentChanged())
00970             it->updateRendering();
00971     }
00972 }
00973 
00974 void DocumentImpl::attach()
00975 {
00976     assert(!attached());
00977 
00978     if ( m_view )
00979         setPaintDevice( m_view );
00980 
00981     // Create the rendering tree
00982     assert(!m_styleSelector);
00983     m_styleSelector = new CSSStyleSelector( this, m_usersheet, m_styleSheets, m_url,
00984                                             pMode == Strict );
00985     m_render = new RenderRoot(this, m_view);
00986     m_styleSelector->computeFontSizes(paintDeviceMetrics(), m_view ? m_view->part()->zoomFactor() : 100);
00987     recalcStyle( Force );
00988 
00989     RenderObject* render = m_render;
00990     m_render = 0;
00991 
00992     NodeBaseImpl::attach();
00993     m_render = render;
00994 }
00995 
00996 void DocumentImpl::detach()
00997 {
00998     RenderObject* render = m_render;
00999 
01000     // indicate destruction mode,  i.e. attached() but m_render == 0
01001     m_render = 0;
01002 
01003     delete m_tokenizer;
01004     m_tokenizer = 0;
01005 
01006     NodeBaseImpl::detach();
01007 
01008     if ( render )
01009         render->detach();
01010 
01011     m_view = 0;
01012 }
01013 
01014 void DocumentImpl::setVisuallyOrdered()
01015 {
01016     visuallyOrdered = true;
01017     if (m_render)
01018         m_render->style()->setVisuallyOrdered(true);
01019 }
01020 
01021 void DocumentImpl::setSelection(NodeImpl* s, int sp, NodeImpl* e, int ep)
01022 {
01023     if ( m_render )
01024         static_cast<RenderRoot*>(m_render)->setSelection(s->renderer(),sp,e->renderer(),ep);
01025 }
01026 
01027 void DocumentImpl::clearSelection()
01028 {
01029     if ( m_render )
01030         static_cast<RenderRoot*>(m_render)->clearSelection();
01031 }
01032 
01033 Tokenizer *DocumentImpl::createTokenizer()
01034 {
01035     return new XMLTokenizer(docPtr(),m_view);
01036 }
01037 
01038 void DocumentImpl::setPaintDevice( QPaintDevice *dev )
01039 {
01040     m_paintDevice = dev;
01041     delete m_paintDeviceMetrics;
01042     m_paintDeviceMetrics = new QPaintDeviceMetrics( dev );
01043 }
01044 
01045 void DocumentImpl::open(  )
01046 {
01047     if (parsing()) return;
01048 
01049     if (m_tokenizer)
01050         close();
01051 
01052     delete m_tokenizer;
01053     m_tokenizer = 0;
01054 
01055     {
01056         RenderObject* render = m_render;
01057         m_render = 0; // indicate destruction mode
01058         removeChildren();
01059         QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
01060         for (; it.current();)
01061             m_windowEventListeners.removeRef(it.current());
01062         m_render = render;
01063     }
01064 
01065     m_tokenizer = createTokenizer();
01066     m_decoderMibEnum = 0;
01067     connect(m_tokenizer,SIGNAL(finishedParsing()),this,SIGNAL(finishedParsing()));
01068     m_tokenizer->begin();
01069 
01070     if (m_view && m_view->part()->jScript())
01071         m_view->part()->jScript()->setSourceFile(m_url,"");
01072 }
01073 
01074 void DocumentImpl::close(  )
01075 {
01076     if (parsing() || !m_tokenizer) return;
01077 
01078     if ( m_render )
01079         m_render->close();
01080 
01081     delete m_tokenizer;
01082     m_tokenizer = 0;
01083 
01084     if (m_view)
01085         m_view->part()->checkEmitLoadEvent();
01086 }
01087 
01088 void DocumentImpl::write( const DOMString &text )
01089 {
01090     write(text.string());
01091 }
01092 
01093 void DocumentImpl::write( const QString &text )
01094 {
01095     if (!m_tokenizer) {
01096         open();
01097         write(QString::fromLatin1("<html><title></title><body>"));
01098     }
01099     m_tokenizer->write(text, false);
01100 
01101     if (m_view && m_view->part()->jScript())
01102         m_view->part()->jScript()->appendSourceFile(m_url,text);
01103 }
01104 
01105 void DocumentImpl::writeln( const DOMString &text )
01106 {
01107     write(text);
01108     write(DOMString("\n"));
01109 }
01110 
01111 void DocumentImpl::finishParsing (  )
01112 {
01113     if(m_tokenizer)
01114         m_tokenizer->finish();
01115 }
01116 
01117 void DocumentImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet)
01118 {
01119 //    kdDebug( 6030 ) << "HTMLDocument::setStyleSheet()" << endl;
01120     m_sheet = new CSSStyleSheetImpl(this, url);
01121     m_sheet->ref();
01122     m_sheet->parseString(sheet);
01123     m_loadingSheet = false;
01124 
01125     updateStyleSelector();
01126 }
01127 
01128 void DocumentImpl::setUserStyleSheet( const QString& sheet )
01129 {
01130     if ( m_usersheet != sheet ) {
01131         m_usersheet = sheet;
01132         updateStyleSelector();
01133     }
01134 }
01135 
01136 CSSStyleSheetImpl* DocumentImpl::elementSheet()
01137 {
01138     if (!m_elemSheet) {
01139         m_elemSheet = new CSSStyleSheetImpl(this, baseURL() );
01140         m_elemSheet->ref();
01141     }
01142     return m_elemSheet;
01143 }
01144 
01145 void DocumentImpl::determineParseMode( const QString &/*str*/ )
01146 {
01147     // For xML documents, use string parse mode
01148     pMode = Strict;
01149     kdDebug(6020) << " using strict parseMode" << endl;
01150 }
01151 
01152 // Please see if there`s a possibility to merge that code
01153 // with the next function and getElementByID().
01154 NodeImpl *DocumentImpl::findElement( Id id )
01155 {
01156     QPtrStack<NodeImpl> nodeStack;
01157     NodeImpl *current = _first;
01158 
01159     while(1)
01160     {
01161         if(!current)
01162         {
01163             if(nodeStack.isEmpty()) break;
01164             current = nodeStack.pop();
01165             current = current->nextSibling();
01166         }
01167         else
01168         {
01169             if(current->id() == id)
01170                 return current;
01171 
01172             NodeImpl *child = current->firstChild();
01173             if(child)
01174             {
01175                 nodeStack.push(current);
01176                 current = child;
01177             }
01178             else
01179             {
01180                 current = current->nextSibling();
01181             }
01182         }
01183     }
01184 
01185     return 0;
01186 }
01187 
01188 NodeImpl *DocumentImpl::nextFocusNode(NodeImpl *fromNode)
01189 {
01190     unsigned short fromTabIndex;
01191 
01192     if (!fromNode) {
01193     // No starting node supplied; begin with the top of the document
01194     NodeImpl *n;
01195 
01196     int lowestTabIndex = 65535;
01197     for (n = this; n != 0; n = n->traverseNextNode()) {
01198         if (n->isSelectable()) {
01199         if ((n->tabIndex() > 0) && (n->tabIndex() < lowestTabIndex))
01200             lowestTabIndex = n->tabIndex();
01201         }
01202     }
01203 
01204     if (lowestTabIndex == 65535)
01205         lowestTabIndex = 0;
01206 
01207     // Go to the first node in the document that has the desired tab index
01208     for (n = this; n != 0; n = n->traverseNextNode()) {
01209         if (n->isSelectable() && (n->tabIndex() == lowestTabIndex))
01210         return n;
01211     }
01212 
01213     return 0;
01214     }
01215     else {
01216     fromTabIndex = fromNode->tabIndex();
01217     }
01218 
01219     if (fromTabIndex == 0) {
01220     // Just need to find the next selectable node after fromNode (in document order) that doesn't have a tab index
01221     NodeImpl *n = fromNode->traverseNextNode();
01222     while (n && !(n->isSelectable() && n->tabIndex() == 0))
01223         n = n->traverseNextNode();
01224     return n;
01225     }
01226     else {
01227     // Find the lowest tab index out of all the nodes except fromNode, that is greater than or equal to fromNode's
01228     // tab index. For nodes with the same tab index as fromNode, we are only interested in those that come after
01229     // fromNode in document order.
01230     // If we don't find a suitable tab index, the next focus node will be one with a tab index of 0.
01231     unsigned short lowestSuitableTabIndex = 65535;
01232     NodeImpl *n;
01233 
01234     bool reachedFromNode = false;
01235     for (n = this; n != 0; n = n->traverseNextNode()) {
01236         if (n->isSelectable() &&
01237         ((reachedFromNode && (n->tabIndex() >= fromTabIndex)) ||
01238          (!reachedFromNode && (n->tabIndex() > fromTabIndex))) &&
01239         (n->tabIndex() < lowestSuitableTabIndex) &&
01240         (n != fromNode)) {
01241 
01242         // We found a selectable node with a tab index at least as high as fromNode's. Keep searching though,
01243         // as there may be another node which has a lower tab index but is still suitable for use.
01244         lowestSuitableTabIndex = n->tabIndex();
01245         }
01246 
01247         if (n == fromNode)
01248         reachedFromNode = true;
01249     }
01250 
01251     if (lowestSuitableTabIndex == 65535) {
01252         // No next node with a tab index -> just take first node with tab index of 0
01253         NodeImpl *n = this;
01254         while (n && !(n->isSelectable() && n->tabIndex() == 0))
01255         n = n->traverseNextNode();
01256         return n;
01257     }
01258 
01259     // Search forwards from fromNode
01260     for (n = fromNode->traverseNextNode(); n != 0; n = n->traverseNextNode()) {
01261         if (n->isSelectable() && (n->tabIndex() == lowestSuitableTabIndex))
01262         return n;
01263     }
01264 
01265     // The next node isn't after fromNode, start from the beginning of the document
01266     for (n = this; n != fromNode; n = n->traverseNextNode()) {
01267         if (n->isSelectable() && (n->tabIndex() == lowestSuitableTabIndex))
01268         return n;
01269     }
01270 
01271     assert(false); // should never get here
01272     return 0;
01273     }
01274 }
01275 
01276 NodeImpl *DocumentImpl::previousFocusNode(NodeImpl *fromNode)
01277 {
01278     NodeImpl *lastNode = this;
01279     while (lastNode->lastChild())
01280     lastNode = lastNode->lastChild();
01281 
01282     if (!fromNode) {
01283     // No starting node supplied; begin with the very last node in the document
01284     NodeImpl *n;
01285 
01286     int highestTabIndex = 0;
01287     for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
01288         if (n->isSelectable()) {
01289         if (n->tabIndex() == 0)
01290             return n;
01291         else if (n->tabIndex() > highestTabIndex)
01292             highestTabIndex = n->tabIndex();
01293         }
01294     }
01295 
01296     // No node with a tab index of 0; just go to the last node with the highest tab index
01297     for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
01298         if (n->isSelectable() && (n->tabIndex() == highestTabIndex))
01299         return n;
01300     }
01301 
01302     return 0;
01303     }
01304     else {
01305     unsigned short fromTabIndex = fromNode->tabIndex();
01306 
01307     if (fromTabIndex == 0) {
01308         // Find the previous selectable node before fromNode (in document order) that doesn't have a tab index
01309         NodeImpl *n = fromNode->traversePreviousNode();
01310         while (n && !(n->isSelectable() && n->tabIndex() == 0))
01311         n = n->traversePreviousNode();
01312         if (n)
01313         return n;
01314 
01315         // No previous nodes with a 0 tab index, go to the last node in the document that has the highest tab index
01316         int highestTabIndex = 0;
01317         for (n = this; n != 0; n = n->traverseNextNode()) {
01318         if (n->isSelectable() && (n->tabIndex() > highestTabIndex))
01319             highestTabIndex = n->tabIndex();
01320         }
01321 
01322         if (highestTabIndex == 0)
01323         return 0;
01324 
01325         for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
01326         if (n->isSelectable() && (n->tabIndex() == highestTabIndex))
01327             return n;
01328         }
01329 
01330         assert(false); // should never get here
01331         return 0;
01332     }
01333     else {
01334         // Find the lowest tab index out of all the nodes except fromNode, that is less than or equal to fromNode's
01335         // tab index. For nodes with the same tab index as fromNode, we are only interested in those before
01336         // fromNode.
01337         // If we don't find a suitable tab index, then there will be no previous focus node.
01338         unsigned short highestSuitableTabIndex = 0;
01339         NodeImpl *n;
01340 
01341         bool reachedFromNode = false;
01342         for (n = this; n != 0; n = n->traverseNextNode()) {
01343         if (n->isSelectable() &&
01344             ((!reachedFromNode && (n->tabIndex() <= fromTabIndex)) ||
01345              (reachedFromNode && (n->tabIndex() < fromTabIndex)))  &&
01346             (n->tabIndex() > highestSuitableTabIndex) &&
01347             (n != fromNode)) {
01348 
01349             // We found a selectable node with a tab index no higher than fromNode's. Keep searching though, as
01350             // there may be another node which has a higher tab index but is still suitable for use.
01351             highestSuitableTabIndex = n->tabIndex();
01352         }
01353 
01354         if (n == fromNode)
01355             reachedFromNode = true;
01356         }
01357 
01358         if (highestSuitableTabIndex == 0) {
01359         // No previous node with a tab index. Since the order specified by HTML is nodes with tab index > 0
01360         // first, this means that there is no previous node.
01361         return 0;
01362         }
01363 
01364         // Search backwards from fromNode
01365         for (n = fromNode->traversePreviousNode(); n != 0; n = n->traversePreviousNode()) {
01366         if (n->isSelectable() && (n->tabIndex() == highestSuitableTabIndex))
01367             return n;
01368         }
01369         // The previous node isn't before fromNode, start from the end of the document
01370         for (n = lastNode; n != fromNode; n = n->traversePreviousNode()) {
01371         if (n->isSelectable() && (n->tabIndex() == highestSuitableTabIndex))
01372             return n;
01373         }
01374 
01375         assert(false); // should never get here
01376         return 0;
01377     }
01378     }
01379 }
01380 
01381 int DocumentImpl::nodeAbsIndex(NodeImpl *node)
01382 {
01383     assert(node->getDocument() == this);
01384 
01385     int absIndex = 0;
01386     for (NodeImpl *n = node; n && n != this; n = n->traversePreviousNode())
01387     absIndex++;
01388     return absIndex;
01389 }
01390 
01391 NodeImpl *DocumentImpl::nodeWithAbsIndex(int absIndex)
01392 {
01393     NodeImpl *n = this;
01394     for (int i = 0; n && (i < absIndex); i++) {
01395     n = n->traverseNextNode();
01396     }
01397     return n;
01398 }
01399 
01400 void DocumentImpl::processHttpEquiv(const DOMString &equiv, const DOMString &content)
01401 {
01402     assert(!equiv.isNull() && !content.isNull());
01403 
01404     KHTMLView *v = getDocument()->view();
01405 
01406     if(strcasecmp(equiv, "refresh") == 0 && v->part()->metaRefreshEnabled())
01407     {
01408         // get delay and url
01409         QString str = content.string().stripWhiteSpace();
01410         int pos = str.find(QRegExp("[;,]"));
01411         if ( pos == -1 )
01412             pos = str.find(QRegExp("[ \t]"));
01413 
01414         if (pos == -1) // There can be no url (David)
01415         {
01416             bool ok = false;
01417             int delay = 0;
01418         delay = content.implementation()->toInt(&ok);
01419             if(ok) v->part()->scheduleRedirection(delay, v->part()->url().url() );
01420         } else {
01421             int delay = 0;
01422             int fract = pos;
01423             bool ok = false;
01424             if ( (fract = str.find('.') ) < 0 || fract > pos)
01425                 fract = pos;
01426         DOMStringImpl* s = content.implementation()->substring(0, fract);
01427         delay = s->toInt(&ok);
01428         delete s;
01429 
01430             pos++;
01431             while(pos < (int)str.length() && str[pos].isSpace()) pos++;
01432             str = str.mid(pos);
01433             if(str.find("url", 0,  false ) == 0)  str = str.mid(3);
01434             str = str.stripWhiteSpace();
01435             if ( str.length() && str[0] == '=' ) str = str.mid( 1 ).stripWhiteSpace();
01436             while(str.length() &&
01437                   (str[str.length()-1] == ';' || str[str.length()-1] == ','))
01438                 str.setLength(str.length()-1);
01439             str = parseURL( DOMString(str) ).string();
01440             if ( ok  || !fract)
01441                 v->part()->scheduleRedirection(delay, getDocument()->completeURL( str ));
01442         }
01443     }
01444     else if(strcasecmp(equiv, "expires") == 0)
01445     {
01446         bool relative = false;
01447         QString str = content.string().stripWhiteSpace();
01448         time_t expire_date = KRFCDate::parseDate(str);
01449         if (!expire_date)
01450         {
01451             expire_date = str.toULong();
01452             relative = true;
01453         }
01454         if (!expire_date)
01455             expire_date = 1; // expire now
01456         if (m_docLoader)
01457             m_docLoader->setExpireDate(expire_date, relative);
01458     }
01459     else if(strcasecmp(equiv, "pragma") == 0 || strcasecmp(equiv, "cache-control") == 0)
01460     {
01461         QString str = content.string().lower().stripWhiteSpace();
01462         KURL url = v->part()->url();
01463         if ((str == "no-cache") && url.protocol().startsWith("http"))
01464         {
01465            KIO::http_update_cache(url, true, 0);
01466         }
01467     }
01468     else if( (strcasecmp(equiv, "set-cookie") == 0))
01469     {
01470         // ### make setCookie work on XML documents too; e.g. in case of <html:meta .....>
01471         HTMLDocumentImpl *d = static_cast<HTMLDocumentImpl *>(this);
01472         d->setCookie(content);
01473     }
01474 }
01475 
01476 bool DocumentImpl::prepareMouseEvent( bool readonly, int _x, int _y, MouseEvent *ev )
01477 {
01478     if ( m_render ) {
01479         assert(m_render->isRoot());
01480         RenderObject::NodeInfo renderInfo(readonly, ev->type == MousePress);
01481         bool isInside = m_render->nodeAtPoint(renderInfo, _x, _y, 0, 0);
01482         ev->innerNode = renderInfo.innerNode();
01483 
01484         if (renderInfo.URLElement()) {
01485             assert(renderInfo.URLElement()->isElementNode());
01486             ElementImpl* e =  static_cast<ElementImpl*>(renderInfo.URLElement());
01487             DOMString href = khtml::parseURL(e->getAttribute(ATTR_HREF));
01488             DOMString target = e->getAttribute(ATTR_TARGET);
01489 
01490             if (!target.isNull() && !href.isNull()) {
01491                 ev->target = target;
01492                 ev->url = href;
01493             }
01494             else
01495                 ev->url = href;
01496 //            qDebug("url: *%s*", ev->url.string().latin1());
01497         }
01498 
01499         if (!readonly)
01500             updateRendering();
01501 
01502         return isInside;
01503     }
01504 
01505 
01506     return false;
01507 }
01508 
01509 // DOM Section 1.1.1
01510 bool DocumentImpl::childAllowed( NodeImpl *newChild )
01511 {
01512     // Documents may contain a maximum of one Element child
01513     if (newChild->nodeType() == Node::ELEMENT_NODE) {
01514         NodeImpl *c;
01515         for (c = firstChild(); c; c = c->nextSibling()) {
01516             if (c->nodeType() == Node::ELEMENT_NODE)
01517                 return false;
01518         }
01519     }
01520 
01521     // Documents may contain a maximum of one DocumentType child
01522     if (newChild->nodeType() == Node::DOCUMENT_TYPE_NODE) {
01523         NodeImpl *c;
01524         for (c = firstChild(); c; c = c->nextSibling()) {
01525             if (c->nodeType() == Node::DOCUMENT_TYPE_NODE)
01526                 return false;
01527         }
01528     }
01529 
01530     return childTypeAllowed(newChild->nodeType());
01531 }
01532 
01533 bool DocumentImpl::childTypeAllowed( unsigned short type )
01534 {
01535     switch (type) {
01536         case Node::ELEMENT_NODE:
01537         case Node::PROCESSING_INSTRUCTION_NODE:
01538         case Node::COMMENT_NODE:
01539         case Node::DOCUMENT_TYPE_NODE:
01540             return true;
01541             break;
01542         default:
01543             return false;
01544     }
01545 }
01546 
01547 NodeImpl *DocumentImpl::cloneNode ( bool /*deep*/ )
01548 {
01549     // Spec says cloning Document nodes is "implementation dependent"
01550     // so we do not support it...
01551     return 0;
01552 }
01553 
01554 NodeImpl::Id DocumentImpl::attrId(DOMStringImpl* _namespaceURI, DOMStringImpl *_name, bool readonly, int* pExceptioncode)
01555 {
01556     // Each document maintains a mapping of attrname -> id for every attr name
01557     // encountered in the document.
01558     // For attrnames without a prefix (no qualified element name) and without matching
01559     // namespace, the value defined in misc/htmlattrs.h is used.
01560     NodeImpl::Id id = 0;
01561 
01562     // First see if it's a HTML attribute name
01563     QConstString n(_name->s, _name->l);
01564     if (!_namespaceURI || !strcasecmp(_namespaceURI, XHTML_NAMESPACE)) {
01565         // we're in HTML namespace if we know the tag.
01566         // xhtml is lower case - case sensitive, easy to implement
01567         if ( htmlMode() == XHtml && (id = khtml::getAttrID(n.string().ascii(), _name->l)) )
01568             return id;
01569         // compatibility: upper case - case insensitive
01570         if ( htmlMode() != XHtml && (id = khtml::getAttrID(n.string().lower().ascii(), _name->l )) )
01571             return id;
01572 
01573         // ok, the fast path didn't work out, we need the full check
01574     }
01575 
01576     // now lets find out the namespace
01577     if (_namespaceURI) {
01578         DOMString nsU(_namespaceURI);
01579         bool found = false;
01580         // ### yeah, this is lame. use a dictionary / map instead
01581         for (unsigned short ns = 0; ns < m_namespaceURICount; ++ns)
01582             if (nsU == DOMString(m_namespaceURIs[ns])) {
01583                 id |= ns << 16;
01584                 found = true;
01585                 break;
01586             }
01587 
01588         if (!found && !readonly) {
01589             // something new, add it
01590             if (m_namespaceURICount >= m_namespaceURIAlloc) {
01591                 m_namespaceURIAlloc += 32;
01592                 DOMStringImpl **newURIs = new DOMStringImpl* [m_namespaceURIAlloc];
01593                 for (unsigned short i = 0; i < m_namespaceURICount; i++)
01594                     newURIs[i] = m_namespaceURIs[i];
01595                 delete [] m_namespaceURIs;
01596                 m_namespaceURIs = newURIs;
01597             }
01598             m_namespaceURIs[m_namespaceURICount++] = _namespaceURI;
01599             _namespaceURI->ref();
01600             id |= m_namespaceURICount << 16;
01601         }
01602     }
01603 
01604     // Look in the m_attrNames array for the name
01605     // ### yeah, this is lame. use a dictionary / map instead
01606     DOMString nme(n.string());
01607     // compatibility mode has to store upper case
01608     if (htmlMode() != XHtml) nme = nme.upper();
01609     for (id = 0; id < m_attrNameCount; id++)
01610         if (DOMString(m_attrNames[id]) == nme)
01611             return ATTR_LAST_ATTR+id;
01612 
01613     // unknown
01614     if (readonly) return 0;
01615 
01616     if (pExceptioncode && !Element::khtmlValidQualifiedName(_name)) {
01617         *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
01618         return 0;
01619     }
01620 
01621     // Name not found in m_attrNames, so let's add it
01622     // ### yeah, this is lame. use a dictionary / map instead
01623     if (m_attrNameCount+1 > m_attrNameAlloc) {
01624         m_attrNameAlloc += 100;
01625         DOMStringImpl **newNames = new DOMStringImpl* [m_attrNameAlloc];
01626         if (m_attrNames) {
01627             unsigned short i;
01628             for (i = 0; i < m_attrNameCount; i++)
01629                 newNames[i] = m_attrNames[i];
01630             delete [] m_attrNames;
01631         }
01632         m_attrNames = newNames;
01633     }
01634 
01635     id = m_attrNameCount++;
01636     m_attrNames[id] = nme.implementation();
01637     m_attrNames[id]->ref();
01638 
01639     return ATTR_LAST_ATTR+id;
01640 }
01641 
01642 DOMString DocumentImpl::attrName(NodeImpl::Id _id) const
01643 {
01644     if (_id >= ATTR_LAST_ATTR)
01645         return m_attrNames[_id-ATTR_LAST_ATTR];
01646     else {
01647         // ### put them in a cache
01648         if (getDocument()->htmlMode() == DocumentImpl::XHtml)
01649             return getAttrName(_id).lower();
01650         else
01651             return getAttrName(_id);
01652     }
01653 }
01654 
01655 NodeImpl::Id DocumentImpl::tagId(DOMStringImpl* _namespaceURI, DOMStringImpl *_name, bool readonly, int *pExceptioncode)
01656 {
01657     if (!_name || !_name->l) return 0;
01658     // Each document maintains a mapping of tag name -> id for every tag name encountered
01659     // in the document.
01660     NodeImpl::Id id = 0;
01661 
01662     // First see if it's a HTML element name
01663     QConstString n(_name->s, _name->l);
01664     if (!_namespaceURI || !strcasecmp(_namespaceURI, XHTML_NAMESPACE)) {
01665         // we're in HTML namespace if we know the tag.
01666         // xhtml is lower case - case sensitive, easy to implement
01667         if ( htmlMode() == XHtml && (id = khtml::getTagID(n.string().ascii(), _name->l)) )
01668             return id;
01669         // compatibility: upper case - case insensitive
01670         if ( htmlMode() != XHtml && (id = khtml::getTagID(n.string().lower().ascii(), _name->l )) )
01671             return id;
01672 
01673         // ok, the fast path didn't work out, we need the full check
01674     }
01675 
01676     // now lets find out the namespace
01677     if (_namespaceURI) {
01678         DOMString nsU(_namespaceURI);
01679         bool found = false;
01680         // ### yeah, this is lame. use a dictionary / map instead
01681         for (unsigned short ns = 0; ns < m_namespaceURICount; ++ns)
01682             if (nsU == DOMString(m_namespaceURIs[ns])) {
01683                 id |= ns << 16;
01684                 found = true;
01685                 break;
01686             }
01687 
01688         if (!found && !readonly) {
01689             // something new, add it
01690             if (m_namespaceURICount >= m_namespaceURIAlloc) {
01691                 m_namespaceURIAlloc += 32;
01692                 DOMStringImpl **newURIs = new DOMStringImpl* [m_namespaceURIAlloc];
01693                 for (unsigned short i = 0; i < m_namespaceURICount; i++)
01694                     newURIs[i] = m_namespaceURIs[i];
01695                 delete [] m_namespaceURIs;
01696                 m_namespaceURIs = newURIs;
01697             }
01698             m_namespaceURIs[m_namespaceURICount++] = _namespaceURI;
01699             _namespaceURI->ref();
01700             id |= m_namespaceURICount << 16;
01701         }
01702     }
01703 
01704     // Look in the m_elementNames array for the name
01705     //DOMString nme(n.string());
01706     DOMString nme( _name );
01707     // ### yeah, this is lame. use a dictionary / map instead
01708     // compatibility mode has to store upper case
01709     if (htmlMode() != XHtml) nme = nme.upper();
01710     for (id = 0; id < m_elementNameCount; id++)
01711         if (DOMString(m_elementNames[id]) == nme)
01712             return ID_LAST_TAG+id;
01713 
01714     // unknown
01715     if (readonly) return 0;
01716 
01717     if (pExceptioncode && !Element::khtmlValidQualifiedName(_name)) {
01718         *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
01719         return 0;
01720     }
01721 
01722     // Name not found in m_elementNames, so let's add it
01723     if (m_elementNameCount+1 > m_elementNameAlloc) {
01724         m_elementNameAlloc += 100;
01725         DOMStringImpl **newNames = new DOMStringImpl* [m_elementNameAlloc];
01726         // ### yeah, this is lame. use a dictionary / map instead
01727         if (m_elementNames) {
01728             unsigned short i;
01729             for (i = 0; i < m_elementNameCount; i++)
01730                 newNames[i] = m_elementNames[i];
01731             delete [] m_elementNames;
01732         }
01733         m_elementNames = newNames;
01734     }
01735 
01736     id = m_elementNameCount++;
01737     m_elementNames[id] = nme.implementation();
01738     m_elementNames[id]->ref();
01739 
01740     return ID_LAST_TAG+id;
01741 }
01742 
01743 DOMString DocumentImpl::tagName(NodeImpl::Id _id) const
01744 {
01745     if (_id >= ID_LAST_TAG)
01746         return m_elementNames[_id-ID_LAST_TAG];
01747     else {
01748         // ### put them in a cache
01749         if (getDocument()->htmlMode() == DocumentImpl::XHtml)
01750             return getTagName(_id).lower();
01751         else
01752             return getTagName(_id);
01753     }
01754 }
01755 
01756 
01757 DOMStringImpl* DocumentImpl::namespaceURI(NodeImpl::Id _id) const
01758 {
01759     if (_id < ID_LAST_TAG)
01760         return htmlMode() == XHtml ? m_namespaceURIs[0] : 0;
01761 
01762     unsigned short ns = _id >> 16;
01763 
01764     if (!ns) return 0;
01765 
01766     return m_namespaceURIs[ns-1];
01767 }
01768 
01769 StyleSheetListImpl* DocumentImpl::styleSheets()
01770 {
01771     return m_styleSheets;
01772 }
01773 
01774 void DocumentImpl::updateStyleSelector()
01775 {
01776     recalcStyleSelector();
01777     recalcStyle(Force);
01778 #if 0
01779 
01780     m_styleSelectorDirty = true;
01781 #endif
01782     if ( renderer() ) {
01783         renderer()->setLayouted( false );
01784         renderer()->setMinMaxKnown( false );
01785     }
01786 }
01787 
01788 
01789 QStringList DocumentImpl::availableStyleSheets() const
01790 {
01791     return m_availableSheets;
01792 }
01793 
01794 void DocumentImpl::recalcStyleSelector()
01795 {
01796     if ( !m_render || !attached() ) return;
01797 
01798     QPtrList<StyleSheetImpl> oldStyleSheets = m_styleSheets->styleSheets;
01799     m_styleSheets->styleSheets.clear();
01800     m_availableSheets.clear();
01801     NodeImpl *n;
01802     for (n = this; n; n = n->traverseNextNode()) {
01803         StyleSheetImpl *sheet = 0;
01804 
01805         if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
01806         {
01807             // Processing instruction (XML documents only)
01808             ProcessingInstructionImpl* pi = static_cast<ProcessingInstructionImpl*>(n);
01809             sheet = pi->sheet();
01810             if (!sheet && !pi->localHref().isEmpty())
01811             {
01812                 // Processing instruction with reference to an element in this document - e.g.
01813                 // <?xml-stylesheet href="#mystyle">, with the element
01814                 // <foo id="mystyle">heading { color: red; }</foo> at some location in
01815                 // the document
01816                 ElementImpl* elem = getElementById(pi->localHref());
01817                 if (elem) {
01818                     DOMString sheetText("");
01819                     NodeImpl *c;
01820                     for (c = elem->firstChild(); c; c = c->nextSibling()) {
01821                         if (c->nodeType() == Node::TEXT_NODE || c->nodeType() == Node::CDATA_SECTION_NODE)
01822                             sheetText += c->nodeValue();
01823                     }
01824 
01825                     CSSStyleSheetImpl *cssSheet = new CSSStyleSheetImpl(this);
01826                     cssSheet->parseString(sheetText);
01827                     pi->setStyleSheet(cssSheet);
01828                     sheet = cssSheet;
01829                 }
01830             }
01831 
01832         }
01833         else if (n->id() == ID_LINK || n->id() == ID_STYLE) {
01834             ElementImpl *e = static_cast<ElementImpl *>(n);
01835             QString title = e->getAttribute( ATTR_TITLE ).string();
01836             if (n->id() == ID_LINK) {
01837                 // <LINK> element
01838                 HTMLLinkElementImpl* l = static_cast<HTMLLinkElementImpl*>(n);
01839                 // awful hack to ensure that we ignore the title attribute for non-stylesheets
01840                 // ### make that nicer!
01841                 if (!(l->sheet() || l->isLoading()))
01842                     title = QString::null;
01843             }
01844             else {
01845                 HTMLStyleElementImpl* s = static_cast<HTMLStyleElementImpl*>(n);
01846                 // awful hack to ensure that we ignore the title attribute for non-stylesheets
01847                 // ### make that nicer!
01848                 if (!(s->sheet() || s->isLoading()))
01849                     title = QString::null;
01850             }
01851 
01852             QString sheetUsed = view()->part()->d->m_sheetUsed;
01853             if ( n->id() == ID_LINK )
01854                 sheet = static_cast<HTMLLinkElementImpl*>(n)->sheet();
01855             else
01856                 // <STYLE> element
01857                 sheet = static_cast<HTMLStyleElementImpl*>(n)->sheet();
01858 
01859             if ( !title.isEmpty() ) {
01860                 if ( sheetUsed.isEmpty() )
01861                     sheetUsed = view()->part()->d->m_sheetUsed = title;
01862                 if ( !m_availableSheets.contains( title ) )
01863                     m_availableSheets.append( title );
01864 
01865                 if ( title != sheetUsed )
01866                     sheet = 0; // this stylesheet wasn't selected
01867             }
01868     }
01869     else if (n->id() == ID_BODY) {
01870             // <BODY> element (doesn't contain styles as such but vlink="..." and friends
01871             // are treated as style declarations)
01872         sheet = static_cast<HTMLBodyElementImpl*>(n)->sheet();
01873         }
01874         if (sheet) {
01875             sheet->ref();
01876             m_styleSheets->styleSheets.append(sheet);
01877         }
01878 
01879         // For HTML documents, stylesheets are not allowed within/after the <BODY> tag. So we
01880         // can stop searching here.
01881         if (isHTMLDocument() && n->id() == ID_BODY)
01882             break;
01883     }
01884 
01885     // De-reference all the stylesheets in the old list
01886     QPtrListIterator<StyleSheetImpl> it(oldStyleSheets);
01887     for (; it.current(); ++it)
01888     it.current()->deref();
01889 
01890     // Create a new style selector
01891     delete m_styleSelector;
01892     QString usersheet = m_usersheet;
01893     if ( m_view && m_view->mediaType() == "print" )
01894     usersheet += m_printSheet;
01895     m_styleSelector = new CSSStyleSelector( this, usersheet, m_styleSheets, m_url,
01896                                             pMode == Strict );
01897 
01898     m_styleSelectorDirty = false;
01899 }
01900 
01901 void DocumentImpl::setFocusNode(NodeImpl *newFocusNode)
01902 {
01903     // don't process focus changes while detaching
01904     if( !m_render ) return;
01905     // Make sure newFocusNode is actually in this document
01906     if (newFocusNode && (newFocusNode->getDocument() != this))
01907         return;
01908 
01909     if (m_focusNode != newFocusNode) {
01910         NodeImpl *oldFocusNode = m_focusNode;
01911         // Set focus on the new node
01912         m_focusNode = newFocusNode;
01913         // Remove focus from the existing focus node (if any)
01914         if (oldFocusNode) {
01915             if (oldFocusNode->active())
01916                 oldFocusNode->setActive(false);
01917 
01918             oldFocusNode->setFocus(false);
01919         oldFocusNode->dispatchHTMLEvent(EventImpl::BLUR_EVENT,false,false);
01920         oldFocusNode->dispatchUIEvent(EventImpl::DOMFOCUSOUT_EVENT);
01921             if ((oldFocusNode == this) && oldFocusNode->hasOneRef()) {
01922                 oldFocusNode->deref(); // deletes this
01923                 return;
01924             }
01925         else {
01926                 oldFocusNode->deref();
01927             }
01928         }
01929 
01930         if (m_focusNode) {
01931             m_focusNode->ref();
01932             m_focusNode->dispatchHTMLEvent(EventImpl::FOCUS_EVENT,false,false);
01933             if (m_focusNode != newFocusNode) return;
01934             m_focusNode->dispatchUIEvent(EventImpl::DOMFOCUSIN_EVENT);
01935             if (m_focusNode != newFocusNode) return;
01936             m_focusNode->setFocus();
01937             if (m_focusNode != newFocusNode) return;
01938 
01939             // eww, I suck. set the qt focus correctly
01940             // ### find a better place in the code for this
01941             if (view()) {
01942                 if (!m_focusNode->renderer() || !m_focusNode->renderer()->isWidget())
01943                     view()->setFocus();
01944                 else if (static_cast<RenderWidget*>(m_focusNode->renderer())->widget())
01945                     static_cast<RenderWidget*>(m_focusNode->renderer())->widget()->setFocus();
01946             }
01947         }
01948 
01949         updateRendering();
01950     }
01951 }
01952 
01953 void DocumentImpl::attachNodeIterator(NodeIteratorImpl *ni)
01954 {
01955     m_nodeIterators.append(ni);
01956 }
01957 
01958 void DocumentImpl::detachNodeIterator(NodeIteratorImpl *ni)
01959 {
01960     m_nodeIterators.remove(ni);
01961 }
01962 
01963 void DocumentImpl::notifyBeforeNodeRemoval(NodeImpl *n)
01964 {
01965     QPtrListIterator<NodeIteratorImpl> it(m_nodeIterators);
01966     for (; it.current(); ++it)
01967         it.current()->notifyBeforeNodeRemoval(n);
01968 }
01969 
01970 bool DocumentImpl::isURLAllowed(const QString& url) const
01971 {
01972     KHTMLView *w = view();
01973 
01974     KURL newURL(completeURL(url));
01975     newURL.setRef(QString::null);
01976 
01977     // Prohibit non-file URLs if we are asked to.
01978     if (!w || w->part()->onlyLocalReferences() && newURL.protocol() != "file")
01979         return false;
01980 
01981     // do we allow this suburl ?
01982     if ( !kapp || !kapp->authorizeURLAction("redirect", w->part()->url(), newURL) )
01983         return false;
01984 
01985     // We allow one level of self-reference because some sites depend on that.
01986     // But we don't allow more than one.
01987     bool foundSelfReference = false;
01988     for (KHTMLPart *part = w->part(); part; part = part->parentPart()) {
01989         KURL partURL = part->url();
01990         partURL.setRef(QString::null);
01991         if (partURL == newURL) {
01992             if (foundSelfReference)
01993                 return false;
01994             foundSelfReference = true;
01995         }
01996     }
01997 
01998     return true;
01999 }
02000 
02001 AbstractViewImpl *DocumentImpl::defaultView() const
02002 {
02003     return m_defaultView;
02004 }
02005 
02006 EventImpl *DocumentImpl::createEvent(const DOMString &eventType, int &exceptioncode)
02007 {
02008     if (eventType == "UIEvents")
02009         return new UIEventImpl();
02010     else if (eventType == "MouseEvents")
02011         return new MouseEventImpl();
02012     else if (eventType == "MutationEvents")
02013         return new MutationEventImpl();
02014     else if (eventType == "HTMLEvents")
02015         return new EventImpl();
02016     else {
02017         exceptioncode = DOMException::NOT_SUPPORTED_ERR;
02018         return 0;
02019     }
02020 }
02021 
02022 CSSStyleDeclarationImpl *DocumentImpl::getOverrideStyle(ElementImpl */*elt*/, DOMStringImpl */*pseudoElt*/)
02023 {
02024     return 0; // ###
02025 }
02026 
02027 void DocumentImpl::defaultEventHandler(EventImpl *evt)
02028 {
02029     // if any html event listeners are registered on the window, then dispatch them here
02030     QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
02031     Event ev(evt);
02032     for (; it.current(); ++it) {
02033         if (it.current()->id == evt->id()) {
02034             evt->setCurrentTarget(this);
02035             it.current()->listener->handleEvent(ev);
02036         return;
02037     }
02038     }
02039 }
02040 
02041 void DocumentImpl::setWindowEventListener(int id, EventListener *listener)
02042 {
02043     // If we already have it we don't want removeWindowEventListener to delete it
02044     if (listener)
02045     listener->ref();
02046     removeWindowEventListener(id);
02047     if (listener) {
02048     RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,false);
02049     m_windowEventListeners.append(rl);
02050     listener->deref();
02051     }
02052 }
02053 
02054 EventListener *DocumentImpl::getWindowEventListener(int id)
02055 {
02056     QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
02057     for (; it.current(); ++it) {
02058     if (it.current()->id == id) {
02059         return it.current()->listener;
02060     }
02061     }
02062 
02063     return 0;
02064 }
02065 
02066 void DocumentImpl::removeWindowEventListener(int id)
02067 {
02068     QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
02069     for (; it.current(); ++it) {
02070     if (it.current()->id == id) {
02071         m_windowEventListeners.removeRef(it.current());
02072         return;
02073     }
02074     }
02075 }
02076 
02077 EventListener *DocumentImpl::createHTMLEventListener(QString code)
02078 {
02079     return view()->part()->createHTMLEventListener(code);
02080 }
02081 
02082 void DocumentImpl::setDecoderCodec(const QTextCodec *codec)
02083 {
02084     m_decoderMibEnum = codec->mibEnum();
02085 }
02086 
02087 // ----------------------------------------------------------------------------
02088 
02089 DocumentFragmentImpl::DocumentFragmentImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
02090 {
02091 }
02092 
02093 DocumentFragmentImpl::DocumentFragmentImpl(const DocumentFragmentImpl &other)
02094     : NodeBaseImpl(other)
02095 {
02096 }
02097 
02098 DOMString DocumentFragmentImpl::nodeName() const
02099 {
02100   return "#document-fragment";
02101 }
02102 
02103 unsigned short DocumentFragmentImpl::nodeType() const
02104 {
02105     return Node::DOCUMENT_FRAGMENT_NODE;
02106 }
02107 
02108 // DOM Section 1.1.1
02109 bool DocumentFragmentImpl::childTypeAllowed( unsigned short type )
02110 {
02111     switch (type) {
02112         case Node::ELEMENT_NODE:
02113         case Node::PROCESSING_INSTRUCTION_NODE:
02114         case Node::COMMENT_NODE:
02115         case Node::TEXT_NODE:
02116         case Node::CDATA_SECTION_NODE:
02117         case Node::ENTITY_REFERENCE_NODE:
02118             return true;
02119             break;
02120         default:
02121             return false;
02122     }
02123 }
02124 
02125 NodeImpl *DocumentFragmentImpl::cloneNode ( bool deep )
02126 {
02127     DocumentFragmentImpl *clone = new DocumentFragmentImpl( docPtr() );
02128     if (deep)
02129         cloneChildNodes(clone);
02130     return clone;
02131 }
02132 
02133 
02134 // ----------------------------------------------------------------------------
02135 
02136 DocumentTypeImpl::DocumentTypeImpl(DOMImplementationImpl *implementation, DocumentPtr *doc,
02137                                    const DOMString &qualifiedName, const DOMString &publicId,
02138                                    const DOMString &systemId)
02139     : NodeImpl(doc), m_implementation(implementation),
02140       m_qualifiedName(qualifiedName), m_publicId(publicId), m_systemId(systemId)
02141 {
02142     m_implementation->ref();
02143 
02144     m_entities = 0;
02145     m_notations = 0;
02146 
02147     // if doc is 0, it is not attached to a document and / or
02148     // therefore does not provide entities or notations. (DOM Level 3)
02149 }
02150 
02151 DocumentTypeImpl::~DocumentTypeImpl()
02152 {
02153     m_implementation->deref();
02154     if (m_entities)
02155         m_entities->deref();
02156     if (m_notations)
02157         m_notations->deref();
02158 }
02159 
02160 void DocumentTypeImpl::copyFrom(const DocumentTypeImpl& other)
02161 {
02162     m_qualifiedName = other.m_qualifiedName;
02163     m_publicId = other.m_publicId;
02164     m_systemId = other.m_systemId;
02165     m_subset = other.m_subset;
02166 }
02167 
02168 DOMString DocumentTypeImpl::nodeName() const
02169 {
02170     return name();
02171 }
02172 
02173 unsigned short DocumentTypeImpl::nodeType() const
02174 {
02175     return Node::DOCUMENT_TYPE_NODE;
02176 }
02177 
02178 // DOM Section 1.1.1
02179 bool DocumentTypeImpl::childTypeAllowed( unsigned short /*type*/ )
02180 {
02181     return false;
02182 }
02183 
02184 NodeImpl *DocumentTypeImpl::cloneNode ( bool /*deep*/ )
02185 {
02186     // Spec says cloning Document nodes is "implementation dependent"
02187     // so we do not support it...
02188     return 0;
02189 }
02190 
02191 #include "dom_docimpl.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:33 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001