cssparser.cpp

来自「将konqueror浏览器移植到ARM9 2410中」· C++ 代码 · 共 2,040 行 · 第 1/5 页

CPP
2,040
字号
/** * This file is part of the DOM implementation for KDE. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) *               1999 Waldo Bastian (bastian@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. * * $Id: cssparser.cpp,v 1.158.2.3 2001/11/01 20:06:20 mueller Exp $ *///#define CSS_DEBUG//#define CSS_AURAL//#define CSS_DEBUG_BCKGR#include <assert.h>#include "css_stylesheetimpl.h"#include "css_stylesheet.h"#include "css_rule.h"#include "css_ruleimpl.h"#include "css_valueimpl.h"#include "csshelper.h"#include "dom_string.h"#include "xml/dom_nodeimpl.h"#include "html/html_documentimpl.h"#include "dom_exception.h"using namespace DOM;#include <kdebug.h>#include <kglobal.h>#include <kglobalsettings.h> // For system fonts#include <kapp.h>#include "htmlhashes.h"#include "misc/helper.h"//// The following file defines the function//     const struct props *findProp(const char *word, int len)//// with 'props->id' a CSS property in the range from CSS_PROP_MIN to// (and including) CSS_PROP_TOTAL-1#include "cssproperties.c"#include "cssvalues.c"int DOM::getPropertyID(const char *tagStr, int len){    const struct props *propsPtr = findProp(tagStr, len);    if (!propsPtr)        return 0;    return propsPtr->id;}// ------------------------------------------------------------------------------------------------------bool StyleBaseImpl::deleteMe(){    if(!m_parent && _ref <= 0) return true;    return false;}void StyleBaseImpl::checkLoaded(){    if(m_parent) m_parent->checkLoaded();}DOMString StyleBaseImpl::baseUrl(){    // try to find the style sheet. If found look for it's url.    // If it has none, look for the parentsheet, or the parentNode and    // try to find out about their url    StyleBaseImpl *b = this;    while(b && !b->isStyleSheet())        b = b->parent();    if(!b) return DOMString();    StyleSheetImpl *sheet = static_cast<StyleSheetImpl *>(b);    if(!sheet->href().isNull())        return sheet->href();    // find parent    if(sheet->parent()) return sheet->parent()->baseUrl();    if(!sheet->ownerNode()) return DOMString();    DocumentImpl *doc = static_cast<DocumentImpl*>(sheet->ownerNode()->nodeType() == Node::DOCUMENT_NODE ? sheet->ownerNode() : sheet->ownerNode()->ownerDocument());    return doc->baseURL();}/* * parsing functions for stylesheets */const QChar *StyleBaseImpl::parseSpace(const QChar *curP, const QChar *endP){  bool sc = false;     // possible start comment?  bool ec = false;     // possible end comment?  bool ic = false;     // in comment?  while (curP < endP)  {      if (ic)      {          if (ec && (*curP == '/'))              ic = false;          else if (*curP == '*')              ec = true;          else              ec = false;      }      else if (sc && (*curP == '*'))      {          ic = true;      }      else if (*curP == '/')      {          sc = true;      }      //else if (!isspace(*curP))      else if (!(curP->isSpace()))      {          return(curP);      }      else      {          sc = false;      }      curP++;  }  return(0);}/* * ParseToChar * * Search for an expected character.  Deals with escaped characters, * quoted strings, and pairs of braces/parens/brackets. */const QChar *StyleBaseImpl::parseToChar(const QChar *curP, const QChar *endP, QChar c, bool chkws, bool endAtBlock){    //kdDebug( 6080 ) << "parsetochar: \"" << QString(curP, endP-curP) << "\" searching " << c << " ws=" << chkws << endl;    bool sq = false; /* in single quote? */    bool dq = false; /* in double quote? */    bool esc = false; /* escape mode? */    while (curP < endP)    {        if (esc)            esc = false;        else if (*curP == '\\')            esc = true;        else if (!sq && (*curP == '"'))            dq = !dq;        else if (!dq && (*curP == '\''))            sq = !sq;        else if (!sq && !dq && *curP == c)            return(curP);        else if (!sq && !dq && chkws && curP->isSpace()) //isspace(*curP))            return(curP);        else if(!sq && !dq ) {            if (*curP == '{') {                if(endAtBlock)                    return curP;                curP = parseToChar(curP + 1, endP, '}', false);                if (!curP)                    return(0);            } else if (*curP == '(') {                curP = parseToChar(curP + 1, endP, ')', false);                if (!curP)                    return(0);            } else if (*curP == '[') {                curP = parseToChar(curP + 1, endP, ']', false);                if (!curP)                    return(0);            }        }        curP++;    }    return(0);}CSSRuleImpl *StyleBaseImpl::parseAtRule(const QChar *&curP, const QChar *endP){    curP++;    const QChar *startP = curP;    while( *curP != ' ' && *curP != '{' && *curP != '\'')        curP++;    QString rule(startP, curP-startP);    rule = rule.lower();    //kdDebug( 6080 ) << "rule = '" << rule << "'" << endl;    if(rule == "import")    {        // load stylesheet and pass it over        curP = parseSpace(curP, endP);        if(!curP) return 0;        startP = curP++;        curP = parseToChar(startP, endP, ';', true);        // Do not allow @import statements after explicity inlined        // declarations.  They should simply be ignored per CSS-1        // specification section 3.0.        if( !curP || hasInlinedDecl ) return 0;        DOMString url = khtml::parseURL(DOMString(startP, curP - startP));        startP = curP;        if(*curP != ';')            curP = parseToChar(startP, endP, ';', false, true);        if(!curP) return 0;        QString media(startP, curP - startP);	media = media.stripWhiteSpace();        // ### check if at the beginning of the stylesheet (no style rule        //     before the import rule)#ifdef CSS_DEBUG        kdDebug( 6080 ) << "at rule: url = '" << url.string()                        << "' media = '" << media << "'"<< endl;#endif        // ignore block following @import rule        if( *curP == '{' ) {            curP++;            curP = parseToChar(curP, endP, '}', false);            if(curP)                curP++;        }        // ### only media="", "screen and "all" are imported for the moment...        // ### add at least "print" here once the MediaList class is implemented        if( !media.isEmpty() && !(media.contains("all") || media.contains("screen") ) )            return 0;        if(!this->isCSSStyleSheet()) return 0;        return new CSSImportRuleImpl(this, url, 0);    }    else if(rule == "charset")    {        // ### invoke decoder        startP = curP++;        curP = parseToChar(startP, endP, ';', false);#ifdef CSS_DEBUG        kdDebug( 6080 ) << "charset = " << QString(startP, curP - startP) << endl;#endif    }    else if(rule == "font-face")    {        startP = curP++;        curP = parseToChar(startP, endP, '{', false);        if ( !curP || curP >= endP ) return 0;        curP++;        curP = parseToChar(curP, endP, '}', false);#ifdef CSS_DEBUG        kdDebug( 6080 ) << "font rule = " << QString(startP, curP - startP) << endl;#endif    }    else if(rule == "media")    {        startP = curP++;        curP = parseToChar(startP, endP, '{', false);	//qDebug("mediaList = '%s'", mediaList.latin1() );        if ( !curP || curP >= endP ) return 0;	QString mediaList = QString( startP, curP - startP);        curP++;	startP = curP;	if ( curP >= endP ) return 0;        curP = parseToChar(curP, endP, '}', false);	if ( !curP || startP >= curP )	    return 0;#ifdef CSS_DEBUG        kdDebug( 6080 ) << "media rule = " << QString(startP, curP - startP) << endl;#endif	if ( mediaList.contains( "screen" ) || mediaList.contains( "all" ) )	    return parseStyleRule(startP, curP);    }    else if(rule == "page")    {        startP = curP++;        curP = parseToChar(startP, endP, '{', false);        if ( !curP || curP >= endP ) return 0;        curP++;        curP = parseToChar(curP, endP, '}', false);#ifdef CSS_DEBUG        kdDebug( 6080 ) << "page rule = " << QString(startP, curP - startP) << endl;#endif    }    return 0;}static DOMString getValue( const QChar *curP, const QChar *endP, const QChar *&endVal){    //QString selecString( curP, endP - curP );    //kdDebug( 6080 ) << "getValue = \"" << selecString << "\"" << endl;    endVal = curP;    endVal++; // ignore first char (could be the ':' form the pseudo classes)    while( endVal < endP && *endVal != '.' && *endVal != ':' && *endVal != '[' )        endVal++;    const QChar *end = endVal;    if(endVal == endP)        endVal = 0;    return DOMString( curP, end - curP);}CSSSelector *StyleBaseImpl::parseSelector2(const QChar *curP, const QChar *endP,                              CSSSelector::Relation relation){    CSSSelector *cs = new CSSSelector();#ifdef CSS_DEBUG    QString selecString( curP, endP - curP );    kdDebug( 6080 ) << "selectString = \"" << selecString << "\"" << endl;#endif    const QChar *endVal = 0;    if (*curP == '#' && (curP < endP && !((*(curP+1)).isDigit())))    {        cs->tag = -1;        cs->attr = ATTR_ID;        cs->match = CSSSelector::Exact;        cs->value = getValue( curP+1, endP, endVal);    }    else if (*curP == '.' && (curP < endP && !((*(curP+1)).isDigit())))    {        cs->tag = -1;        cs->attr = ATTR_CLASS;        cs->match = CSSSelector::List;        cs->value = getValue( curP+1, endP, endVal);    }    else if (*curP == ':'  && (curP < endP && !((*(curP+1)).isDigit())))    {        // pseudo attributes (:link, :hover, ...), they are case insensitive.        cs->tag = -1;        cs->match = CSSSelector::Pseudo;        cs->value = getValue(curP+1, endP, endVal);        cs->value = cs->value.implementation()->lower();    }    else    {        const QChar *startP = curP;        QString tag;        while (curP < endP)        {            if (*curP =='#' && (curP < endP && !((*(curP+1)).isDigit())))            {                tag = QString( startP, curP-startP );                cs->attr = ATTR_ID;                cs->match = CSSSelector::Exact;                cs->value = getValue(curP+1, endP, endVal);                break;            }            else if (*curP == '.' && (curP < endP && !((*(curP+1)).isDigit())))            {                tag = QString( startP, curP - startP );                cs->attr = ATTR_CLASS;                cs->match = CSSSelector::List;                cs->value = getValue(curP+1, endP, endVal);                break;            }            else if (*curP == ':'  && (curP < endP && !((*(curP+1)).isDigit())))            {                // pseudo attributes (:link, :hover, ...), they are case insensitive.                tag = QString( startP, curP - startP );                cs->match = CSSSelector::Pseudo;                cs->value = getValue(curP+1, endP, endVal);                cs->value = cs->value.implementation()->lower();                break;            }            else if (*curP == '[')            {                tag = QString( startP, curP - startP );                curP++;                if ( curP >= endP ) {                    delete cs;                    return 0;                }#ifdef CSS_DEBUG                kdDebug( 6080 ) << "tag = " << tag << endl;#endif                const QChar *closebracket = parseToChar(curP, endP, ']', false);                if (!closebracket)                {                    kdWarning()<<"error in css: closing bracket not found!"<<endl;                    return 0;                }                QString attr;                const QChar *equal = parseToChar(curP, closebracket, '=', false);                if(!equal)

⌨️ 快捷键说明

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