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