DOMString ElementImpl::openTagStartToString() const { DOMString result = DOMString("<") + tagName(); NamedAttrMapImpl *attrMap = attributes(true); if (attrMap) { unsigned long numAttrs = attrMap->length(); for (unsigned long i = 0; i < numAttrs; i++) { result += " "; AttributeImpl *attribute = attrMap->attributeItem(i); AttrImpl *attr = attribute->attrImpl(); if (attr) { result += attr->toString(); } else { result += getDocument()->attrName(attribute->id()); if (!attribute->value().isNull()) { result += "=\""; // FIXME: substitute entities for any instances of " or ' result += attribute->value(); result += "\""; } } } } return result; }
void ElementImpl::setAttributeMap( NamedAttrMapImpl* list ) { if (inDocument()) getDocument()->incDOMTreeVersion(); // If setting the whole map changes the id attribute, we need to // call updateId. AttributeImpl *oldId = namedAttrMap ? namedAttrMap->getAttributeItem(ATTR_ID) : 0; AttributeImpl *newId = list ? list->getAttributeItem(ATTR_ID) : 0; if (oldId || newId) { updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); } if(namedAttrMap) namedAttrMap->deref(); namedAttrMap = list; if(namedAttrMap) { namedAttrMap->ref(); namedAttrMap->element = this; unsigned int len = namedAttrMap->length(); for(unsigned int i = 0; i < len; i++) attributeChanged(namedAttrMap->attrs[i]); } }
NamedAttrMapImpl& NamedAttrMapImpl::operator=(const NamedAttrMapImpl& other) { // clone all attributes in the other map, but attach to our element if (!element) return *this; // If assigning the map changes the id attribute, we need to call // updateId. AttributeImpl *oldId = getAttributeItem(ATTR_ID); AttributeImpl *newId = other.getAttributeItem(ATTR_ID); if (oldId || newId) { element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); } clearAttributes(); len = other.len; attrs = new AttributeImpl* [len]; // first initialize attrs vector, then call attributeChanged on it // this allows attributeChanged to use getAttribute for (uint i = 0; i < len; i++) { attrs[i] = other.attrs[i]->clone(); attrs[i]->ref(); } // FIXME: This is wasteful. The class list could be preserved on a copy, and we // wouldn't have to waste time reparsing the attribute. // The derived class, HTMLNamedAttrMapImpl, which manages a parsed class list for the CLASS attribute, // will update its member variable when parse attribute is called. for(uint i = 0; i < len; i++) element->attributeChanged(attrs[i], true); return *this; }
void ElementImpl::setAttribute(NodeImpl::Id id, DOMStringImpl* value, int &exceptioncode ) { if (inDocument()) getDocument()->incDOMTreeVersion(); // allocate attributemap if necessary AttributeImpl* old = attributes(false)->getAttributeItem(id); // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly if (namedAttrMap->isReadOnly()) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return; } if (id == ATTR_ID) { updateId(old ? old->value() : nullAtom, value); } if (old && !value) namedAttrMap->removeAttribute(id); else if (!old && value) namedAttrMap->addAttribute(createAttribute(id, value)); else if (old && value) { old->setValue(value); attributeChanged(old); } }
NodeImpl *KHTMLParser::handleIsindex( Token *t ) { NodeImpl *n; HTMLFormElementImpl *myform = form; if ( !myform ) { myform = new HTMLFormElementImpl(document); n = myform; } else n = new HTMLDivElementImpl( document ); NodeImpl *child = new HTMLHRElementImpl( document ); n->addChild( child ); AttributeImpl* a = t->attrs ? t->attrs->getAttributeItem(ATTR_PROMPT) : 0; #if APPLE_CHANGES && !KWIQ DOMString text = searchableIndexIntroduction(); #elif KWIQ // FIXME: KWIQ: Internationalization. Hardcoded string. DOMString text = "This is a searchable index. Enter search keywords: "; #else DOMString text = i18n("This is a searchable index. Enter search keywords: "); #endif if (a) text = DOMString(a->value()) + " "; child = new TextImpl(document, text); n->addChild( child ); child = new HTMLIsIndexElementImpl(document, myform); static_cast<ElementImpl *>(child)->setAttribute(ATTR_TYPE, "khtml_isindex"); n->addChild( child ); child = new HTMLHRElementImpl( document ); n->addChild( child ); return n; }
NodeImpl *KHTMLParser::handleIsindex( Token *t ) { NodeImpl *n; HTMLFormElementImpl *myform = form; if ( !myform ) { myform = new HTMLFormElementImpl(document, true); n = myform; } else n = new HTMLDivElementImpl( document, ID_DIV ); NodeImpl *child = new HTMLHRElementImpl( document ); n->addChild( child ); AttributeImpl* a = t->attrs ? t->attrs->getAttributeItem(ATTR_PROMPT) : 0; DOMString text = i18n("This is a searchable index. Enter search keywords: "); if (a) text = a->value(); child = new TextImpl(document, text.implementation()); n->addChild( child ); child = new HTMLIsIndexElementImpl(document, myform); static_cast<ElementImpl *>(child)->setAttribute(ATTR_TYPE, "khtml_isindex"); n->addChild( child ); child = new HTMLHRElementImpl( document ); n->addChild( child ); return n; }
// The DOM2 spec doesn't say that removeAttribute[NS] throws NOT_FOUND_ERR // if the attribute is not found, but at this level we have to throw NOT_FOUND_ERR // because of removeNamedItem, removeNamedItemNS, and removeAttributeNode. Node NamedAttrMapImpl::removeNamedItem ( NodeImpl::Id id, int &exceptioncode ) { // ### should this really be raised when the attribute to remove isn't there at all? // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly if (isReadOnly()) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return Node(); } AttributeImpl* a = getAttributeItem(id); if (!a) { exceptioncode = DOMException::NOT_FOUND_ERR; return Node(); } if (!a->attrImpl()) a->allocateImpl(element); Node r(a->attrImpl()); if (id == ATTR_ID) { element->updateId(a->value(), nullAtom); } removeAttribute(id); return r; }
AttrImpl *NamedAttrMapImpl::getNamedItem ( NodeImpl::Id id ) const { AttributeImpl* a = getAttributeItem(id); if (!a) return 0; if (!a->attrImpl()) a->allocateImpl(element); return a->attrImpl(); }
const AtomicString& ElementImpl::getAttribute(NodeImpl::Id id) const { if (id == ATTR_STYLE) updateStyleAttributeIfNeeded(); if (namedAttrMap) { AttributeImpl* a = namedAttrMap->getAttributeItem(id); if (a) return a->value(); } return nullAtom; }
void ElementImpl::dump(QTextStream *stream, QString ind) const { updateStyleAttributeIfNeeded(); if (namedAttrMap) { for (uint i = 0; i < namedAttrMap->length(); i++) { AttributeImpl *attr = namedAttrMap->attributeItem(i); *stream << " " << DOMString(getDocument()->attrName(attr->id())).string().ascii() << "=\"" << DOMString(attr->value()).string().ascii() << "\""; } } NodeBaseImpl::dump(stream,ind); }
void ElementImpl::removedFromDocument() { if (hasID()) { NamedAttrMapImpl *attrs = attributes(true); if (attrs) { AttributeImpl *idAttr = attrs->getAttributeItem(ATTR_ID); if (idAttr && !idAttr->isNull()) { updateId(idAttr->value(), nullAtom); } } } NodeBaseImpl::removedFromDocument(); }
void ObjectResolver::Resolve() { for (auto it = objectRefs.Begin(); it != objectRefs.End(); ++it) { auto refIt = objects.Find(it->oldId); // See if we can find the referred to object if (refIt != objects.End()) { AttributeImpl<ObjectRef>* typedAttr = static_cast<AttributeImpl<ObjectRef>*>(it->attr); typedAttr->SetValue(it->object, ObjectRef(refIt->second->Id())); } else LOGWARNING("Could not resolve object reference " + String(it->oldId)); } }
Node NamedAttrMapImpl::setNamedItem ( NodeImpl* arg, int &exceptioncode ) { if (!element) { exceptioncode = DOMException::NOT_FOUND_ERR; return 0; } // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. if (isReadOnly()) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return 0; } // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map. if (arg->getDocument() != element->getDocument()) { exceptioncode = DOMException::WRONG_DOCUMENT_ERR; return 0; } // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node if (!arg->isAttributeNode()) { exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return 0; } AttrImpl *attr = static_cast<AttrImpl*>(arg); AttributeImpl* a = attr->attrImpl(); AttributeImpl* old = getAttributeItem(a->id()); if (old == a) return arg; // we know about it already // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object. // The DOM user must explicitly clone Attr nodes to re-use them in other elements. if (attr->ownerElement()) { exceptioncode = DOMException::INUSE_ATTRIBUTE_ERR; return 0; } if (a->id() == ATTR_ID) { element->updateId(old ? old->value() : nullAtom, a->value()); } // ### slightly inefficient - resizes attribute array twice. Node r; if (old) { if (!old->attrImpl()) old->allocateImpl(element); r = old->_impl; removeAttribute(a->id()); } addAttribute(a); return r; }
void ElementImpl::insertedIntoDocument() { // need to do superclass processing first so inDocument() is true // by the time we reach updateId NodeBaseImpl::insertedIntoDocument(); if (hasID()) { NamedAttrMapImpl *attrs = attributes(true); if (attrs) { AttributeImpl *idAttr = attrs->getAttributeItem(ATTR_ID); if (idAttr && !idAttr->isNull()) { updateId(nullAtom, idAttr->value()); } } } }
DOMString ElementImpl::openTagStartToString(bool expandurls) const { DOMString result = DOMString("<") + tagName(); NamedAttrMapImpl *attrMap = attributes(true); if(attrMap) { unsigned long numAttrs = attrMap->length(); for(unsigned long i = 0; i < numAttrs; i++) { result += " "; AttributeImpl *attribute = attrMap->attrAt(i); AttrImpl *attr = attribute->attr(); if(attr) { result += attr->toString(); } else { result += getDocument()->getName(NodeImpl::AttributeId, attribute->id()); if(!attribute->value().isNull()) { result += "=\""; // FIXME: substitute entities for any instances of " or ' // Expand out all urls, i.e. the src and href attributes if(expandurls && (attribute->id() == ATTR_SRC || attribute->id() == ATTR_HREF)) if(getDocument()) { // We need to sanitize the urls - strip out the passwords. // FIXME: are src= and href= the only places that might have a password and need to be sanitized? KURL safeURL(getDocument()->completeURL(attribute->value().string())); safeURL.setPass(QString::null); result += safeURL.htmlURL(); } else { kdWarning() << "getDocument() returned false"; result += attribute->value(); } else result += attribute->value(); result += "\""; } } } } return result; }
bool HTMLNamedAttrMapImpl::mapsEquivalent(const HTMLNamedAttrMapImpl* otherMap) const { // The # of decls must match. if (declCount() != otherMap->declCount()) return false; // The values for each decl must match. for (uint i = 0; i < length(); i++) { HTMLAttributeImpl* attr = attributeItem(i); if (attr->decl()) { AttributeImpl* otherAttr = otherMap->getAttributeItem(attr->id()); if (!otherAttr || (attr->value() != otherAttr->value())) return false; } } return true; }
void NamedAttrMapImpl::removeAttribute(NodeImpl::Id id) { unsigned long index = len+1; for (unsigned long i = 0; i < len; ++i) if (attrs[i]->id() == id) { index = i; break; } if (index >= len) return; // Remove the attribute from the list AttributeImpl* attr = attrs[index]; if (attrs[index]->_impl) attrs[index]->_impl->m_element = 0; if (len == 1) { delete [] attrs; attrs = 0; len = 0; } else { AttributeImpl **newAttrs = new AttributeImpl* [len-1]; uint i; for (i = 0; i < uint(index); i++) newAttrs[i] = attrs[i]; len--; for (; i < len; i++) newAttrs[i] = attrs[i+1]; delete [] attrs; attrs = newAttrs; } // Notify the element that the attribute has been removed // dispatch appropriate mutation events if (element && !attr->_value.isNull()) { AtomicString value = attr->_value; attr->_value = nullAtom; element->attributeChanged(attr); attr->_value = value; } if (element) { element->dispatchAttrRemovalEvent(attr); element->dispatchSubtreeModifiedEvent(false); } attr->deref(); }
AttributeImpl* AttributeImpl::clone(bool) const { AttributeImpl* result = new AttributeImpl(m_id, _value); result->setPrefix(_prefix); return result; }
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); } }
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); } }
void RenderPartObject::updateWidget() { QString url; QString serviceType; QStringList params; KHTMLPart *part = m_view->part(); setNeedsLayoutAndMinMaxRecalc(); if (element()->id() == ID_OBJECT) { HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element()); // Check for a child EMBED tag. HTMLEmbedElementImpl *embed = 0; for (NodeImpl *child = o->firstChild(); child; child = child->nextSibling()) { if (child->id() == ID_EMBED) { embed = static_cast<HTMLEmbedElementImpl *>( child ); break; } } // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT. HTMLElementImpl *embedOrObject; if (embed) { embedOrObject = (HTMLElementImpl *)embed; DOMString attribute = embedOrObject->getAttribute(ATTR_WIDTH); if (!attribute.isEmpty()) { o->setAttribute(ATTR_WIDTH, attribute); } attribute = embedOrObject->getAttribute(ATTR_HEIGHT); if (!attribute.isEmpty()) { o->setAttribute(ATTR_HEIGHT, attribute); } url = embed->url; serviceType = embed->serviceType; } else { embedOrObject = (HTMLElementImpl *)o; } // If there was no URL or type defined in EMBED, try the OBJECT tag. if (url.isEmpty()) { url = o->url; } if (serviceType.isEmpty()) { serviceType = o->serviceType; } // Then try the PARAM tags for the URL and type attributes. NodeImpl *child = o->firstChild(); while (child && (url.isEmpty() || serviceType.isEmpty())) { if (child->id() == ID_PARAM) { HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child ); QString name = p->name().lower(); if (url.isEmpty() && (QString::equals(name,"src") || QString::equals(name,"movie") || QString::equals(name,"code"))) { url = p->value(); } if (serviceType.isEmpty() && QString::equals(name,"type")) { serviceType = p->value(); } } child = child->nextSibling(); } // Lastly try to map a specific CLASSID to a type. if (serviceType.isEmpty() && !o->classId.isEmpty()) { if (o->classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000")) { // It is ActiveX, but the nsplugin system handling // should also work, that's why we don't override the // serviceType with application/x-activex-handler // but let the KTrader in khtmlpart::createPart() detect // the user's preference: launch with activex viewer or // with nspluginviewer (Niko) serviceType = "application/x-shockwave-flash"; } else if(o->classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) { serviceType = "audio/x-pn-realaudio-plugin"; } else if(o->classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) { serviceType = "video/quicktime"; } else if(o->classId.contains("166B1BCA-3F9C-11CF-8075-444553540000")) { serviceType = "application/x-director"; } else { // We have a clsid, means this is activex (Niko) serviceType = "application/x-activex-handler"; } // TODO: add more plugins here } // If no URL and type, abort. if (url.isEmpty() && serviceType.isEmpty()) { #ifdef DEBUG_LAYOUT kdDebug() << "RenderPartObject::close - empty url and serverType" << endl; #endif return; } // Turn the attributes of either the EMBED tag or OBJECT tag into an array. NamedAttrMapImpl* attributes = embedOrObject->attributes(); if (attributes) { for (unsigned long i = 0; i < attributes->length(); ++i) { AttributeImpl* it = attributes->attributeItem(i); params.append(o->getDocument()->attrName(it->id()).string() + "=\"" + it->value().string() + "\""); } } params.append( QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( o->classId ) ); params.append( QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( o->getAttribute(ATTR_CODEBASE).string() ) ); part->requestObject( this, url, serviceType, params ); } else if ( element()->id() == ID_EMBED ) { HTMLEmbedElementImpl *o = static_cast<HTMLEmbedElementImpl *>(element()); url = o->url; serviceType = o->serviceType; if ( url.isEmpty() && serviceType.isEmpty() ) { #ifdef DEBUG_LAYOUT kdDebug() << "RenderPartObject::close - empty url and serverType" << endl; #endif return; } // add all attributes set on the embed object NamedAttrMapImpl* a = o->attributes(); if (a) { for (unsigned long i = 0; i < a->length(); ++i) { AttributeImpl* it = a->attributeItem(i); params.append(o->getDocument()->attrName(it->id()).string() + "=\"" + it->value().string() + "\""); } } part->requestObject( this, url, serviceType, params ); } else { assert(element()->id() == ID_IFRAME); HTMLIFrameElementImpl *o = static_cast<HTMLIFrameElementImpl *>(element()); url = o->url.string(); if (url.isEmpty()) url = "about:blank"; KHTMLView *v = static_cast<KHTMLView *>(m_view); bool requestSucceeded = v->part()->requestFrame( this, url, o->name.string(), QStringList(), true ); if (requestSucceeded && QString::equals(url,"about:blank")) { KHTMLPart *newPart = v->part()->findFrame( o->name.string() ); if (newPart && newPart->xmlDocImpl()) { newPart->xmlDocImpl()->setBaseURL( v->part()->baseURL().url() ); } } } }