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
id == CSS_VAL_MARQUEE)
00496 valid_primitive =
true;
00497
break;
00498
00499
case CSS_PROP_LIST_STYLE_POSITION:
00500
if (
id == CSS_VAL_INSIDE ||
id == CSS_VAL_OUTSIDE )
00501 valid_primitive =
true;
00502
break;
00503
00504
case CSS_PROP_LIST_STYLE_TYPE:
00505
00506
00507
00508
00509
if ((
id >= CSS_VAL_DISC &&
id <= CSS_VAL_KATAKANA_IROHA) ||
id == CSS_VAL_NONE)
00510 valid_primitive =
true;
00511
break;
00512
00513
case CSS_PROP_DISPLAY:
00514
00515
00516
00517
if ((
id >= CSS_VAL_INLINE &&
id <= CSS_VAL_TABLE_CAPTION) ||
id == CSS_VAL_NONE)
00518 valid_primitive =
true;
00519
break;
00520
00521
case CSS_PROP_DIRECTION:
00522
if (
id == CSS_VAL_LTR ||
id == CSS_VAL_RTL )
00523 valid_primitive =
true;
00524
break;
00525
00526
case CSS_PROP_TEXT_TRANSFORM:
00527
if ((
id >= CSS_VAL_CAPITALIZE &&
id <= CSS_VAL_LOWERCASE) ||
id == CSS_VAL_NONE)
00528 valid_primitive =
true;
00529
break;
00530
00531
case CSS_PROP_FLOAT:
00532
if (
id == CSS_VAL_LEFT ||
id == CSS_VAL_RIGHT ||
00533
id == CSS_VAL_NONE ||
id == CSS_VAL_CENTER)
00534 valid_primitive =
true;
00535
break;
00536
00537
case CSS_PROP_CLEAR:
00538
if (
id == CSS_VAL_NONE ||
id == CSS_VAL_LEFT ||
00539
id == CSS_VAL_RIGHT||
id == CSS_VAL_BOTH)
00540 valid_primitive =
true;
00541
break;
00542
00543
case CSS_PROP_TEXT_ALIGN:
00544
00545
if ( (
id >= CSS_VAL__KHTML_AUTO &&
id <= CSS_VAL__KHTML_CENTER ) ||
00546 value->unit == CSSPrimitiveValue::CSS_STRING )
00547 valid_primitive =
true;
00548
break;
00549
00550
case CSS_PROP_OUTLINE_STYLE:
00551
case CSS_PROP_BORDER_TOP_STYLE:
00552
case CSS_PROP_BORDER_RIGHT_STYLE:
00553
case CSS_PROP_BORDER_BOTTOM_STYLE:
00554
case CSS_PROP_BORDER_LEFT_STYLE:
00555
if (
id >= CSS_VAL_NONE &&
id <= CSS_VAL_DOUBLE)
00556 valid_primitive =
true;
00557
break;
00558
00559
case CSS_PROP_FONT_WEIGHT:
00560
00561
if (
id >= CSS_VAL_NORMAL &&
id <= CSS_VAL_900) {
00562
00563 valid_primitive =
true;
00564 }
else if ( validUnit( value, FInteger|FNonNeg,
false ) ) {
00565
int weight = (
int)value->fValue;
00566
if ( (weight % 100) )
00567
break;
00568 weight /= 100;
00569
if ( weight >= 1 && weight <= 9 ) {
00570
id = CSS_VAL_100 + weight - 1;
00571 valid_primitive =
true;
00572 }
00573 }
00574
break;
00575
00576
case CSS_PROP_BACKGROUND_REPEAT:
00577
if (
id >= CSS_VAL_REPEAT &&
id <= CSS_VAL_NO_REPEAT )
00578 valid_primitive =
true;
00579
break;
00580
00581
case CSS_PROP_BACKGROUND_ATTACHMENT:
00582
if (
id == CSS_VAL_SCROLL ||
id == CSS_VAL_FIXED )
00583 valid_primitive =
true;
00584
break;
00585
00586
case CSS_PROP_BACKGROUND_POSITION:
00587
if (
id ) {
00588
00589
00590
00591
00592
00593
int pos[2];
00594 pos[0] = -1;
00595 pos[1] = -1;
00596
bool invalid =
false;
00597
switch(
id ) {
00598
case CSS_VAL_TOP:
00599 pos[1] = 0;
00600
break;
00601
case CSS_VAL_BOTTOM:
00602 pos[1] = 100;
00603
break;
00604
case CSS_VAL_LEFT:
00605 pos[0] = 0;
00606
break;
00607
case CSS_VAL_RIGHT:
00608 pos[0] = 100;
00609
break;
00610
case CSS_VAL_CENTER:
00611
break;
00612
default:
00613 invalid =
true;
00614 }
00615
if ( invalid )
00616
break;
00617 value = valueList->next();
00618
if ( value ) {
00619
id = value->id;
00620
switch(
id ) {
00621
case CSS_VAL_TOP:
00622
if ( pos[1] != -1 )
00623 invalid =
true;
00624 pos[1] = 0;
00625
break;
00626
case CSS_VAL_BOTTOM:
00627
if ( pos[1] != -1 )
00628 invalid =
true;
00629 pos[1] = 100;
00630
break;
00631
case CSS_VAL_LEFT:
00632
if ( pos[0] != -1 )
00633 invalid =
true;
00634 pos[0] = 0;
00635
break;
00636
case CSS_VAL_RIGHT:
00637
if ( pos[0] != -1 )
00638 invalid =
true;
00639 pos[0] = 100;
00640
break;
00641
case CSS_VAL_CENTER:
00642
break;
00643
default:
00644 invalid =
true;
00645 }
00646
if ( !invalid )
00647 value = valueList->next();
00648 }
00649
if ( pos[0] == -1 )
00650 pos[0] = 50;
00651
if ( pos[1] == -1 )
00652 pos[1] = 50;
00653 addProperty( CSS_PROP_BACKGROUND_POSITION_X,
00654
new CSSPrimitiveValueImpl( pos[0], CSSPrimitiveValue::CSS_PERCENTAGE ),
00655 important );
00656 addProperty( CSS_PROP_BACKGROUND_POSITION_Y,
00657
new CSSPrimitiveValueImpl( pos[1], CSSPrimitiveValue::CSS_PERCENTAGE ),
00658 important );
00659 }
else {
00660
bool ok = parseValue( CSS_PROP_BACKGROUND_POSITION_X, important );
00661
if ( !ok )
00662
break;
00663 value = valueList->current();
00664
if ( value )
00665 ok = parseValue( CSS_PROP_BACKGROUND_POSITION_Y, important );
00666
if ( !ok )
00667 addProperty( CSS_PROP_BACKGROUND_POSITION_Y,
00668
new CSSPrimitiveValueImpl( 50, CSSPrimitiveValue::CSS_PERCENTAGE ),
00669 important );
00670 }
00671
return true;
00672
00673
case CSS_PROP_BACKGROUND_POSITION_X:
00674
case CSS_PROP_BACKGROUND_POSITION_Y:
00675 valid_primitive = validUnit( value, FPercent|FLength, strict&(!nonCSSHint) );
00676
break;
00677
00678
case CSS_PROP_BORDER_SPACING:
00679 {
00680
const int properties[2] = { CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING,
00681 CSS_PROP__KHTML_BORDER_VERTICAL_SPACING };
00682
int num = valueList->numValues;
00683
if (num == 1) {
00684
if (!parseValue(properties[0], important))
return false;
00685 CSSValueImpl* value = parsedProperties[numParsedProperties-1]->value();
00686 addProperty(properties[1], value, important);
00687
return true;
00688 }
00689
else if (num == 2) {
00690
if (!parseValue(properties[0], important))
return false;
00691
if (!parseValue(properties[1], important))
return false;
00692
return true;
00693 }
00694
return false;
00695 }
00696
case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING:
00697
case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING:
00698 valid_primitive = validUnit(value, FLength|FNonNeg, strict&(!nonCSSHint));
00699
break;
00700
00701
case CSS_PROP_SCROLLBAR_FACE_COLOR:
00702
case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
00703
case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
00704
case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
00705
case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
00706
case CSS_PROP_SCROLLBAR_TRACK_COLOR:
00707
case CSS_PROP_SCROLLBAR_ARROW_COLOR:
00708
case CSS_PROP_SCROLLBAR_BASE_COLOR:
00709
if ( strict )
00710
break;
00711
00712
case CSS_PROP_OUTLINE_COLOR:
00713
00714
if ( propId == CSS_PROP_OUTLINE_COLOR &&
id == CSS_VAL_INVERT ) {
00715 valid_primitive =
true;
00716
break;
00717 }
00718
00719
case CSS_PROP_BACKGROUND_COLOR:
00720
if ( propId == CSS_PROP_BACKGROUND_COLOR &&
id == CSS_VAL_TRANSPARENT ) {
00721 valid_primitive =
true;
00722
break;
00723 }
00724
00725
case CSS_PROP_COLOR:
00726
case CSS_PROP_BORDER_TOP_COLOR:
00727
case CSS_PROP_BORDER_RIGHT_COLOR:
00728
case CSS_PROP_BORDER_BOTTOM_COLOR:
00729
case CSS_PROP_BORDER_LEFT_COLOR:
00730
case CSS_PROP__KHTML_TEXT_DECORATION_COLOR:
00731
if (
id == CSS_VAL__KHTML_TEXT ||
id == CSS_VAL_MENU ||
00732 (
id >= CSS_VAL_AQUA &&
id <= CSS_VAL_WINDOWTEXT ) ||
00733
id == CSS_VAL_TRANSPARENT ||
00734 (
id >= CSS_VAL_GREY &&
id < CSS_VAL__KHTML_TEXT && (nonCSSHint|!strict) ) ) {
00735 valid_primitive =
true;
00736 }
else {
00737 parsedValue = parseColor();
00738
if ( parsedValue )
00739 valueList->next();
00740 }
00741
break;
00742
00743
case CSS_PROP_CURSOR:
00744
00745
00746
00747
00748
if ( !strict &&
id == CSS_VAL_HAND ) {
00749
id = CSS_VAL_POINTER;
00750 valid_primitive =
true;
00751 }
else if (
id >= CSS_VAL_AUTO &&
id <= CSS_VAL_HELP )
00752 valid_primitive =
true;
00753
break;
00754
00755
case CSS_PROP_BACKGROUND_IMAGE:
00756
case CSS_PROP_LIST_STYLE_IMAGE:
00757
00758
if (
id == CSS_VAL_NONE ) {
00759 parsedValue =
new CSSImageValueImpl();
00760 valueList->next();
00761
#ifdef CSS_DEBUG
00762
kdDebug( 6080 ) <<
"empty image " <<
endl;
00763
#endif
00764
}
else if ( value->unit == CSSPrimitiveValue::CSS_URI ) {
00765
00766
DOMString uri = khtml::parseURL( domString( value->string ) );
00767
if ( !uri.
isEmpty() ) {
00768 parsedValue =
new CSSImageValueImpl(
00769
DOMString(
KURL( styleElement->baseURL(), uri.
string()).url()),
00770 styleElement );
00771 valueList->next();
00772
#ifdef CSS_DEBUG
00773
kdDebug( 6080 ) <<
"image, url=" << uri.
string() <<
" base=" << styleElement->baseURL().url() <<
endl;
00774
#endif
00775
}
00776 }
00777
break;
00778
00779
case CSS_PROP_OUTLINE_WIDTH:
00780
case CSS_PROP_BORDER_TOP_WIDTH:
00781
case CSS_PROP_BORDER_RIGHT_WIDTH:
00782
case CSS_PROP_BORDER_BOTTOM_WIDTH:
00783
case CSS_PROP_BORDER_LEFT_WIDTH:
00784
if (
id == CSS_VAL_THIN ||
id == CSS_VAL_MEDIUM ||
id == CSS_VAL_THICK)
00785 valid_primitive =
true;
00786
else
00787 valid_primitive = ( validUnit( value, FLength, strict&(!nonCSSHint) ) );
00788
break;
00789
00790
case CSS_PROP_LETTER_SPACING:
00791
case CSS_PROP_WORD_SPACING:
00792
if (
id == CSS_VAL_NORMAL )
00793 valid_primitive =
true;
00794
else
00795 valid_primitive = validUnit( value, FLength, strict&(!nonCSSHint) );
00796
break;
00797
00798
case CSS_PROP_TEXT_INDENT:
00799 valid_primitive = ( !
id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
00800
break;
00801
00802
case CSS_PROP_PADDING_TOP:
00803
case CSS_PROP_PADDING_RIGHT:
00804
case CSS_PROP_PADDING_BOTTOM:
00805
case CSS_PROP_PADDING_LEFT:
00806 valid_primitive = ( !
id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
00807
break;
00808
00809
case CSS_PROP_MAX_HEIGHT:
00810
case CSS_PROP_MAX_WIDTH:
00811
if (
id == CSS_VAL_NONE ) {
00812 valid_primitive =
true;
00813
break;
00814 }
00815
00816
case CSS_PROP_MIN_HEIGHT:
00817
case CSS_PROP_MIN_WIDTH:
00818 valid_primitive = ( !
id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
00819
break;
00820
00821
case CSS_PROP_FONT_SIZE:
00822
00823
if (
id >= CSS_VAL_XX_SMALL &&
id <= CSS_VAL_LARGER)
00824 valid_primitive =
true;
00825
else
00826 valid_primitive = ( validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
00827
break;
00828
00829
case CSS_PROP_FONT_STYLE:
00830
if (
id == CSS_VAL_NORMAL ||
id == CSS_VAL_ITALIC ||
id == CSS_VAL_OBLIQUE)
00831 valid_primitive =
true;
00832
break;
00833
00834
case CSS_PROP_FONT_VARIANT:
00835
if (
id == CSS_VAL_NORMAL ||
id == CSS_VAL_SMALL_CAPS)
00836 valid_primitive =
true;
00837
break;
00838
00839
case CSS_PROP_VERTICAL_ALIGN:
00840
00841
00842
00843
if (
id >= CSS_VAL_BASELINE &&
id <= CSS_VAL__KHTML_BASELINE_MIDDLE )
00844 valid_primitive =
true;
00845
else
00846 valid_primitive = ( !
id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
00847
break;
00848
00849
case CSS_PROP_HEIGHT:
00850
case CSS_PROP_WIDTH:
00851
if (
id == CSS_VAL_AUTO )
00852 valid_primitive =
true;
00853
else
00854
00855 valid_primitive = ( !
id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
00856
break;
00857
00858
case CSS_PROP_BOTTOM:
00859
case CSS_PROP_LEFT:
00860
case CSS_PROP_RIGHT:
00861
case CSS_PROP_TOP:
00862
case CSS_PROP_MARGIN_TOP:
00863
case CSS_PROP_MARGIN_RIGHT:
00864
case CSS_PROP_MARGIN_BOTTOM:
00865
case CSS_PROP_MARGIN_LEFT:
00866
if (
id == CSS_VAL_AUTO )
00867 valid_primitive =
true;
00868
else
00869 valid_primitive = ( !
id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
00870
break;
00871
00872
case CSS_PROP_Z_INDEX:
00873
00874
if (
id == CSS_VAL_AUTO ) {
00875 valid_primitive =
true;
00876
break;
00877 }
00878
00879
case CSS_PROP_ORPHANS:
00880
case CSS_PROP_WIDOWS:
00881
00882 valid_primitive = ( !
id && validUnit( value, FInteger,
false ) );
00883
break;
00884
00885
case CSS_PROP_LINE_HEIGHT:
00886
if (
id == CSS_VAL_NORMAL )
00887 valid_primitive =
true;
00888
else
00889 valid_primitive = ( !
id && validUnit( value, FNumber|FLength|FPercent, strict&(!nonCSSHint) ) );
00890
break;
00891
#if 0
00892
00893
case CSS_PROP_COUNTER_INCREMENT:
00894
case CSS_PROP_COUNTER_RESET:
00895
if (
id == CSS_VAL_NONE )
00896 valid_primitive =
true;
00897
else {
00898 CSSValueListImpl *list =
new CSSValueListImpl;
00899
int pos=0, pos2;
00900
while( 1 )
00901 {
00902 pos2 = value.find(
',', pos);
00903
QString face = value.mid(pos, pos2-pos);
00904 face = face.stripWhiteSpace();
00905
if(face.length() == 0)
break;
00906
00907
if(face[0] ==
'\"') face.remove(0, 1);
00908
if(face[face.length()-1] ==
'\"') face = face.left(face.length()-1);
00909
00910 list->append(
new CSSPrimitiveValueImpl(
DOMString(face), CSSPrimitiveValue::CSS_STRING));
00911 pos = pos2 + 1;
00912
if(pos2 == -1)
break;
00913 }
00914
00915
if(list->length()) {
00916 parsedValue = list;
00917 valueList->next();
00918 }
else
00919
delete list;
00920
break;
00921 }
00922
#endif
00923
case CSS_PROP_FONT_FAMILY:
00924
00925 {
00926 parsedValue = parseFontFamily();
00927
break;
00928 }
00929
00930
case CSS_PROP_TEXT_DECORATION:
00931
00932
if (
id == CSS_VAL_NONE) {
00933 valid_primitive =
true;
00934 }
else {
00935 CSSValueListImpl *list =
new CSSValueListImpl;
00936
bool is_valid =
true;
00937
while( is_valid && value ) {
00938
switch ( value->id ) {
00939
case CSS_VAL_BLINK:
00940
break;
00941
case CSS_VAL_UNDERLINE:
00942
case CSS_VAL_OVERLINE:
00943
case CSS_VAL_LINE_THROUGH:
00944 list->append(
new CSSPrimitiveValueImpl( value->id ) );
00945
break;
00946
default:
00947 is_valid =
false;
00948 }
00949 value = valueList->next();
00950 }
00951
00952
if(list->length() && is_valid) {
00953 parsedValue = list;
00954 valueList->next();
00955 }
else {
00956
delete list;
00957 }
00958 }
00959
break;
00960
00961
case CSS_PROP_TABLE_LAYOUT:
00962
if (
id == CSS_VAL_AUTO ||
id == CSS_VAL_FIXED )
00963 valid_primitive =
true;
00964
break;
00965
00966
case CSS_PROP__KHTML_FLOW_MODE:
00967
if (
id == CSS_VAL__KHTML_NORMAL ||
id == CSS_VAL__KHTML_AROUND_FLOATS )
00968 valid_primitive =
true;
00969
break;
00970
00971
00972
case CSS_PROP__KHTML_USER_INPUT:
00973
if (
id == CSS_VAL_NONE ||
id == CSS_VAL_ENABLED ||
id == CSS_VAL_DISABLED )
00974 valid_primitive =
true;
00975
00976
break;
00977
case CSS_PROP__KHTML_MARQUEE: {
00978
const int properties[5] = { CSS_PROP__KHTML_MARQUEE_DIRECTION, CSS_PROP__KHTML_MARQUEE_INCREMENT,
00979 CSS_PROP__KHTML_MARQUEE_REPETITION,
00980 CSS_PROP__KHTML_MARQUEE_STYLE, CSS_PROP__KHTML_MARQUEE_SPEED };
00981
return parseShortHand(properties, 5, important);
00982 }
00983
case CSS_PROP__KHTML_MARQUEE_DIRECTION:
00984
if (
id == CSS_VAL_FORWARDS ||
id == CSS_VAL_BACKWARDS ||
id == CSS_VAL_AHEAD ||
00985
id == CSS_VAL_REVERSE ||
id == CSS_VAL_LEFT ||
id == CSS_VAL_RIGHT ||
id == CSS_VAL_DOWN ||
00986
id == CSS_VAL_UP ||
id == CSS_VAL_AUTO)
00987 valid_primitive =
true;
00988
break;
00989
case CSS_PROP__KHTML_MARQUEE_INCREMENT:
00990
if (
id == CSS_VAL_SMALL ||
id == CSS_VAL_LARGE ||
id == CSS_VAL_MEDIUM)
00991 valid_primitive =
true;
00992
else
00993 valid_primitive = validUnit(value, FLength|FPercent, strict&(!nonCSSHint));
00994
break;
00995
case CSS_PROP__KHTML_MARQUEE_STYLE:
00996
if (
id == CSS_VAL_NONE ||
id == CSS_VAL_SLIDE ||
id == CSS_VAL_SCROLL ||
id == CSS_VAL_ALTERNATE ||
00997
id == CSS_VAL_UNFURL)
00998 valid_primitive =
true;
00999
break;
01000
case CSS_PROP__KHTML_MARQUEE_REPETITION:
01001
if (
id == CSS_VAL_INFINITE)
01002 valid_primitive =
true;
01003
else
01004 valid_primitive = validUnit(value, FInteger|FNonNeg, strict&(!nonCSSHint));
01005
break;
01006
case CSS_PROP__KHTML_MARQUEE_SPEED:
01007
if (
id == CSS_VAL_NORMAL ||
id == CSS_VAL_SLOW ||
id == CSS_VAL_FAST)
01008 valid_primitive =
true;
01009
else
01010 valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict&(!nonCSSHint));
01011
break;
01012
01013
01014
01015
case CSS_PROP_BACKGROUND:
01016
01017
01018 {
01019
const int properties[5] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,
01020 CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION,
01021 CSS_PROP_BACKGROUND_COLOR };
01022
return parseShortHand(properties, 5, important);
01023 }
01024
case CSS_PROP_BORDER:
01025
01026 {
01027
const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
01028 CSS_PROP_BORDER_COLOR };
01029
return parseShortHand(properties, 3, important);
01030 }
01031
case CSS_PROP_BORDER_TOP:
01032
01033 {
01034
const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
01035 CSS_PROP_BORDER_TOP_COLOR};
01036
return parseShortHand(properties, 3, important);
01037 }
01038
case CSS_PROP_BORDER_RIGHT:
01039
01040 {
01041
const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
01042 CSS_PROP_BORDER_RIGHT_COLOR };
01043
return parseShortHand(properties, 3, important);
01044 }
01045
case CSS_PROP_BORDER_BOTTOM:
01046
01047 {
01048
const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
01049 CSS_PROP_BORDER_BOTTOM_COLOR };
01050
return parseShortHand(properties, 3, important);
01051 }
01052
case CSS_PROP_BORDER_LEFT:
01053
01054 {
01055
const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
01056 CSS_PROP_BORDER_LEFT_COLOR };
01057
return parseShortHand(properties, 3, important);
01058 }
01059
case CSS_PROP_OUTLINE:
01060
01061 {
01062
const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
01063 CSS_PROP_OUTLINE_COLOR };
01064
return parseShortHand(properties, 3, important);
01065 }
01066
case CSS_PROP_BORDER_COLOR:
01067
01068 {
01069
const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
01070 CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
01071
return parse4Values(properties, important);
01072 }
01073
case CSS_PROP_BORDER_WIDTH:
01074
01075 {
01076
const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
01077 CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
01078
return parse4Values(properties, important);
01079 }
01080
case CSS_PROP_BORDER_STYLE:
01081
01082 {
01083
const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
01084 CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
01085
return parse4Values(properties, important);
01086 }
01087
case CSS_PROP_MARGIN:
01088
01089 {
01090
const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
01091 CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
01092
return parse4Values(properties, important);
01093 }
01094
case CSS_PROP_PADDING:
01095
01096 {
01097
const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
01098 CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
01099
return parse4Values(properties, important);
01100 }
01101
case CSS_PROP_FONT:
01102
01103
01104
if (
id >= CSS_VAL_CAPTION &&
id <= CSS_VAL_STATUS_BAR )
01105 valid_primitive =
true;
01106
else
01107
return parseFont(important);
01108
01109
case CSS_PROP_LIST_STYLE:
01110 {
01111
const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
01112 CSS_PROP_LIST_STYLE_IMAGE };
01113
return parseShortHand(properties, 3, important);
01114 }
01115
default:
01116
01117
01118
01119
break;
01120 }
01121
01122
if ( valid_primitive ) {
01123
if (
id != 0 ) {
01124
01125 parsedValue =
new CSSPrimitiveValueImpl(
id );
01126 }
else if ( value->unit == CSSPrimitiveValue::CSS_STRING )
01127 parsedValue =
new CSSPrimitiveValueImpl( domString( value->string ),
01128 (CSSPrimitiveValue::UnitTypes) value->unit );
01129
else if ( value->unit >= CSSPrimitiveValue::CSS_NUMBER &&
01130 value->unit <= CSSPrimitiveValue::CSS_KHZ ) {
01131
01132 parsedValue =
new CSSPrimitiveValueImpl( value->fValue,
01133 (CSSPrimitiveValue::UnitTypes) value->unit );
01134 }
else if ( value->unit >= Value::Q_EMS ) {
01135
01136 parsedValue =
new CSSQuirkPrimitiveValueImpl( value->fValue, CSSPrimitiveValue::CSS_EMS );
01137 }
01138 valueList->next();
01139 }
01140
if ( parsedValue ) {
01141 addProperty( propId, parsedValue, important );
01142
return true;
01143 }
01144
return false;
01145 }
01146
01147
bool CSSParser::parseShortHand(
const int *properties,
int numProperties,
bool important )
01148 {
01149
01150
01151
01152
01153 inParseShortHand =
true;
01154
01155
bool found =
false;
01156
bool fnd[6];
01157
for(
int i = 0; i < numProperties; i++ )
01158 fnd[i] =
false;
01159
01160
#ifdef CSS_DEBUG
01161
kdDebug(6080) <<
"PSH: numProperties=" << numProperties <<
endl;
01162
#endif
01163
01164
while ( valueList->current() ) {
01165 found =
false;
01166
01167
for (
int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
01168
if (!fnd[propIndex]) {
01169
#ifdef CSS_DEBUG
01170
kdDebug(6080) <<
"LOOKING FOR: " << getPropertyName(properties[propIndex]).
string() <<
endl;
01171
#endif
01172
if ( parseValue( properties[propIndex], important ) ) {
01173 fnd[propIndex] = found =
true;
01174
#ifdef CSS_DEBUG
01175
kdDebug(6080) <<
"FOUND: " << getPropertyName(properties[propIndex]).
string() <<
endl;
01176
#endif
01177
}
01178 }
01179 }
01180
01181
01182
if (!found) {
01183
#ifdef CSS_DEBUG
01184
qDebug(
"didn't find anything" );
01185
#endif
01186
inParseShortHand =
false;
01187
return false;
01188 }
01189 }
01190
01191
01192
for (
int i = 0; i < numProperties; ++i) {
01193
if (!fnd[i])
01194 addProperty(properties[i],
new CSSInitialValueImpl(), important);
01195 }
01196
01197 inParseShortHand =
false;
01198
#ifdef CSS_DEBUG
01199
kdDebug( 6080 ) <<
"parsed shorthand" <<
endl;
01200
#endif
01201
return true;
01202 }
01203
01204
bool CSSParser::parse4Values(
const int *properties,
bool important )
01205 {
01206
01207
01208
01209
01210
01211
01212
01213
01214
int num = inParseShortHand ? 1 : valueList->numValues;
01215
01216
01217
01218
switch( num ) {
01219
case 1: {
01220
if( !parseValue( properties[0], important ) )
return false;
01221 CSSValueImpl *value = parsedProperties[numParsedProperties-1]->value();
01222 addProperty( properties[1], value, important );
01223 addProperty( properties[2], value, important );
01224 addProperty( properties[3], value, important );
01225
return true;
01226 }
01227
case 2: {
01228
01229
if( !parseValue( properties[0], important ) )
return false;
01230
if( !parseValue( properties[1], important ) )
return false;
01231 CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();
01232 addProperty( properties[2], value, important );
01233 value = parsedProperties[numParsedProperties-2]->value();
01234 addProperty( properties[3], value, important );
01235
return true;
01236 }
01237
case 3: {
01238
if( !parseValue( properties[0], important ) )
return false;
01239
if( !parseValue( properties[1], important ) )
return false;
01240
if( !parseValue( properties[2], important ) )
return false;
01241 CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();
01242 addProperty( properties[3], value, important );
01243
return true;
01244 }
01245
case 4: {
01246
if( !parseValue( properties[0], important ) )
return false;
01247
if( !parseValue( properties[1], important ) )
return false;
01248
if( !parseValue( properties[2], important ) )
return false;
01249
if( !parseValue( properties[3], important ) )
return false;
01250
return true;
01251 }
01252
default:
01253
return false;
01254 }
01255 }
01256
01257
01258
01259
01260
bool CSSParser::parseContent(
int propId,
bool important )
01261 {
01262 CSSValueListImpl* values =
new CSSValueListImpl();
01263
01264 Value *val;
01265 CSSValueImpl *parsedValue = 0;
01266
while ( (val = valueList->current()) ) {
01267
if ( val->unit == CSSPrimitiveValue::CSS_URI ) {
01268
01269
DOMString value = khtml::parseURL(domString(val->string));
01270 parsedValue =
new CSSImageValueImpl(
01271
DOMString(
KURL( styleElement->baseURL(), value.
string()).url() ), styleElement );
01272
#ifdef CSS_DEBUG
01273
kdDebug( 6080 ) <<
"content, url=" << value.
string() <<
" base=" << styleElement->baseURL().url( ) <<
endl;
01274
#endif
01275
}
else if ( val->unit == Value::Function ) {
01276
01277 ValueList *args = val->function->args;
01278
QString fname = qString( val->function->name ).lower();
01279
if ( fname !=
"attr(" || !args )
01280
return false;
01281
if ( args->numValues != 1)
01282
return false;
01283 Value *a = args->current();
01284 parsedValue =
new CSSPrimitiveValueImpl(domString(a->string), CSSPrimitiveValue::CSS_ATTR);
01285 }
else if ( val->unit == CSSPrimitiveValue::CSS_IDENT ) {
01286
01287
01288
01289
01290 }
else if ( val->unit == CSSPrimitiveValue::CSS_STRING ) {
01291 parsedValue =
new CSSPrimitiveValueImpl(domString(val->string), CSSPrimitiveValue::CSS_STRING);
01292 }
01293
if (parsedValue)
01294 values->append(parsedValue);
01295
else
01296
break;
01297 valueList->next();
01298 }
01299
if ( values->length() ) {
01300 addProperty( propId, values, important );
01301 valueList->next();
01302
return true;
01303 }
01304
delete values;
01305
return false;
01306 }
01307
01308
bool CSSParser::parseShape(
int propId,
bool important )
01309 {
01310 Value *value = valueList->current();
01311 ValueList *args = value->function->args;
01312
QString fname = qString( value->function->name ).lower();
01313
01314
if ( fname !=
"rect(" || !args )
01315
return false;
01316
01317
01318
if ( args->numValues != 4 && args->numValues != 7 )
01319
return false;
01320 RectImpl *rect =
new RectImpl();
01321
bool valid =
true;
01322
int i = 0;
01323 Value *a = args->current();
01324
while ( a ) {
01325 valid = validUnit( a, FLength, strict );
01326
if ( !valid )
01327
break;
01328 CSSPrimitiveValueImpl *length =
01329
new CSSPrimitiveValueImpl( a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit );
01330
if ( i == 0 )
01331 rect->setTop( length );
01332
else if ( i == 1 )
01333 rect->setRight( length );
01334
else if ( i == 2 )
01335 rect->setBottom( length );
01336
else
01337 rect->setLeft( length );
01338 a = args->next();
01339
if ( a && args->numValues == 7 ) {
01340
if ( a->unit == Value::Operator && a->iValue ==
',' ) {
01341 a = args->next();
01342 }
else {
01343 valid =
false;
01344
break;
01345 }
01346 }
01347 i++;
01348 }
01349
if ( valid ) {
01350 addProperty( propId,
new CSSPrimitiveValueImpl( rect ), important );
01351 valueList->next();
01352
return true;
01353 }
01354
delete rect;
01355
return false;
01356 }
01357
01358
01359
bool CSSParser::parseFont(
bool important )
01360 {
01361
01362
bool valid =
true;
01363 Value *value = valueList->current();
01364 FontValueImpl *font =
new FontValueImpl;
01365
01366
while ( value ) {
01367
01368
01369
01370
int id = value->id;
01371
if (
id ) {
01372
if (
id == CSS_VAL_NORMAL ) {
01373
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
else if (
id == CSS_VAL_ITALIC ||
id == CSS_VAL_OBLIQUE ) {
01383
if ( font->style )
01384
goto invalid;
01385 font->style =
new CSSPrimitiveValueImpl(
id );
01386 }
else if (
id == CSS_VAL_SMALL_CAPS ) {
01387
if ( font->variant )
01388
goto invalid;
01389 font->variant =
new CSSPrimitiveValueImpl(
id );
01390 }
else if (
id >= CSS_VAL_BOLD &&
id <= CSS_VAL_LIGHTER ) {
01391
if ( font->weight )
01392
goto invalid;
01393 font->weight =
new CSSPrimitiveValueImpl(
id );
01394 }
else {
01395 valid =
false;
01396 }
01397 }
else if ( !font->weight && validUnit( value, FInteger|FNonNeg,
true ) ) {
01398
int weight = (
int)value->fValue;
01399
int val = 0;
01400
if ( weight == 100 )
01401 val = CSS_VAL_100;
01402
else if ( weight == 200 )
01403 val = CSS_VAL_200;
01404
else if ( weight == 300 )
01405 val = CSS_VAL_300;
01406
else if ( weight == 400 )
01407 val = CSS_VAL_400;
01408
else if ( weight == 500 )
01409 val = CSS_VAL_500;
01410
else if ( weight == 600 )
01411 val = CSS_VAL_600;
01412
else if ( weight == 700 )
01413 val = CSS_VAL_700;
01414
else if ( weight == 800 )
01415 val = CSS_VAL_800;
01416
else if ( weight == 900 )
01417 val = CSS_VAL_900;
01418
01419
if ( val )
01420 font->weight =
new CSSPrimitiveValueImpl( val );
01421
else
01422 valid =
false;
01423 }
else {
01424 valid =
false;
01425 }
01426
if ( !valid )
01427
break;
01428 value = valueList->next();
01429 }
01430
if ( !value )
01431
goto invalid;
01432
01433
01434
if ( !font->style )
01435 font->style =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01436
if ( !font->variant )
01437 font->variant =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01438
if ( !font->weight )
01439 font->weight =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01440
01441
01442
01443
01444
01445
if ( value->id >= CSS_VAL_XX_SMALL && value->id <= CSS_VAL_LARGER )
01446 font->size =
new CSSPrimitiveValueImpl( value->id );
01447
else if ( validUnit( value, FLength|FPercent, strict ) ) {
01448 font->size =
new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit );
01449 }
01450 value = valueList->next();
01451
if ( !font->size || !value )
01452
goto invalid;
01453
01454
01455
01456
if ( value->unit == Value::Operator && value->iValue ==
'/' ) {
01457
01458 value = valueList->next();
01459
if ( !value )
01460
goto invalid;
01461
if ( value->id == CSS_VAL_NORMAL ) {
01462
01463 }
else if ( validUnit( value, FNumber|FLength|FPercent, strict ) ) {
01464 font->lineHeight =
new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit );
01465 }
else {
01466
goto invalid;
01467 }
01468 value = valueList->next();
01469
if ( !value )
01470
goto invalid;
01471 }
01472
if ( !font->lineHeight )
01473 font->lineHeight =
new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
01474
01475
01476
01477 font->family = parseFontFamily();
01478
01479
if ( valueList->current() || !font->family )
01480
goto invalid;
01481
01482
01483 addProperty( CSS_PROP_FONT, font, important );
01484
return true;
01485
01486 invalid:
01487
01488
delete font;
01489
return false;
01490 }
01491
01492 CSSValueListImpl *CSSParser::parseFontFamily()
01493 {
01494
01495 CSSValueListImpl *list =
new CSSValueListImpl;
01496 Value *value = valueList->current();
01497
QString currFace;
01498
01499
while ( value ) {
01500
01501
01502
01503
01504 Value* nextValue = valueList->next();
01505
bool nextValBreaksFont = !nextValue ||
01506 (nextValue->unit == Value::Operator && nextValue->iValue ==
',');
01507
bool nextValIsFontName = nextValue &&
01508 ((nextValue->id >= CSS_VAL_SERIF && nextValue->id <= CSS_VAL_MONOSPACE) ||
01509 (nextValue->unit == CSSPrimitiveValue::CSS_STRING ||
01510 nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
01511
01512
if (value->id >= CSS_VAL_SERIF && value->id <= CSS_VAL_MONOSPACE) {
01513
if (!currFace.isNull()) {
01514 currFace +=
' ';
01515 currFace += qString(value->string);
01516 }
01517
else if (nextValBreaksFont || !nextValIsFontName) {
01518
if ( !currFace.isNull() ) {
01519 list->append(
new FontFamilyValueImpl( currFace ) );
01520 currFace = QString::null;
01521 }
01522 list->append(
new CSSPrimitiveValueImpl(value->id));
01523 }
01524
else {
01525 currFace = qString( value->string );
01526 }
01527 }
01528
else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
01529
01530 currFace = QString::null;
01531 list->append(
new FontFamilyValueImpl(qString( value->string) ) );
01532 }
01533
else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
01534
if (!currFace.isNull()) {
01535 currFace +=
' ';
01536 currFace += qString(value->string);
01537 }
01538
else if (nextValBreaksFont || !nextValIsFontName) {
01539
if ( !currFace.isNull() ) {
01540 list->append(
new FontFamilyValueImpl( currFace ) );
01541 currFace = QString::null;
01542 }
01543 list->append(
new FontFamilyValueImpl( qString( value->string ) ) );
01544 }
01545
else {
01546 currFace = qString( value->string);
01547 }
01548 }
01549
else {
01550
01551
break;
01552 }
01553
01554
if (!nextValue)
01555
break;
01556
01557
if (nextValBreaksFont) {
01558 value = valueList->next();
01559
if ( !currFace.isNull() )
01560 list->append(
new FontFamilyValueImpl( currFace ) );
01561 currFace = QString::null;
01562 }
01563
else if (nextValIsFontName)
01564 value = nextValue;
01565
else
01566
break;
01567 }
01568
01569
if ( !currFace.isNull() )
01570 list->append(
new FontFamilyValueImpl( currFace ) );
01571
01572
if ( !list->length() ) {
01573
delete list;
01574 list = 0;
01575 }
01576
return list;
01577 }
01578
01579
01580
static bool parseColor(
const QString &name, QRgb& rgb)
01581 {
01582
int len =
name.length();
01583
01584
if ( !len )
01585
return false;
01586
01587
01588
bool ok;
01589
01590
if ( len == 3 || len == 6 ) {
01591
int val =
name.toInt(&ok, 16);
01592
if ( ok ) {
01593
if (len == 6) {
01594 rgb = (0xff << 24) | val;
01595
return true;
01596 }
01597
else if ( len == 3 ) {
01598
01599 rgb = (0xff << 24) |
01600 (val&0xf00)<<12 | (val&0xf00)<<8 |
01601 (val&0xf0)<<8 | (val&0xf0)<<4 |
01602 (val&0xf)<<4 | (val&0xf);
01603
return true;
01604 }
01605 }
01606 }
01607
01608
01609
QColor tc;
01610 tc.setNamedColor(
name.lower());
01611
if ( tc.isValid() ) {
01612 rgb = tc.rgb();
01613
return true;
01614 }
01615
01616
return false;
01617 }
01618
01619
01620 CSSPrimitiveValueImpl *CSSParser::parseColor()
01621 {
01622 QRgb c = khtml::transparentColor;
01623 Value *value = valueList->current();
01624
if ( !strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
01625 value->fValue >= 0. && value->fValue < 1000000. ) {
01626
QString str;
01627 str.sprintf(
"%06d", (
int)(value->fValue+.5) );
01628 if ( !::parseColor( str, c ) )
01629
return 0;
01630 }
else if ( value->unit == CSSPrimitiveValue::CSS_RGBCOLOR ||
01631 value->unit == CSSPrimitiveValue::CSS_IDENT ||
01632 (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION) ) {
01633 if ( !::parseColor( qString( value->string ), c) )
01634
return 0;
01635 }
01636
else if ( value->unit == Value::Function &&
01637 value->function->args != 0 &&
01638 value->function->args->numValues == 5 &&
01639 qString( value->function->name ).lower() ==
"rgb(" ) {
01640 ValueList *args = value->function->args;
01641 Value *v = args->current();
01642
if ( !validUnit( v, FInteger|FPercent,
true ) )
01643
return 0;
01644
int r = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01645 v = args->next();
01646
if ( v->unit != Value::Operator && v->iValue !=
',' )
01647
return 0;
01648 v = args->next();
01649
if ( !validUnit( v, FInteger|FPercent,
true ) )
01650
return 0;
01651
int g = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01652 v = args->next();
01653
if ( v->unit != Value::Operator && v->iValue !=
',' )
01654
return 0;
01655 v = args->next();
01656
if ( !validUnit( v, FInteger|FPercent,
true ) )
01657
return 0;
01658
int b = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01659 r = kMax( 0, kMin( 255, r ) );
01660 g = kMax( 0, kMin( 255, g ) );
01661 b = kMax( 0, kMin( 255, b ) );
01662 c = qRgb( r, g, b );
01663 }
01664
else if ( value->unit == Value::Function &&
01665 value->function->args != 0 &&
01666 value->function->args->numValues == 7 &&
01667 qString( value->function->name ).lower() ==
"rgba(" ) {
01668 ValueList *args = value->function->args;
01669 Value *v = args->current();
01670
if ( !validUnit( v, FInteger|FPercent,
true ) )
01671
return 0;
01672
int r = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01673 v = args->next();
01674
if ( v->unit != Value::Operator && v->iValue !=
',' )
01675
return 0;
01676 v = args->next();
01677
if ( !validUnit( v, FInteger|FPercent,
true ) )
01678
return 0;
01679
int g = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01680 v = args->next();
01681
if ( v->unit != Value::Operator && v->iValue !=
',' )
01682
return 0;
01683 v = args->next();
01684
if ( !validUnit( v, FInteger|FPercent,
true ) )
01685
return 0;
01686
int b = (
int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
01687 v = args->next();
01688
if ( v->unit != Value::Operator && v->iValue !=
',' )
01689
return 0;
01690 v = args->next();
01691
if ( !validUnit( v, FNumber,
true ) )
01692
return 0;
01693 r = QMAX( 0, QMIN( 255, r ) );
01694 g = QMAX( 0, QMIN( 255, g ) );
01695 b = QMAX( 0, QMIN( 255, b ) );
01696
int a = (
int)(QMAX( 0, QMIN( 1.0f, v->fValue ) ) * 255);
01697 c = qRgba( r, g, b, a );
01698 }
01699
else
01700
return 0;
01701
01702
return new CSSPrimitiveValueImpl(c);
01703 }
01704
01705
01706
static inline int yyerror(
const char *str ) {
01707
01708
#ifdef CSS_DEBUG
01709
kdDebug( 6080 ) <<
"CSS parse error " << str <<
endl;
01710
#else
01711
Q_UNUSED( str );
01712
#endif
01713
return 1;
01714 }
01715
01716
#define END 0
01717
01718
#include "parser.h"
01719
01720
int DOM::CSSParser::lex(
void *_yylval )
01721 {
01722 YYSTYPE *yylval = (YYSTYPE *)_yylval;
01723
int token = lex();
01724
int length;
01725
unsigned short *t = text( &length );
01726
01727
#ifdef TOKEN_DEBUG
01728
qDebug(
"CSSTokenizer: got token %d: '%s'", token, token == END ?
"" :
QString( (
QChar *)t, length ).latin1() );
01729
#endif
01730
switch( token ) {
01731
case '{':
01732 block_nesting++;
01733
break;
01734
case '}':
01735
if ( block_nesting )
01736 block_nesting--;
01737
break;
01738
case END:
01739
if ( block_nesting ) {
01740 block_nesting--;
01741
return '}';
01742 }
01743
break;
01744
case S:
01745
case SGML_CD:
01746
case INCLUDES:
01747
case DASHMATCH:
01748
break;
01749
01750
case URI:
01751
case STRING:
01752
case IDENT:
01753
case HASH:
01754
case DIMEN:
01755
case UNICODERANGE:
01756
case FUNCTION:
01757 yylval->string.string = t;
01758 yylval->string.length = length;
01759
break;
01760
01761
case IMPORT_SYM:
01762
case PAGE_SYM:
01763
case MEDIA_SYM:
01764
case FONT_FACE_SYM:
01765
case CHARSET_SYM:
01766
01767
case IMPORTANT_SYM:
01768
break;
01769
01770
case QEMS:
01771 length--;
01772
case GRADS:
01773 length--;
01774
case DEGS:
01775
case RADS:
01776
case KHERZ:
01777 length--;
01778
case MSECS:
01779
case HERZ:
01780
case EMS:
01781
case EXS:
01782
case PXS:
01783
case CMS:
01784
case MMS:
01785
case INS:
01786
case PTS:
01787
case PCS:
01788 length--;
01789
case SECS:
01790
case PERCENTAGE:
01791 length--;
01792
case NUMBER:
01793 yylval->val =
QString( (QChar *)t, length ).toDouble();
01794
01795
break;
01796
01797
default:
01798
break;
01799 }
01800
01801
return token;
01802 }
01803
01804
static inline int toHex(
char c ) {
01805
if (
'0' <= c && c <=
'9' )
01806
return c -
'0';
01807
if (
'a' <= c && c <=
'f' )
01808
return c -
'a' + 10;
01809
if (
'A' <= c && c<=
'F' )
01810
return c -
'A' + 10;
01811
return 0;
01812 }
01813
01814
unsigned short *DOM::CSSParser::text(
int *length)
01815 {
01816
unsigned short *start = yytext;
01817
int l = yyleng;
01818
switch( yyTok ) {
01819
case STRING:
01820 l--;
01821
01822
case HASH:
01823 start++;
01824 l--;
01825
break;
01826
case URI:
01827
01828
01829
01830
01831 start += 4;
01832 l -= 5;
01833
01834
while ( l &&
01835 (*start ==
' ' || *start ==
'\t' || *start ==
'\r' ||
01836 *start ==
'\n' || *start ==
'\f' ) ) {
01837 start++; l--;
01838 }
01839
if ( *start ==
'"' || *start ==
'\'' ) {
01840 start++; l--;
01841 }
01842
while ( l &&
01843 (start[l-1] ==
' ' || start[l-1] ==
'\t' || start[l-1] ==
'\r' ||
01844 start[l-1] ==
'\n' || start[l-1] ==
'\f' ) ) {
01845 l--;
01846 }
01847
if ( l && (start[l-1] ==
'\"' || start[l-1] ==
'\'' ) )
01848 l--;
01849
01850
default:
01851
break;
01852 }
01853
01854
01855
unsigned short *out = start;
01856
unsigned short *escape = 0;
01857
01858
for (
int i = 0; i < l; i++ ) {
01859
unsigned short *current = start+i;
01860
if ( escape == current - 1 ) {
01861
if ( ( *current >=
'0' && *current <=
'9' ) ||
01862 ( *current >=
'a' && *current <=
'f' ) ||
01863 ( *current >=
'A' && *current <=
'F' ) )
01864
continue;
01865
if ( yyTok == STRING &&
01866 ( *current ==
'\n' || *current ==
'\r' || *current ==
'\f' ) ) {
01867
01868
if ( *current !=
'\r' )
01869 escape = 0;
01870
continue;
01871 }
01872
01873
01874 *out++ = *current;
01875 escape = 0;
01876
continue;
01877 }
01878
if ( escape == current - 2 && yyTok == STRING &&
01879 *(current-1) ==
'\r' && *current ==
'\n' ) {
01880 escape = 0;
01881
continue;
01882 }
01883
if ( escape > current - 7 &&
01884 ( ( *current >=
'0' && *current <=
'9' ) ||
01885 ( *current >=
'a' && *current <=
'f' ) ||
01886 ( *current >=
'A' && *current <=
'F' ) ) )
01887
continue;
01888
if ( escape ) {
01889
01890
int uc = 0;
01891 escape++;
01892
while ( escape < current ) {
01893
01894 uc *= 16;
01895 uc += toHex( *escape );
01896 escape++;
01897 }
01898
01899
01900
if ( uc > 0xffff )
01901 uc = 0xfffd;
01902 *(out++) = (
unsigned short)uc;
01903 escape = 0;
01904
if ( *current ==
' ' ||
01905 *current ==
'\t' ||
01906 *current ==
'\r' ||
01907 *current ==
'\n' ||
01908 *current ==
'\f' )
01909
continue;
01910 }
01911
if ( !escape && *current ==
'\\' ) {
01912 escape = current;
01913
continue;
01914 }
01915 *(out++) = *current;
01916 }
01917
if ( escape ) {
01918
01919
int uc = 0;
01920 escape++;
01921
while ( escape < start+l ) {
01922
01923 uc *= 16;
01924 uc += toHex( *escape );
01925 escape++;
01926 }
01927
01928
01929
if ( uc > 0xffff )
01930 uc = 0xfffd;
01931 *(out++) = (
unsigned short)uc;
01932 }
01933
01934 *length = out - start;
01935
return start;
01936 }
01937
01938
01939
#define YY_DECL int DOM::CSSParser::lex()
01940
#define yyconst const
01941
typedef int yy_state_type;
01942
typedef unsigned int YY_CHAR;
01943
01944
#define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c)
01945
#define YY_DO_BEFORE_ACTION \
01946
yytext = yy_bp; \
01947
yyleng = (int) (yy_cp - yy_bp); \
01948
yy_hold_char = *yy_cp; \
01949
*yy_cp = 0; \
01950
yy_c_buf_p = yy_cp;
01951
#define YY_BREAK break;
01952
#define ECHO qDebug( "%s", QString( (QChar *)yytext, yyleng ).latin1() )
01953
#define YY_RULE_SETUP
01954
#define INITIAL 0
01955
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
01956
#define YY_START ((yy_start - 1) / 2)
01957
#define yyterminate() yyTok = END; return yyTok
01958
#define YY_FATAL_ERROR(a) qFatal(a)
01959
#define BEGIN yy_start = 1 + 2 *
01960
#define COMMENT 1
01961
01962
#include "tokenizer.cpp"