khtml Library API Documentation

cssparser.cpp

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