# khtml Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# css_base.cpp

    00001 /*
    00002  * This file is part of the DOM implementation for KDE.
    00003  *
    00004  * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
    00005  *               1999 Waldo Bastian (bastian@kde.org)
    00006  *               2001 Andreas Schlapbach (schlpbch@iam.unibe.ch)
    00007  *               2001-2003 Dirk Mueller (mueller@kde.org)
    00008  *               2002 Apple Computer, Inc.
    00009  *               2004 Allan Sandfeld Jensen (kde@carewolf.com)
    00010  *
    00011  * This library is free software; you can redistribute it and/or
    00012  * modify it under the terms of the GNU Library General Public
    00013  * License as published by the Free Software Foundation; either
    00014  * version 2 of the License, or (at your option) any later version.
    00015  *
    00016  * This library is distributed in the hope that it will be useful,
    00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00019  * Library General Public License for more details.
    00020  *
    00021  * You should have received a copy of the GNU Library General Public License
    00022  * along with this library; see the file COPYING.LIB.  If not, write to
    00023  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00024  * Boston, MA 02111-1307, USA.
    00025  */
    00026
    00027 //#define CSS_DEBUG
    00028
    00029 #include <assert.h>
    00030 #include <kdebug.h>
    00031
    00032 #include "css_base.h"
    00033
    00034 #ifdef CSS_DEBUG
    00035 #include "cssproperties.h"
    00036 #endif
    00037
    00038 #include "css_stylesheetimpl.h"
    00039 #include "xml/dom_docimpl.h"
    00040 #include "misc/htmlhashes.h"
    00041 #include "css_valueimpl.h"
    00042 using namespace DOM;
    00043
    00044 void StyleBaseImpl::checkLoaded() const
    00045 {
    00046     if(m_parent) m_parent->checkLoaded();
    00047 }
    00048
    00049 StyleSheetImpl* StyleBaseImpl::stylesheet()
    00050 {
    00051     StyleBaseImpl* b = this;
    00052     while(b && !b->isStyleSheet())
    00053         b = b->m_parent;
    00054     return static_cast<StyleSheetImpl *>(b);
    00055 }
    00056
    00057 KURL StyleBaseImpl::baseURL()
    00058 {
    00059     // try to find the style sheet. If found look for its url.
    00060     // If it has none, look for the parentsheet, or the parentNode and
    00061     // try to find out about their url
    00062
    00063     StyleSheetImpl *sheet = stylesheet();
    00064
    00065     if(!sheet) return KURL();
    00066
    00067     if(!sheet->href().isNull())
    00068         return KURL( sheet->href().string() );
    00069
    00070     // find parent
    00071     if(sheet->parent()) return sheet->parent()->baseURL();
    00072
    00073     if(!sheet->ownerNode()) return KURL();
    00074
    00075     return sheet->ownerNode()->getDocument()->baseURL();
    00076 }
    00077
    00078 void StyleBaseImpl::setParsedValue(int propId, const CSSValueImpl *parsedValue,
    00079                    bool important, bool nonCSSHint, QPtrList<CSSProperty> *propList)
    00080 {
    00081     QPtrListIterator<CSSProperty> propIt(*propList);
    00082     propIt.toLast(); // just remove the top one - not sure what should happen if we have multiple instances of the property
    00083     while (propIt.current() &&
    00084            ( propIt.current()->m_id != propId || propIt.current()->nonCSSHint != nonCSSHint ||
    00085              propIt.current()->m_bImportant != important) )
    00086         --propIt;
    00087     if (propIt.current())
    00088         propList->removeRef(propIt.current());
    00089
    00090     CSSProperty *prop = new CSSProperty();
    00091     prop->m_id = propId;
    00092     prop->setValue((CSSValueImpl *) parsedValue);
    00093     prop->m_bImportant = important;
    00094     prop->nonCSSHint = nonCSSHint;
    00095
    00096     propList->append(prop);
    00097 #ifdef CSS_DEBUG
    00098     kdDebug( 6080 ) << "added property: " << getPropertyName(propId).string()
    00099                     // non implemented yet << ", value: " << parsedValue->cssText().string()
    00100                     << " important: " << prop->m_bImportant
    00101                     << " nonCSS: " << prop->nonCSSHint << endl;
    00102 #endif
    00103 }
    00104
    00105 // ------------------------------------------------------------------------------
    00106
    00107 StyleListImpl::~StyleListImpl()
    00108 {
    00109     StyleBaseImpl *n;
    00110
    00111     if(!m_lstChildren) return;
    00112
    00113     for( n = m_lstChildren->first(); n != 0; n = m_lstChildren->next() )
    00114     {
    00115         n->setParent(0);
    00116         if( !n->refCount() ) delete n;
    00117     }
    00118     delete m_lstChildren;
    00119 }
    00120
    00121 // --------------------------------------------------------------------------------
    00122
    00123 void CSSSelector::print(void)
    00124 {
    00125     kdDebug( 6080 ) << "[Selector: tag = " <<       QString::number(tag,16) << ", attr = \"" << attr << "\", match = \"" << match
    00126             << "\" value = \"" << value.string().latin1() << "\" relation = " << (int)relation
    00127             << "]" << endl;
    00128     if ( tagHistory )
    00129         tagHistory->print();
    00130     kdDebug( 6080 ) << "    specificity = " << specificity() << endl;
    00131 }
    00132
    00133 unsigned int CSSSelector::specificity() const
    00134 {
    00135     if ( nonCSSHint )
    00136         return 0;
    00137
    00138     int s = ((( tag & NodeImpl_IdLocalMask ) == 0xffff) ? 0 : 1);
    00139     switch(match)
    00140     {
    00141     case Id:
    00142     s += 0x10000;
    00143     break;
    00144     case Exact:
    00145     case Set:
    00146     case List:
    00147     case Hyphen:
    00148     case PseudoClass:
    00149     case PseudoElement:
    00150     case Contain:
    00151     case Begin:
    00152     case End:
    00153         s += 0x100;
    00154     case None:
    00155         break;
    00156     }
    00157     if(tagHistory)
    00158         s += tagHistory->specificity();
    00159     // make sure it doesn't overflow
    00160     return s & 0xffffff;
    00161 }
    00162
    00163 void CSSSelector::extractPseudoType() const
    00164 {
    00165     if (match != PseudoClass && match != PseudoElement)
    00166         return;
    00167     _pseudoType = PseudoOther;
    00168     bool element = false;
    00169     bool compat = false;
    00170     if (!value.isEmpty()) {
    00171         value = value.lower();
    00172         switch (value[0]) {
    00173             case 'a':
    00174                 if (value == "active")
    00175                     _pseudoType = PseudoActive;
    00176                 else if (value == "after") {
    00177                     _pseudoType = PseudoAfter;
    00178                     element = compat = true;
    00179                 }
    00180                 break;
    00181             case 'b':
    00182                 if (value == "before") {
    00183                     _pseudoType = PseudoBefore;
    00184                     element = compat = true;
    00185                 }
    00186                 break;
    00187             case 'c':
    00188                 if (value == "checked")
    00189                     _pseudoType = PseudoChecked;
    00190                 else if (value == "contains(")
    00191                     _pseudoType = PseudoContains;
    00192                 break;
    00193             case 'd':
    00194                 if (value == "disabled")
    00195                     _pseudoType = PseudoDisabled;
    00196                 break;
    00197             case 'e':
    00198                 if (value == "empty")
    00199                     _pseudoType = PseudoEmpty;
    00200                 else if (value == "enabled")
    00201                     _pseudoType = PseudoEnabled;
    00202                 break;
    00203             case 'f':
    00204                 if (value == "first-child")
    00205                     _pseudoType = PseudoFirstChild;
    00206                 else if (value == "first-letter") {
    00207                     _pseudoType = PseudoFirstLetter;
    00208                     element = compat = true;
    00209                 }
    00210                 else if (value == "first-line") {
    00211                     _pseudoType = PseudoFirstLine;
    00212                     element = compat = true;
    00213                 }
    00214                 else if (value == "first-of-type")
    00215                     _pseudoType = PseudoFirstOfType;
    00216                 else if (value == "focus")
    00217                     _pseudoType = PseudoFocus;
    00218                 break;
    00219             case 'h':
    00220                 if (value == "hover")
    00221                     _pseudoType = PseudoHover;
    00222                 break;
    00223             case 'i':
    00224                 if (value == "indeterminate")
    00225                     _pseudoType = PseudoIndeterminate;
    00226                 break;
    00227             case 'l':
    00228                 if (value == "link")
    00229                     _pseudoType = PseudoLink;
    00230                 else if (value == "lang(")
    00231                     _pseudoType = PseudoLang;
    00232                 else if (value == "last-child")
    00233                     _pseudoType = PseudoLastChild;
    00234                 else if (value == "last-of-type")
    00235                     _pseudoType = PseudoLastOfType;
    00236                 break;
    00237             case 'n':
    00238                 if (value == "not(")
    00239                     _pseudoType = PseudoNot;
    00240                 else if (value == "nth-child(")
    00241                     _pseudoType = PseudoNthChild;
    00242                 else if (value == "nth-last-child(")
    00243                     _pseudoType = PseudoNthLastChild;
    00244                 else if (value == "nth-of-type(")
    00245                     _pseudoType = PseudoNthOfType;
    00246                 else if (value == "nth-last-of-type(")
    00247                     _pseudoType = PseudoNthLastOfType;
    00248                 break;
    00249             case 'o':
    00250                 if (value == "only-child")
    00251                     _pseudoType = PseudoOnlyChild;
    00252                 else if (value == "only-of-type")
    00253                     _pseudoType = PseudoOnlyOfType;
    00254                 break;
    00255             case 'r':
    00256                 if (value == "root")
    00257                     _pseudoType = PseudoRoot;
    00258                 break;
    00259             case 's':
    00260                 if (value == "selection") {
    00261                     _pseudoType = PseudoSelection;
    00262                     element = true;
    00263                 }
    00264                 break;
    00265             case 't':
    00266                 if (value == "target")
    00267                     _pseudoType = PseudoTarget;
    00268                 break;
    00269             case 'v':
    00270                 if (value == "visited")
    00271                     _pseudoType = PseudoVisited;
    00272                 break;
    00273         }
    00274     }
    00275     if (match == PseudoClass && element)
    00276         if (!compat) _pseudoType = PseudoOther;
    00277         else match = PseudoElement;
    00278     else
    00279     if (match == PseudoElement && !element)
    00280         _pseudoType = PseudoOther;
    00281     value = DOMString();
    00282 }
    00283
    00284
    00285 bool CSSSelector::operator == ( const CSSSelector &other ) const
    00286 {
    00287     const CSSSelector *sel1 = this;
    00288     const CSSSelector *sel2 = &other;
    00289
    00290     while ( sel1 && sel2 ) {
    00291         //assert(sel1->_pseudoType != PseudoNotParsed);
    00292         //assert(sel2->_pseudoType != PseudoNotParsed);
    00293     if ( sel1->tag != sel2->tag || sel1->attr != sel2->attr ||
    00294          sel1->relation != sel2->relation || sel1->match != sel2->match ||
    00295          sel1->nonCSSHint != sel2->nonCSSHint ||
    00296          sel1->value != sel2->value ||
    00297              sel1->pseudoType() != sel2->pseudoType() ||
    00298              sel1->string_arg != sel2->string_arg)
    00299         return false;
    00300     sel1 = sel1->tagHistory;
    00301     sel2 = sel2->tagHistory;
    00302     }
    00303     if ( sel1 || sel2 )
    00304     return false;
    00305     return true;
    00306 }
    00307
    00308 DOMString CSSSelector::selectorText() const
    00309 {
    00310     // #### fix namespace
    00311     DOMString str;
    00312     const CSSSelector* cs = this;
    00313     if ( cs->tag == 0xffffffff && cs->attr == ATTR_ID && cs->match == CSSSelector::Id )
    00314     {
    00315         str = "#";
    00316         str += cs->value;
    00317     }
    00318     else if ( cs->tag == 0xffffffff && cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
    00319     {
    00320         str = ".";
    00321         str += cs->value;
    00322     }
    00323     else if ( cs->tag == 0xffffffff && cs->match == CSSSelector::PseudoClass )
    00324     {
    00325         str = ":";
    00326         str += cs->value;
    00327     }
    00328     else if ( cs->tag == 0xffffffff && cs->match == CSSSelector::PseudoElement )
    00329     {
    00330         str = "::";
    00331         str += cs->value;
    00332     }
    00333     else
    00334     {
    00335         if ( cs->tag == 0xffffffff )
    00336             str = "*";
    00337         else if ( cs->tag != 0xffff )
    00338             str = getTagName( cs->tag );
    00339         if ( cs->attr == ATTR_ID && cs->match == CSSSelector::Id )
    00340         {
    00341             str += "#";
    00342             str += cs->value;
    00343         }
    00344         else if ( cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
    00345         {
    00346             str += ".";
    00347             str += cs->value;
    00348         }
    00349         else if ( cs->match == CSSSelector::PseudoClass )
    00350         {
    00351             str += ":";
    00352             str += cs->value;
    00353         }
    00354         else if ( cs->match == CSSSelector::PseudoElement )
    00355         {
    00356             str += "::";
    00357             str += cs->value;
    00358         }
    00359         // optional attribute
    00360         else if ( cs->attr ) {
    00361             DOMString attrName = getAttrName( cs->attr );
    00362             str += "[";
    00363             str += attrName;
    00364             switch (cs->match) {
    00365             case CSSSelector::Exact:
    00366                 str += "=";
    00367                 break;
    00368             case CSSSelector::Set:
    00369                 str += " "; // ## correct?
    00370                 break;
    00371             case CSSSelector::List:
    00372                 str += "~=";
    00373                 break;
    00374             case CSSSelector::Hyphen:
    00375                 str += "|=";
    00376                 break;
    00377             case CSSSelector::Begin:
    00378                 str += "^=";
    00379                 break;
    00380             case CSSSelector::End:
    00381                 str += "$=";
    00382                 break;
    00383             case CSSSelector::Contain:
    00384                 str += "*=";
    00385                 break;
    00386             default:
    00387                 kdWarning(6080) << "Unhandled case in CSSStyleRuleImpl::selectorText : match=" << cs->match << endl;
    00388             }
    00389             str += "\"";
    00390             str += cs->value;
    00391             str += "\"]";
    00392         }
    00393     }
    00394     if ( cs->tagHistory ) {
    00395         DOMString tagHistoryText = cs->tagHistory->selectorText();
    00396         if ( cs->relation == DirectAdjacent )
    00397             str = tagHistoryText + " + " + str;
    00398         else if ( cs->relation == IndirectAdjacent )
    00399             str = tagHistoryText + " ~ " + str;
    00400         else if ( cs->relation == Child )
    00401             str = tagHistoryText + " > " + str;
    00402         else if ( cs->relation == SubSelector )
    00403             str += tagHistoryText; // the ":" is provided by selectorText()
    00404         else // Descendant
    00405             str = tagHistoryText + " " + str;
    00406     }
    00407     return str;
    00408 }
    00409
    00410 // ----------------------------------------------------------------------------

This file is part of the documentation for khtml Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:33:06 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003