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
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
00098 if (qualifiedName.isNull()) {
00099 exceptioncode = DOMException::NAMESPACE_ERR;
00100 return 0;
00101 }
00102
00103
00104 if (!Element::khtmlValidQualifiedName(qualifiedName)) {
00105 exceptioncode = DOMException::INVALID_CHARACTER_ERR;
00106 return 0;
00107 }
00108
00109
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& ) 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
00131
00132 if (dtype && (dtype->getDocument() || dtype->implementation() != this)) {
00133 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
00134 return 0;
00135 }
00136
00137
00138 DocumentImpl *doc = new DocumentImpl(this, 0);
00139
00140
00141
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 *, DOMStringImpl *media,
00159 int &)
00160 {
00161
00162
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
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
00221
00222 m_doctype = new DocumentTypeImpl(_implementation, document,
00223 DOMString() ,
00224 DOMString() ,
00225 DOMString() );
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 , name.implementation(),
00317 false , 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
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
00384 }
00385
00386 NodeImpl::Id nodeId = getDocument()->attrId(getDocument()->namespaceURI(id()), localName.implementation(), false , 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 )
00434 {
00435
00436 if (!Element::khtmlValidQualifiedName(_qualifiedName)) {
00437 *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
00438 return 0;
00439 }
00440
00441
00442
00443
00444
00445
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
00460
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
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
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
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
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
00598
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
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
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
00681 case ID_BASEFONT:
00682 n = new HTMLBaseFontElementImpl(docPtr());
00683 break;
00684 case ID_FONT:
00685 n = new HTMLFontElementImpl(docPtr());
00686 break;
00687
00688
00689 case ID_DEL:
00690 case ID_INS:
00691 n = new HTMLGenericElementImpl(docPtr(), id);
00692 break;
00693
00694
00695 case ID_A:
00696 n = new HTMLAnchorElementImpl(docPtr());
00697 break;
00698
00699
00700 case ID_IMG:
00701 n = new HTMLImageElementImpl(docPtr());
00702 break;
00703 case ID_MAP:
00704 n = new HTMLMapElementImpl(docPtr());
00705
00706 break;
00707 case ID_AREA:
00708 n = new HTMLAreaElementImpl(docPtr());
00709 break;
00710
00711
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
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
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
00758
00759
00760 case ID_ADDRESS:
00761 case ID_CENTER:
00762 n = new HTMLGenericElementImpl(docPtr(), id);
00763 break;
00764
00765
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
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
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
00800 case ID_TEXT:
00801 kdDebug( 6020 ) << "Use document->createTextNode()" << endl;
00802 break;
00803
00804 default:
00805 if ( id )
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 , unsigned long , NodeFilter &,
00850 bool )
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
00871
00872
00873 if (m_inStyleRecalc)
00874 return;
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
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
00903 _style->setFontDef(fontDef);
00904 _style->htmlFont().update( paintDeviceMetrics() );
00905 if ( parseMode() != Strict )
00906 _style->setHtmlHacks(true);
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
00925
00926
00927
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
00946
00947
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
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
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
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
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 & )
01141 {
01142
01143 pMode = Strict;
01144 kdDebug(6020) << " using strict parseMode" << endl;
01145 }
01146
01147
01148
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
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
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
01216 NodeImpl *n = fromNode->traverseNextNode();
01217 while (n && !(n->isSelectable() && n->tabIndex() == 0))
01218 n = n->traverseNextNode();
01219 return n;
01220 }
01221 else {
01222
01223
01224
01225
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
01238
01239 lowestSuitableTabIndex = n->tabIndex();
01240 }
01241
01242 if (n == fromNode)
01243 reachedFromNode = true;
01244 }
01245
01246 if (lowestSuitableTabIndex == 65535) {
01247
01248 NodeImpl *n = this;
01249 while (n && !(n->isSelectable() && n->tabIndex() == 0))
01250 n = n->traverseNextNode();
01251 return n;
01252 }
01253
01254
01255 for (n = fromNode->traverseNextNode(); n != 0; n = n->traverseNextNode()) {
01256 if (n->isSelectable() && (n->tabIndex() == lowestSuitableTabIndex))
01257 return n;
01258 }
01259
01260
01261 for (n = this; n != fromNode; n = n->traverseNextNode()) {
01262 if (n->isSelectable() && (n->tabIndex() == lowestSuitableTabIndex))
01263 return n;
01264 }
01265
01266 assert(false);
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
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
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
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
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);
01326 return 0;
01327 }
01328 else {
01329
01330
01331
01332
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
01345
01346 highestSuitableTabIndex = n->tabIndex();
01347 }
01348
01349 if (n == fromNode)
01350 reachedFromNode = true;
01351 }
01352
01353 if (highestSuitableTabIndex == 0) {
01354
01355
01356 return 0;
01357 }
01358
01359
01360 for (n = fromNode->traversePreviousNode(); n != 0; n = n->traversePreviousNode()) {
01361 if (n->isSelectable() && (n->tabIndex() == highestSuitableTabIndex))
01362 return n;
01363 }
01364
01365 for (n = lastNode; n != fromNode; n = n->traversePreviousNode()) {
01366 if (n->isSelectable() && (n->tabIndex() == highestSuitableTabIndex))
01367 return n;
01368 }
01369
01370 assert(false);
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
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)
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;
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
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
01492 }
01493
01494 if (!readonly)
01495 updateRendering();
01496
01497 return isInside;
01498 }
01499
01500
01501 return false;
01502 }
01503
01504
01505 bool DocumentImpl::childAllowed( NodeImpl *newChild )
01506 {
01507
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
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 )
01543 {
01544
01545
01546 return 0;
01547 }
01548
01549 NodeImpl::Id DocumentImpl::attrId(DOMStringImpl* _namespaceURI, DOMStringImpl *_name, bool readonly, int* pExceptioncode)
01550 {
01551
01552
01553
01554
01555 NodeImpl::Id id = 0;
01556
01557
01558 QConstString n(_name->s, _name->l);
01559 if (!_namespaceURI || !strcasecmp(_namespaceURI, XHTML_NAMESPACE)) {
01560
01561
01562 if ( htmlMode() == XHtml && (id = khtml::getAttrID(n.string().ascii(), _name->l)) )
01563 return id;
01564
01565 if ( htmlMode() != XHtml && (id = khtml::getAttrID(n.string().lower().ascii(), _name->l )) )
01566 return id;
01567
01568
01569 }
01570
01571
01572 if (_namespaceURI) {
01573 DOMString nsU(_namespaceURI);
01574 bool found = false;
01575
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
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
01600
01601 DOMString nme(n.string());
01602
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
01609 if (readonly) return 0;
01610
01611 if (pExceptioncode && !Element::khtmlValidQualifiedName(_name)) {
01612 *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
01613 return 0;
01614 }
01615
01616
01617
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
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
01654
01655 NodeImpl::Id id = 0;
01656
01657
01658 QConstString n(_name->s, _name->l);
01659 if (!_namespaceURI || !strcasecmp(_namespaceURI, XHTML_NAMESPACE)) {
01660
01661
01662 if ( htmlMode() == XHtml && (id = khtml::getTagID(n.string().ascii(), _name->l)) )
01663 return id;
01664
01665 if ( htmlMode() != XHtml && (id = khtml::getTagID(n.string().lower().ascii(), _name->l )) )
01666 return id;
01667
01668
01669 }
01670
01671
01672 if (_namespaceURI) {
01673 DOMString nsU(_namespaceURI);
01674 bool found = false;
01675
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
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
01700
01701 DOMString nme( _name );
01702
01703
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
01710 if (readonly) return 0;
01711
01712 if (pExceptioncode && !Element::khtmlValidQualifiedName(_name)) {
01713 *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
01714 return 0;
01715 }
01716
01717
01718 if (m_elementNameCount+1 > m_elementNameAlloc) {
01719 m_elementNameAlloc += 100;
01720 DOMStringImpl **newNames = new DOMStringImpl* [m_elementNameAlloc];
01721
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
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
01803 ProcessingInstructionImpl* pi = static_cast<ProcessingInstructionImpl*>(n);
01804 sheet = pi->sheet();
01805 if (!sheet && !pi->localHref().isEmpty())
01806 {
01807
01808
01809
01810
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
01833 HTMLLinkElementImpl* l = static_cast<HTMLLinkElementImpl*>(n);
01834
01835
01836 if (!(l->sheet() || l->isLoading()))
01837 title = QString::null;
01838 }
01839 else {
01840 HTMLStyleElementImpl* s = static_cast<HTMLStyleElementImpl*>(n);
01841
01842
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
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;
01862 }
01863 }
01864 else if (n->id() == ID_BODY) {
01865
01866
01867 sheet = static_cast<HTMLBodyElementImpl*>(n)->sheet();
01868 }
01869 if (sheet) {
01870 sheet->ref();
01871 m_styleSheets->styleSheets.append(sheet);
01872 }
01873
01874
01875
01876 if (isHTMLDocument() && n->id() == ID_BODY)
01877 break;
01878 }
01879
01880
01881 QPtrListIterator<StyleSheetImpl> it(oldStyleSheets);
01882 for (; it.current(); ++it)
01883 it.current()->deref();
01884
01885
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
01899 if( !m_render ) return;
01900
01901 if (newFocusNode && (newFocusNode->getDocument() != this))
01902 return;
01903
01904 if (m_focusNode != newFocusNode) {
01905 NodeImpl *oldFocusNode = m_focusNode;
01906
01907 m_focusNode = newFocusNode;
01908
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();
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
01935
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
01973 if (!w || w->part()->onlyLocalReferences() && newURL.protocol() != "file")
01974 return false;
01975
01976
01977 if ( !kapp || !kapp->authorizeURLAction("redirect", w->part()->url(), newURL) )
01978 return false;
01979
01980
01981
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 *, DOMStringImpl *)
02018 {
02019 return 0;
02020 }
02021
02022 void DocumentImpl::defaultEventHandler(EventImpl *evt)
02023 {
02024
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
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
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
02143
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
02174 bool DocumentTypeImpl::childTypeAllowed( unsigned short )
02175 {
02176 return false;
02177 }
02178
02179 NodeImpl *DocumentTypeImpl::cloneNode ( bool )
02180 {
02181
02182
02183 return 0;
02184 }
02185
02186 #include "dom_docimpl.moc"