⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htmlparser.cpp

📁 将konqueror浏览器移植到ARM9 2410中
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*    This file is part of the KDE libraries    Copyright (C) 1997 Martin Jones (mjones@kde.org)              (C) 1997 Torben Weis (weis@kde.org)              (C) 1999,2001 Lars Knoll (knoll@kde.org)              (C) 2000,2001 Dirk Mueller (mueller@kde.org)    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public License    along with this library; see the file COPYING.LIB.  If not, write to    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,    Boston, MA 02111-1307, USA.*///----------------------------------------------------------------------------//// KDE HTML Widget -- HTML Parser//#define PARSER_DEBUG#include "htmlparser.h"#include "dom_nodeimpl.h"#include "dom_exception.h"#include "html_baseimpl.h"#include "html_blockimpl.h"#include "html_documentimpl.h"#include "html_elementimpl.h"#include "html_formimpl.h"#include "html_headimpl.h"#include "html_imageimpl.h"#include "html_inlineimpl.h"#include "html_listimpl.h"#include "html_miscimpl.h"#include "html_tableimpl.h"#include "html_objectimpl.h"#include "dom_textimpl.h"#include "htmlhashes.h"#include "htmltokenizer.h"#include "khtmlview.h"#include "khtml_part.h"#include "cssproperties.h"#include "cssvalues.h"#include "rendering/render_object.h"#include <kdebug.h>#include <klocale.h>using namespace DOM;using namespace khtml;//----------------------------------------------------------------------------/** * @internal */class HTMLStackElem{public:    HTMLStackElem( int _id,                   int _level,                   DOM::NodeImpl *_node,                   HTMLStackElem * _next        )        :        id(_id),        level(_level),        node(_node),        next(_next)        { }    int       id;    int       level;    NodeImpl *node;    HTMLStackElem *next;};/** * @internal * * The parser parses tokenized input into the document, building up the * document tree. If the document is wellformed, parsing it is * straightforward. * Unfortunately, people can't write wellformed HTML documents, so the parser * has to be tolerant about errors. * * We have to take care of the following error conditions: * 1. The element being added is explicitly forbidden inside some outer tag. *    In this case we should close all tags up to the one, which forbids *    the element, and add it afterwards. * 2. We are not allowed to add the element directly. It could be, that *    the person writing the document forgot some tag inbetween (or that the *    tag inbetween is optional...) This could be the case with the following *    tags: HTML HEAD BODY TBODY TR TD LI (did I forget any?) * 3. We wan't to add a block element inside to an inline element. Close all *    inline elements up to the next higher block element. * 4. If this doesn't help close elements, until we are allowed to add the *    element or ignore the tag. * */KHTMLParser::KHTMLParser( KHTMLView *_parent, DocumentPtr *doc){    //kdDebug( 6035 ) << "parser constructor" << endl;#if SPEED_DEBUG > 0    qt.start();#endif    HTMLWidget    = _parent;    document      = doc;    document->ref();    blockStack = 0;    // ID_CLOSE_TAG == Num of tags    forbiddenTag = new ushort[ID_CLOSE_TAG+1];    reset();}KHTMLParser::KHTMLParser( DOM::DocumentFragmentImpl *i, DocumentPtr *doc ){    HTMLWidget = 0;    document = doc;    document->ref();    forbiddenTag = new ushort[ID_CLOSE_TAG+1];    blockStack = 0;    reset();    current = i;    inBody = true;    inSelect = false;}KHTMLParser::~KHTMLParser(){#if SPEED_DEBUG > 0    kdDebug( ) << "TIME: parsing time was = " << qt.elapsed() << endl;#endif    document->deref();    freeBlock();    delete [] forbiddenTag;    delete isindex;}void KHTMLParser::reset(){    current = document->document();    freeBlock();    // before parsing no tags are forbidden...    memset(forbiddenTag, 0, (ID_CLOSE_TAG+1)*sizeof(ushort));    inBody = false;    noRealBody = true;    haveFrameSet = false;    inSelect = false;    _inline = false;    form = 0;    map = 0;    head = 0;    end = false;    isindex = 0;    flat = false;    haveKonqBlock = false;    discard_until = 0;}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) << "inline=" << _inline << " inBody=" << inBody << " noRealBody=" << noRealBody << " 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()->parseMode() != DocumentImpl::Strict)        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 ) {#ifdef PARSER_DEBUG        if(t->text)            kdDebug(6035) << "length="<< t->text->l << " text='" << QConstString(t->text->s, t->text->l).string() << "'" << endl;#endif        if ( inBody ) noRealBody = false;    }    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]) popOneBlock();    if ( !insertNode(n) ) {        // we couldn't insert the node...#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){    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]);            current = newNode;#if SPEED_DEBUG < 2            if(!n->attached() && HTMLWidget )  n->attach();#endif            //_inline = current->isInline();            if(current->isInline()) _inline = true;        }        else {#if SPEED_DEBUG < 2            if(!n->attached() && HTMLWidget)  n->attach();	    if(n->renderer()) n->renderer()->close();#endif            flat = false;        }#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;        // 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;            // 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 ) {                head->addChild(n);#if SPEED_DEBUG < 2                if(!n->attached() && HTMLWidget)                    n->attach();#endif                return true;            }            break;        case ID_HTML:            if (!current->isDocumentNode())                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_STYLE + ID_CLOSE_TAG;                return false;            }            break;            // SCRIPT and OBJECT are allowd 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<NamedAttrMapImpl*>(n->attributes());                NamedAttrMapImpl *bodymap = static_cast<NamedAttrMapImpl*>(doc()->body()->attributes());                unsigned long attrNo;                int exceptioncode;                bool changed = false;                for (attrNo = 0; map && attrNo < map->length(); attrNo++)                    if(!bodymap->getNamedItem(static_cast<AttrImpl*>(map->item(attrNo))->name())) {                        doc()->body()->setAttributeNode(static_cast<AttrImpl*>(map->item(attrNo)->cloneNode(false,exceptioncode)), exceptioncode);                        changed = true;                    }                if ( changed )                    doc()->applyChanges();                noRealBody = false;            } 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:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -