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