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