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