bool Node::hasAttributes() { if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); if (!impl->isElementNode()) return false; ElementImpl* e = static_cast<ElementImpl*>(impl); return e->attributes(true) && e->attributes(true)->length(); }
bool XMLHandler::startElement( const QString& namespaceURI, const QString& /*localName*/, const QString& qName, const QXmlAttributes& atts ) { if (m_currentNode->nodeType() == Node::TEXT_NODE) exitText(); ElementImpl *newElement; if (namespaceURI.isNull()) newElement = m_doc->createElement(qName); else newElement = m_doc->createElementNS(namespaceURI,qName); // ### handle exceptions int i; for (i = 0; i < atts.length(); i++) newElement->setAttribute(atts.localName(i),atts.value(i)); if (m_currentNode->addChild(newElement)) { if (m_view) newElement->attach(m_view); m_currentNode = newElement; return TRUE; } else { delete newElement; return FALSE; } }
void HTMLTableElementImpl::close() { ElementImpl* firstBody = tFirstBody(); if (firstBody && !firstBody->closed()) firstBody->close(); HTMLElementImpl::close(); }
ElementImpl *HTMLDocumentImpl::createElement(const DOMString &name, int *pExceptioncode) { ElementImpl *e = createHTMLElement(name); if(e) { e->setHTMLCompat(htmlMode() != XHtml); return e; } return DocumentImpl::createElement(name, pExceptioncode); }
QString NodeImpl::recursive_toHTML( ) const { QString me; // Copy who I am into the htmlText string if ( nodeType() == Node::TEXT_NODE ) me = nodeValue().string(); else { // If I am an element, not a text me = QChar('<') + nodeName().string(); // print attributes if( nodeType() == Node::ELEMENT_NODE ) { ElementImpl *el = const_cast<ElementImpl*>(static_cast<const ElementImpl *>(this)); AttrImpl *attr; int exceptioncode; NamedNodeMapImpl *attrs = el->attributes(); unsigned long lmap = attrs->length(exceptioncode); for( unsigned int j=0; j<lmap; j++ ) { attr = static_cast<AttrImpl*>(attrs->item(j,exceptioncode)); me += " " + attr->name().string() + "=\"" + attr->value().string() + "\""; } } // print ending bracket of start tag if( firstChild() == 0 ) // if element has no endtag me += " />"; else // if element has endtag me += ">"; } NodeImpl* n; if( (n = firstChild()) ) { // print firstChild me += n->recursive_toHTML( ); // Print my ending tag if ( nodeType() != Node::TEXT_NODE ) me += "</" + nodeName().string() + ">"; } // print next sibling if( (n = nextSibling()) ) me += n->recursive_toHTML( ); return me; }
NodeImpl *ElementImpl::cloneNode(bool deep) { // ### we lose the namespace here ... FIXME int exceptioncode; ElementImpl *clone = getDocument()->createElement(tagName(), exceptioncode); if (!clone) return 0; // clone attributes if (namedAttrMap) *clone->attributes() = *namedAttrMap; if (deep) cloneChildNodes(clone); return clone; }
void NodeImpl::printTree(int indent) { QString ind; QString s; ind.fill(' ', indent); // ### find out why this isn't working if(isElementNode()) { s = ind + "<" + nodeName().string(); ElementImpl *el = const_cast<ElementImpl*>(static_cast<const ElementImpl *>(this)); AttrImpl *attr; int exceptioncode; NamedNodeMapImpl *attrs = el->attributes(); unsigned long lmap = attrs->length(exceptioncode); for( unsigned int j=0; j<lmap; j++ ) { attr = static_cast<AttrImpl*>(attrs->item(j,exceptioncode)); s += " " + attr->name().string() + "=\"" + attr->value().string() + "\""; } if(!firstChild()) s += " />"; else s += ">"; } else s = ind + "'" + nodeValue().string() + "'"; kdDebug() << s << endl; NodeImpl *child = firstChild(); while( child ) { child->printTree(indent+2); child = child->nextSibling(); } if(isElementNode() && firstChild()) kdDebug() << ind << "</" << nodeName().string() << ">" << endl; }
bool XMLHandler::startElement(const QString &namespaceURI, const QString & /*localName*/, const QString &qName, const QXmlAttributes &atts) { if(currentNode()->nodeType() == Node::TEXT_NODE) exitText(); DOMString nsURI; if(!namespaceURI.isNull()) nsURI = DOMString(namespaceURI); else // No namespace declared, default to the no namespace nsURI = DOMString(""); ElementImpl *newElement = m_doc->createElementNS(nsURI, qName); if(!newElement) return false; int i; for(i = 0; i < atts.length(); i++) { int exceptioncode = 0; QString uriString = atts.uri(i); QString qnString = atts.qName(i); fixUpNSURI(uriString, qnString); DOMString uri(uriString); DOMString qn(qnString); DOMString val(atts.value(i)); newElement->setAttributeNS(uri, qn, val, exceptioncode); if(exceptioncode) // exception setting attributes return false; } if(newElement->id() == ID_SCRIPT || newElement->id() == makeId(xhtmlNamespace, ID_SCRIPT)) static_cast< HTMLScriptElementImpl * >(newElement)->setCreatedByParser(true); // this is tricky. in general the node doesn't have to attach to the one it's in. as far // as standards go this is wrong, but there's literally thousands of documents where // we see <p><ul>...</ul></p>. the following code is there for those cases. // when we can't attach to the currently holding us node we try to attach to its parent bool attached = false; for(NodeImpl *current = currentNode(); current; current = current->parent()) { attached = current->addChild(newElement); if(attached) break; } if(attached) { if(m_view && !newElement->attached() && !m_doc->hasPendingSheets()) newElement->attach(); pushNode(newElement); return true; } else { delete newElement; return false; } // ### DOM spec states: "if there is no markup inside an element's content, the text is contained in a // single object implementing the Text interface that is the only child of the element."... do we // need to ensure that empty elements always have an empty text child? }
CSSStyleDeclarationImpl *Editor::selectionComputedStyle(NodeImpl *&nodeToRemove) const { nodeToRemove = 0; if (!m_part->xmlDocImpl()) { return 0; } EditorContext *ctx = m_part->editorContext(); if (ctx->m_selection.state() == Selection::NONE) { return 0; } Range range(ctx->m_selection.toRange()); Position pos(range.startContainer().handle(), range.startOffset()); assert(pos.notEmpty()); ElementImpl *elem = pos.element(); ElementImpl *styleElement = elem; int exceptionCode = 0; if (m_typingStyle) { styleElement = m_part->xmlDocImpl()->createHTMLElement("SPAN"); // assert(exceptionCode == 0); styleElement->setAttribute(ATTR_STYLE, m_typingStyle->cssText().implementation()); // assert(exceptionCode == 0); TextImpl *text = m_part->xmlDocImpl()->createEditingTextNode(""); styleElement->appendChild(text, exceptionCode); assert(exceptionCode == 0); elem->appendChild(styleElement, exceptionCode); assert(exceptionCode == 0); nodeToRemove = styleElement; } return new RenderStyleDeclarationImpl(styleElement); }
bool KHTMLParser::insertNode(NodeImpl *n, bool flat) { int id = n->id(); // let's be stupid and just try to insert it. // this should work if the document is wellformed #ifdef PARSER_DEBUG NodeImpl *tmp = current; #endif NodeImpl *newNode = current->addChild(n); if ( newNode ) { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "added " << n->nodeName().string() << " to " << tmp->nodeName().string() << ", new current=" << newNode->nodeName().string() << endl; #endif // don't push elements without end tag on the stack if(tagPriority[id] != 0 && !flat) { pushBlock(id, tagPriority[id]); if (newNode == current) popBlock(id); else setCurrent(newNode); #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif } else { #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); if (n->maintainsState()) { document->document()->registerMaintainsState(n); QStringList &states = document->document()->restoreState(); if (!states.isEmpty()) n->restoreState(states); } n->closeRenderer(); #endif } return true; } else { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "ADDING NODE FAILED!!!! current = " << current->nodeName().string() << ", new = " << n->nodeName().string() << endl; #endif // error handling... HTMLElementImpl *e; bool handled = false; // switch according to the element to insert switch(id) { case ID_TR: case ID_TH: case ID_TD: if (inStrayTableContent && !isTableRelatedTag(current->id())) { // pop out to the nearest enclosing table-related tag. while (!isTableRelatedTag(current->id())) popOneBlock(); return insertNode(n); } break; case ID_COMMENT: break; case ID_HEAD: // ### alllow not having <HTML> in at all, as per HTML spec if (!current->isDocumentNode() && current->id() != ID_HTML ) return false; break; // We can deal with a base, meta and link element in the body, by just adding the element to head. case ID_META: case ID_LINK: case ID_BASE: if( !head ) createHead(); if( head ) { if ( head->addChild(n) ) { #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif return true; } else { return false; } } break; case ID_HTML: if (!current->isDocumentNode() ) { if ( doc()->firstChild()->id() == ID_HTML) { // we have another <HTML> element.... apply attributes to existing one // make sure we don't overwrite already existing attributes NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true); NamedAttrMapImpl *bmap = static_cast<ElementImpl*>(doc()->firstChild())->attributes(false); bool changed = false; for (unsigned long l = 0; map && l < map->length(); ++l) { AttributeImpl* it = map->attributeItem(l); changed = !bmap->getAttributeItem(it->id()); bmap->insertAttribute(it->clone(false)); } if ( changed ) doc()->recalcStyle( NodeImpl::Inherit ); } return false; } break; case ID_TITLE: case ID_STYLE: if ( !head ) createHead(); if ( head ) { DOM::NodeImpl *newNode = head->addChild(n); if ( newNode ) { pushBlock(id, tagPriority[id]); setCurrent(newNode); #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif } else { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "adding style before to body failed!!!!" << endl; #endif discard_until = ID_STYLE + ID_CLOSE_TAG; return false; } return true; } else if(inBody) { discard_until = ID_STYLE + ID_CLOSE_TAG; return false; } break; // SCRIPT and OBJECT are allowed in the body. case ID_BODY: if(inBody && doc()->body()) { // we have another <BODY> element.... apply attributes to existing one // make sure we don't overwrite already existing attributes // some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor> NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true); NamedAttrMapImpl *bmap = doc()->body()->attributes(false); bool changed = false; for (unsigned long l = 0; map && l < map->length(); ++l) { AttributeImpl* it = map->attributeItem(l); changed = !bmap->getAttributeItem(it->id()); bmap->insertAttribute(it->clone(false)); } if ( changed ) doc()->recalcStyle( NodeImpl::Inherit ); } else if ( current->isDocumentNode() ) break; return false; break; // the following is a hack to move non rendered elements // outside of tables. // needed for broken constructs like <table><form ...><tr>.... case ID_INPUT: { ElementImpl *e = static_cast<ElementImpl *>(n); DOMString type = e->getAttribute(ATTR_TYPE); if ( strcasecmp( type, "hidden" ) == 0 && form) { form->addChild(n); #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif return true; } break; } case ID_TEXT: // ignore text inside the following elements. switch(current->id()) { case ID_SELECT: return false; default: ; // fall through!! }; break; case ID_DD: case ID_DT: e = new HTMLDListElementImpl(document); if ( insertNode(e) ) { insertNode(n); return true; } break; case ID_AREA: { if(map) { map->addChild(n); #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif handled = true; } else return false; return true; } default: break; } // switch on the currently active element switch(current->id()) { case ID_HTML: switch(id) { case ID_SCRIPT: case ID_STYLE: case ID_META: case ID_LINK: case ID_OBJECT: case ID_EMBED: case ID_TITLE: case ID_ISINDEX: case ID_BASE: if(!head) { head = new HTMLHeadElementImpl(document); e = head; insertNode(e); handled = true; } break; case ID_TEXT: { TextImpl *t = static_cast<TextImpl *>(n); if (t->containsOnlyWhitespace()) return false; /* Fall through to default */ } default: if ( haveFrameSet ) break; e = new HTMLBodyElementImpl(document); startBody(); insertNode(e); handled = true; break; } break; case ID_HEAD: // we can get here only if the element is not allowed in head. if (id == ID_HTML) return false; else { // This means the body starts here... if ( haveFrameSet ) break; popBlock(ID_HEAD); e = new HTMLBodyElementImpl(document); startBody(); insertNode(e); handled = true; } break; case ID_BODY: break; case ID_CAPTION: // Illegal content in a caption. Close the caption and try again. popBlock(ID_CAPTION); switch( id ) { case ID_THEAD: case ID_TFOOT: case ID_TBODY: case ID_TR: case ID_TD: case ID_TH: return insertNode(n, flat); } break; case ID_TABLE: case ID_THEAD: case ID_TFOOT: case ID_TBODY: case ID_TR: switch(id) { case ID_TABLE: popBlock(ID_TABLE); // end the table handled = true; // ...and start a new one break; case ID_TEXT: { TextImpl *t = static_cast<TextImpl *>(n); if (t->containsOnlyWhitespace()) return false; DOMStringImpl *i = t->string(); unsigned int pos = 0; while(pos < i->l && ( *(i->s+pos) == QChar(' ') || *(i->s+pos) == QChar(0xa0))) pos++; if(pos == i->l) break; } default: { NodeImpl *node = current; NodeImpl *parent = node->parentNode(); NodeImpl *parentparent = parent->parentNode(); if (n->isTextNode() || ( node->id() == ID_TR && ( parent->id() == ID_THEAD || parent->id() == ID_TBODY || parent->id() == ID_TFOOT ) && parentparent->id() == ID_TABLE ) || ( !checkChild( ID_TR, id ) && ( node->id() == ID_THEAD || node->id() == ID_TBODY || node->id() == ID_TFOOT ) && parent->id() == ID_TABLE )) { node = (node->id() == ID_TABLE) ? node : ((node->id() == ID_TR) ? parentparent : parent); NodeImpl *parent = node->parentNode(); int exceptioncode = 0; parent->insertBefore( n, node, exceptioncode ); if ( exceptioncode ) { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "adding content before table failed!" << endl; #endif break; } if (n->isElementNode() && tagPriority[id] != 0 && !flat && endTag[id] != DOM::FORBIDDEN) { pushBlock(id, tagPriority[id]); setCurrent(n); inStrayTableContent++; blockStack->strayTableContent = true; } return true; } if ( current->id() == ID_TR ) e = new HTMLTableCellElementImpl(document, ID_TD); else if ( current->id() == ID_TABLE ) e = new HTMLTableSectionElementImpl( document, ID_TBODY, true /* implicit */ ); else e = new HTMLTableRowElementImpl( document ); insertNode(e); handled = true; break; } // end default } // end switch break; case ID_OBJECT: discard_until = id + ID_CLOSE_TAG; return false; case ID_UL: case ID_OL: case ID_DIR: case ID_MENU: e = new HTMLDivElementImpl(document); insertNode(e); handled = true; break; case ID_DL: popBlock(ID_DL); handled = true; break; case ID_DT: popBlock(ID_DT); handled = true; break; case ID_SELECT: if( n->isInline() ) return false; break; case ID_P: case ID_H1: case ID_H2: case ID_H3: case ID_H4: case ID_H5: case ID_H6: if(!n->isInline()) { popBlock(current->id()); handled = true; } break; case ID_OPTION: case ID_OPTGROUP: if (id == ID_OPTGROUP) { popBlock(current->id()); handled = true; } else if(id == ID_SELECT) { // IE treats a nested select as </select>. Let's do the same popBlock( ID_SELECT ); break; } break; // head elements in the body should be ignored. case ID_ADDRESS: popBlock(ID_ADDRESS); handled = true; break; case ID_COLGROUP: if (id != ID_TEXT) { popBlock(ID_COLGROUP); handled = true; } break; case ID_FONT: popBlock(ID_FONT); handled = true; break; default: if(current->isDocumentNode()) { if(current->firstChild() == 0) { e = new HTMLHtmlElementImpl(document); insertNode(e); handled = true; } } else if(current->isInline()) { popInlineBlocks(); handled = true; } } // if we couldn't handle the error, just rethrow the exception... if(!handled) { //kdDebug( 6035 ) << "Exception handler failed in HTMLPArser::insertNode()" << endl; return false; } return insertNode(n); } }
void KHTMLParser::parseToken(Token *t) { if (t->id > 2*ID_CLOSE_TAG) { kdDebug( 6035 ) << "Unknown tag!! tagID = " << t->id << endl; return; } if(discard_until) { if(t->id == discard_until) discard_until = 0; // do not skip </iframe> if ( discard_until || current->id() + ID_CLOSE_TAG != t->id ) return; } #ifdef PARSER_DEBUG kdDebug( 6035 ) << "\n\n==> parser: processing token " << getTagName(t->id).string() << "(" << t->id << ")" << " current = " << getTagName(current->id()).string() << "(" << current->id() << ")" << endl; kdDebug(6035) << " inBody=" << inBody << " haveFrameSet=" << haveFrameSet << endl; #endif // holy shit. apparently some sites use </br> instead of <br> // be compatible with IE and NS if(t->id == ID_BR+ID_CLOSE_TAG && document->document()->inCompatMode()) t->id -= ID_CLOSE_TAG; if(t->id > ID_CLOSE_TAG) { processCloseTag(t); return; } // ignore spaces, if we're not inside a paragraph or other inline code if( t->id == ID_TEXT && t->text ) { if(inBody && !skipMode() && current->id() != ID_STYLE && current->id() != ID_TITLE && current->id() != ID_SCRIPT && !t->text->containsOnlyWhitespace()) haveContent = true; #ifdef PARSER_DEBUG kdDebug(6035) << "length="<< t->text->l << " text='" << QConstString(t->text->s, t->text->l).string() << "'" << endl; #endif } NodeImpl *n = getElement(t); // just to be sure, and to catch currently unimplemented stuff if(!n) return; // set attributes if(n->isElementNode()) { ElementImpl *e = static_cast<ElementImpl *>(n); e->setAttributeMap(t->attrs); // take care of optional close tags if(endTag[e->id()] == DOM::OPTIONAL) popBlock(t->id); } // if this tag is forbidden inside the current context, pop // blocks until we are allowed to add it... while(forbiddenTag[t->id]) { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "t->id: " << t->id << " is forbidden :-( " << endl; #endif popOneBlock(); } if (!insertNode(n, t->flat)) { // we couldn't insert the node... if(n->isElementNode()) { ElementImpl *e = static_cast<ElementImpl *>(n); e->setAttributeMap(0); } #ifdef PARSER_DEBUG kdDebug( 6035 ) << "insertNode failed current=" << current->id() << ", new=" << n->id() << "!" << endl; #endif if (map == n) { #ifdef PARSER_DEBUG kdDebug( 6035 ) << " --> resetting map!" << endl; #endif map = 0; } if (form == n) { #ifdef PARSER_DEBUG kdDebug( 6035 ) << " --> resetting form!" << endl; #endif form = 0; } delete n; } }
bool KHTMLParser::insertNode(NodeImpl *n, bool flat) { int id = n->id(); // let's be stupid and just try to insert it. // this should work if the document is wellformed #ifdef PARSER_DEBUG NodeImpl *tmp = current; #endif NodeImpl *newNode = current->addChild(n); if ( newNode ) { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "added " << n->nodeName().string() << " to " << tmp->nodeName().string() << ", new current=" << newNode->nodeName().string() << endl; #endif // have to do this here (and not when creating the node, as we don't know before where we add the LI element to. if ( id == ID_LI && n->isElementNode() ) { int cid = current->id(); if ( cid != ID_UL && cid != ID_OL ) static_cast<HTMLElementImpl*>(n)->addCSSProperty(CSS_PROP_LIST_STYLE_POSITION, CSS_VAL_INSIDE); } // don't push elements without end tag on the stack if(tagPriority[id] != 0 && !flat) { #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget ) n->attach(); #endif if(n->isInline()) m_inline = true; pushBlock(id, tagPriority[id]); current = newNode; } else { #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); if (n->maintainsState()) { document->document()->registerMaintainsState(n); QString state(document->document()->nextState()); if (!state.isNull()) n->restoreState(state); } if(n->renderer()) n->renderer()->close(); #endif if(n->isInline()) m_inline = true; } #if SPEED_DEBUG < 1 if(tagPriority[id] == 0 && n->renderer()) n->renderer()->calcMinMaxWidth(); #endif return true; } else { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "ADDING NODE FAILED!!!! current = " << current->nodeName().string() << ", new = " << n->nodeName().string() << endl; #endif // error handling... HTMLElementImpl *e; bool handled = false; // never create anonymous objects just to hold a space. if ( id == ID_TEXT && static_cast<TextImpl *>(n)->string()->l == 1 && static_cast<TextImpl *>(n)->string()->s[0] == " " ) return false; // switch according to the element to insert switch(id) { case ID_COMMENT: break; case ID_HEAD: // ### alllow not having <HTML> in at all, as per HTML spec if (!current->isDocumentNode() && current->id() != ID_HTML ) return false; break; case ID_META: case ID_LINK: case ID_ISINDEX: case ID_BASE: if( !head ) createHead(); if( head ) { if ( head->addChild(n) ) { #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif } return true; } break; case ID_HTML: if (!current->isDocumentNode() ) { if ( doc()->firstChild()->id() == ID_HTML) { // we have another <HTML> element.... apply attributes to existing one // make sure we don't overwrite already existing attributes NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true); NamedAttrMapImpl *bmap = static_cast<ElementImpl*>(doc()->firstChild())->attributes(false); bool changed = false; for (unsigned long l = 0; map && l < map->length(); ++l) { AttributeImpl* it = map->attributeItem(l); changed = !bmap->getAttributeItem(it->id()); bmap->insertAttribute(new AttributeImpl(it->id(), it->val())); } if ( changed ) doc()->recalcStyle( NodeImpl::Inherit ); } return false; } break; case ID_TITLE: case ID_STYLE: if ( !head ) createHead(); if ( head ) { DOM::NodeImpl *newNode = head->addChild(n); if ( newNode ) { pushBlock(id, tagPriority[id]); current = newNode; #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif } else { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "adding style before to body failed!!!!" << endl; #endif discard_until = ID_STYLE + ID_CLOSE_TAG; return false; } return true; } else if(inBody) { discard_until = id + ID_CLOSE_TAG; return false; } break; case ID_SCRIPT: // if we failed to insert it, go into skip mode discard_until = id + ID_CLOSE_TAG; break; case ID_BODY: if(inBody && doc()->body()) { // we have another <BODY> element.... apply attributes to existing one // make sure we don't overwrite already existing attributes // some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor> NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true); NamedAttrMapImpl *bmap = doc()->body()->attributes(false); bool changed = false; for (unsigned long l = 0; map && l < map->length(); ++l) { AttributeImpl* it = map->attributeItem(l); changed = !bmap->getAttributeItem(it->id()); bmap->insertAttribute(new AttributeImpl(it->id(), it->val())); } if ( changed ) doc()->recalcStyle( NodeImpl::Inherit ); } else if ( current->isDocumentNode() ) break; return false; break; // the following is a hack to move non rendered elements // outside of tables. // needed for broken constructs like <table><form ...><tr>.... case ID_INPUT: { ElementImpl *e = static_cast<ElementImpl *>(n); DOMString type = e->getAttribute(ATTR_TYPE); if ( strcasecmp( type, "hidden" ) != 0 ) break; // Fall through! } case ID_TEXT: // ignore text inside the following elements. switch(current->id()) { case ID_SELECT: return false; default: ; // fall through!! }; break; case ID_DD: case ID_DT: e = new HTMLDListElementImpl(document); if ( insertNode(e) ) { insertNode(n); return true; } break; case ID_AREA: { if(map) { map->addChild(n); #if SPEED_DEBUG < 2 if(!n->attached() && HTMLWidget) n->attach(); #endif handled = true; } else return false; return true; } case ID_TD: case ID_TH: // lets try to close the konqblock if ( haveKonqBlock ) { popBlock( ID__KONQBLOCK ); haveKonqBlock = false; return insertNode( n ); } default: break; } // switch on the currently active element switch(current->id()) { case ID_HTML: switch(id) { case ID_SCRIPT: case ID_STYLE: case ID_META: case ID_LINK: case ID_OBJECT: case ID_EMBED: case ID_TITLE: case ID_ISINDEX: case ID_BASE: if(!head) { head = new HTMLHeadElementImpl(document); e = head; insertNode(e); handled = true; } break; default: if ( haveFrameSet ) break; e = new HTMLBodyElementImpl(document); startBody(); insertNode(e); handled = true; break; } break; case ID_HEAD: // we can get here only if the element is not allowed in head. if (id == ID_HTML) return false; else { // This means the body starts here... if ( haveFrameSet ) break; popBlock(ID_HEAD); e = new HTMLBodyElementImpl(document); startBody(); insertNode(e); handled = true; } break; case ID_BODY: break; case ID__KONQBLOCK: switch( id ) { case ID_THEAD: case ID_TFOOT: case ID_TBODY: case ID_TR: case ID_TD: case ID_TH: // now the actual table contents starts // lets close our anonymous block before the table // and go ahead! popBlock( ID__KONQBLOCK ); haveKonqBlock = false; handled = checkChild( current->id(), id ); break; default: break; } break; case ID_TABLE: case ID_THEAD: case ID_TFOOT: case ID_TBODY: case ID_TR: switch(id) { case ID_TABLE: popBlock(ID_TABLE); // end the table handled = checkChild( current->id(), id); break; case ID_TEXT: { TextImpl *t = static_cast<TextImpl *>(n); DOMStringImpl *i = t->string(); unsigned int pos = 0; while(pos < i->l && ( *(i->s+pos) == QChar(' ') || *(i->s+pos) == QChar(0xa0))) pos++; if(pos == i->l) break; } default: { NodeImpl *node = current; NodeImpl *parent = node->parentNode(); NodeImpl *parentparent = parent->parentNode(); if(( node->id() == ID_TR && ( parent->id() == ID_THEAD || parent->id() == ID_TBODY || parent->id() == ID_TFOOT ) && parentparent->id() == ID_TABLE ) || ( !checkChild( ID_TR, id ) && ( node->id() == ID_THEAD || node->id() == ID_TBODY || node->id() == ID_TFOOT ) && parent->id() == ID_TABLE ) ) { node = ( node->id() == ID_TR ) ? parentparent : parent; NodeImpl *parent = node->parentNode(); int exceptioncode = 0; NodeImpl *container = new HTMLGenericElementImpl( document, ID__KONQBLOCK ); parent->insertBefore( container, node, exceptioncode ); if ( exceptioncode ) { #ifdef PARSER_DEBUG kdDebug( 6035 ) << "adding anonymous container before table failed!" << endl; #endif break; } if ( !container->attached() && HTMLWidget ) container->attach(); pushBlock( ID__KONQBLOCK, tagPriority[ID__KONQBLOCK] ); haveKonqBlock = true; current = container; handled = true; break; } if ( current->id() == ID_TR ) e = new HTMLTableCellElementImpl(document, ID_TD); else if ( current->id() == ID_TABLE ) e = new HTMLTableSectionElementImpl( document, ID_TBODY, true /* implicit */ ); else e = new HTMLTableRowElementImpl( document ); insertNode(e); handled = true; break; } // end default } // end switch break; case ID_OBJECT: discard_until = id + ID_CLOSE_TAG; return false; case ID_UL: case ID_OL: case ID_DIR: case ID_MENU: e = new HTMLLIElementImpl(document); e->addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_NONE); insertNode(e); handled = true; break; case ID_SELECT: if( n->isInline() ) return false; break; case ID_P: case ID_H1: case ID_H2: case ID_H3: case ID_H4: case ID_H5: case ID_H6: if(!n->isInline()) { popBlock(current->id()); handled = true; } break; case ID_OPTION: if (id == ID_OPTGROUP) { popBlock(ID_OPTION); handled = true; } else if(id == ID_SELECT) { // IE treats a nested select as </select>. Let's do the same popBlock( ID_SELECT ); break; } break; // head elements in the body should be ignored. case ID_DL: case ID_DT: case ID_ADDRESS: case ID_COLGROUP: case ID_FONT: case ID_CAPTION: popBlock(current->id()); handled = true; break; default: if(current->isDocumentNode()) { if(current->firstChild() == 0) { e = new HTMLHtmlElementImpl(document); insertNode(e); handled = true; } } else if(current->isInline()) { popInlineBlocks(); handled = true; } } // if we couldn't handle the error, just rethrow the exception... if(!handled) { //kdDebug( 6035 ) << "Exception handler failed in HTMLPArser::insertNode()" << endl; return false; } return insertNode(n); } }