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