css_base.cpp00001
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 = ((localNamePart(tag) == anyLocalName) ? 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
00312 DOMString str;
00313 const CSSSelector* cs = this;
00314 Q_UINT16 tag = localNamePart(cs->tag);
00315 if ( tag == anyLocalName && cs->attr == ATTR_ID && cs->match == CSSSelector::Id )
00316 {
00317 str = "#";
00318 str += cs->value;
00319 }
00320 else if ( tag == anyLocalName && cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
00321 {
00322 str = ".";
00323 str += cs->value;
00324 }
00325 else if ( tag == anyLocalName && cs->match == CSSSelector::PseudoClass )
00326 {
00327 str = ":";
00328 str += cs->value;
00329 }
00330 else if ( tag == anyLocalName && cs->match == CSSSelector::PseudoElement )
00331 {
00332 str = "::";
00333 str += cs->value;
00334 }
00335 else
00336 {
00337 if ( tag == anyLocalName )
00338 str = "*";
00339 else if ( tag != anyLocalName )
00340 str = getTagName( cs->tag );
00341 if ( cs->attr == ATTR_ID && cs->match == CSSSelector::Id )
00342 {
00343 str += "#";
00344 str += cs->value;
00345 }
00346 else if ( cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
00347 {
00348 str += ".";
00349 str += cs->value;
00350 }
00351 else if ( cs->match == CSSSelector::PseudoClass )
00352 {
00353 str += ":";
00354 str += cs->value;
00355 }
00356 else if ( cs->match == CSSSelector::PseudoElement )
00357 {
00358 str += "::";
00359 str += cs->value;
00360 }
00361
00362 else if ( cs->attr ) {
00363 DOMString attrName = getAttrName( cs->attr );
00364 str += "[";
00365 str += attrName;
00366 switch (cs->match) {
00367 case CSSSelector::Exact:
00368 str += "=";
00369 break;
00370 case CSSSelector::Set:
00371 str += " ";
00372 break;
00373 case CSSSelector::List:
00374 str += "~=";
00375 break;
00376 case CSSSelector::Hyphen:
00377 str += "|=";
00378 break;
00379 case CSSSelector::Begin:
00380 str += "^=";
00381 break;
00382 case CSSSelector::End:
00383 str += "$=";
00384 break;
00385 case CSSSelector::Contain:
00386 str += "*=";
00387 break;
00388 default:
00389 kdWarning(6080) << "Unhandled case in CSSStyleRuleImpl::selectorText : match=" << cs->match << endl;
00390 }
00391 str += "\"";
00392 str += cs->value;
00393 str += "\"]";
00394 }
00395 }
00396 if ( cs->tagHistory ) {
00397 DOMString tagHistoryText = cs->tagHistory->selectorText();
00398 if ( cs->relation == DirectAdjacent )
00399 str = tagHistoryText + " + " + str;
00400 else if ( cs->relation == IndirectAdjacent )
00401 str = tagHistoryText + " ~ " + str;
00402 else if ( cs->relation == Child )
00403 str = tagHistoryText + " > " + str;
00404 else if ( cs->relation == SubSelector )
00405 str += tagHistoryText;
00406 else
00407 str = tagHistoryText + " " + str;
00408 }
00409 return str;
00410 }
00411
00412
|