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 & NodeImpl_IdLocalMask ) == 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