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 Pseudo:
00149
case Contain:
00150
case Begin:
00151
case End:
00152 s += 0x100;
00153
case None:
00154
break;
00155 }
00156
if(tagHistory)
00157 s += tagHistory->specificity();
00158
00159
return s & 0xffffff;
00160 }
00161
00162
void CSSSelector::extractPseudoType()
const
00163
{
00164
if (match != Pseudo)
00165
return;
00166 _pseudoType = PseudoOther;
00167
if (!value.isEmpty()) {
00168 value = value.lower();
00169
switch (value[0]) {
00170
case 'a':
00171
if (value ==
"active")
00172 _pseudoType = PseudoActive;
00173
else if (value ==
"after")
00174 _pseudoType = PseudoAfter;
00175
break;
00176
case 'b':
00177
if (value ==
"before")
00178 _pseudoType = PseudoBefore;
00179
break;
00180
case 'c':
00181
if (value ==
"checked")
00182 _pseudoType = PseudoChecked;
00183
else if (value ==
"contains(")
00184 _pseudoType = PseudoContains;
00185
break;
00186
case 'd':
00187
if (value ==
"disabled")
00188 _pseudoType = PseudoDisabled;
00189
break;
00190
case 'e':
00191
if (value ==
"empty")
00192 _pseudoType = PseudoEmpty;
00193
else if (value ==
"enabled")
00194 _pseudoType = PseudoEnabled;
00195
break;
00196
case 'f':
00197
if (value ==
"first-child")
00198 _pseudoType = PseudoFirstChild;
00199
else if (value ==
"first-letter")
00200 _pseudoType = PseudoFirstLetter;
00201
else if (value ==
"first-line")
00202 _pseudoType = PseudoFirstLine;
00203
else if (value ==
"first-of-type")
00204 _pseudoType = PseudoFirstOfType;
00205
else if (value ==
"focus")
00206 _pseudoType = PseudoFocus;
00207
break;
00208
case 'h':
00209
if (value ==
"hover")
00210 _pseudoType = PseudoHover;
00211
break;
00212
case 'i':
00213
if (value ==
"indeterminate")
00214 _pseudoType = PseudoIndeterminate;
00215
break;
00216
case 'l':
00217
if (value ==
"link")
00218 _pseudoType = PseudoLink;
00219
else if (value ==
"lang(")
00220 _pseudoType = PseudoLang;
00221
else if (value ==
"last-child")
00222 _pseudoType = PseudoLastChild;
00223
else if (value ==
"last-of-type")
00224 _pseudoType = PseudoLastOfType;
00225
break;
00226
case 'n':
00227
if (value ==
"not(")
00228 _pseudoType = PseudoNot;
00229
else if (value ==
"nth-child(")
00230 _pseudoType = PseudoNthChild;
00231
else if (value ==
"nth-last-child(")
00232 _pseudoType = PseudoNthLastChild;
00233
else if (value ==
"nth-of-type(")
00234 _pseudoType = PseudoNthOfType;
00235
else if (value ==
"nth-last-of-type(")
00236 _pseudoType = PseudoNthLastOfType;
00237
break;
00238
case 'o':
00239
if (value ==
"only-child")
00240 _pseudoType = PseudoOnlyChild;
00241
else if (value ==
"only-of-type")
00242 _pseudoType = PseudoOnlyOfType;
00243
break;
00244
case 'r':
00245
if (value ==
"root")
00246 _pseudoType = PseudoRoot;
00247
break;
00248
case 's':
00249
if (value ==
"selection")
00250 _pseudoType = PseudoSelection;
00251
break;
00252
case 't':
00253
if (value ==
"target")
00254 _pseudoType = PseudoTarget;
00255
break;
00256
case 'v':
00257
if (value ==
"visited")
00258 _pseudoType = PseudoVisited;
00259
break;
00260 }
00261 }
00262
00263 value =
DOMString();
00264 }
00265
00266
00267
bool CSSSelector::operator == (
const CSSSelector &other )
const
00268
{
00269
const CSSSelector *sel1 =
this;
00270
const CSSSelector *sel2 = &other;
00271
00272
while ( sel1 && sel2 ) {
00273
00274
00275
if ( sel1->tag != sel2->tag || sel1->attr != sel2->attr ||
00276 sel1->relation != sel2->relation || sel1->match != sel2->match ||
00277 sel1->nonCSSHint != sel2->nonCSSHint ||
00278 sel1->value != sel2->value ||
00279 sel1->pseudoType() != sel2->pseudoType() ||
00280 sel1->string_arg != sel2->string_arg)
00281
return false;
00282 sel1 = sel1->tagHistory;
00283 sel2 = sel2->tagHistory;
00284 }
00285
if ( sel1 || sel2 )
00286
return false;
00287
return true;
00288 }
00289
00290
DOMString CSSSelector::selectorText()
const
00291
{
00292
00293
DOMString str;
00294
const CSSSelector* cs =
this;
00295
if ( cs->tag == 0xffffffff && cs->attr == ATTR_ID && cs->match == CSSSelector::Id )
00296 {
00297 str =
"#";
00298 str += cs->value;
00299 }
00300
else if ( cs->tag == 0xffffffff && cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
00301 {
00302 str =
".";
00303 str += cs->value;
00304 }
00305
else if ( cs->tag == 0xffffffff && cs->match == CSSSelector::Pseudo )
00306 {
00307 str =
":";
00308 str += cs->value;
00309 }
00310
else
00311 {
00312
if ( cs->tag == 0xffffffff )
00313 str =
"*";
00314
else if ( cs->tag != 0xffff )
00315 str = getTagName( cs->tag );
00316
if ( cs->attr == ATTR_ID && cs->match == CSSSelector::Id )
00317 {
00318 str +=
"#";
00319 str += cs->value;
00320 }
00321
else if ( cs->attr == ATTR_CLASS && cs->match == CSSSelector::List )
00322 {
00323 str +=
".";
00324 str += cs->value;
00325 }
00326
else if ( cs->match == CSSSelector::Pseudo )
00327 {
00328 str +=
":";
00329 str += cs->value;
00330 }
00331
00332
else if ( cs->attr ) {
00333
DOMString attrName = getAttrName( cs->attr );
00334 str +=
"[";
00335 str += attrName;
00336
switch (cs->match) {
00337
case CSSSelector::Exact:
00338 str +=
"=";
00339
break;
00340
case CSSSelector::Set:
00341 str +=
" ";
00342
break;
00343
case CSSSelector::List:
00344 str +=
"~=";
00345
break;
00346
case CSSSelector::Hyphen:
00347 str +=
"|=";
00348
break;
00349
case CSSSelector::Begin:
00350 str +=
"^=";
00351
break;
00352
case CSSSelector::End:
00353 str +=
"$=";
00354
break;
00355
case CSSSelector::Contain:
00356 str +=
"*=";
00357
break;
00358
default:
00359
kdWarning(6080) <<
"Unhandled case in CSSStyleRuleImpl::selectorText : match=" << cs->match <<
endl;
00360 }
00361 str +=
"\"";
00362 str += cs->value;
00363 str +=
"\"]";
00364 }
00365 }
00366
if ( cs->tagHistory ) {
00367
DOMString tagHistoryText = cs->tagHistory->selectorText();
00368
if ( cs->relation == DirectAdjacent )
00369 str = tagHistoryText +
" + " + str;
00370
else if ( cs->relation == IndirectAdjacent )
00371 str = tagHistoryText +
" ~ " + str;
00372
else if ( cs->relation == Child )
00373 str = tagHistoryText +
" > " + str;
00374
else if ( cs->relation == SubSelector )
00375 str += tagHistoryText;
00376
else
00377 str = tagHistoryText +
" " + str;
00378 }
00379
return str;
00380 }
00381
00382