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
#define YYDEBUG 0
00026
00027
#include <kdebug.h>
00028
#include <kglobal.h>
00029
#include <kurl.h>
00030
00031
#include "cssparser.h"
00032
#include "css_valueimpl.h"
00033
#include "css_ruleimpl.h"
00034
#include "css_stylesheetimpl.h"
00035
#include "cssproperties.h"
00036
#include "cssvalues.h"
00037
#include "misc/helper.h"
00038
#include "csshelper.h"
00039
using namespace DOM;
00040
00041
#include <stdlib.h>
00042
#include <assert.h>
00043
00044
00045
#define BACKGROUND_SKIP_CENTER( num ) \
00046
if ( !pos_ok[ num ] && expected != 1 ) { \
00047
pos_ok[num] = true; \
00048
pos[num] = 0; \
00049
skip_next = false; \
00050
}
00051
00052 ValueList::ValueList()
00053 {
00054 values = (Value *) malloc( 16 *
sizeof ( Value ) );
00055 numValues = 0;
00056 currentValue = 0;
00057 maxValues = 16;
00058 }
00059
00060 ValueList::~ValueList()
00061 {
00062
for (
int i = 0; i < numValues; i++ ) {
00063
#ifdef CSS_DEBUG
00064
kdDebug( 6080 ) <<
" value: (unit=" << values[i].unit <<
")"<<
endl;
00065
#endif
00066
if ( values[i].unit == Value::Function )
00067
delete values[i].function;
00068 }
00069 free( values );
00070 }
00071
00072
void ValueList::addValue(
const Value &val )
00073 {
00074
if ( numValues >= maxValues ) {
00075 maxValues += 16;
00076 values = (Value *) realloc( values, maxValues*
sizeof( Value ) );
00077 }
00078 values[numValues++] = val;
00079 }
00080
00081
00082
using namespace DOM;
00083
00084
#if YYDEBUG > 0
00085
extern int cssyydebug;
00086
#endif
00087
00088
extern int cssyyparse(
void * parser );
00089
00090 CSSParser *CSSParser::currentParser = 0;
00091
00092 CSSParser::CSSParser(
bool strictParsing )
00093 {
00094
#ifdef CSS_DEBUG
00095
kdDebug( 6080 ) <<
"CSSParser::CSSParser this=" <<
this <<
endl;
00096
#endif
00097
strict = strictParsing;
00098
00099 parsedProperties = (CSSProperty **) malloc( 32 *
sizeof( CSSProperty * ) );
00100 numParsedProperties = 0;
00101 maxParsedProperties = 32;
00102
00103 defaultNamespace = 0xffff;
00104
00105 data = 0;
00106 valueList = 0;
00107 rule = 0;
00108
id = 0;
00109 important =
false;
00110 nonCSSHint =
false;
00111 inParseShortHand =
false;
00112 yy_start = 1;
00113
00114
#if YYDEBUG > 0
00115
cssyydebug = 1;
00116
#endif
00117
00118 }
00119
00120 CSSParser::~CSSParser()
00121 {
00122
if ( numParsedProperties )
00123 clearProperties();
00124 free( parsedProperties );
00125
00126
delete valueList;
00127
00128
#ifdef CSS_DEBUG
00129
kdDebug( 6080 ) <<
"CSSParser::~CSSParser this=" <<
this <<
endl;
00130
#endif
00131
00132 free( data );
00133
00134 }
00135
00136
void CSSParser::runParser(
int length)
00137 {
00138 data[length-1] = 0;
00139 data[length-2] = 0;
00140 data[length-3] =
' ';
00141
00142 yyTok = -1;
00143 block_nesting = 0;
00144 yy_hold_char = 0;
00145 yyleng = 0;
00146 yytext = yy_c_buf_p = data;
00147 yy_hold_char = *yy_c_buf_p;
00148
00149 CSSParser *old = currentParser;
00150 currentParser =
this;
00151 cssyyparse(
this );
00152 currentParser = old;
00153 }
00154
00155
void CSSParser::parseSheet( CSSStyleSheetImpl *sheet,
const DOMString &string )
00156 {
00157 styleElement = sheet;
00158
00159
int length = string.
length() + 3;
00160 data = (
unsigned short *)malloc( length *
sizeof(
unsigned short ) );
00161 memcpy( data, string.
unicode(), string.
length()*
sizeof(
unsigned short) );
00162
00163
#ifdef CSS_DEBUG
00164
kdDebug( 6080 ) <<
">>>>>>> start parsing style sheet" <<
endl;
00165
#endif
00166
runParser(length);
00167
#ifdef CSS_DEBUG
00168
kdDebug( 6080 ) <<
"<<<<<<< done parsing style sheet" <<
endl;
00169
#endif
00170
00171
delete rule;
00172 rule = 0;
00173 }
00174
00175 CSSRuleImpl *CSSParser::parseRule( DOM::CSSStyleSheetImpl *sheet,
const DOM::DOMString &string )
00176 {
00177 styleElement = sheet;
00178
00179
const char khtml_rule[] =
"@-khtml-rule{";
00180
int length = string.
length() + 4 + strlen(khtml_rule);
00181 assert( !data );
00182 data = (
unsigned short *)malloc( length *
sizeof(
unsigned short ) );
00183
for (
unsigned int i = 0; i < strlen(khtml_rule); i++ )
00184 data[i] = khtml_rule[i];
00185 memcpy( data + strlen( khtml_rule ), string.
unicode(), string.
length()*
sizeof(
unsigned short) );
00186
00187 data[length-4] =
'}';
00188
00189 runParser(length);
00190
00191 CSSRuleImpl *result = rule;
00192 rule = 0;
00193
00194
return result;
00195 }
00196
00197
bool CSSParser::parseValue( DOM::CSSStyleDeclarationImpl *declaration,
int _id,
const DOM::DOMString &string,
00198
bool _important,
bool _nonCSSHint )
00199 {
00200
#ifdef CSS_DEBUG
00201
kdDebug( 6080 ) <<
"CSSParser::parseValue: id=" << _id <<
" important=" << _important
00202 <<
" nonCSSHint=" << _nonCSSHint <<
" value='" << string.
string() <<
"'" <<
endl;
00203
#endif
00204
00205 styleElement = declaration->stylesheet();
00206
00207
const char khtml_value[] =
"@-khtml-value{";
00208
int length = string.
length() + 4 + strlen(khtml_value);
00209 assert( !data );
00210 data = (
unsigned short *)malloc( length *
sizeof(
unsigned short ) );
00211
for (
unsigned int i = 0; i < strlen(khtml_value); i++ )
00212 data[i] = khtml_value[i];
00213 memcpy( data + strlen( khtml_value ), string.
unicode(), string.
length()*
sizeof(
unsigned short) );
00214 data[length-4] =
'}';
00215
00216
00217
id = _id;
00218 important = _important;
00219 nonCSSHint = _nonCSSHint;
00220
00221 runParser(length);
00222
00223
delete rule;
00224 rule = 0;
00225
00226
bool ok =
false;
00227
if ( numParsedProperties ) {
00228 ok =
true;
00229
for (
int i = 0; i < numParsedProperties; i++ ) {
00230 declaration->removeProperty(parsedProperties[i]->m_id, nonCSSHint);
00231 declaration->values()->append( parsedProperties[i] );
00232 }
00233 numParsedProperties = 0;
00234 }
00235
00236
return ok;
00237 }
00238
00239
bool CSSParser::parseDeclaration( DOM::CSSStyleDeclarationImpl *declaration,
const DOM::DOMString &string,
00240
bool _nonCSSHint )
00241 {
00242
#ifdef CSS_DEBUG
00243
kdDebug( 6080 ) <<
"CSSParser::parseDeclaration: nonCSSHint=" << nonCSSHint
00244 <<
" value='" << string.
string() <<
"'" <<
endl;
00245
#endif
00246
00247 styleElement = declaration->stylesheet();
00248
00249
const char khtml_decls[] =
"@-khtml-decls{";
00250
int length = string.
length() + 4 + strlen(khtml_decls);
00251 assert( !data );
00252 data = (
unsigned short *)malloc( length *
sizeof(
unsigned short ) );
00253
for (
unsigned int i = 0; i < strlen(khtml_decls); i++ )
00254 data[i] = khtml_decls[i];
00255 memcpy( data + strlen( khtml_decls ), string.
unicode(), string.
length()*
sizeof(
unsigned short) );
00256 data[length-4] =
'}';
00257
00258 nonCSSHint = _nonCSSHint;
00259
00260 runParser(length);
00261
00262
delete rule;
00263 rule = 0;
00264
00265
bool ok =
false;
00266
if ( numParsedProperties ) {
00267 ok =
true;
00268
for (
int i = 0; i < numParsedProperties; i++ ) {
00269 declaration->removeProperty(parsedProperties[i]->m_id,
false);
00270 declaration->values()->append( parsedProperties[i] );
00271 }
00272 numParsedProperties = 0;
00273 }
00274
00275
return ok;
00276 }
00277
00278
void CSSParser::addProperty(
int propId, CSSValueImpl *value,
bool important )
00279 {
00280 CSSProperty *prop =
new CSSProperty;
00281 prop->m_id = propId;
00282 prop->setValue( value );
00283 prop->m_bImportant = important;
00284 prop->nonCSSHint = nonCSSHint;
00285
00286
if ( numParsedProperties >= maxParsedProperties ) {
00287 maxParsedProperties += 32;
00288 parsedProperties = (CSSProperty **) realloc( parsedProperties,
00289 maxParsedProperties*
sizeof( CSSProperty * ) );
00290 }
00291 parsedProperties[numParsedProperties++] = prop;
00292 }
00293
00294 CSSStyleDeclarationImpl *CSSParser::createStyleDeclaration( CSSStyleRuleImpl *rule )
00295 {
00296
QPtrList<CSSProperty> *propList =
new QPtrList<CSSProperty>;
00297 propList->setAutoDelete(
true );
00298
for (
int i = 0; i < numParsedProperties; i++ )
00299 propList->append( parsedProperties[i] );
00300
00301 numParsedProperties = 0;
00302
return new CSSStyleDeclarationImpl(rule, propList);
00303 }
00304
00305
void CSSParser::clearProperties()
00306 {
00307
for (
int i = 0; i < numParsedProperties; i++ )
00308
delete parsedProperties[i];
00309 numParsedProperties = 0;
00310 }
00311
00312 DOM::DocumentImpl *CSSParser::document()
const
00313
{
00314
const StyleBaseImpl* root = styleElement;
00315 DocumentImpl *doc = 0;
00316
while (root->parent())
00317 root = root->parent();
00318
if (root->isCSSStyleSheet())
00319 doc = static_cast<const CSSStyleSheetImpl*>(root)->doc();
00320
return doc;
00321 }
00322
00323
00324
00325
enum Units
00326 {
00327 FUnknown = 0x0000,
00328 FInteger = 0x0001,
00329 FNumber = 0x0002,
00330 FPercent = 0x0004,
00331 FLength = 0x0008,
00332 FAngle = 0x0010,
00333 FTime = 0x0020,
00334 FFrequency = 0x0040,
00335 FRelative = 0x0100,
00336 FNonNeg = 0x0200
00337 };
00338
00339
static bool validUnit( Value *value,
int unitflags,
bool strict )
00340 {
00341
if ( unitflags & FNonNeg && value->fValue < 0 )
00342
return false;
00343
00344
bool b =
false;
00345
switch( value->unit ) {
00346
case CSSPrimitiveValue::CSS_NUMBER:
00347 b = (unitflags & FNumber);
00348
if ( !b && ( (unitflags & FLength) && (value->fValue == 0 || !strict ) ) ) {
00349 value->unit = CSSPrimitiveValue::CSS_PX;
00350 b =
true;
00351 }
00352
if ( !b && ( unitflags & FInteger ) &&
00353 (value->fValue - (
int)value->fValue) < 0.001 )
00354 b =
true;
00355
break;
00356
case CSSPrimitiveValue::CSS_PERCENTAGE:
00357 b = (unitflags & FPercent);
00358
break;
00359
case Value::Q_EMS:
00360
case CSSPrimitiveValue::CSS_EMS:
00361
case CSSPrimitiveValue::CSS_EXS:
00362
case CSSPrimitiveValue::CSS_PX:
00363
case CSSPrimitiveValue::CSS_CM:
00364
case CSSPrimitiveValue::CSS_MM:
00365
case CSSPrimitiveValue::CSS_IN:
00366
case CSSPrimitiveValue::CSS_PT:
00367
case CSSPrimitiveValue::CSS_PC:
00368 b = (unitflags & FLength);
00369
break;
00370
case CSSPrimitiveValue::CSS_MS:
00371
case CSSPrimitiveValue::CSS_S:
00372 b = (unitflags & FTime);
00373
break;
00374
case CSSPrimitiveValue::CSS_DEG:
00375
case CSSPrimitiveValue::CSS_RAD:
00376
case CSSPrimitiveValue::CSS_GRAD:
00377
case CSSPrimitiveValue::CSS_HZ:
00378
case CSSPrimitiveValue::CSS_KHZ:
00379
case CSSPrimitiveValue::CSS_DIMENSION:
00380
default:
00381
break;
00382 }
00383
return b;
00384 }
00385
00386 CSSPrimitiveValueImpl *CSSParser::parseBackgroundPositionXY(
int propId,
bool forward,
bool &ok )
00387 {
00388
if (
forward )
00389 valueList->next();
00390
00391 Value *value = valueList->current();
00392
00393 ok =
true;
00394
00395
if ( !value )
00396
return 0;
00397
00398
int id = value->id;
00399
00400
switch (
id ) {
00401
case 0:
00402
if ( !validUnit( value, FPercent|FLength, strict&(!nonCSSHint) ) )
00403 ok =
false;
00404
break;
00405
00406
case CSS_VAL_LEFT:
00407
case CSS_VAL_RIGHT:
00408
if ( propId == CSS_PROP_BACKGROUND_POSITION_Y ) {
00409 ok =
false;
00410
break;
00411 }
00412
case CSS_VAL_TOP:
00413
case CSS_VAL_BOTTOM:
00414
if ( propId == CSS_PROP_BACKGROUND_POSITION_X && (
id == CSS_VAL_BOTTOM ||
id == CSS_VAL_TOP ) ) {
00415 ok =
false;
00416
break;
00417 }
00418
case CSS_VAL_CENTER:
00419
return new CSSPrimitiveValueImpl(
id );
00420
break;
00421
default:
00422 ok =
false;
00423 }
00424
if ( !ok )
00425
return 0;
00426
return new CSSPrimitiveValueImpl( value->fValue,
00427 (CSSPrimitiveValue::UnitTypes) value->unit );
00428 }
00429
00430
00431
bool CSSParser::parseValue(
int propId,
bool important,
int expected )
00432 {
00433
if ( !valueList )
return false;
00434
00435 Value *value = valueList->current();
00436
00437
if ( !value )
00438
return false;
00439
00440
int id = value->id;
00441
00442
if (
id == CSS_VAL_INHERIT && expected == 1 ) {
00443 addProperty( propId,
new CSSInheritedValueImpl(), important );
00444
return true;
00445 }
else if (
id == CSS_VAL_INITIAL && expected == 1 ) {
00446 addProperty(propId,
new CSSInitialValueImpl(), important);
00447
return true;
00448 }
00449
bool valid_primitive =
false;
00450 CSSValueImpl *parsedValue = 0;
00451
00452
switch(propId) {
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
case CSS_PROP_SIZE:
00463
00464
00465
if (
id)
00466 valid_primitive =
true;
00467
break;
00468
case CSS_PROP_UNICODE_BIDI:
00469
if (
id == CSS_VAL_NORMAL ||
00470
id == CSS_VAL_EMBED ||
00471
id == CSS_VAL_BIDI_OVERRIDE )
00472 valid_primitive =
true;
00473
break;
00474
00475
case CSS_PROP_POSITION:
00476
if (
id == CSS_VAL_STATIC ||
00477
id == CSS_VAL_RELATIVE ||
00478
id == CSS_VAL_ABSOLUTE ||
00479
id == CSS_VAL_FIXED )
00480 valid_primitive =
true;
00481
break;
00482
00483
case CSS_PROP_PAGE_BREAK_AFTER:
00484
case CSS_PROP_PAGE_BREAK_BEFORE:
00485
if (
id == CSS_VAL_AUTO ||
00486
id == CSS_VAL_ALWAYS ||
00487
id == CSS_VAL_AVOID ||
00488
id == CSS_VAL_LEFT ||
00489
id == CSS_VAL_RIGHT )
00490 valid_primitive =
true;
00491
break;
00492
00493
case CSS_PROP_PAGE_BREAK_INSIDE:
00494
if (
id == CSS_VAL_AUTO ||
00495
id == CSS_VAL_AVOID )
00496 valid_primitive =
true;
00497
break;
00498
00499
case CSS_PROP_EMPTY_CELLS:
00500
if (
id == CSS_VAL_SHOW ||
00501
id == CSS_VAL_HIDE )
00502 valid_primitive =
true;
00503
break;
00504
00505
case CSS_PROP_QUOTES:
00506
if (
id == CSS_VAL_NONE) {
00507 valid_primitive =
true;
00508 }
else {
00509 QuotesValueImpl *quotes =
new QuotesValueImpl;
00510
bool is_valid =
true;
00511
QString open,
close;
00512 Value *val=valueList->current();
00513
while (val) {
00514
if (val->unit == CSSPrimitiveValue::CSS_STRING)
00515
open = qString(val->string);
00516
else {
00517 is_valid =
false;
00518
break;
00519 }
00520 valueList->next();
00521 val=valueList->current();
00522
if (val && val->unit == CSSPrimitiveValue::CSS_STRING)
00523
close = qString(val->string);
00524
else {
00525 is_valid =
false;
00526
break;
00527 }
00528 quotes->addLevel(open, close);
00529 valueList->next();
00530 val=valueList->current();
00531 }
00532
if (is_valid)
00533 parsedValue = quotes;
00534
00535 }
00536
break;
00537
00538
case CSS_PROP_CONTENT:
00539
00540
return parseContent( propId, important );
00541
00542
case CSS_PROP_WHITE_SPACE:
00543
if (
id == CSS_VAL_NORMAL ||
00544
id == CSS_VAL_PRE ||
00545
id == CSS_VAL_PRE_WRAP ||
00546
id == CSS_VAL_PRE_LINE ||
00547
id == CSS_VAL_NOWRAP )
00548 valid_primitive =
true;
00549
break;
00550
00551
case CSS_PROP_CLIP:
00552
if (
id == CSS_VAL_AUTO )
00553 valid_primitive =
true;
00554
else if ( value->unit == Value::Function )
00555
return parseShape( propId, important );
00556
break;
00557
00558
00559
00560
00561
case CSS_PROP_CAPTION_SIDE:
00562
if (
id == CSS_VAL_LEFT ||
id == CSS_VAL_RIGHT ||
00563
id == CSS_VAL_TOP ||
id == CSS_VAL_BOTTOM)
00564 valid_primitive =
true;
00565
break;
00566
00567
case CSS_PROP_BORDER_COLLAPSE:
00568
if (
id == CSS_VAL_COLLAPSE ||
id == CSS_VAL_SEPARATE )
00569 valid_primitive =
true;
00570
break;
00571
00572
case CSS_PROP_VISIBILITY:
00573
if (
id == CSS_VAL_VISIBLE ||
id == CSS_VAL_HIDDEN ||
id == CSS_VAL_COLLAPSE)
00574 valid_primitive =
true;
00575
break;
00576
00577
case CSS_PROP_OVERFLOW:
00578
if (
id == CSS_VAL_VISIBLE ||
id == CSS_VAL_HIDDEN ||
id == CSS_VAL_SCROLL ||
id == CSS_VAL_AUTO ||
00579
id == CSS_VAL_MARQUEE)
00580 valid_primitive =
true;
00581
break;
00582
00583
case CSS_PROP_LIST_STYLE_POSITION:
00584
if (
id == CSS_VAL_INSIDE ||
id == CSS_VAL_OUTSIDE )
00585 valid_primitive =
true;
00586
break;
00587
00588
case CSS_PROP_LIST_STYLE_TYPE:
00589
00590
00591
00592
00593
if ((
id >= CSS_VAL_DISC &&
id <= CSS_VAL__KHTML_CLOSE_QUOTE) ||
id == CSS_VAL_NONE)
00594 valid_primitive =
true;
00595
break;
00596
00597
case CSS_PROP_DISPLAY:
00598
00599
00600
00601
if ((
id >= CSS_VAL_INLINE &&
id <= CSS_VAL_TABLE_CAPTION) ||
id == CSS_VAL_NONE)
00602 valid_primitive =
true;
00603
break;
00604
00605
case CSS_PROP_DIRECTION:
00606
if (
id == CSS_VAL_LTR ||
id == CSS_VAL_RTL )
00607 valid_primitive =
true;
00608
break;
00609
00610
case CSS_PROP_TEXT_TRANSFORM:
00611
if ((
id >= CSS_VAL_CAPITALIZE &&
id <= CSS_VAL_LOWERCASE) ||
id == CSS_VAL_NONE)
00612 valid_primitive =
true;
00613
break;
00614
00615
case CSS_PROP_FLOAT:
00616
if (
id == CSS_VAL_LEFT ||
id == CSS_VAL_RIGHT ||
00617
id == CSS_VAL_NONE ||
id == CSS_VAL_CENTER)
00618 valid_primitive =
true;
00619
break;
00620
00621
case CSS_PROP_CLEAR:
00622
if (
id == CSS_VAL_NONE ||
id == CSS_VAL_LEFT ||
00623
id == CSS_VAL_RIGHT||
id == CSS_VAL_BOTH)
00624 valid_primitive =
true;
00625
break;
00626
00627
case CSS_PROP_TEXT_ALIGN:
00628
00629
if ( (
id >= CSS_VAL__KHTML_AUTO &&
id <= CSS_VAL__KHTML_CENTER ) ||
00630 value->unit == CSSPrimitiveValue::CSS_STRING )
00631 valid_primitive =
true;
00632
break;
00633
00634
case CSS_PROP_OUTLINE_STYLE:
00635
case CSS_PROP_BORDER_TOP_STYLE:
00636
case CSS_PROP_BORDER_RIGHT_STYLE:
00637
case CSS_PROP_BORDER_BOTTOM_STYLE:
00638
case CSS_PROP_BORDER_LEFT_STYLE:
00639
if (
id >= CSS_VAL__KHTML_NATIVE &&
id <= CSS_VAL_DOUBLE)
00640 valid_primitive =
true;
00641
break;
00642
00643
case CSS_PROP_FONT_WEIGHT:
00644
00645
if (
id >= CSS_VAL_NORMAL &&
id <= CSS_VAL_900) {
00646
00647 valid_primitive =
true;
00648 }
else if ( validUnit( value, FInteger|FNonNeg,
false ) ) {
00649
int weight = (
int)value->fValue;
00650
if ( (weight % 100) )
00651
break;
00652 weight /= 100;
00653
if ( weight >= 1 && weight <= 9 ) {
00654
id = CSS_VAL_100 + weight - 1;
00655 valid_primitive =
true;
00656 }
00657 }
00658
break;
00659
00660
case CSS_PROP_BACKGROUND_REPEAT:
00661
if (
id >= CSS_VAL_REPEAT &&
id <= CSS_VAL_NO_REPEAT )
00662 valid_primitive =
true;
00663
break;
00664
00665
case CSS_PROP_BACKGROUND_ATTACHMENT:
00666
if (
id == CSS_VAL_SCROLL ||
id == CSS_VAL_FIXED )
00667 valid_primitive =
true;
00668
break;
00669
00670
case CSS_PROP_BACKGROUND_POSITION:
00671 {
00672 CSSPrimitiveValueImpl *pos[2];
00673 pos[0] = 0;
00674 pos[1] = 0;
00675
bool pos_ok[2];
00676 pos_ok[0] =
true;
00677 pos_ok[1] =
true;
00678
00679
00680
bool skip_next =
true;
00681
00682
00683
00684
00685
00686
00687
00688
00689
bool invalid =
false;
00690
switch(
id ) {
00691
case CSS_VAL_TOP:
00692 pos[0] = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_X,
true, pos_ok[0] );
00693
if ( pos[0] && pos_ok[0] && pos[0]->primitiveType() != CSSPrimitiveValue::CSS_IDENT )
00694 pos_ok[0] =
false;
00695 BACKGROUND_SKIP_CENTER( 0 )
00696 pos[1] = new CSSPrimitiveValueImpl( 0, CSSPrimitiveValue::CSS_PERCENTAGE );
00697 break;
00698 case CSS_VAL_BOTTOM:
00699 pos[0] = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_X, true, pos_ok[0] );
00700 kdDebug() << "pos[0] " << pos[0] << " " << pos_ok[0] << endl;
00701 if ( pos[0] && pos_ok[0] && pos[0]->primitiveType() != CSSPrimitiveValue::CSS_IDENT )
00702 pos_ok[0] = false;
00703 BACKGROUND_SKIP_CENTER( 0 )
00704 pos[1] = new CSSPrimitiveValueImpl( 100, CSSPrimitiveValue::CSS_PERCENTAGE );
00705 break;
00706 case CSS_VAL_LEFT:
00707 pos[0] = new CSSPrimitiveValueImpl( 0, CSSPrimitiveValue::CSS_PERCENTAGE );
00708 pos[1] = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_Y, true, pos_ok[1] );
00709 BACKGROUND_SKIP_CENTER( 1 )
00710
00711 break;
00712 case CSS_VAL_RIGHT:
00713 pos[0] = new CSSPrimitiveValueImpl( 100, CSSPrimitiveValue::CSS_PERCENTAGE );
00714 pos[1] = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_Y, true, pos_ok[1] );
00715 BACKGROUND_SKIP_CENTER( 1 )
00716
00717 break;
00718 case CSS_VAL_CENTER:
00719 value = valueList->next();
00720 if ( !value ) {
00721
00722 pos[0] = 0;
00723 pos[1] = 0;
00724 }
else {
00725
bool ok =
true;
00726 CSSPrimitiveValueImpl *possibly_x = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_Y,
false, ok );
00727
if ( !ok ) {
00728 assert( !possibly_x );
00729 pos[0] = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_X,
false, pos_ok[0] );
00730 BACKGROUND_SKIP_CENTER( 0 )
00731 pos[1] = 0;
00732 } else {
00733 pos[0] = 0;
00734 pos[1] = possibly_x;
00735 }
00736 }
00737
break;
00738
case 0:
00739 pos[0] = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_X,
false, pos_ok[0] );
00740
if ( pos[0] ) {
00741 pos[1] = parseBackgroundPositionXY( CSS_PROP_BACKGROUND_POSITION_Y,
true, pos_ok[1] );
00742
00743
if ( pos_ok[1] && pos[1] && pos[1]->primitiveType() == CSSPrimitiveValue::CSS_IDENT ) {
00744
00745
00746
switch ( pos[1]->getIdent() )
00747 {
00748
case CSS_VAL_RIGHT:
00749
case CSS_VAL_LEFT:
00750 pos_ok[1] =
false;
00751
break;
00752 }
00753 }
00754 }
00755
break;
00756
default:
00757 invalid =
true;
00758 }
00759
if ( invalid )
00760
break;
00761
00762
if ( !pos_ok[0] || !pos_ok[1] ) {
00763
delete pos[0];
00764
delete pos[1];
00765
return false;
00766 }
00767
00768
00769
if ( !pos[0] )
00770 pos[0] =
new CSSPrimitiveValueImpl( 50, CSSPrimitiveValue::CSS_PERCENTAGE );
00771
else if ( pos[0]->primitiveType() == CSSPrimitiveValue::CSS_IDENT )
00772 {
00773
00774
id = pos[0]->getIdent();
00775
delete pos[0];
00776
switch (
id ) {
00777
case CSS_VAL_LEFT:
00778 pos[0] =
new CSSPrimitiveValueImpl( 0, CSSPrimitiveValue::CSS_PERCENTAGE );
00779
break;
00780
case CSS_VAL_CENTER:
00781 pos[0] =
new CSSPrimitiveValueImpl( 50, CSSPrimitiveValue::CSS_PERCENTAGE );
00782
break;
00783
case CSS_VAL_RIGHT:
00784 pos[0] =
new CSSPrimitiveValueImpl( 100, CSSPrimitiveValue::CSS_PERCENTAGE );
00785
break;
00786
default:
00787 pos[0] = 0;
00788 assert(
false );
00789
break;
00790 }
00791 }
00792
if ( !pos[1] )
00793 pos[1] =
new CSSPrimitiveValueImpl( 50, CSSPrimitiveValue::CSS_PERCENTAGE );
00794
else if ( pos[1]->primitiveType() == CSSPrimitiveValue::CSS_IDENT )
00795 {
00796
00797
id = pos[1]->getIdent();
00798
delete pos[1];
00799
switch (
id ) {
00800
case CSS_VAL_TOP:
00801 pos[1] =
new CSSPrimitiveValueImpl( 0, CSSPrimitiveValue::CSS_PERCENTAGE );
00802
break;
00803
case CSS_VAL_CENTER:
00804 pos[1] =
new CSSPrimitiveValueImpl( 50, CSSPrimitiveValue::CSS_PERCENTAGE );
00805
break;
00806
case CSS_VAL_BOTTOM:
00807 pos[1] =
new CSSPrimitiveValueImpl( 100, CSSPrimitiveValue::CSS_PERCENTAGE );
00808
break;
00809
default:
00810 pos[1] = 0;
00811 assert(
false );
00812
break;
00813 }
00814 }
00815 --expected;
00816
if ( skip_next )
00817 valueList->next();
00818
if ( valueList->current() && expected == 0)
00819
return false;
00820
00821 addProperty( CSS_PROP_BACKGROUND_POSITION_X,
00822 pos[0],
00823 important );
00824 addProperty( CSS_PROP_BACKGROUND_POSITION_Y,
00825 pos[1],
00826 important );
00827
return true;
00828 }
00829
case CSS_PROP_BORDER_SPACING:
00830 {
00831
const int properties[2] = { CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING,
00832 CSS_PROP__KHTML_BORDER_VERTICAL_SPACING };
00833
int num = valueList->numValues;
00834
if (num == 1) {
00835
if (!parseValue(properties[0], important))
return false;
00836 CSSValueImpl* value = parsedProperties[numParsedProperties-1]->value();
00837 addProperty(properties[1], value, important);
00838
return true;
00839 }
00840
else if (num == 2) {
00841
if (!parseValue(properties[0], important, 2))
return false;
00842
if (!parseValue(properties[1], important, 1))
return false;
00843
return true;
00844 }
00845
return false;
00846 }
00847
case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING:
00848
case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING:
00849 valid_primitive = validUnit(value, FLength|FNonNeg, strict&(!nonCSSHint));
00850
break;
00851
00852
case CSS_PROP_SCROLLBAR_FACE_COLOR:
00853
case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
00854
case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
00855
case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
00856
case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
00857
case CSS_PROP_SCROLLBAR_TRACK_COLOR:
00858
case CSS_PROP_SCROLLBAR_ARROW_COLOR:
00859
case CSS_PROP_SCROLLBAR_BASE_COLOR:
00860
if ( strict )
00861
break;
00862
00863
case CSS_PROP_OUTLINE_COLOR:
00864
00865
if ( propId == CSS_PROP_OUTLINE_COLOR &&
id == CSS_VAL_INVERT ) {
00866 valid_primitive =
true;
00867
break;
00868 }
00869
00870
case CSS_PROP_BACKGROUND_COLOR:
00871
if ( propId == CSS_PROP_BACKGROUND_COLOR &&
id == CSS_VAL_TRANSPARENT ) {
00872 valid_primitive =
true;
00873
break;
00874 }
00875
00876
case CSS_PROP_COLOR:
00877
case CSS_PROP_BORDER_TOP_COLOR:
00878
case CSS_PROP_BORDER_RIGHT_COLOR:
00879
case CSS_PROP_BORDER_BOTTOM_COLOR:
00880
case CSS_PROP_BORDER_LEFT_COLOR:
00881
case CSS_PROP__KHTML_TEXT_DECORATION_COLOR:
00882
if (
id == CSS_VAL__KHTML_TEXT ||
id == CSS_VAL_MENU ||
00883 (
id >= CSS_VAL_AQUA &&
id <= CSS_VAL_WINDOWTEXT ) ||
00884
id == CSS_VAL_TRANSPARENT ||
00885 (
id >= CSS_VAL_GREY &&
id < CSS_VAL__KHTML_TEXT && (nonCSSHint|!strict) ) ) {
00886 valid_primitive =
true;
00887 }
else {
00888 parsedValue = parseColor();
00889
if ( parsedValue )
00890 valueList->next();
00891 }
00892
break;
00893
00894
case CSS_PROP_CURSOR:
00895
00896
00897
00898
00899
if ( !strict &&
id == CSS_VAL_HAND ) {
00900
id = CSS_VAL_POINTER;
00901 valid_primitive =
true;
00902 }
else if (
id >= CSS_VAL_AUTO &&
id <= CSS_VAL_HELP )
00903 valid_primitive =
true;
00904
break;
00905
00906
case CSS_PROP_BACKGROUND_IMAGE:
00907
case CSS_PROP_LIST_STYLE_IMAGE:
00908
00909
if (
id == CSS_VAL_NONE ) {
00910 parsedValue =
new CSSImageValueImpl();
00911 valueList->next();
00912
#ifdef CSS_DEBUG
00913
kdDebug( 6080 ) <<
"empty image " <<
endl;
00914
#endif
00915
}
else if ( value->unit == CSSPrimitiveValue::CSS_URI ) {
00916
00917
DOMString uri = khtml::parseURL( domString( value->string ) );
00918
if ( !uri.
isEmpty() ) {
00919 parsedValue =
new CSSImageValueImpl(
00920
DOMString(
KURL( styleElement->baseURL(), uri.
string()).url()),
00921 styleElement );
00922 valueList->next();
00923
#ifdef CSS_DEBUG
00924
kdDebug( 6080 ) <<
"image, url=" << uri.
string() <<
" base=" << styleElement->baseURL().url() <<
endl;
00925
#endif
00926
}
00927 }
00928
break;
00929
00930
case CSS_PROP_OUTLINE_WIDTH:
00931
case CSS_PROP_BORDER_TOP_WIDTH:
00932
case CSS_PROP_BORDER_RIGHT_WIDTH:
00933
case CSS_PROP_BORDER_BOTTOM_WIDTH:
00934
case CSS_PROP_BORDER_LEFT_WIDTH:
00935
if (
id == CSS_VAL_THIN ||
id == CSS_VAL_MEDIUM ||
id == CSS_VAL_THICK)
00936 valid_primitive =
true;
00937
else
00938 valid_primitive = ( validUnit( value, FLength, strict&(!nonCSSHint) ) );
00939
break;
00940
00941
case CSS_PROP_LETTER_SPACING:
00942
case CSS_PROP_WORD_SPACING:
00943
if (
id == CSS_VAL_NORMAL )
00944 valid_primitive =
true;
00945
else
00946 valid_primitive = validUnit( value, FLength, strict&(!nonCSSHint) );
00947
break;
00948
00949
case CSS_PROP_TEXT_INDENT:
00950 valid_primitive = ( !
id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
00951
break;
00952
00953
case CSS_PROP_PADDING_TOP:
00954
case CSS_PROP_PADDING_RIGHT:
00955
case CSS_PROP_PADDING_BOTTOM:
00956
case CSS_PROP_PADDING_LEFT:
00957 valid_primitive = ( !
id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
00958
break;
00959
00960
case CSS_PROP_MAX_HEIGHT:
00961
case CSS_PROP_MAX_WIDTH:
00962
if (
id == CSS_VAL_NONE ) {
00963 valid_primitive =
true;
00964
break;
00965 }
00966
00967
case CSS_PROP_MIN_HEIGHT:
00968
case CSS_PROP_MIN_WIDTH:
00969 valid_primitive = ( !
id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
00970
break;
00971
00972
case CSS_PROP_FONT_SIZE:
00973
00974
if (
id >= CSS_VAL_XX_SMALL &&
id <= CSS_VAL_LARGER)
00975 valid_primitive =
true;
00976
else
00977 valid_primitive = ( validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
00978
break;
00979
00980
case CSS_PROP_FONT_STYLE:
00981
if (
id == CSS_VAL_NORMAL ||
id == CSS_VAL_ITALIC ||
id == CSS_VAL_OBLIQUE)
00982 valid_primitive =
true;
00983
break;
00984
00985
case CSS_PROP_FONT_VARIANT:
00986
if (
id == CSS_VAL_NORMAL ||
id == CSS_VAL_SMALL_CAPS)
00987 valid_primitive =
true;
00988
break;
00989
00990
case CSS_PROP_VERTICAL_ALIGN:
00991
00992
00993
00994
if (
id >= CSS_VAL_BASELINE &&
id <= CSS_VAL__KHTML_BASELINE_MIDDLE )
00995 valid_primitive =
true;
00996
else
00997 valid_primitive = ( !
id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
00998
break;
00999
01000
case CSS_PROP_HEIGHT:
01001
case CSS_PROP_WIDTH:
01002
if (
id == CSS_VAL_AUTO )
01003 valid_primitive =
true;
01004
else
01005
01006 valid_primitive = ( !
id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
01007
break;
01008
01009
case CSS_PROP_BOTTOM:
01010
case CSS_PROP_LEFT:
01011
case CSS_PROP_RIGHT:
01012
case CSS_PROP_TOP:
01013
case CSS_PROP_MARGIN_TOP:
01014
case CSS_PROP_MARGIN_RIGHT:
01015
case CSS_PROP_MARGIN_BOTTOM:
01016
case CSS_PROP_MARGIN_LEFT:
01017
if (
id == CSS_VAL_AUTO )
01018 valid_primitive =
true;
01019
else
01020 valid_primitive = ( !
id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
01021
break;
01022
01023
case CSS_PROP_Z_INDEX:
01024
01025
if (
id == CSS_VAL_AUTO ) {
01026 valid_primitive =
true;
01027
break;
01028 }
01029
01030
case CSS_PROP_ORPHANS:
01031
case CSS_PROP_WIDOWS:
01032
01033 valid_primitive = ( !
id && validUnit( value, FInteger,
false ) );
01034
break;
01035
01036
case CSS_PROP_LINE_HEIGHT:
01037
if (
id == CSS_VAL_NORMAL )
01038 valid_primitive =
true;
01039
else
01040 valid_primitive = ( !
id && validUnit( value, FNumber|FLength|FPercent, strict&(!nonCSSHint) ) );
01041
break;
01042
case CSS_PROP_COUNTER_INCREMENT:
01043
if (
id == CSS_VAL_NONE )
01044 valid_primitive =
true;
01045
else
01046
return parseCounter(propId,
true, important);
01047
break;
01048
case CSS_PROP_COUNTER_RESET:
01049
if (
id == CSS_VAL_NONE )
01050 valid_primitive =
true;
01051
else
01052
return parseCounter(propId,
false, important);
01053
break;
01054
01055
case CSS_PROP_FONT_FAMILY:
01056
01057 {
01058 parsedValue = parseFontFamily();
01059
break;
01060 }
01061
01062
case CSS_PROP_TEXT_DECORATION:
01063
01064
if (
id == CSS_VAL_NONE) {
01065 valid_primitive =
true;
01066 }
else {
01067 CSSValueListImpl *list =
new CSSValueListImpl;
01068
bool is_valid =
true;
01069
while( is_valid && value ) {
01070
switch ( value->id ) {
01071
case CSS_VAL_BLINK:
01072
break;
01073
case CSS_VAL_UNDERLINE:
01074
case CSS_VAL_OVERLINE:
01075
case CSS_VAL_LINE_THROUGH:
01076 list->append(
new CSSPrimitiveValueImpl( value->id ) );
01077
break;
01078
default:
01079 is_valid =
false;
01080 }
01081 value = valueList->next();
01082 }
01083
01084
if(list->length() && is_valid) {
01085 parsedValue = list;
01086 valueList->next();
01087 }
else {
01088
delete list;
01089 }
01090 }
01091
break;
01092
01093
case CSS_PROP_TABLE_LAYOUT:
01094
if (
id == CSS_VAL_AUTO ||
id == CSS_VAL_FIXED )
01095 valid_primitive =
true;
01096
break;
01097
01098
case CSS_PROP__KHTML_FLOW_MODE:
01099
if (
id == CSS_VAL__KHTML_NORMAL ||
id == CSS_VAL__KHTML_AROUND_FLOATS )
01100 valid_primitive =
true;
01101
break;
01102
01103
01104
case CSS_PROP_BOX_SIZING:
01105
if (
id == CSS_VAL_BORDER_BOX ||
id == CSS_VAL_CONTENT_BOX )
01106 valid_primitive =
true;
01107
break;
01108
case CSS_PROP_OUTLINE_OFFSET:
01109 valid_primitive = validUnit(value, FLength, strict);
01110
break;
01111
case CSS_PROP_TEXT_SHADOW:
01112
if (
id == CSS_VAL_NONE)
01113 valid_primitive =
true;
01114
else
01115
return parseShadow(propId, important);
01116
break;
01117
case CSS_PROP_OPACITY:
01118 valid_primitive = validUnit(value, FNumber, strict);
01119
break;
01120
case CSS_PROP__KHTML_USER_INPUT:
01121
if (
id == CSS_VAL_NONE ||
id == CSS_VAL_ENABLED ||
id == CSS_VAL_DISABLED )
01122 valid_primitive =
true;
01123
01124
break;
01125
case CSS_PROP__KHTML_MARQUEE: {
01126
const int properties[5] = { CSS_PROP__KHTML_MARQUEE_DIRECTION, CSS_PROP__KHTML_MARQUEE_INCREMENT,
01127 CSS_PROP__KHTML_MARQUEE_REPETITION,
01128 CSS_PROP__KHTML_MARQUEE_STYLE, CSS_PROP__KHTML_MARQUEE_SPEED };
01129
return parseShortHand(properties, 5, important);
01130 }
01131
case CSS_PROP__KHTML_MARQUEE_DIRECTION:
01132
if (
id == CSS_VAL_FORWARDS ||
id == CSS_VAL_BACKWARDS ||
id == CSS_VAL_AHEAD ||
01133
id == CSS_VAL_REVERSE ||
id == CSS_VAL_LEFT ||
id == CSS_VAL_RIGHT ||
id == CSS_VAL_DOWN ||
01134
id == CSS_VAL_UP ||
id == CSS_VAL_AUTO)
01135 valid_primitive =
true;
01136
break;
01137
case CSS_PROP__KHTML_MARQUEE_INCREMENT:
01138
if (
id == CSS_VAL_SMALL ||
id == CSS_VAL_LARGE ||
id == CSS_VAL_MEDIUM)
01139 valid_primitive =
true;
01140
else
01141 valid_primitive = validUnit(value, FLength|FPercent, strict&(!nonCSSHint));
01142
break;
01143
case CSS_PROP__KHTML_MARQUEE_STYLE:
01144
if (
id == CSS_VAL_NONE ||
id == CSS_VAL_SLIDE ||
id == CSS_VAL_SCROLL ||
id == CSS_VAL_ALTERNATE ||
01145
id == CSS_VAL_UNFURL)
01146 valid_primitive =
true;
01147
break;
01148
case CSS_PROP__KHTML_MARQUEE_REPETITION:
01149
if (
id == CSS_VAL_INFINITE)
01150 valid_primitive =
true;
01151
else
01152 valid_primitive = validUnit(value, FInteger|FNonNeg, strict&(!nonCSSHint));
01153
break;
01154
case CSS_PROP__KHTML_MARQUEE_SPEED:
01155
if (
id == CSS_VAL_NORMAL ||
id == CSS_VAL_SLOW ||
id == CSS_VAL_FAST)
01156 valid_primitive =
true;
01157
else
01158 valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict&(!nonCSSHint));
01159
break;
01160
01161
01162
01163
case CSS_PROP_BACKGROUND:
01164
01165
01166 {
01167
01168
01169
01170
01171
01172
const int properties[5] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,
01173 CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION,
01174 CSS_PROP_BACKGROUND_COLOR };
01175
return parseShortHand(properties, 5, important);
01176 }
01177
case CSS_PROP_BORDER:
01178
01179 {
01180
const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
01181 CSS_PROP_BORDER_COLOR };
01182
return parseShortHand(properties, 3, important);
01183 }
01184
case CSS_PROP_BORDER_TOP:
01185
01186 {
01187
const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
01188 CSS_PROP_BORDER_TOP_COLOR};
01189
return parseShortHand(properties, 3, important);
01190 }
01191
case CSS_PROP_BORDER_RIGHT:
01192
01193 {
01194
const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
01195 CSS_PROP_BORDER_RIGHT_COLOR };
01196
return parseShortHand(properties, 3, important);
01197 }
01198
case CSS_PROP_BORDER_BOTTOM:
01199
01200 {
01201
const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
01202 CSS_PROP_BORDER_BOTTOM_COLOR };
01203
return parseShortHand(properties, 3, important);
01204 }
01205
case CSS_PROP_BORDER_LEFT:
01206
01207 {
01208
const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
01209 CSS_PROP_BORDER_LEFT_COLOR };
01210
return parseShortHand(properties, 3, important);
01211 }
01212
case CSS_PROP_OUTLINE:
01213
01214 {
01215
const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
01216 CSS_PROP_OUTLINE_COLOR };
01217
return parseShortHand(properties, 3, important);
01218 }
01219
case CSS_PROP_BORDER_COLOR:
01220
01221 {
01222
const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
01223 CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
01224
return parse4Values(properties, important);
01225 }
01226
case CSS_PROP_BORDER_WIDTH:
01227
01228 {
01229
const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
01230 CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
01231
return parse4Values(properties, important);
01232 }
01233
case CSS_PROP_BORDER_STYLE:
01234
01235 {
01236
const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
01237 CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
01238
return parse4Values(properties, important);
01239 }
01240
case CSS_PROP_MARGIN:
01241
01242 {
01243
const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
01244 CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
01245
return parse4Values(properties, important);
01246 }
01247
case CSS_PROP_PADDING:
01248
01249 {
01250
const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
01251 CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
01252
return parse4Values(properties, important);
01253 }
01254
case CSS_PROP_FONT:
01255
01256
01257
if (
id >= CSS_VAL_CAPTION &&
id <= CSS_VAL_STATUS_BAR )
01258 valid_primitive =
true;
01259
else
01260
return parseFont(important);
01261
01262
case CSS_PROP_LIST_STYLE:
01263 {
01264
const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
01265 CSS_PROP_LIST_STYLE_IMAGE };
01266
return parseShortHand(properties, 3, important);
01267 }
01268
default:
01269
01270
01271
01272
break;
01273 }
01274
01275
if ( valid_primitive ) {
01276
01277
if (
id != 0 ) {
01278
01279 parsedValue =
new CSSPrimitiveValueImpl(
id );
01280 }
else if ( value->unit == CSSPrimitiveValue::CSS_STRING )
01281 parsedValue =
new CSSPrimitiveValueImpl( domString( value->string ),
01282 (CSSPrimitiveValue::UnitTypes) value->unit );
01283
else if ( value->unit >= CSSPrimitiveValue::CSS_NUMBER &&
01284 value->unit <= CSSPrimitiveValue::CSS_KHZ ) {
01285
01286 parsedValue =
new CSSPrimitiveValueImpl( value->fValue,
01287 (CSSPrimitiveValue::UnitTypes) value->unit );
01288 }
else if ( value->unit >= Value::Q_EMS ) {
01289
01290 parsedValue =
new CSSQuirkPrimitiveValueImpl( value->fValue, CSSPrimitiveValue::CSS_EMS );
01291 }
01292 --expected;
01293 valueList->next();
01294
if ( valueList->current() && expected == 0)
01295 {
01296
delete parsedValue;
01297 parsedValue = 0;
01298 }
01299 }
01300
if ( parsedValue ) {
01301 addProperty( propId, parsedValue, important );
01302
return true;
01303 }
01304
return false;
01305 }
01306
01307
bool CSSParser::parseShortHand(
const int *properties,
int numProperties,
bool important )
01308 {
01309
01310
01311
01312
01313 inParseShortHand =
true;
01314
01315
bool found =
false;
01316
int oldPropIndex = numParsedProperties;
01317
bool fnd[6];
01318
for(
int i = 0; i < numProperties; i++ )
01319 fnd[i] =
false;
01320
01321
#ifdef CSS_DEBUG
01322
kdDebug(6080) <<
"PSH: numProperties=" << numProperties <<
endl;
01323
#endif
01324
01325
while ( valueList->current() ) {
01326 found =
false;
01327
01328
for (
int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
01329
if (!fnd[propIndex]) {
01330
#ifdef CSS_DEBUG
01331
kdDebug(6080) <<
"LOOKING FOR: " << getPropertyName(properties[propIndex]).
string() <<
endl;
01332
#endif
01333
if ( parseValue( properties[propIndex], important, numProperties ) ) {
01334 fnd[propIndex] = found =
true;
01335
#ifdef CSS_DEBUG
01336
kdDebug(6080) <<
"FOUND: " << getPropertyName(properties[propIndex]).
string() <<
endl;
01337
#endif
01338
}
01339 }
01340 }
01341
01342
01343
if (!found) {
01344
#ifdef CSS_DEBUG
01345
qDebug(
"didn't find anything" );
01346
#endif
01347
01348
01349
for (
int i = oldPropIndex; i < numParsedProperties; ++i )
01350
delete parsedProperties[i];
01351
01352 numParsedProperties = oldPropIndex;
01353 inParseShortHand =
false;
01354
return false;
01355 }
01356 }
01357
01358
01359
for (
int i = 0; i < numProperties; ++i) {
01360
if (!fnd[i])
01361 addProperty(properties[i],
new CSSInitialValueImpl(), important);
01362 }
01363
01364 inParseShortHand =
false;
01365
#ifdef CSS_DEBUG
01366
kdDebug( 6080 ) <<
"parsed shorthand" <<
endl;
01367
#endif
01368
return true;
01369 }
01370
01371
bool CSSParser::parse4Values(
const int *properties,
bool important )
01372 {
01373
01374
01375
01376
01377
01378
01379
01380
01381
int num = inParseShortHand ? 1 : valueList->numValues;
01382
01383
01384
01385
switch( num ) {
01386
case 1: {
01387
if( !parseValue( properties[0], important, valueList->numValues ) )
return false;
01388 CSSValueImpl *value = parsedProperties[numParsedProperties-1]->value();
01389 addProperty( properties[1], value, important );
01390 addProperty( properties[2], value, important );
01391 addProperty( properties[3], value, important );
01392
return true;
01393 }
01394
case 2: {
01395
01396
if( !parseValue( properties[0], important, valueList->numValues ) )
return false;
01397
if( !parseValue( properties[1], important, valueList->numValues) )
return false;
01398 CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();
01399 addProperty( properties[2], value, important );
01400 value = parsedProperties[numParsedProperties-2]->value();
01401 addProperty( properties[3], value, important );
01402
return true;
01403 }
01404
case 3: {
01405
if( !parseValue( properties[0], important, valueList->numValues ) )
return false;
01406
if( !parseValue( properties[1], important, valueList->numValues ) )
return false;
01407
if( !parseValue( properties[2], important, valueList->numValues ) )
return false;
01408 CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();
01409 addProperty( properties[3], value, important );
01410
return true;
01411 }
01412
case 4: {
01413
if( !parseValue( properties[0], important, valueList->numValues ) )
return false;
01414
if( !parseValue( properties[1], important, valueList->numValues ) )
return false;
01415
if( !parseValue( properties[2], important, valueList->numValues ) )
return false;
01416
if( !parseValue( properties[3], important, valueList->numValues ) )
return false;
01417
return true;
01418 }
01419
default:
01420
return false;
01421 }
01422 }
01423
01424
01425
01426
01427
bool CSSParser::parseContent(
int propId,
bool important )
01428 {
01429 CSSValueListImpl* values =
new CSSValueListImpl();
01430
01431 Value *val;
01432 CSSValueImpl *parsedValue = 0;
01433
while ( (val = valueList->current()) ) {
01434
if ( val->unit == CSSPrimitiveValue::CSS_URI ) {
01435
01436
DOMString value = khtml::parseURL(domString(val->string));
01437 parsedValue =
new CSSImageValueImpl(
01438
DOMString(
KURL( styleElement->baseURL(), value.
string()).url() ), styleElement );
01439
#ifdef CSS_DEBUG
01440
kdDebug( 6080 ) <<
"content, url=" << value.
string() <<
" base=" << styleElement->baseURL().url( ) <<
endl;
01441
#endif
01442
}
else if ( val->unit == Value::Function ) {
01443
01444 ValueList *args = val->function->args;
01445
QString fname = qString( val->function->name ).lower();
01446
if (!args)
return false;
01447
if (fname ==
"attr(") {
01448
if ( args->numValues != 1)
01449
return false;
01450 Value *a = args->current();
01451 parsedValue =
new CSSPrimitiveValueImpl(domString(a->string), CSSPrimitiveValue::CSS_ATTR);
01452 }
01453
else
01454
if (fname ==
"counter(") {
01455 parsedValue = parseCounterContent(args,
false);
01456
if (!parsedValue)
return false;
01457 }
else
01458
if (fname ==
"counters(") {
01459 parsedValue = parseCounterContent(args,
true);
01460
if (!parsedValue)
return false;
01461 }
01462
else
01463
return false;
01464
01465 }
else if ( val->unit == CSSPrimitiveValue::CSS_IDENT ) {
01466
01467
if ( val->id == CSS_VAL_OPEN_QUOTE ||
01468 val->id == CSS_VAL_CLOSE_QUOTE ||
01469 val->id == CSS_VAL_NO_OPEN_QUOTE ||
01470 val->id == CSS_VAL_NO_CLOSE_QUOTE ) {
01471 parsedValue =
new CSSPrimitiveValueImpl(val->id);
01472 }
01473 }
else if ( val->unit == CSSPrimitiveValue::CSS_STRING ) {
01474 parsedValue =
new CSSPrimitiveValueImpl(domString(val->string), CSSPrimitiveValue::CSS_STRING);
01475 }
01476
if (parsedValue)
01477 values->append(parsedValue);
01478
else
01479
break;
01480 valueList->next();
01481 }
01482
if ( values->length() ) {
01483 addProperty( propId, values, important );
01484 valueList->next();
01485
return true;
01486 }
01487
delete values;
01488
return false;
01489 }
01490
01491 CSSValueImpl* CSSParser::parseCounterContent(ValueList *args,
bool counters)
01492 {
01493
if (counters || (args->numValues != 1 && args->numValues != 3))
01494
if (!counters || (args->numValues != 3 && args->numValues != 5))
01495
return 0;
01496
01497 CounterImpl *counter =
new CounterImpl;
01498 Value *i = args->current();
01499
01500 counter->m_identifier = domString(i->string);
01501
if (counters) {
01502 i = args->next();
01503
if (i->unit != Value::Operator || i->iValue !=
',')
goto invalid;
01504 i = args->next();
01505
if (i->unit != CSSPrimitiveValue::CSS_STRING)
goto invalid;
01506 counter->m_separator = domString(i->string);
01507 }
01508 counter->m_listStyle = CSS_VAL_DECIMAL - CSS_VAL_DISC;
01509 i = args->next();
01510
if (i) {
01511
if (i->unit != Value::Operator || i->iValue !=
',')
goto invalid;
01512 i = args->next();
01513
if (i->unit != CSSPrimitiveValue::CSS_IDENT)
goto invalid;
01514
if (i->id < CSS_VAL_DISC || i->id > CSS_VAL__KHTML_CLOSE_QUOTE)
goto invalid;
01515 counter->m_listStyle = i->id - CSS_VAL_DISC;
01516 }
01517
return new CSSPrimitiveValueImpl(counter);
01518 invalid:
01519
delete counter;
01520
return 0;
01521 }
01522
01523
bool CSSParser::parseShape(
int propId,
bool important )
01524 {
01525 Value *value = valueList->current();
01526 ValueList *args = value->function->args;
01527
QString fname = qString( value->function->name ).lower();
01528
01529
if ( fname !=
"rect(" || !args )
01530
return false;
01531
01532
01533
if ( args->numValues != 4 && args->numValues != 7 )
01534
return false;
01535 RectImpl *rect =
new RectImpl();
01536
bool valid =
true;
01537
int i = 0;
01538 Value *a = args->current();
01539
while ( a ) {
01540 valid = validUnit( a, FLength, strict );
01541
if ( !valid )
01542
break;
01543 CSSPrimitiveValueImpl *length =
01544
new CSSPrimitiveValueImpl( a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit );
01545
if ( i == 0 )
01546 rect->setTop( length );
01547
else if ( i == 1 )
01548 rect->setRight( length );
01549
else if ( i == 2 )
01550 rect->setBottom( length );
01551
else
01552 rect->setLeft( length );
01553 a = args->next();
01554
if ( a && args->numValues == 7 ) {
01555
if ( a->unit == Value::Operator && a->iValue ==
',' ) {
01556 a = args->next();
01557 }
else {
01558 valid =
false;
01559
break;
01560 }
01561 }
01562 i++;
01563 }
01564
if ( valid ) {
01565 addProperty( propId,
new CSSPrimitiveValueImpl( rect ), important );
01566 valueList->next();
01567
return true;
01568 }
01569
delete rect;
01570
return false;
01571 }
01572
01573
01574
bool CSSParser::parseFont(
bool important )
01575 {
01576
01577
bool valid =
true;
01578 Value *value = valueList->current();
01579 FontValueImpl *font =
new FontValueImpl;
01580
01581
while ( value ) {
01582
01583
01584
01585
int id = value->id;
01586
if (
id ) {
01587
if (
id == CSS_VAL_NORMAL ) {
01588
01589 }
01590
01591
01592
01593
01594
01595
01596
01597
else if (
id == CSS_VAL_ITALIC ||
id == CSS_VAL_OBLIQUE ) {
01598
if ( font->style )
01599
goto invalid;
01600 font->style =
new CSSPrimitiveValueImpl(
id );
01601 }
else if (
id == CSS_VAL_SMALL_CAPS ) {
01602
if ( font->variant )
01603
goto invalid;
01604 font->variant =
new CSSPrimitiveValueImpl(
id );
01605 }
else if (
id >= CSS_VAL_BOLD &&
id <= CSS_VAL_LIGHTER ) {
01606
if ( font->weight )
01607
goto invalid;
01608 font->weight =
new CSSPrimitiveValueImpl(
id );
01609 }
else {
01610 valid =
false;
01611 }
01612 }
else if ( !font->weight && validUnit( value, FInteger|FNonNeg,
true ) ) {
01613
int weight = (
int)value->fValue;
01614
int val = 0;
01615
if ( weight == 100 )
01616 val = CSS_VAL_100;
01617
else if ( weight == 200 )
01618 val = CSS_VAL_200;
01619
else if ( weight == 300 )
01620 val = CSS_VAL_300;
01621
else if ( weight == 400 )
01622 val = CSS_VAL_400;
01623
else if ( weight == 500 )
01624 val = CSS_VAL_500;
01625
else if ( weight == 600 )
01626 val = CSS_VAL_600;
01627
else if ( weight == 700 )
01628 val = CSS_VAL_700;
01629
else if ( weight == 800 )
01630 val = CSS_VAL_800;
01631
else if ( weight == 900 )
01632 val = CSS_VAL_900;
01633
01634
if ( val )
01635 font->weight =
new CSSPrimitiveValueImpl( val );
01636
else
01637 valid =
false;
01638 }
else {
01639 valid =
false;
01640 }
01641
if ( !valid )
01642
break;
01643 value = valueList->next();
01644 }
01645
if ( !value )
01646
goto invalid;
01647
01648
01649
if ( !font->style )
01650 font->style =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01651
if ( !font->variant )
01652 font->variant =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01653
if ( !font->weight )
01654 font->weight =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01655
01656
01657
01658
01659
01660
if ( value->id >= CSS_VAL_XX_SMALL && value->id <= CSS_VAL_LARGER )
01661 font->size =
new CSSPrimitiveValueImpl( value->id );
01662
else if ( validUnit( value, FLength|FPercent, strict ) ) {
01663 font->size =
new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit );
01664 }
01665 value = valueList->next();
01666
if ( !font->size || !value )
01667
goto invalid;
01668
01669
01670
01671
if ( value->unit == Value::Operator && value->iValue ==
'/' ) {
01672
01673 value = valueList->next();
01674
if ( !value )
01675
goto invalid;
01676
if ( value->id == CSS_VAL_NORMAL ) {
01677
01678 }
else if ( validUnit( value, FNumber|FLength|FPercent, strict ) ) {
01679 font->lineHeight =
new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit );
01680 }
else {
01681
goto invalid;
01682 }
01683 value = valueList->next();
01684
if ( !value )
01685
goto invalid;
01686 }
01687
if ( !font->lineHeight )
01688 font->lineHeight =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01689
01690
01691
01692 font->family = parseFontFamily();
01693
01694
if ( valueList->current() || !font->family )
01695
goto invalid;
01696
01697
01698 addProperty( CSS_PROP_FONT, font, important );
01699
return true;
01700
01701 invalid:
01702
01703
delete font;
01704
return false;
01705 }
01706
01707 CSSValueListImpl *CSSParser::parseFontFamily()
01708 {
01709
01710 CSSValueListImpl *list =
new CSSValueListImpl;
01711 Value *value = valueList->current();
01712
QString currFace;
01713
01714
while ( value ) {
01715
01716
01717
01718
01719 Value* nextValue = valueList->next();
01720
bool nextValBreaksFont = !nextValue ||
01721 (nextValue->unit == Value::Operator && nextValue->iValue ==
',');
01722
bool nextValIsFontName = nextValue &&
01723 ((nextValue->id >= CSS_VAL_SERIF && nextValue->id <= CSS_VAL_MONOSPACE) ||
01724 (nextValue->unit == CSSPrimitiveValue::CSS_STRING ||
01725 nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
01726
01727
if (value->id >= CSS_VAL_SERIF && value->id <= CSS_VAL_MONOSPACE) {
01728
if (!currFace.isNull()) {
01729 currFace +=
' ';
01730 currFace += qString(value->string);
01731 }
01732
else if (nextValBreaksFont || !nextValIsFontName) {
01733
if ( !currFace.isNull() ) {
01734 list->append(
new FontFamilyValueImpl( currFace ) );
01735 currFace = QString::null;
01736 }
01737 list->append(
new CSSPrimitiveValueImpl(value->id));
01738 }
01739
else {
01740 currFace = qString( value->string );
01741 }
01742 }
01743
else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
01744
01745 currFace = QString::null;
01746 list->append(
new FontFamilyValueImpl(qString( value->string) ) );
01747 }
01748
else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
01749
if (!currFace.isNull()) {
01750 currFace +=
' ';
01751 currFace += qString(value->string);
01752 }
01753
else if (nextValBreaksFont || !nextValIsFontName) {
01754
if ( !currFace.isNull() ) {
01755 list->append(
new FontFamilyValueImpl( currFace ) );
01756 currFace = QString::null;
01757 }
01758 list->append(
new FontFamilyValueImpl( qString( value->string ) ) );
01759 }
01760
else {
01761 currFace = qString( value->string);
01762 }
01763 }
01764
else {
01765
01766
break;
01767 }
01768
01769
if (!nextValue)
01770
break;
01771
01772
if (nextValBreaksFont) {
01773 value = valueList->next();
01774
if ( !currFace.isNull() )
01775 list->append(
new FontFamilyValueImpl( currFace ) );
01776 currFace = QString::null;
01777 }
01778
else if (nextValIsFontName)
01779 value = nextValue;
01780
else
01781
break;
01782 }
01783
01784
if ( !currFace.isNull() )
01785 list->append(
new FontFamilyValueImpl( currFace ) );
01786
01787
if ( !list->length() ) {
01788
delete list;
01789 list = 0;
01790 }
01791
return list;
01792 }
01793
01794
01795
static bool parseColor(
int unit,
const QString &name, QRgb& rgb)
01796 {
01797
int len =
name.length();
01798
01799
if ( !len )
01800
return false;
01801
01802
01803
bool ok;
01804
01805
if ( len == 3 || len == 6 ) {
01806
int val =
name.toInt(&ok, 16);
01807
if ( ok ) {
01808
if (len == 6) {
01809 rgb = (0xff << 24) | val;
01810
return true;
01811 }
01812
else if ( len == 3 ) {
01813
01814 rgb = (0xff << 24) |
01815 (val&0xf00)<<12 | (val&0xf00)<<8 |
01816 (val&0xf0)<<8 | (val&0xf0)<<4 |
01817 (val&0xf)<<4 | (val&0xf);
01818
return true;
01819 }
01820 }
01821 }
01822
01823
if ( unit == CSSPrimitiveValue::CSS_IDENT ) {
01824
01825
QColor tc;
01826 tc.setNamedColor(
name.lower());
01827
if ( tc.isValid() ) {
01828 rgb = tc.rgb();
01829
return true;
01830 }
01831 }
01832
01833
return false;
01834 }
01835
01836 CSSPrimitiveValueImpl *CSSParser::parseColor()
01837 {
01838
return parseColorFromValue(valueList->current());
01839 }
01840
01841 CSSPrimitiveValueImpl *CSSParser::parseColorFromValue(Value* value)
01842 {
01843 QRgb c = khtml::transparentColor;
01844
if ( !strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
01845 value->fValue >= 0. && value->fValue < 1000000. ) {
01846
QString str;
01847 str.sprintf(
"%06d", (
int)(value->fValue+.5) );
01848 if ( !::parseColor( value->unit, str, c ) )
01849
return 0;
01850 }
else if ( value->unit == CSSPrimitiveValue::CSS_RGBCOLOR ||
01851 value->unit == CSSPrimitiveValue::CSS_IDENT ||
01852 (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION) ) {
01853
if ( !::parseColor( value->unit, qString( value->string ), c) )
01854
return 0;
01855 }
01856
else if ( value->unit == Value::Function &&
01857 value->function->args != 0 &&
01858 value->function->args->numValues == 5 &&
01859 qString( value->function->name ).lower() ==
"rgb(" ) {
01860 ValueList *args = value->function->args;
01861 Value *v = args->current();
01862
if ( !validUnit( v, FInteger|FPercent,
true ) )
01863
return 0;
01864
int r = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01865 v = args->next();
01866
if ( v->unit != Value::Operator && v->iValue !=
',' )
01867
return 0;
01868 v = args->next();
01869
if ( !validUnit( v, FInteger|FPercent,
true ) )
01870
return 0;
01871
int g = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01872 v = args->next();
01873
if ( v->unit != Value::Operator && v->iValue !=
',' )
01874
return 0;
01875 v = args->next();
01876
if ( !validUnit( v, FInteger|FPercent,
true ) )
01877
return 0;
01878
int b = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01879 r = kMax( 0, kMin( 255, r ) );
01880 g = kMax( 0, kMin( 255, g ) );
01881 b = kMax( 0, kMin( 255, b ) );
01882 c = qRgb( r, g, b );
01883 }
01884
else if ( value->unit == Value::Function &&
01885 value->function->args != 0 &&
01886 value->function->args->numValues == 7 &&
01887 qString( value->function->name ).lower() ==
"rgba(" ) {
01888 ValueList *args = value->function->args;
01889 Value *v = args->current();
01890
if ( !validUnit( v, FInteger|FPercent,
true ) )
01891
return 0;
01892
int r = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01893 v = args->next();
01894
if ( v->unit != Value::Operator && v->iValue !=
',' )
01895
return 0;
01896 v = args->next();
01897
if ( !validUnit( v, FInteger|FPercent,
true ) )
01898
return 0;
01899
int g = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01900 v = args->next();
01901
if ( v->unit != Value::Operator && v->iValue !=
',' )
01902
return 0;
01903 v = args->next();
01904
if ( !validUnit( v, FInteger|FPercent,
true ) )
01905
return 0;
01906
int b = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01907 v = args->next();
01908
if ( v->unit != Value::Operator && v->iValue !=
',' )
01909
return 0;
01910 v = args->next();
01911
if ( !validUnit( v, FNumber,
true ) )
01912
return 0;
01913 r = QMAX( 0, QMIN( 255, r ) );
01914 g = QMAX( 0, QMIN( 255, g ) );
01915 b = QMAX( 0, QMIN( 255, b ) );
01916
int a = (
int)(QMAX( 0, QMIN( 1.0f, v->fValue ) ) * 255);
01917 c = qRgba( r, g, b, a );
01918 }
01919
else
01920
return 0;
01921
01922
return new CSSPrimitiveValueImpl(c);
01923 }
01924
01925
01926
01927
struct ShadowParseContext {
01928 ShadowParseContext()
01929 :values(0), x(0), y(0), blur(0), color(0),
01930 allowX(true), allowY(false), allowBlur(false), allowColor(true),
01931 allowBreak(true)
01932 {}
01933
01934 ~ShadowParseContext() {
01935
if (!allowBreak) {
01936
delete values;
01937
delete x;
01938
delete y;
01939
delete blur;
01940
delete color;
01941 }
01942 }
01943
01944
bool allowLength() {
return allowX || allowY || allowBlur; }
01945
01946
bool failed() {
return allowBreak =
false; }
01947
01948
void commitValue() {
01949
01950
if (x || y || blur || color) {
01951
if (!values)
01952 values =
new CSSValueListImpl();
01953
01954
01955 values->append(
new ShadowValueImpl(x, y, blur, color));
01956 }
01957
01958
01959 x = y = blur = color = 0;
01960 allowX = allowColor = allowBreak =
true;
01961 allowY = allowBlur =
false;
01962 }
01963
01964
void commitLength(Value* v) {
01965 CSSPrimitiveValueImpl* val =
new CSSPrimitiveValueImpl(v->fValue,
01966 (CSSPrimitiveValue::UnitTypes)v->unit);
01967
if (allowX) {
01968 x = val;
01969 allowX =
false; allowY =
true; allowColor =
false; allowBreak =
false;
01970 }
01971
else if (allowY) {
01972 y = val;
01973 allowY =
false; allowBlur =
true; allowColor =
true; allowBreak =
true;
01974 }
01975
else if (allowBlur) {
01976 blur = val;
01977 allowBlur =
false;
01978 }
01979 }
01980
01981
void commitColor(CSSPrimitiveValueImpl* val) {
01982 color = val;
01983 allowColor =
false;
01984
if (allowX)
01985 allowBreak =
false;
01986
else
01987 allowBlur =
false;
01988 }
01989
01990 CSSValueListImpl* values;
01991 CSSPrimitiveValueImpl* x;
01992 CSSPrimitiveValueImpl* y;
01993 CSSPrimitiveValueImpl* blur;
01994 CSSPrimitiveValueImpl* color;
01995
01996
bool allowX;
01997
bool allowY;
01998
bool allowBlur;
01999
bool allowColor;
02000
bool allowBreak;
02001 };
02002
02003
bool CSSParser::parseShadow(
int propId,
bool important)
02004 {
02005 ShadowParseContext context;
02006 Value* val;
02007
while ((val = valueList->current())) {
02008
02009
if (val->unit == Value::Operator) {
02010
if (val->iValue !=
',' || !context.allowBreak)
02011
02012
02013
return context.failed();
02014
02015
02016 context.commitValue();
02017 }
02018
02019
else if (validUnit(val, FLength,
true)) {
02020
02021
if (!context.allowLength())
02022
return context.failed();
02023
02024
02025 context.commitLength(val);
02026 }
02027
else {
02028
02029 CSSPrimitiveValueImpl* parsedColor = 0;
02030
bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU ||
02031 (val->id >= CSS_VAL_GREY && val->id <= CSS_VAL__KHTML_TEXT && !strict));
02032
if (isColor) {
02033
if (!context.allowColor)
02034
return context.failed();
02035 parsedColor =
new CSSPrimitiveValueImpl(val->id);
02036 }
02037
02038
if (!parsedColor)
02039
02040 parsedColor = parseColorFromValue(val);
02041
02042
if (!parsedColor || !context.allowColor)
02043
return context.failed();
02044
02045
02046 context.commitColor(parsedColor);
02047 }
02048
02049 valueList->next();
02050 }
02051
02052
if (context.allowBreak) {
02053 context.commitValue();
02054
if (context.values->length()) {
02055 addProperty(propId, context.values, important);
02056 valueList->next();
02057
return true;
02058 }
02059 }
02060
02061
return context.failed();
02062 }
02063
02064
bool CSSParser::parseCounter(
int propId,
bool increment,
bool important)
02065 {
02066
enum { ID, VAL } state = ID;
02067
02068 CSSValueListImpl *list =
new CSSValueListImpl;
02069
DOMString c;
02070 Value* val;
02071
while (
true) {
02072 val = valueList->current();
02073
switch (state) {
02074
case ID:
02075
if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
02076 c = qString(val->string);
02077 state = VAL;
02078 valueList->next();
02079
continue;
02080 }
02081
break;
02082
case VAL: {
02083
short i = 0;
02084
if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
02085 i = (
short)val->fValue;
02086 valueList->next();
02087 }
else
02088 i = (increment) ? 1 : 0;
02089
02090 CounterActImpl *cv =
new CounterActImpl(c,i);
02091 list->append(cv);
02092 state = ID;
02093
continue;
02094 }
02095 }
02096
break;
02097 }
02098
if(list->length() > 0) {
02099 addProperty( propId, list, important );
02100
return true;
02101 }
02102
delete list;
02103
return false;
02104 }
02105
02106
static inline int yyerror(
const char *str ) {
02107
02108
#ifdef CSS_DEBUG
02109
kdDebug( 6080 ) <<
"CSS parse error " << str <<
endl;
02110
#else
02111
Q_UNUSED( str );
02112
#endif
02113
return 1;
02114 }
02115
02116
#define END 0
02117
02118
#include "parser.h"
02119
02120
int DOM::CSSParser::lex(
void *_yylval )
02121 {
02122 YYSTYPE *yylval = (YYSTYPE *)_yylval;
02123
int token = lex();
02124
int length;
02125
unsigned short *t = text( &length );
02126
02127
#ifdef TOKEN_DEBUG
02128
qDebug(
"CSSTokenizer: got token %d: '%s'", token, token == END ?
"" :
QString( (
QChar *)t, length ).latin1() );
02129
#endif
02130
switch( token ) {
02131
case '{':
02132 block_nesting++;
02133
break;
02134
case '}':
02135
if ( block_nesting )
02136 block_nesting--;
02137
break;
02138
case END:
02139
if ( block_nesting ) {
02140 block_nesting--;
02141
return '}';
02142 }
02143
break;
02144
case S:
02145
case SGML_CD:
02146
case INCLUDES:
02147
case DASHMATCH:
02148
break;
02149
02150
case URI:
02151
case STRING:
02152
case IDENT:
02153
case NTH:
02154
case HASH:
02155
case DIMEN:
02156
case UNICODERANGE:
02157
case NOTFUNCTION:
02158
case FUNCTION:
02159 yylval->string.string = t;
02160 yylval->string.length = length;
02161
break;
02162
02163
case IMPORT_SYM:
02164
case PAGE_SYM:
02165
case MEDIA_SYM:
02166
case FONT_FACE_SYM:
02167
case CHARSET_SYM:
02168
02169
case IMPORTANT_SYM:
02170
break;
02171
02172
case QEMS:
02173 length--;
02174
case GRADS:
02175 length--;
02176
case DEGS:
02177
case RADS:
02178
case KHERZ:
02179 length--;
02180
case MSECS:
02181
case HERZ:
02182
case EMS:
02183
case EXS:
02184
case PXS:
02185
case CMS:
02186
case MMS:
02187
case INS:
02188
case PTS:
02189
case PCS:
02190 length--;
02191
case SECS:
02192
case PERCENTAGE:
02193 length--;
02194
case NUMBER:
02195 yylval->val =
QString( (QChar *)t, length ).toDouble();
02196
02197
break;
02198
02199
default:
02200
break;
02201 }
02202
02203
return token;
02204 }
02205
02206
static inline int toHex(
char c ) {
02207
if (
'0' <= c && c <=
'9' )
02208
return c -
'0';
02209
if (
'a' <= c && c <=
'f' )
02210
return c -
'a' + 10;
02211
if (
'A' <= c && c<=
'F' )
02212
return c -
'A' + 10;
02213
return 0;
02214 }
02215
02216
unsigned short *DOM::CSSParser::text(
int *length)
02217 {
02218
unsigned short *start = yytext;
02219
int l = yyleng;
02220
switch( yyTok ) {
02221
case STRING:
02222 l--;
02223
02224
case HASH:
02225 start++;
02226 l--;
02227
break;
02228
case URI:
02229
02230
02231
02232
02233 start += 4;
02234 l -= 5;
02235
02236
while ( l &&
02237 (*start ==
' ' || *start ==
'\t' || *start ==
'\r' ||
02238 *start ==
'\n' || *start ==
'\f' ) ) {
02239 start++; l--;
02240 }
02241
if ( *start ==
'"' || *start ==
'\'' ) {
02242 start++; l--;
02243 }
02244
while ( l &&
02245 (start[l-1] ==
' ' || start[l-1] ==
'\t' || start[l-1] ==
'\r' ||
02246 start[l-1] ==
'\n' || start[l-1] ==
'\f' ) ) {
02247 l--;
02248 }
02249
if ( l && (start[l-1] ==
'\"' || start[l-1] ==
'\'' ) )
02250 l--;
02251
02252
default:
02253
break;
02254 }
02255
02256
02257
unsigned short *out = start;
02258
unsigned short *escape = 0;
02259
02260
for (
int i = 0; i < l; i++ ) {
02261
unsigned short *current = start+i;
02262
if ( escape == current - 1 ) {
02263
if ( ( *current >=
'0' && *current <=
'9' ) ||
02264 ( *current >=
'a' && *current <=
'f' ) ||
02265 ( *current >=
'A' && *current <=
'F' ) )
02266
continue;
02267
if ( yyTok == STRING &&
02268 ( *current ==
'\n' || *current ==
'\r' || *current ==
'\f' ) ) {
02269
02270
if ( *current !=
'\r' )
02271 escape = 0;
02272
continue;
02273 }
02274
02275
02276 *out++ = *current;
02277 escape = 0;
02278
continue;
02279 }
02280
if ( escape == current - 2 && yyTok == STRING &&
02281 *(current-1) ==
'\r' && *current ==
'\n' ) {
02282 escape = 0;
02283
continue;
02284 }
02285
if ( escape > current - 7 &&
02286 ( ( *current >=
'0' && *current <=
'9' ) ||
02287 ( *current >=
'a' && *current <=
'f' ) ||
02288 ( *current >=
'A' && *current <=
'F' ) ) )
02289
continue;
02290
if ( escape ) {
02291
02292
int uc = 0;
02293 escape++;
02294
while ( escape < current ) {
02295
02296 uc *= 16;
02297 uc += toHex( *escape );
02298 escape++;
02299 }
02300
02301
02302
if ( uc > 0xffff )
02303 uc = 0xfffd;
02304 *(out++) = (
unsigned short)uc;
02305 escape = 0;
02306
if ( *current ==
' ' ||
02307 *current ==
'\t' ||
02308 *current ==
'\r' ||
02309 *current ==
'\n' ||
02310 *current ==
'\f' )
02311
continue;
02312 }
02313
if ( !escape && *current ==
'\\' ) {
02314 escape = current;
02315
continue;
02316 }
02317 *(out++) = *current;
02318 }
02319
if ( escape ) {
02320
02321
int uc = 0;
02322 escape++;
02323
while ( escape < start+l ) {
02324
02325 uc *= 16;
02326 uc += toHex( *escape );
02327 escape++;
02328 }
02329
02330
02331
if ( uc > 0xffff )
02332 uc = 0xfffd;
02333 *(out++) = (
unsigned short)uc;
02334 }
02335
02336 *length = out - start;
02337
return start;
02338 }
02339
02340
02341
#define YY_DECL int DOM::CSSParser::lex()
02342
#define yyconst const
02343
typedef int yy_state_type;
02344
typedef unsigned int YY_CHAR;
02345
02346
#define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c)
02347
#define YY_DO_BEFORE_ACTION \
02348
yytext = yy_bp; \
02349
yyleng = (int) (yy_cp - yy_bp); \
02350
yy_hold_char = *yy_cp; \
02351
*yy_cp = 0; \
02352
yy_c_buf_p = yy_cp;
02353
#define YY_BREAK break;
02354
#define ECHO qDebug( "%s", QString( (QChar *)yytext, yyleng ).latin1() )
02355
#define YY_RULE_SETUP
02356
#define INITIAL 0
02357
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
02358
#define YY_START ((yy_start - 1) / 2)
02359
#define yyterminate() yyTok = END; return yyTok
02360
#define YY_FATAL_ERROR(a) qFatal(a)
02361
#define BEGIN yy_start = 1 + 2 *
02362
#define COMMENT 1
02363
02364
#include "tokenizer.cpp"