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
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
00060
00061
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
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();
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
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
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
00292
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
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
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 += " ";
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;
00404 else
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.