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     removeChildren();
01056     QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
01057     for (; it.current();)
01058         m_windowEventListeners.removeRef(it.current());
01059 
01060     m_tokenizer = createTokenizer();
01061     m_decoderMibEnum = 0;
01062     connect(m_tokenizer,SIGNAL(finishedParsing()),this,SIGNAL(finishedParsing()));
01063     m_tokenizer->begin();
01064 
01065     if (m_view && m_view->part()->jScript())
01066         m_view->part()->jScript()->setSourceFile(m_url,"");
01067 }
01068 
01069 void DocumentImpl::close(  )
01070 {
01071     if (parsing() || !m_tokenizer) return;
01072 
01073     if ( m_render )
01074         m_render->close();
01075 
01076     delete m_tokenizer;
01077     m_tokenizer = 0;
01078 
01079     if (m_view)
01080         m_view->part()->checkEmitLoadEvent();
01081 }
01082 
01083 void DocumentImpl::write( const DOMString &text )
01084 {
01085     write(text.string());
01086 }
01087 
01088 void DocumentImpl::write( const QString &text )
01089 {
01090     if (!m_tokenizer) {
01091         open();
01092         write(QString::fromLatin1("<html><title></title><body>"));
01093     }
01094     m_tokenizer->write(text, false);
01095 
01096     if (m_view && m_view->part()->jScript())
01097         m_view->part()->jScript()->appendSourceFile(m_url,text);
01098 }
01099 
01100 void DocumentImpl::writeln( const DOMString &text )
01101 {
01102     write(text);
01103     write(DOMString("\n"));
01104 }
01105 
01106 void DocumentImpl::finishParsing (  )
01107 {
01108     if(m_tokenizer)
01109         m_tokenizer->finish();
01110 }
01111 
01112 void DocumentImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet)
01113 {
01114 //    kdDebug( 6030 ) << "HTMLDocument::setStyleSheet()" << endl;
01115     m_sheet = new CSSStyleSheetImpl(this, url);
01116     m_sheet->ref();
01117     m_sheet->parseString(sheet);
01118     m_loadingSheet = false;
01119 
01120     updateStyleSelector();
01121 }
01122 
01123 void DocumentImpl::setUserStyleSheet( const QString& sheet )
01124 {
01125     if ( m_usersheet != sheet ) {
01126         m_usersheet = sheet;
01127         updateStyleSelector();
01128     }
01129 }
01130 
01131 CSSStyleSheetImpl* DocumentImpl::elementSheet()
01132 {
01133     if (!m_elemSheet) {
01134         m_elemSheet = new CSSStyleSheetImpl(this, baseURL() );
01135         m_elemSheet->ref();
01136     }
01137     return m_elemSheet;
01138 }
01139 
01140 void DocumentImpl::determineParseMode( const QString &/*str*/ )
01141 {
01142     // For xML documents, use string parse mode
01143     pMode = Strict;
01144     kdDebug(6020) << " using strict parseMode" << endl;
01145 }
01146 
01147 // Please see if there`s a possibility to merge that code
01148 // with the next function and getElementByID().
01149 NodeImpl *DocumentImpl::findElement( Id id )
01150 {
01151     QPtrStack<NodeImpl> nodeStack;
01152     NodeImpl *current = _first;
01153 
01154     while(1)
01155     {
01156         if(!current)
01157         {
01158             if(nodeStack.isEmpty()) break;
01159             current = nodeStack.pop();
01160             current = current->nextSibling();
01161         }
01162         else
01163         {
01164             if(current->id() == id)
01165                 return current;
01166 
01167             NodeImpl *child = current->firstChild();
01168             if(child)
01169             {
01170                 nodeStack.push(current);
01171                 current = child;
01172             }
01173             else
01174             {
01175                 current = current->nextSibling();
01176             }
01177         }
01178     }
01179 
01180     return 0;
01181 }
01182 
01183 NodeImpl *DocumentImpl::nextFocusNode(NodeImpl *fromNode)
01184 {
01185     unsigned short fromTabIndex;
01186 
01187     if (!fromNode) {
01188     // No starting node supplied; begin with the top of the document
01189     NodeImpl *n;
01190 
01191     int lowestTabIndex = 65535;
01192     for (n = this; n != 0; n = n->traverseNextNode()) {
01193         if (n->isSelectable()) {
01194         if ((n->tabIndex() > 0) && (n->tabIndex() < lowestTabIndex))
01195             lowestTabIndex = n->tabIndex();
01196         }
01197     }
01198 
01199     if (lowestTabIndex == 65535)
01200         lowestTabIndex = 0;
01201 
01202     // Go to the first node in the document that has the desired tab index
01203     for (n = this; n != 0; n = n->traverseNextNode()) {
01204         if (n->isSelectable() && (n->tabIndex() == lowestTabIndex))
01205         return n;
01206     }
01207 
01208     return 0;
01209     }
01210     else {
01211     fromTabIndex = fromNode->tabIndex();
01212     }
01213 
01214     if (fromTabIndex == 0) {
01215     // Just need to find the next selectable node after fromNode (in document order) that doesn't have a tab index
01216     NodeImpl *n = fromNode->traverseNextNode();
01217     while (n && !(n->isSelectable() && n->tabIndex() == 0))
01218         n = n->traverseNextNode();
01219     return n;
01220     }
01221     else {
01222     // Find the lowest tab index out of all the nodes except fromNode, that is greater than or equal to fromNode's
01223     // tab index. For nodes with the same tab index as fromNode, we are only interested in those that come after
01224     // fromNode in document order.
01225     // If we don't find a suitable tab index, the next focus node will be one with a tab index of 0.
01226     unsigned short lowestSuitableTabIndex = 65535;
01227     NodeImpl *n;
01228 
01229     bool reachedFromNode = false;
01230     for (n = this; n != 0; n = n->traverseNextNode()) {
01231         if (n->isSelectable() &&
01232         ((reachedFromNode && (n->tabIndex() >= fromTabIndex)) ||
01233          (!reachedFromNode && (n->tabIndex() > fromTabIndex))) &&
01234         (n->tabIndex() < lowestSuitableTabIndex) &&
01235         (n != fromNode)) {
01236 
01237         // We found a selectable node with a tab index at least as high as fromNode's. Keep searching though,
01238         // as there may be another node which has a lower tab index but is still suitable for use.
01239         lowestSuitableTabIndex = n->tabIndex();
01240         }
01241 
01242         if (n == fromNode)
01243         reachedFromNode = true;
01244     }
01245 
01246     if (lowestSuitableTabIndex == 65535) {
01247         // No next node with a tab index -> just take first node with tab index of 0
01248         NodeImpl *n = this;
01249         while (n && !(n->isSelectable() && n->tabIndex() == 0))
01250         n = n->traverseNextNode();
01251         return n;
01252     }
01253 
01254     // Search forwards from fromNode
01255     for (n = fromNode->traverseNextNode(); n != 0; n = n->traverseNextNode()) {
01256         if (n->isSelectable() && (n->tabIndex() == lowestSuitableTabIndex))
01257         return n;
01258     }
01259 
01260     // The next node isn't after fromNode, start from the beginning of the document
01261     for (n = this; n != fromNode; n = n->traverseNextNode()) {
01262         if (n->isSelectable() && (n->tabIndex() == lowestSuitableTabIndex))
01263         return n;
01264     }
01265 
01266     assert(false); // should never get here
01267     return 0;
01268     }
01269 }
01270 
01271 NodeImpl *DocumentImpl::previousFocusNode(NodeImpl *fromNode)
01272 {
01273     NodeImpl *lastNode = this;
01274     while (lastNode->lastChild())
01275     lastNode = lastNode->lastChild();
01276 
01277     if (!fromNode) {
01278     // No starting node supplied; begin with the very last node in the document
01279     NodeImpl *n;
01280 
01281     int highestTabIndex = 0;
01282     for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
01283         if (n->isSelectable()) {
01284         if (n->tabIndex() == 0)
01285             return n;
01286         else if (n->tabIndex() > highestTabIndex)
01287             highestTabIndex = n->tabIndex();
01288         }
01289     }
01290 
01291     // No node with a tab index of 0; just go to the last node with the highest tab index
01292     for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
01293         if (n->isSelectable() && (n->tabIndex() == highestTabIndex))
01294         return n;
01295     }
01296 
01297     return 0;
01298     }
01299     else {
01300     unsigned short fromTabIndex = fromNode->tabIndex();
01301 
01302     if (fromTabIndex == 0) {
01303         // Find the previous selectable node before fromNode (in document order) that doesn't have a tab index
01304         NodeImpl *n = fromNode->traversePreviousNode();
01305         while (n && !(n->isSelectable() && n->tabIndex() == 0))
01306         n = n->traversePreviousNode();
01307         if (n)
01308         return n;
01309 
01310         // No previous nodes with a 0 tab index, go to the last node in the document that has the highest tab index
01311         int highestTabIndex = 0;
01312         for (n = this; n != 0; n = n->traverseNextNode()) {
01313         if (n->isSelectable() && (n->tabIndex() > highestTabIndex))
01314             highestTabIndex = n->tabIndex();
01315         }
01316 
01317         if (highestTabIndex == 0)
01318         return 0;
01319 
01320         for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
01321         if (n->isSelectable() && (n->tabIndex() == highestTabIndex))
01322             return n;
01323         }
01324 
01325         assert(false); // should never get here
01326         return 0;
01327     }
01328     else {
01329         // Find the lowest tab index out of all the nodes except fromNode, that is less than or equal to fromNode's
01330         // tab index. For nodes with the same tab index as fromNode, we are only interested in those before
01331         // fromNode.
01332         // If we don't find a suitable tab index, then there will be no previous focus node.
01333         unsigned short highestSuitableTabIndex = 0;
01334         NodeImpl *n;
01335 
01336         bool reachedFromNode = false;
01337         for (n = this; n != 0; n = n->traverseNextNode()) {
01338         if (n->isSelectable() &&
01339             ((!reachedFromNode && (n->tabIndex() <= fromTabIndex)) ||
01340              (reachedFromNode && (n->tabIndex() < fromTabIndex)))  &&
01341             (n->tabIndex() > highestSuitableTabIndex) &&
01342             (n != fromNode)) {
01343 
01344             // We found a selectable node with a tab index no higher than fromNode's. Keep searching though, as
01345             // there may be another node which has a higher tab index but is still suitable for use.
01346             highestSuitableTabIndex = n->tabIndex();
01347         }
01348 
01349         if (n == fromNode)
01350             reachedFromNode = true;
01351         }
01352 
01353         if (highestSuitableTabIndex == 0) {
01354         // No previous node with a tab index. Since the order specified by HTML is nodes with tab index > 0
01355         // first, this means that there is no previous node.
01356         return 0;
01357         }
01358 
01359         // Search backwards from fromNode
01360         for (n = fromNode->traversePreviousNode(); n != 0; n = n->traversePreviousNode()) {
01361         if (n->isSelectable() && (n->tabIndex() == highestSuitableTabIndex))
01362             return n;
01363         }
01364         // The previous node isn't before fromNode, start from the end of the document
01365         for (n = lastNode; n != fromNode; n = n->traversePreviousNode()) {
01366         if (n->isSelectable() && (n->tabIndex() == highestSuitableTabIndex))
01367             return n;
01368         }
01369 
01370         assert(false); // should never get here
01371         return 0;
01372     }
01373     }
01374 }
01375 
01376 int DocumentImpl::nodeAbsIndex(NodeImpl *node)
01377 {
01378     assert(node->getDocument() == this);
01379 
01380     int absIndex = 0;
01381     for (NodeImpl *n = node; n && n != this; n = n->traversePreviousNode())
01382     absIndex++;
01383     return absIndex;
01384 }
01385 
01386 NodeImpl *DocumentImpl::nodeWithAbsIndex(int absIndex)
01387 {
01388     NodeImpl *n = this;
01389     for (int i = 0; n && (i < absIndex); i++) {
01390     n = n->traverseNextNode();
01391     }
01392     return n;
01393 }
01394 
01395 void DocumentImpl::processHttpEquiv(const DOMString &equiv, const DOMString &content)
01396 {
01397     assert(!equiv.isNull() && !content.isNull());
01398 
01399     KHTMLView *v = getDocument()->view();
01400 
01401     if(strcasecmp(equiv, "refresh") == 0 && v->part()->metaRefreshEnabled())
01402     {
01403         // get delay and url
01404         QString str = content.string().stripWhiteSpace();
01405         int pos = str.find(QRegExp("[;,]"));
01406         if ( pos == -1 )
01407             pos = str.find(QRegExp("[ \t]"));
01408 
01409         if (pos == -1) // There can be no url (David)
01410         {
01411             bool ok = false;
01412             int delay = 0;
01413         delay = content.implementation()->toInt(&ok);
01414             if(ok) v->part()->scheduleRedirection(delay, v->part()->url().url() );
01415         } else {
01416             int delay = 0;
01417             int fract = pos;
01418             bool ok = false;
01419             if ( (fract = str.find('.') ) < 0 || fract > pos)
01420                 fract = pos;
01421         DOMStringImpl* s = content.implementation()->substring(0, fract);
01422         delay = s->toInt(&ok);
01423         delete s;
01424 
01425             pos++;
01426             while(pos < (int)str.length() && str[pos].isSpace()) pos++;
01427             str = str.mid(pos);
01428             if(str.find("url", 0,  false ) == 0)  str = str.mid(3);
01429             str = str.stripWhiteSpace();
01430             if ( str.length() && str[0] == '=' ) str = str.mid( 1 ).stripWhiteSpace();
01431             while(str.length() &&
01432                   (str[str.length()-1] == ';' || str[str.length()-1] == ','))
01433                 str.setLength(str.length()-1);
01434             str = parseURL( DOMString(str) ).string();
01435             if ( ok  || !fract)
01436                 v->part()->scheduleRedirection(delay, getDocument()->completeURL( str ));
01437         }
01438     }
01439     else if(strcasecmp(equiv, "expires") == 0)
01440     {
01441         bool relative = false;
01442         QString str = content.string().stripWhiteSpace();
01443         time_t expire_date = KRFCDate::parseDate(str);
01444         if (!expire_date)
01445         {
01446             expire_date = str.toULong();
01447             relative = true;
01448         }
01449         if (!expire_date)
01450             expire_date = 1; // expire now
01451         if (m_docLoader)
01452             m_docLoader->setExpireDate(expire_date, relative);
01453     }
01454     else if(strcasecmp(equiv, "pragma") == 0 || strcasecmp(equiv, "cache-control") == 0)
01455     {
01456         QString str = content.string().lower().stripWhiteSpace();
01457         KURL url = v->part()->url();
01458         if ((str == "no-cache") && url.protocol().startsWith("http"))
01459         {
01460            KIO::http_update_cache(url, true, 0);
01461         }
01462     }
01463     else if( (strcasecmp(equiv, "set-cookie") == 0))
01464     {
01465         // ### make setCookie work on XML documents too; e.g. in case of <html:meta .....>
01466         HTMLDocumentImpl *d = static_cast<HTMLDocumentImpl *>(this);
01467         d->setCookie(content);
01468     }
01469 }
01470 
01471 bool DocumentImpl::prepareMouseEvent( bool readonly, int _x, int _y, MouseEvent *ev )
01472 {
01473     if ( m_render ) {
01474         assert(m_render->isRoot());
01475         RenderObject::NodeInfo renderInfo(readonly, ev->type == MousePress);
01476         bool isInside = m_render->nodeAtPoint(renderInfo, _x, _y, 0, 0);
01477         ev->innerNode = renderInfo.innerNode();
01478 
01479         if (renderInfo.URLElement()) {
01480             assert(renderInfo.URLElement()->isElementNode());
01481             ElementImpl* e =  static_cast<ElementImpl*>(renderInfo.URLElement());
01482             DOMString href = khtml::parseURL(e->getAttribute(ATTR_HREF));
01483             DOMString target = e->getAttribute(ATTR_TARGET);
01484 
01485             if (!target.isNull() && !href.isNull()) {
01486                 ev->target = target;
01487                 ev->url = href;
01488             }
01489             else
01490                 ev->url = href;
01491 //            qDebug("url: *%s*", ev->url.string().latin1());
01492         }
01493 
01494         if (!readonly)
01495             updateRendering();
01496 
01497         return isInside;
01498     }
01499 
01500 
01501     return false;
01502 }
01503 
01504 // DOM Section 1.1.1
01505 bool DocumentImpl::childAllowed( NodeImpl *newChild )
01506 {
01507     // Documents may contain a maximum of one Element child
01508     if (newChild->nodeType() == Node::ELEMENT_NODE) {
01509         NodeImpl *c;
01510         for (c = firstChild(); c; c = c->nextSibling()) {
01511             if (c->nodeType() == Node::ELEMENT_NODE)
01512                 return false;
01513         }
01514     }
01515 
01516     // Documents may contain a maximum of one DocumentType child
01517     if (newChild->nodeType() == Node::DOCUMENT_TYPE_NODE) {
01518         NodeImpl *c;
01519         for (c = firstChild(); c; c = c->nextSibling()) {
01520             if (c->nodeType() == Node::DOCUMENT_TYPE_NODE)
01521                 return false;
01522         }
01523     }
01524 
01525     return childTypeAllowed(newChild->nodeType());
01526 }
01527 
01528 bool DocumentImpl::childTypeAllowed( unsigned short type )
01529 {
01530     switch (type) {
01531         case Node::ELEMENT_NODE:
01532         case Node::PROCESSING_INSTRUCTION_NODE:
01533         case Node::COMMENT_NODE:
01534         case Node::DOCUMENT_TYPE_NODE:
01535             return true;
01536             break;
01537         default:
01538             return false;
01539     }
01540 }
01541 
01542 NodeImpl *DocumentImpl::cloneNode ( bool /*deep*/ )
01543 {
01544     // Spec says cloning Document nodes is "implementation dependent"
01545     // so we do not support it...
01546     return 0;
01547 }
01548 
01549 NodeImpl::Id DocumentImpl::attrId(DOMStringImpl* _namespaceURI, DOMStringImpl *_name, bool readonly, int* pExceptioncode)
01550 {
01551     // Each document maintains a mapping of attrname -> id for every attr name
01552     // encountered in the document.
01553     // For attrnames without a prefix (no qualified element name) and without matching
01554     // namespace, the value defined in misc/htmlattrs.h is used.
01555     NodeImpl::Id id = 0;
01556 
01557     // First see if it's a HTML attribute name
01558     QConstString n(_name->s, _name->l);
01559     if (!_namespaceURI || !strcasecmp(_namespaceURI, XHTML_NAMESPACE)) {
01560         // we're in HTML namespace if we know the tag.
01561         // xhtml is lower case - case sensitive, easy to implement
01562         if ( htmlMode() == XHtml && (id = khtml::getAttrID(n.string().ascii(), _name->l)) )
01563             return id;
01564         // compatibility: upper case - case insensitive
01565         if ( htmlMode() != XHtml && (id = khtml::getAttrID(n.string().lower().ascii(), _name->l )) )
01566             return id;
01567 
01568         // ok, the fast path didn't work out, we need the full check
01569     }
01570 
01571     // now lets find out the namespace
01572     if (_namespaceURI) {
01573         DOMString nsU(_namespaceURI);
01574         bool found = false;
01575         // ### yeah, this is lame. use a dictionary / map instead
01576         for (unsigned short ns = 0; ns < m_namespaceURICount; ++ns)
01577             if (nsU == DOMString(m_namespaceURIs[ns])) {
01578                 id |= ns << 16;
01579                 found = true;
01580                 break;
01581             }
01582 
01583         if (!found && !readonly) {
01584             // something new, add it
01585             if (m_namespaceURICount >= m_namespaceURIAlloc) {
01586                 m_namespaceURIAlloc += 32;
01587                 DOMStringImpl **newURIs = new DOMStringImpl* [m_namespaceURIAlloc];
01588                 for (unsigned short i = 0; i < m_namespaceURICount; i++)
01589                     newURIs[i] = m_namespaceURIs[i];
01590                 delete [] m_namespaceURIs;
01591                 m_namespaceURIs = newURIs;
01592             }
01593             m_namespaceURIs[m_namespaceURICount++] = _namespaceURI;
01594             _namespaceURI->ref();
01595             id |= m_namespaceURICount << 16;
01596         }
01597     }
01598 
01599     // Look in the m_attrNames array for the name
01600     // ### yeah, this is lame. use a dictionary / map instead
01601     DOMString nme(n.string());
01602     // compatibility mode has to store upper case
01603     if (htmlMode() != XHtml) nme = nme.upper();
01604     for (id = 0; id < m_attrNameCount; id++)
01605         if (DOMString(m_attrNames[id]) == nme)
01606             return ATTR_LAST_ATTR+id;
01607 
01608     // unknown
01609     if (readonly) return 0;
01610 
01611     if (pExceptioncode && !Element::khtmlValidQualifiedName(_name)) {
01612         *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
01613         return 0;
01614     }
01615 
01616     // Name not found in m_attrNames, so let's add it
01617     // ### yeah, this is lame. use a dictionary / map instead
01618     if (m_attrNameCount+1 > m_attrNameAlloc) {
01619         m_attrNameAlloc += 100;
01620         DOMStringImpl **newNames = new DOMStringImpl* [m_attrNameAlloc];
01621         if (m_attrNames) {
01622             unsigned short i;
01623             for (i = 0; i < m_attrNameCount; i++)
01624                 newNames[i] = m_attrNames[i];
01625             delete [] m_attrNames;
01626         }
01627         m_attrNames = newNames;
01628     }
01629 
01630     id = m_attrNameCount++;
01631     m_attrNames[id] = nme.implementation();
01632     m_attrNames[id]->ref();
01633 
01634     return ATTR_LAST_ATTR+id;
01635 }
01636 
01637 DOMString DocumentImpl::attrName(NodeImpl::Id _id) const
01638 {
01639     if (_id >= ATTR_LAST_ATTR)
01640         return m_attrNames[_id-ATTR_LAST_ATTR];
01641     else {
01642         // ### put them in a cache
01643         if (getDocument()->htmlMode() == DocumentImpl::XHtml)
01644             return getAttrName(_id).lower();
01645         else
01646             return getAttrName(_id);
01647     }
01648 }
01649 
01650 NodeImpl::Id DocumentImpl::tagId(DOMStringImpl* _namespaceURI, DOMStringImpl *_name, bool readonly, int *pExceptioncode)
01651 {
01652     if (!_name || !_name->l) return 0;
01653     // Each document maintains a mapping of tag name -> id for every tag name encountered
01654     // in the document.
01655     NodeImpl::Id id = 0;
01656 
01657     // First see if it's a HTML element name
01658     QConstString n(_name->s, _name->l);
01659     if (!_namespaceURI || !strcasecmp(_namespaceURI, XHTML_NAMESPACE)) {
01660         // we're in HTML namespace if we know the tag.
01661         // xhtml is lower case - case sensitive, easy to implement
01662         if ( htmlMode() == XHtml && (id = khtml::getTagID(n.string().ascii(), _name->l)) )
01663             return id;
01664         // compatibility: upper case - case insensitive
01665         if ( htmlMode() != XHtml && (id = khtml::getTagID(n.string().lower().ascii(), _name->l )) )
01666             return id;
01667 
01668         // ok, the fast path didn't work out, we need the full check
01669     }
01670 
01671     // now lets find out the namespace
01672     if (_namespaceURI) {
01673         DOMString nsU(_namespaceURI);
01674         bool found = false;
01675         // ### yeah, this is lame. use a dictionary / map instead
01676         for (unsigned short ns = 0; ns < m_namespaceURICount; ++ns)
01677             if (nsU == DOMString(m_namespaceURIs[ns])) {
01678                 id |= ns << 16;
01679                 found = true;
01680                 break;
01681             }
01682 
01683         if (!found && !readonly) {
01684             // something new, add it
01685             if (m_namespaceURICount >= m_namespaceURIAlloc) {
01686                 m_namespaceURIAlloc += 32;
01687                 DOMStringImpl **newURIs = new DOMStringImpl* [m_namespaceURIAlloc];
01688                 for (unsigned short i = 0; i < m_namespaceURICount; i++)
01689                     newURIs[i] = m_namespaceURIs[i];
01690                 delete [] m_namespaceURIs;
01691                 m_namespaceURIs = newURIs;
01692             }
01693             m_namespaceURIs[m_namespaceURICount++] = _namespaceURI;
01694             _namespaceURI->ref();
01695             id |= m_namespaceURICount << 16;
01696         }
01697     }
01698 
01699     // Look in the m_elementNames array for the name
01700     //DOMString nme(n.string());
01701     DOMString nme( _name );
01702     // ### yeah, this is lame. use a dictionary / map instead
01703     // compatibility mode has to store upper case
01704     if (htmlMode() != XHtml) nme = nme.upper();
01705     for (id = 0; id < m_elementNameCount; id++)
01706         if (DOMString(m_elementNames[id]) == nme)
01707             return ID_LAST_TAG+id;
01708 
01709     // unknown
01710     if (readonly) return 0;
01711 
01712     if (pExceptioncode && !Element::khtmlValidQualifiedName(_name)) {
01713         *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
01714         return 0;
01715     }
01716 
01717     // Name not found in m_elementNames, so let's add it
01718     if (m_elementNameCount+1 > m_elementNameAlloc) {
01719         m_elementNameAlloc += 100;
01720         DOMStringImpl **newNames = new DOMStringImpl* [m_elementNameAlloc];
01721         // ### yeah, this is lame. use a dictionary / map instead
01722         if (m_elementNames) {
01723             unsigned short i;
01724             for (i = 0; i < m_elementNameCount; i++)
01725                 newNames[i] = m_elementNames[i];
01726             delete [] m_elementNames;
01727         }
01728         m_elementNames = newNames;
01729     }
01730 
01731     id = m_elementNameCount++;
01732     m_elementNames[id] = nme.implementation();
01733     m_elementNames[id]->ref();
01734 
01735     return ID_LAST_TAG+id;
01736 }
01737 
01738 DOMString DocumentImpl::tagName(NodeImpl::Id _id) const
01739 {
01740     if (_id >= ID_LAST_TAG)
01741         return m_elementNames[_id-ID_LAST_TAG];
01742     else {
01743         // ### put them in a cache
01744         if (getDocument()->htmlMode() == DocumentImpl::XHtml)
01745             return getTagName(_id).lower();
01746         else
01747             return getTagName(_id);
01748     }
01749 }
01750 
01751 
01752 DOMStringImpl* DocumentImpl::namespaceURI(NodeImpl::Id _id) const
01753 {
01754     if (_id < ID_LAST_TAG)
01755         return htmlMode() == XHtml ? m_namespaceURIs[0] : 0;
01756 
01757     unsigned short ns = _id >> 16;
01758 
01759     if (!ns) return 0;
01760 
01761     return m_namespaceURIs[ns-1];
01762 }
01763 
01764 StyleSheetListImpl* DocumentImpl::styleSheets()
01765 {
01766     return m_styleSheets;
01767 }
01768 
01769 void DocumentImpl::updateStyleSelector()
01770 {
01771     recalcStyleSelector();
01772     recalcStyle(Force);
01773 #if 0
01774 
01775     m_styleSelectorDirty = true;
01776 #endif
01777     if ( renderer() ) {
01778         renderer()->setLayouted( false );
01779         renderer()->setMinMaxKnown( false );
01780     }
01781 }
01782 
01783 
01784 QStringList DocumentImpl::availableStyleSheets() const
01785 {
01786     return m_availableSheets;
01787 }
01788 
01789 void DocumentImpl::recalcStyleSelector()
01790 {
01791     if ( !m_render || !attached() ) return;
01792 
01793     QPtrList<StyleSheetImpl> oldStyleSheets = m_styleSheets->styleSheets;
01794     m_styleSheets->styleSheets.clear();
01795     m_availableSheets.clear();
01796     NodeImpl *n;
01797     for (n = this; n; n = n->traverseNextNode()) {
01798         StyleSheetImpl *sheet = 0;
01799 
01800         if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
01801         {
01802             // Processing instruction (XML documents only)
01803             ProcessingInstructionImpl* pi = static_cast<ProcessingInstructionImpl*>(n);
01804             sheet = pi->sheet();
01805             if (!sheet && !pi->localHref().isEmpty())
01806             {
01807                 // Processing instruction with reference to an element in this document - e.g.
01808                 // <?xml-stylesheet href="#mystyle">, with the element
01809                 // <foo id="mystyle">heading { color: red; }</foo> at some location in
01810                 // the document
01811                 ElementImpl* elem = getElementById(pi->localHref());
01812                 if (elem) {
01813                     DOMString sheetText("");
01814                     NodeImpl *c;
01815                     for (c = elem->firstChild(); c; c = c->nextSibling()) {
01816                         if (c->nodeType() == Node::TEXT_NODE || c->nodeType() == Node::CDATA_SECTION_NODE)
01817                             sheetText += c->nodeValue();
01818                     }
01819 
01820                     CSSStyleSheetImpl *cssSheet = new CSSStyleSheetImpl(this);
01821                     cssSheet->parseString(sheetText);
01822                     pi->setStyleSheet(cssSheet);
01823                     sheet = cssSheet;
01824                 }
01825             }
01826 
01827         }
01828         else if (n->id() == ID_LINK || n->id() == ID_STYLE) {
01829             ElementImpl *e = static_cast<ElementImpl *>(n);
01830             QString title = e->getAttribute( ATTR_TITLE ).string();
01831             if (n->id() == ID_LINK) {
01832                 // <LINK> element
01833                 HTMLLinkElementImpl* l = static_cast<HTMLLinkElementImpl*>(n);
01834                 // awful hack to ensure that we ignore the title attribute for non-stylesheets
01835                 // ### make that nicer!
01836                 if (!(l->sheet() || l->isLoading()))
01837                     title = QString::null;
01838             }
01839             else {
01840                 HTMLStyleElementImpl* s = static_cast<HTMLStyleElementImpl*>(n);
01841                 // awful hack to ensure that we ignore the title attribute for non-stylesheets
01842                 // ### make that nicer!
01843                 if (!(s->sheet() || s->isLoading()))
01844                     title = QString::null;
01845             }
01846 
01847             QString sheetUsed = view()->part()->d->m_sheetUsed;
01848             if ( n->id() == ID_LINK )
01849                 sheet = static_cast<HTMLLinkElementImpl*>(n)->sheet();
01850             else
01851                 // <STYLE> element
01852                 sheet = static_cast<HTMLStyleElementImpl*>(n)->sheet();
01853 
01854             if ( !title.isEmpty() ) {
01855                 if ( sheetUsed.isEmpty() )
01856                     sheetUsed = view()->part()->d->m_sheetUsed = title;
01857                 if ( !m_availableSheets.contains( title ) )
01858                     m_availableSheets.append( title );
01859 
01860                 if ( title != sheetUsed )
01861                     sheet = 0; // this stylesheet wasn't selected
01862             }
01863     }
01864     else if (n->id() == ID_BODY) {
01865             // <BODY> element (doesn't contain styles as such but vlink="..." and friends
01866             // are treated as style declarations)
01867         sheet = static_cast<HTMLBodyElementImpl*>(n)->sheet();
01868         }
01869         if (sheet) {
01870             sheet->ref();
01871             m_styleSheets->styleSheets.append(sheet);
01872         }
01873 
01874         // For HTML documents, stylesheets are not allowed within/after the <BODY> tag. So we
01875         // can stop searching here.
01876         if (isHTMLDocument() && n->id() == ID_BODY)
01877             break;
01878     }
01879 
01880     // De-reference all the stylesheets in the old list
01881     QPtrListIterator<StyleSheetImpl> it(oldStyleSheets);
01882     for (; it.current(); ++it)
01883     it.current()->deref();
01884 
01885     // Create a new style selector
01886     delete m_styleSelector;
01887     QString usersheet = m_usersheet;
01888     if ( m_view && m_view->mediaType() == "print" )
01889     usersheet += m_printSheet;
01890     m_styleSelector = new CSSStyleSelector( this, usersheet, m_styleSheets, m_url,
01891                                             pMode == Strict );
01892 
01893     m_styleSelectorDirty = false;
01894 }
01895 
01896 void DocumentImpl::setFocusNode(NodeImpl *newFocusNode)
01897 {
01898     // don't process focus changes while detaching
01899     if( !m_render ) return;
01900     // Make sure newFocusNode is actually in this document
01901     if (newFocusNode && (newFocusNode->getDocument() != this))
01902         return;
01903 
01904     if (m_focusNode != newFocusNode) {
01905         NodeImpl *oldFocusNode = m_focusNode;
01906         // Set focus on the new node
01907         m_focusNode = newFocusNode;
01908         // Remove focus from the existing focus node (if any)
01909         if (oldFocusNode) {
01910             if (oldFocusNode->active())
01911                 oldFocusNode->setActive(false);
01912 
01913             oldFocusNode->setFocus(false);
01914         oldFocusNode->dispatchHTMLEvent(EventImpl::BLUR_EVENT,false,false);
01915         oldFocusNode->dispatchUIEvent(EventImpl::DOMFOCUSOUT_EVENT);
01916             if ((oldFocusNode == this) && oldFocusNode->hasOneRef()) {
01917                 oldFocusNode->deref(); // deletes this
01918                 return;
01919             }
01920         else {
01921                 oldFocusNode->deref();
01922             }
01923         }
01924 
01925         if (m_focusNode) {
01926             m_focusNode->ref();
01927             m_focusNode->dispatchHTMLEvent(EventImpl::FOCUS_EVENT,false,false);
01928             if (m_focusNode != newFocusNode) return;
01929             m_focusNode->dispatchUIEvent(EventImpl::DOMFOCUSIN_EVENT);
01930             if (m_focusNode != newFocusNode) return;
01931             m_focusNode->setFocus();
01932             if (m_focusNode != newFocusNode) return;
01933 
01934             // eww, I suck. set the qt focus correctly
01935             // ### find a better place in the code for this
01936             if (view()) {
01937                 if (!m_focusNode->renderer() || !m_focusNode->renderer()->isWidget())
01938                     view()->setFocus();
01939                 else if (static_cast<RenderWidget*>(m_focusNode->renderer())->widget())
01940                     static_cast<RenderWidget*>(m_focusNode->renderer())->widget()->setFocus();
01941             }
01942         }
01943 
01944         updateRendering();
01945     }
01946 }
01947 
01948 void DocumentImpl::attachNodeIterator(NodeIteratorImpl *ni)
01949 {
01950     m_nodeIterators.append(ni);
01951 }
01952 
01953 void DocumentImpl::detachNodeIterator(NodeIteratorImpl *ni)
01954 {
01955     m_nodeIterators.remove(ni);
01956 }
01957 
01958 void DocumentImpl::notifyBeforeNodeRemoval(NodeImpl *n)
01959 {
01960     QPtrListIterator<NodeIteratorImpl> it(m_nodeIterators);
01961     for (; it.current(); ++it)
01962         it.current()->notifyBeforeNodeRemoval(n);
01963 }
01964 
01965 bool DocumentImpl::isURLAllowed(const QString& url) const
01966 {
01967     KHTMLView *w = view();
01968 
01969     KURL newURL(completeURL(url));
01970     newURL.setRef(QString::null);
01971 
01972     // Prohibit non-file URLs if we are asked to.
01973     if (!w || w->part()->onlyLocalReferences() && newURL.protocol() != "file")
01974         return false;
01975 
01976     // do we allow this suburl ?
01977     if ( !kapp || !kapp->authorizeURLAction("redirect", w->part()->url(), newURL) )
01978         return false;
01979 
01980     // We allow one level of self-reference because some sites depend on that.
01981     // But we don't allow more than one.
01982     bool foundSelfReference = false;
01983     for (KHTMLPart *part = w->part(); part; part = part->parentPart()) {
01984         KURL partURL = part->url();
01985         partURL.setRef(QString::null);
01986         if (partURL == newURL) {
01987             if (foundSelfReference)
01988                 return false;
01989             foundSelfReference = true;
01990         }
01991     }
01992 
01993     return true;
01994 }
01995 
01996 AbstractViewImpl *DocumentImpl::defaultView() const
01997 {
01998     return m_defaultView;
01999 }
02000 
02001 EventImpl *DocumentImpl::createEvent(const DOMString &eventType, int &exceptioncode)
02002 {
02003     if (eventType == "UIEvents")
02004         return new UIEventImpl();
02005     else if (eventType == "MouseEvents")
02006         return new MouseEventImpl();
02007     else if (eventType == "MutationEvents")
02008         return new MutationEventImpl();
02009     else if (eventType == "HTMLEvents")
02010         return new EventImpl();
02011     else {
02012         exceptioncode = DOMException::NOT_SUPPORTED_ERR;
02013         return 0;
02014     }
02015 }
02016 
02017 CSSStyleDeclarationImpl *DocumentImpl::getOverrideStyle(ElementImpl */*elt*/, DOMStringImpl */*pseudoElt*/)
02018 {
02019     return 0; // ###
02020 }
02021 
02022 void DocumentImpl::defaultEventHandler(EventImpl *evt)
02023 {
02024     // if any html event listeners are registered on the window, then dispatch them here
02025     QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
02026     Event ev(evt);
02027     for (; it.current(); ++it) {
02028         if (it.current()->id == evt->id()) {
02029             evt->setCurrentTarget(this);
02030             it.current()->listener->handleEvent(ev);
02031         return;
02032     }
02033     }
02034 }
02035 
02036 void DocumentImpl::setWindowEventListener(int id, EventListener *listener)
02037 {
02038     // If we already have it we don't want removeWindowEventListener to delete it
02039     if (listener)
02040     listener->ref();
02041     removeWindowEventListener(id);
02042     if (listener) {
02043     RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,false);
02044     m_windowEventListeners.append(rl);
02045     listener->deref();
02046     }
02047 }
02048 
02049 EventListener *DocumentImpl::getWindowEventListener(int id)
02050 {
02051     QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
02052     for (; it.current(); ++it) {
02053     if (it.current()->id == id) {
02054         return it.current()->listener;
02055     }
02056     }
02057 
02058     return 0;
02059 }
02060 
02061 void DocumentImpl::removeWindowEventListener(int id)
02062 {
02063     QPtrListIterator<RegisteredEventListener> it(m_windowEventListeners);
02064     for (; it.current(); ++it) {
02065     if (it.current()->id == id) {
02066         m_windowEventListeners.removeRef(it.current());
02067         return;
02068     }
02069     }
02070 }
02071 
02072 EventListener *DocumentImpl::createHTMLEventListener(QString code)
02073 {
02074     return view()->part()->createHTMLEventListener(code);
02075 }
02076 
02077 void DocumentImpl::setDecoderCodec(const QTextCodec *codec)
02078 {
02079     m_decoderMibEnum = codec->mibEnum();
02080 }
02081 
02082 // ----------------------------------------------------------------------------
02083 
02084 DocumentFragmentImpl::DocumentFragmentImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
02085 {
02086 }
02087 
02088 DocumentFragmentImpl::DocumentFragmentImpl(const DocumentFragmentImpl &other)
02089     : NodeBaseImpl(other)
02090 {
02091 }
02092 
02093 DOMString DocumentFragmentImpl::nodeName() const
02094 {
02095   return "#document-fragment";
02096 }
02097 
02098 unsigned short DocumentFragmentImpl::nodeType() const
02099 {
02100     return Node::DOCUMENT_FRAGMENT_NODE;
02101 }
02102 
02103 // DOM Section 1.1.1
02104 bool DocumentFragmentImpl::childTypeAllowed( unsigned short type )
02105 {
02106     switch (type) {
02107         case Node::ELEMENT_NODE:
02108         case Node::PROCESSING_INSTRUCTION_NODE:
02109         case Node::COMMENT_NODE:
02110         case Node::TEXT_NODE:
02111         case Node::CDATA_SECTION_NODE:
02112         case Node::ENTITY_REFERENCE_NODE:
02113             return true;
02114             break;
02115         default:
02116             return false;
02117     }
02118 }
02119 
02120 NodeImpl *DocumentFragmentImpl::cloneNode ( bool deep )
02121 {
02122     DocumentFragmentImpl *clone = new DocumentFragmentImpl( docPtr() );
02123     if (deep)
02124         cloneChildNodes(clone);
02125     return clone;
02126 }
02127 
02128 
02129 // ----------------------------------------------------------------------------
02130 
02131 DocumentTypeImpl::DocumentTypeImpl(DOMImplementationImpl *implementation, DocumentPtr *doc,
02132                                    const DOMString &qualifiedName, const DOMString &publicId,
02133                                    const DOMString &systemId)
02134     : NodeImpl(doc), m_implementation(implementation),
02135       m_qualifiedName(qualifiedName), m_publicId(publicId), m_systemId(systemId)
02136 {
02137     m_implementation->ref();
02138 
02139     m_entities = 0;
02140     m_notations = 0;
02141 
02142     // if doc is 0, it is not attached to a document and / or
02143     // therefore does not provide entities or notations. (DOM Level 3)
02144 }
02145 
02146 DocumentTypeImpl::~DocumentTypeImpl()
02147 {
02148     m_implementation->deref();
02149     if (m_entities)
02150         m_entities->deref();
02151     if (m_notations)
02152         m_notations->deref();
02153 }
02154 
02155 void DocumentTypeImpl::copyFrom(const DocumentTypeImpl& other)
02156 {
02157     m_qualifiedName = other.m_qualifiedName;
02158     m_publicId = other.m_publicId;
02159     m_systemId = other.m_systemId;
02160     m_subset = other.m_subset;
02161 }
02162 
02163 DOMString DocumentTypeImpl::nodeName() const
02164 {
02165     return name();
02166 }
02167 
02168 unsigned short DocumentTypeImpl::nodeType() const
02169 {
02170     return Node::DOCUMENT_TYPE_NODE;
02171 }
02172 
02173 // DOM Section 1.1.1
02174 bool DocumentTypeImpl::childTypeAllowed( unsigned short /*type*/ )
02175 {
02176     return false;
02177 }
02178 
02179 NodeImpl *DocumentTypeImpl::cloneNode ( bool /*deep*/ )
02180 {
02181     // Spec says cloning Document nodes is "implementation dependent"
02182     // so we do not support it...
02183     return 0;
02184 }
02185 
02186 #include "dom_docimpl.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.3.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Thu Feb 10 20:54:30 2005 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001