css_base.cpp
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 #include <assert.h>
00029 #include <kdebug.h>
00030 
00031 #include "css_base.h"
00032 
00033 #ifdef CSS_DEBUG
00034 #include "cssproperties.h"
00035 #endif
00036 
00037 #include "css_stylesheetimpl.h"
00038 #include "xml/dom_docimpl.h"
00039 #include "misc/htmlhashes.h"
00040 #include "css_valueimpl.h"
00041 using namespace DOM;
00042 
00043 void StyleBaseImpl::checkLoaded() const
00044 {
00045     if(m_parent) m_parent->checkLoaded();
00046 }
00047 
00048 StyleSheetImpl* StyleBaseImpl::stylesheet()
00049 {
00050     StyleBaseImpl* b = this;
00051     while(b && !b->isStyleSheet())
00052         b = b->m_parent;
00053     return static_cast<StyleSheetImpl *>(b);
00054 }
00055 
00056 KURL StyleBaseImpl::baseURL()
00057 {
00058     
00059     
00060     
00061 
00062     StyleSheetImpl *sheet = stylesheet();
00063 
00064     if(!sheet) return KURL();
00065 
00066     if(!sheet->href().isNull())
00067         return KURL( sheet->href().string() );
00068 
00069     
00070     if(sheet->parent()) return sheet->parent()->baseURL();
00071 
00072     if(!sheet->ownerNode()) return KURL();
00073 
00074     return sheet->ownerNode()->getDocument()->baseURL();
00075 }
00076 
00077 void StyleBaseImpl::setParsedValue(int propId, const CSSValueImpl *parsedValue,
00078                    bool important, bool nonCSSHint, QPtrList<CSSProperty> *propList)
00079 {
00080     QPtrListIterator<CSSProperty> propIt(*propList);
00081     propIt.toLast(); 
00082     while (propIt.current() &&
00083            ( propIt.current()->m_id != propId || propIt.current()->nonCSSHint != nonCSSHint ||
00084              propIt.current()->m_bImportant != important) )
00085         --propIt;
00086     if (propIt.current())
00087         propList->removeRef(propIt.current());
00088 
00089     CSSProperty *prop = new CSSProperty();
00090     prop->m_id = propId;
00091     prop->setValue((CSSValueImpl *) parsedValue);
00092     prop->m_bImportant = important;
00093     prop->nonCSSHint = nonCSSHint;
00094 
00095     propList->append(prop);
00096 #ifdef CSS_DEBUG
00097     kdDebug( 6080 ) << "added property: " << getPropertyName(propId).string()
00098                     
00099                     << " important: " << prop->m_bImportant
00100                     << " nonCSS: " << prop->nonCSSHint << endl;
00101 #endif
00102 }
00103 
00104 
00105 
00106 StyleListImpl::~StyleListImpl()
00107 {
00108     StyleBaseImpl *n;
00109 
00110     if(!m_lstChildren) return;
00111 
00112     for( n = m_lstChildren->first(); n != 0; n = m_lstChildren->next() )
00113     {
00114         n->setParent(0);
00115         if( !n->refCount() ) delete n;
00116     }
00117     delete m_lstChildren;
00118 }
00119 
00120 
00121 
00122 void CSSSelector::print(void)
00123 {
00124     kdDebug( 6080 ) << "[Selector: tag = " <<       QString::number(tag,16) << ", attr = \"" << attr << "\", match = \"" << match
00125             << "\" value = \"" << value.string().latin1() << "\" relation = " << (int)relation
00126             << "]" << endl;
00127     if ( tagHistory )
00128         tagHistory->print();
00129     kdDebug( 6080 ) << "    specificity = " << specificity() << endl;
00130 }
00131 
00132 unsigned int CSSSelector::specificity() const
00133 {
00134     if ( nonCSSHint )
00135         return 0;
00136 
00137     int s = ((tag == 0xffff) ? 0 : 1);
00138     switch(match)
00139     {
00140     case Id:
00141     s += 0x10000;
00142     break;
00143     case Exact:
00144     case Set:
00145     case List:
00146     case Hyphen:
00147     case Pseudo:
00148     case Contain:
00149     case Begin:
00150     case End:
00151         s += 0x100;
00152     case None:
00153         break;
00154     }
00155     if(tagHistory)
00156         s += tagHistory->specificity();
00157     
00158     return s & 0xffffff;
00159 }
00160 
00161 void CSSSelector::extractPseudoType() const
00162 {
00163     if (match != Pseudo)
00164         return;
00165     _pseudoType = PseudoOther;
00166     if (!value.isEmpty()) {
00167         value = value.lower();
00168         switch (value[0]) {
00169             case 'a':
00170                 if (value == "active")
00171                     _pseudoType = PseudoActive;
00172                 else if (value == "after")
00173                     _pseudoType = PseudoAfter;
00174                 break;
00175             case 'b':
00176                 if (value == "before")
00177                     _pseudoType = PseudoBefore;
00178                 break;
00179             case 'e':
00180                 if (value == "empty")
00181                     _pseudoType = PseudoEmpty;
00182                 break;
00183             case 'f':
00184                 if (value == "first-child")
00185                     _pseudoType = PseudoFirstChild;
00186                 else if (value == "first-letter")
00187                     _pseudoType = PseudoFirstLetter;
00188                 else if (value == "first-line")
00189                     _pseudoType = PseudoFirstLine;
00190                 else if (value == "focus")
00191                     _pseudoType = PseudoFocus;
00192                 break;
00193             case 'h':
00194                 if (value == "hover")
00195                     _pseudoType = PseudoHover;
00196                 break;
00197             case 'l':
00198                 if (value == "link")
00199                     _pseudoType = PseudoLink;
00200                 else if (value == "lang(")
00201                     _pseudoType = PseudoLang;
00202                 else if (value == "last-child")
00203                     _pseudoType = PseudoLastChild;
00204                 break;
00205             case 'n':
00206                 if (value == "not(")
00207                     _pseudoType = PseudoNot;
00208                 break;
00209             case 'o':
00210                 if (value == "only-child")
00211                     _pseudoType = PseudoOnlyChild;
00212                 break;
00213             case 'r':
00214                 if (value == "root")
00215                     _pseudoType = PseudoRoot;
00216                 break;
00217             case 's':
00218                 if (value == "selection")
00219                     _pseudoType = PseudoSelection;
00220                 break;
00221             case 't':
00222                 if (value == "target")
00223                     _pseudoType = PseudoTarget;
00224                 break;
00225             case 'v':
00226                 if (value == "visited")
00227                     _pseudoType = PseudoVisited;
00228                 break;
00229         }
00230     }
00231 
00232     value = DOMString();
00233 }
00234 
00235 
00236 bool CSSSelector::operator == ( const CSSSelector &other ) const
00237 {
00238     const CSSSelector *sel1 = this;
00239     const CSSSelector *sel2 = &other;
00240 
00241     while ( sel1 && sel2 ) {
00242         
00243         
00244     if ( sel1->tag != sel2->tag || sel1->attr != sel2->attr ||
00245          sel1->relation != sel2->relation || sel1->match != sel2->match ||
00246          sel1->nonCSSHint != sel2->nonCSSHint ||
00247          sel1->value != sel2->value ||
00248              sel1->pseudoType() != sel2->pseudoType())
00249         return false;
00250     sel1 = sel1->tagHistory;
00251     sel2 = sel2->tagHistory;
00252     }
00253     if ( sel1 || sel2 )
00254     return false;
00255     return true;
00256 }
00257 
00258 DOMString CSSSelector::selectorText() const
00259 {
00260     
00261     DOMString str;
00262     const CSSSelector* cs = this;
00263     if ( cs->tag == 0xffff && cs->attr == ATTR_ID && cs->match == CSSSelector::Exact )
00264     {
00265         str = "#";
00266         str += cs->value;
00267     }
00268     else if ( cs->tag == 0xffff && cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
00269     {
00270         str = ".";
00271         str += cs->value;
00272     }
00273     else if ( cs->tag == 0xffff && cs->match == CSSSelector::Pseudo )
00274     {
00275         str = ":";
00276         str += cs->value;
00277     }
00278     else
00279     {
00280         if ( cs->tag == 0xffff )
00281             str = "*";
00282         else
00283             str = getTagName( cs->tag );
00284         if ( cs->attr == ATTR_ID && cs->match == CSSSelector::Exact )
00285         {
00286             str += "#";
00287             str += cs->value;
00288         }
00289         else if ( cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
00290         {
00291             str += ".";
00292             str += cs->value;
00293         }
00294         else if ( cs->match == CSSSelector::Pseudo )
00295         {
00296             str += ":";
00297             str += cs->value;
00298         }
00299         
00300         if ( cs->attr ) {
00301             DOMString attrName = getAttrName( cs->attr );
00302             str += "[";
00303             str += attrName;
00304             switch (cs->match) {
00305             case CSSSelector::Exact:
00306                 str += "=";
00307                 break;
00308             case CSSSelector::Set:
00309                 str += " "; 
00310                 break;
00311             case CSSSelector::List:
00312                 str += "~=";
00313                 break;
00314             case CSSSelector::Hyphen:
00315                 str += "|=";
00316                 break;
00317             case CSSSelector::Begin:
00318                 str += "^=";
00319                 break;
00320             case CSSSelector::End:
00321                 str += "$=";
00322                 break;
00323             case CSSSelector::Contain:
00324                 str += "*=";
00325                 break;
00326             default:
00327                 kdWarning(6080) << "Unhandled case in CSSStyleRuleImpl::selectorText : match=" << cs->match << endl;
00328             }
00329             str += "\"";
00330             str += cs->value;
00331             str += "\"]";
00332         }
00333     }
00334     if ( cs->tagHistory ) {
00335         DOMString tagHistoryText = cs->tagHistory->selectorText();
00336         if ( cs->relation == Sibling )
00337             str = tagHistoryText + " + " + str;
00338         else if ( cs->relation == Child )
00339             str = tagHistoryText + " > " + str;
00340         else if ( cs->relation == SubSelector )
00341             str += tagHistoryText; 
00342         else 
00343             str = tagHistoryText + " " + str;
00344     }
00345     return str;
00346 }
00347 
00348 
 
This file is part of the documentation for khtml Library Version 3.2.0.