ed26e233556caaf553d338f98bf8f3cde177fcf0
[WebKit-https.git] / WebCore / css / cssparser.cpp
1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
5  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
6  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "config.h"
25 #include "cssparser.h"
26
27 #include "CSSBorderImageValue.h"
28 #include "CSSImageValue.h"
29 #include "CSSCharsetRule.h"
30 #include "CSSImportRule.h"
31 #include "CSSInheritedValue.h"
32 #include "CSSInitialValue.h"
33 #include "CSSMediaRule.h"
34 #include "CSSMutableStyleDeclaration.h"
35 #include "CSSPrimitiveValue.h"
36 #include "CSSProperty.h"
37 #include "CSSPropertyNames.h"
38 #include "CSSRuleList.h"
39 #include "CSSSelector.h"
40 #include "CSSStyleRule.h"
41 #include "CSSStyleSheet.h"
42 #include "CSSQuirkPrimitiveValue.h"
43 #include "CSSValueKeywords.h"
44 #include "CSSValueList.h"
45 #include "DashboardRegion.h"
46 #include "Document.h"
47 #include "FontFamilyValue.h"
48 #include "FontValue.h"
49 #include "KURL.h"
50 #include "MediaList.h"
51 #include "Pair.h"
52 #include "ShadowValue.h"
53 #include "csshelper.h"
54 #include "MediaQueryExp.h"
55
56 #define YYDEBUG 0
57
58 #if YYDEBUG > 0
59 extern int cssyydebug;
60 #endif
61
62 extern int cssyyparse(void* parser);
63
64 using namespace std;
65
66 namespace WebCore {
67
68 ValueList::~ValueList()
69 {
70      size_t numValues = m_values.size();
71      for (size_t i = 0; i < numValues; i++)
72          if (m_values[i].unit == Value::Function)
73              delete m_values[i].function;
74 }
75
76 namespace {
77     class ShorthandScope {
78     public:
79         ShorthandScope(CSSParser* parser, int propId) : m_parser(parser)
80         {
81             if (!(m_parser->m_inParseShorthand++))
82                 m_parser->m_currentShorthand = propId;
83         }
84         ~ShorthandScope()
85         {
86             if (!(--m_parser->m_inParseShorthand))
87                 m_parser->m_currentShorthand = 0;
88         }
89
90     private:
91         CSSParser* m_parser;
92     };
93 }
94
95 CSSParser* CSSParser::currentParser = 0;
96
97 CSSParser::CSSParser(bool strictParsing)
98     : m_floatingMediaQuery(0)
99     , m_floatingMediaQueryExp(0)
100     , m_floatingMediaQueryExpList(0)
101 {
102 #ifdef CSS_DEBUG
103     kdDebug(6080) << "CSSParser::CSSParser this=" << this << endl;
104 #endif
105     strict = strictParsing;
106
107     parsedProperties = (CSSProperty **)fastMalloc(32 * sizeof(CSSProperty *));
108     numParsedProperties = 0;
109     maxParsedProperties = 32;
110
111     data = 0;
112     valueList = 0;
113     id = 0;
114     important = false;
115     m_inParseShorthand = 0;
116     m_currentShorthand = 0;
117     m_implicitShorthand = false;
118
119     defaultNamespace = starAtom;
120     
121     yy_start = 1;
122
123 #if YYDEBUG > 0
124     cssyydebug = 1;
125 #endif
126 }
127
128 CSSParser::~CSSParser()
129 {
130     clearProperties();
131     fastFree(parsedProperties);
132
133     delete valueList;
134
135     fastFree(data);
136
137     if (m_floatingMediaQueryExpList) {
138         deleteAllValues(*m_floatingMediaQueryExpList);
139         delete m_floatingMediaQueryExpList;
140     }
141     delete m_floatingMediaQueryExp;
142     delete m_floatingMediaQuery;
143     deleteAllValues(m_floatingSelectors);
144     deleteAllValues(m_floatingValueLists);
145     deleteAllValues(m_floatingFunctions);
146 }
147
148 void ParseString::lower()
149 {
150     // Fast case for all-ASCII.
151     UChar ored = 0;
152     for (int i = 0; i < length; i++)
153         ored |= characters[i];
154     if (ored & ~0x7F)
155         for (int i = 0; i < length; i++)
156             characters[i] = u_tolower(characters[i]);
157     else
158         for (int i = 0; i < length; i++)
159             characters[i] = tolower(characters[i]);
160 }
161
162 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
163 {
164     int length = string.length() + strlen(prefix) + strlen(suffix) + 2;
165
166     if (data)
167         fastFree(data);
168     
169     data = static_cast<UChar*>(fastMalloc(length * sizeof(UChar)));
170     for (unsigned i = 0; i < strlen(prefix); i++)
171         data[i] = prefix[i];
172     
173     memcpy(data + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
174
175     unsigned start = strlen(prefix) + string.length();
176     unsigned end = start + strlen(suffix);
177     for (unsigned i = start; i < end; i++)
178         data[i] = suffix[i - start];
179
180     data[length - 1] = 0;
181     data[length - 2] = 0;
182
183     yy_hold_char = 0;
184     yyleng = 0;
185     yytext = yy_c_buf_p = data;
186     yy_hold_char = *yy_c_buf_p;
187 }
188
189 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string)
190 {
191     styleElement = sheet;
192     defaultNamespace = starAtom; // Reset the default namespace.
193     
194     setupParser("", string, "");
195
196     CSSParser* old = currentParser;
197     currentParser = this;
198     cssyyparse(this);
199     currentParser = old;
200
201     rule = 0;
202 }
203
204 PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet *sheet, const String &string)
205 {
206     styleElement = sheet;
207     
208     setupParser("@-webkit-rule{", string, "} ");
209
210     CSSParser* old = currentParser;
211     currentParser = this;
212     cssyyparse(this);
213     currentParser = old;
214
215     return rule.release();
216 }
217
218 bool CSSParser::parseValue(CSSMutableStyleDeclaration *declaration, int _id, const String &string, bool _important)
219 {
220     styleElement = declaration->stylesheet();
221
222     setupParser("@-webkit-value{", string, "} ");
223
224     id = _id;
225     important = _important;
226     
227     CSSParser* old = currentParser;
228     currentParser = this;
229     cssyyparse(this);
230     currentParser = old;
231     
232     rule = 0;
233
234     bool ok = false;
235     if (numParsedProperties) {
236         ok = true;
237         declaration->addParsedProperties(parsedProperties, numParsedProperties);
238         clearProperties();
239     }
240
241     return ok;
242 }
243
244 RGBA32 CSSParser::parseColor(const String &string)
245 {
246     RGBA32 color = 0;
247     RefPtr<CSSMutableStyleDeclaration>dummyStyleDeclaration = new CSSMutableStyleDeclaration;
248
249     CSSParser parser(true);
250
251     // First try creating a color specified by name or the "#" syntax.
252     if (!parser.parseColor(string.deprecatedString(), color)) {
253     
254         // Now try to create a color from the rgb() or rgba() syntax.
255         if (parser.parseColor(dummyStyleDeclaration.get(), string)) {
256             CSSValue* value = parser.parsedProperties[0]->value();
257             if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {
258                 CSSPrimitiveValue *primitiveValue = static_cast<CSSPrimitiveValue *>(value);
259                 color = primitiveValue->getRGBColorValue();
260             }
261         }
262     }
263     
264     return color;
265 }
266
267 bool CSSParser::parseColor(CSSMutableStyleDeclaration *declaration, const String &string)
268 {
269     styleElement = declaration->stylesheet();
270
271     setupParser("@-webkit-decls{color:", string, "} ");
272
273     CSSParser* old = currentParser;
274     currentParser = this;
275     cssyyparse(this);
276     currentParser = old;
277
278     rule = 0;
279
280     bool ok = false;
281     if (numParsedProperties && parsedProperties[0]->m_id == CSS_PROP_COLOR)
282         ok = true;
283
284     return ok;
285 }
286
287 bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration *declaration, const String &string)
288 {
289     styleElement = declaration->stylesheet();
290
291     setupParser("@-webkit-decls{", string, "} ");
292
293     CSSParser* old = currentParser;
294     currentParser = this;
295     cssyyparse(this);
296     currentParser = old;
297
298     rule = 0;
299
300     bool ok = false;
301     if (numParsedProperties) {
302         ok = true;
303         declaration->addParsedProperties(parsedProperties, numParsedProperties);
304         clearProperties();
305     }
306
307     return ok;
308 }
309
310 bool CSSParser::parseMediaQuery(MediaList* queries, const String& string)
311 {
312     if (string.isEmpty() || string.isNull()) {
313         return true;
314     }
315
316     mediaQuery = 0;
317     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
318     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
319     setupParser ("@-webkit-mediaquery ", string, "} ");
320
321     CSSParser* old = currentParser;
322     currentParser = this;
323     cssyyparse(this);
324     currentParser = old;
325
326     bool ok = false;
327     if (mediaQuery) {
328         ok = true;
329         queries->appendMediaQuery(mediaQuery);
330         mediaQuery = 0;
331     }
332
333     return ok;
334 }
335
336
337 void CSSParser::addProperty(int propId, CSSValue *value, bool important)
338 {
339     CSSProperty *prop = new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand);
340     if (numParsedProperties >= maxParsedProperties) {
341         maxParsedProperties += 32;
342         parsedProperties = (CSSProperty **)fastRealloc(parsedProperties,
343                                                        maxParsedProperties*sizeof(CSSProperty *));
344     }
345     parsedProperties[numParsedProperties++] = prop;
346 }
347
348 void CSSParser::rollbackLastProperties(int num)
349 {
350     ASSERT(num >= 0);
351     ASSERT(numParsedProperties >= num);
352
353     for (int i = 0; i < num; ++i)
354         delete parsedProperties[--numParsedProperties];
355 }
356
357 void CSSParser::clearProperties()
358 {
359     for (int i = 0; i < numParsedProperties; i++)
360         delete parsedProperties[i];
361     numParsedProperties = 0;
362 }
363
364 Document *CSSParser::document() const
365 {
366     StyleBase *root = styleElement;
367     Document *doc = 0;
368     while (root->parent())
369         root = root->parent();
370     if (root->isCSSStyleSheet())
371         doc = static_cast<CSSStyleSheet*>(root)->doc();
372     return doc;
373 }
374
375 bool CSSParser::validUnit(Value* value, Units unitflags, bool strict)
376 {
377     if (unitflags & FNonNeg && value->fValue < 0)
378         return false;
379
380     bool b = false;
381     switch(value->unit) {
382     case CSSPrimitiveValue::CSS_NUMBER:
383         b = (unitflags & FNumber);
384         if (!b && ((unitflags & FLength) && (value->fValue == 0 || !strict))) {
385             value->unit = CSSPrimitiveValue::CSS_PX;
386             b = true;
387         }
388         if (!b && (unitflags & FInteger) && value->isInt)
389             b = true;
390         break;
391     case CSSPrimitiveValue::CSS_PERCENTAGE:
392         b = (unitflags & FPercent);
393         break;
394     case Value::Q_EMS:
395     case CSSPrimitiveValue::CSS_EMS:
396     case CSSPrimitiveValue::CSS_EXS:
397     case CSSPrimitiveValue::CSS_PX:
398     case CSSPrimitiveValue::CSS_CM:
399     case CSSPrimitiveValue::CSS_MM:
400     case CSSPrimitiveValue::CSS_IN:
401     case CSSPrimitiveValue::CSS_PT:
402     case CSSPrimitiveValue::CSS_PC:
403         b = (unitflags & FLength);
404         break;
405     case CSSPrimitiveValue::CSS_MS:
406     case CSSPrimitiveValue::CSS_S:
407         b = (unitflags & FTime);
408         break;
409     case CSSPrimitiveValue::CSS_DEG:
410     case CSSPrimitiveValue::CSS_RAD:
411     case CSSPrimitiveValue::CSS_GRAD:
412     case CSSPrimitiveValue::CSS_HZ:
413     case CSSPrimitiveValue::CSS_KHZ:
414     case CSSPrimitiveValue::CSS_DIMENSION:
415     default:
416         break;
417     }
418     return b;
419 }
420
421 bool CSSParser::parseValue(int propId, bool important)
422 {
423     if (!valueList)
424         return false;
425
426     Value *value = valueList->current();
427
428     if (!value)
429         return false;
430
431     int id = value->id;
432
433     int num = inShorthand() ? 1 : valueList->size();
434
435     if (id == CSS_VAL_INHERIT) {
436         if (num != 1)
437             return false;
438         addProperty(propId, new CSSInheritedValue(), important);
439         return true;
440     }
441     else if (id == CSS_VAL_INITIAL) {
442         if (num != 1)
443             return false;
444         addProperty(propId, new CSSInitialValue(), important);
445         return true;
446     }
447
448     bool valid_primitive = false;
449     CSSValue *parsedValue = 0;
450
451     switch(propId) {
452         /* The comment to the left defines all valid value of this properties as defined
453          * in CSS 2, Appendix F. Property index
454          */
455
456         /* All the CSS properties are not supported by the renderer at the moment.
457          * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
458          * (see parseAuralValues). As we don't support them at all this seems reasonable.
459          */
460
461     case CSS_PROP_SIZE:                 // <length>{1,2} | auto | portrait | landscape | inherit
462     case CSS_PROP_QUOTES:               // [<string> <string>]+ | none | inherit
463 //     case CSS_PROP_PAGE:                 // <identifier> | auto // ### CHECK
464         // ### To be done
465         if (id)
466             valid_primitive = true;
467         break;
468     case CSS_PROP_UNICODE_BIDI:         // normal | embed | bidi-override | inherit
469         if (id == CSS_VAL_NORMAL ||
470              id == CSS_VAL_EMBED ||
471              id == CSS_VAL_BIDI_OVERRIDE)
472             valid_primitive = true;
473         break;
474
475     case CSS_PROP_POSITION:             // static | relative | absolute | fixed | inherit
476         if (id == CSS_VAL_STATIC ||
477              id == CSS_VAL_RELATIVE ||
478              id == CSS_VAL_ABSOLUTE ||
479              id == CSS_VAL_FIXED)
480             valid_primitive = true;
481         break;
482
483     case CSS_PROP_PAGE_BREAK_AFTER:     // auto | always | avoid | left | right | inherit
484     case CSS_PROP_PAGE_BREAK_BEFORE:    // auto | always | avoid | left | right | inherit
485         if (id == CSS_VAL_AUTO ||
486              id == CSS_VAL_ALWAYS ||
487              id == CSS_VAL_AVOID ||
488              id == CSS_VAL_LEFT ||
489              id == CSS_VAL_RIGHT)
490             valid_primitive = true;
491         break;
492
493     case CSS_PROP_PAGE_BREAK_INSIDE:    // avoid | auto | inherit
494         if (id == CSS_VAL_AUTO ||
495              id == CSS_VAL_AVOID)
496             valid_primitive = true;
497         break;
498
499     case CSS_PROP_EMPTY_CELLS:          // show | hide | inherit
500         if (id == CSS_VAL_SHOW ||
501              id == CSS_VAL_HIDE)
502             valid_primitive = true;
503         break;
504
505     case CSS_PROP_CONTENT:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
506         // close-quote | no-open-quote | no-close-quote ]+ | inherit
507         return parseContent(propId, important);
508         break;
509
510     case CSS_PROP_WHITE_SPACE:          // normal | pre | nowrap | inherit
511         if (id == CSS_VAL_NORMAL ||
512             id == CSS_VAL_PRE ||
513             id == CSS_VAL_PRE_WRAP ||
514             id == CSS_VAL_PRE_LINE ||
515             id == CSS_VAL_NOWRAP)
516             valid_primitive = true;
517         break;
518
519     case CSS_PROP_CLIP:                 // <shape> | auto | inherit
520         if (id == CSS_VAL_AUTO)
521             valid_primitive = true;
522         else if (value->unit == Value::Function)
523             return parseShape(propId, important);
524         break;
525
526     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
527      * correctly and allows optimization in WebCore::applyRule(..)
528      */
529     case CSS_PROP_CAPTION_SIDE:         // top | bottom | left | right | inherit
530         if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT ||
531             id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM)
532             valid_primitive = true;
533         break;
534
535     case CSS_PROP_BORDER_COLLAPSE:      // collapse | separate | inherit
536         if (id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE)
537             valid_primitive = true;
538         break;
539
540     case CSS_PROP_VISIBILITY:           // visible | hidden | collapse | inherit
541         if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_COLLAPSE)
542             valid_primitive = true;
543         break;
544
545     case CSS_PROP_OVERFLOW:             // visible | hidden | scroll | auto | marquee | overlay | inherit
546     case CSS_PROP_OVERFLOW_X:
547     case CSS_PROP_OVERFLOW_Y:
548         if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_SCROLL || id == CSS_VAL_AUTO ||
549             id == CSS_VAL_OVERLAY || id == CSS_VAL__WEBKIT_MARQUEE)
550             valid_primitive = true;
551         break;
552
553     case CSS_PROP_LIST_STYLE_POSITION:  // inside | outside | inherit
554         if (id == CSS_VAL_INSIDE || id == CSS_VAL_OUTSIDE)
555             valid_primitive = true;
556         break;
557
558     case CSS_PROP_LIST_STYLE_TYPE:
559         // disc | circle | square | decimal | decimal-leading-zero | lower-roman |
560         // upper-roman | lower-greek | lower-alpha | lower-latin | upper-alpha |
561         // upper-latin | hebrew | armenian | georgian | cjk-ideographic | hiragana |
562         // katakana | hiragana-iroha | katakana-iroha | none | inherit
563         if ((id >= CSS_VAL_DISC && id <= CSS_VAL_KATAKANA_IROHA) || id == CSS_VAL_NONE)
564             valid_primitive = true;
565         break;
566
567     case CSS_PROP_DISPLAY:
568         // inline | block | list-item | run-in | inline-block | table |
569         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
570         // table-column-group | table-column | table-cell | table-caption | box | inline-box | none | inherit
571         if ((id >= CSS_VAL_INLINE && id <= CSS_VAL__WEBKIT_INLINE_BOX) || id == CSS_VAL_NONE)
572             valid_primitive = true;
573         break;
574
575     case CSS_PROP_DIRECTION:            // ltr | rtl | inherit
576         if (id == CSS_VAL_LTR || id == CSS_VAL_RTL)
577             valid_primitive = true;
578         break;
579
580     case CSS_PROP_TEXT_TRANSFORM:       // capitalize | uppercase | lowercase | none | inherit
581         if ((id >= CSS_VAL_CAPITALIZE && id <= CSS_VAL_LOWERCASE) || id == CSS_VAL_NONE)
582             valid_primitive = true;
583         break;
584
585     case CSS_PROP_FLOAT:                // left | right | none | inherit + center for buggy CSS
586         if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT ||
587              id == CSS_VAL_NONE || id == CSS_VAL_CENTER)
588             valid_primitive = true;
589         break;
590
591     case CSS_PROP_CLEAR:                // none | left | right | both | inherit
592         if (id == CSS_VAL_NONE || id == CSS_VAL_LEFT ||
593              id == CSS_VAL_RIGHT|| id == CSS_VAL_BOTH)
594             valid_primitive = true;
595         break;
596
597     case CSS_PROP_TEXT_ALIGN:
598         // left | right | center | justify | khtml_left | khtml_right | khtml_center | <string> | inherit
599         if ((id >= CSS_VAL__WEBKIT_AUTO && id <= CSS_VAL__WEBKIT_CENTER) ||
600              value->unit == CSSPrimitiveValue::CSS_STRING)
601             valid_primitive = true;
602         break;
603
604     case CSS_PROP_OUTLINE_STYLE:        // <border-style> | auto | inherit
605         if (id == CSS_VAL_AUTO) {
606             valid_primitive = true;
607             break;
608         } // Fall through!
609     case CSS_PROP_BORDER_TOP_STYLE:     //// <border-style> | inherit
610     case CSS_PROP_BORDER_RIGHT_STYLE:   //   Defined as:    none | hidden | dotted | dashed |
611     case CSS_PROP_BORDER_BOTTOM_STYLE:  //   solid | double | groove | ridge | inset | outset
612     case CSS_PROP_BORDER_LEFT_STYLE:    ////
613         if (id >= CSS_VAL_NONE && id <= CSS_VAL_DOUBLE)
614             valid_primitive = true;
615         break;
616
617     case CSS_PROP_FONT_WEIGHT:  // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 |
618         // 500 | 600 | 700 | 800 | 900 | inherit
619         if (id >= CSS_VAL_NORMAL && id <= CSS_VAL_900) {
620             // Allready correct id
621             valid_primitive = true;
622         } else if (validUnit(value, FInteger|FNonNeg, false)) {
623             int weight = (int)value->fValue;
624             if ((weight % 100))
625                 break;
626             weight /= 100;
627             if (weight >= 1 && weight <= 9) {
628                 id = CSS_VAL_100 + weight - 1;
629                 valid_primitive = true;
630             }
631         }
632         break;
633
634     case CSS_PROP_BORDER_SPACING: {
635         const int properties[2] = { CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING,
636                                     CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING };
637         if (num == 1) {
638             ShorthandScope scope(this, CSS_PROP_BORDER_SPACING);
639             if (!parseValue(properties[0], important))
640                 return false;
641             CSSValue* value = parsedProperties[numParsedProperties-1]->value();
642             addProperty(properties[1], value, important);
643             return true;
644         }
645         else if (num == 2) {
646             ShorthandScope scope(this, CSS_PROP_BORDER_SPACING);
647             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
648                 return false;
649             return true;
650         }
651         return false;
652     }
653     case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING:
654     case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING:
655         valid_primitive = validUnit(value, FLength|FNonNeg, strict);
656         break;
657     case CSS_PROP_SCROLLBAR_FACE_COLOR:         // IE5.5
658     case CSS_PROP_SCROLLBAR_SHADOW_COLOR:       // IE5.5
659     case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:    // IE5.5
660     case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:      // IE5.5
661     case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:   // IE5.5
662     case CSS_PROP_SCROLLBAR_TRACK_COLOR:        // IE5.5
663     case CSS_PROP_SCROLLBAR_ARROW_COLOR:        // IE5.5
664         if (strict)
665             break;
666         /* nobreak */
667     case CSS_PROP_OUTLINE_COLOR:        // <color> | invert | inherit
668         // Outline color has "invert" as additional keyword.
669         // Also, we want to allow the special focus color even in strict parsing mode.
670         if (propId == CSS_PROP_OUTLINE_COLOR && (id == CSS_VAL_INVERT || id == CSS_VAL__WEBKIT_FOCUS_RING_COLOR)) {
671             valid_primitive = true;
672             break;
673         }
674         /* nobreak */
675     case CSS_PROP_BACKGROUND_COLOR:     // <color> | inherit
676     case CSS_PROP_BORDER_TOP_COLOR:     // <color> | inherit
677     case CSS_PROP_BORDER_RIGHT_COLOR:   // <color> | inherit
678     case CSS_PROP_BORDER_BOTTOM_COLOR:  // <color> | inherit
679     case CSS_PROP_BORDER_LEFT_COLOR:    // <color> | inherit
680     case CSS_PROP_COLOR:                // <color> | inherit
681     case CSS_PROP_TEXT_LINE_THROUGH_COLOR: // CSS3 text decoration colors
682     case CSS_PROP_TEXT_UNDERLINE_COLOR:
683     case CSS_PROP_TEXT_OVERLINE_COLOR:
684         if (id == CSS_VAL__WEBKIT_TEXT)
685             valid_primitive = true; // Always allow this, even when strict parsing is on,
686                                     // since we use this in our UA sheets.
687         else if (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT || id == CSS_VAL_MENU ||
688              (id >= CSS_VAL__WEBKIT_FOCUS_RING_COLOR && id < CSS_VAL__WEBKIT_TEXT && !strict)) {
689             valid_primitive = true;
690         } else {
691             parsedValue = parseColor();
692             if (parsedValue)
693                 valueList->next();
694         }
695         break;
696
697     case CSS_PROP_CURSOR:
698         // [<uri>,]*  [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
699         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize | 
700         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help ] ] | inherit
701         if (!strict && id == CSS_VAL_HAND) { // MSIE 5 compatibility :/
702             id = CSS_VAL_POINTER;
703             valid_primitive = true;
704         } else if (id >= CSS_VAL_AUTO && id <= CSS_VAL_HELP)
705             valid_primitive = true;
706         else if (value->unit == CSSPrimitiveValue::CSS_URI) {
707             String uri = parseURL(domString(value->string));
708             if (!uri.isEmpty()) {
709                 parsedValue = new CSSImageValue(String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()), styleElement);
710                 // FIXME: we don't support fallback cursors yet, but ignoring the remaining values
711                 // will at least let compliant declarations parse.
712                 addProperty(propId, parsedValue, important);
713                 return true;
714             }
715         }
716         break;
717
718     case CSS_PROP_BACKGROUND_ATTACHMENT:
719     case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
720     case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
721     case CSS_PROP_BACKGROUND_IMAGE:
722     case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
723     case CSS_PROP_BACKGROUND_POSITION:
724     case CSS_PROP_BACKGROUND_POSITION_X:
725     case CSS_PROP_BACKGROUND_POSITION_Y:
726     case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
727     case CSS_PROP_BACKGROUND_REPEAT: {
728         CSSValue *val1 = 0, *val2 = 0;
729         int propId1, propId2;
730         if (parseBackgroundProperty(propId, propId1, propId2, val1, val2)) {
731             addProperty(propId1, val1, important);
732             if (val2)
733                 addProperty(propId2, val2, important);
734             return true;
735         }
736         return false;
737     }
738     case CSS_PROP_LIST_STYLE_IMAGE:     // <uri> | none | inherit
739         if (id == CSS_VAL_NONE) {
740             parsedValue = new CSSImageValue();
741             valueList->next();
742         }
743         else if (value->unit == CSSPrimitiveValue::CSS_URI) {
744             // ### allow string in non strict mode?
745             String uri = parseURL(domString(value->string));
746             if (!uri.isEmpty()) {
747                 parsedValue = new CSSImageValue(
748                     String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()),
749                     styleElement);
750                 valueList->next();
751             }
752         }
753         break;
754
755     case CSS_PROP_OUTLINE_WIDTH:        // <border-width> | inherit
756     case CSS_PROP_BORDER_TOP_WIDTH:     //// <border-width> | inherit
757     case CSS_PROP_BORDER_RIGHT_WIDTH:   //   Which is defined as
758     case CSS_PROP_BORDER_BOTTOM_WIDTH:  //   thin | medium | thick | <length>
759     case CSS_PROP_BORDER_LEFT_WIDTH:    ////
760         if (id == CSS_VAL_THIN || id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK)
761             valid_primitive = true;
762         else
763             valid_primitive = validUnit(value, FLength, strict);
764         break;
765
766     case CSS_PROP_LETTER_SPACING:       // normal | <length> | inherit
767     case CSS_PROP_WORD_SPACING:         // normal | <length> | inherit
768         if (id == CSS_VAL_NORMAL)
769             valid_primitive = true;
770         else
771             valid_primitive = validUnit(value, FLength, strict);
772         break;
773
774     case CSS_PROP_WORD_WRAP:           // normal | break-word
775         if (id == CSS_VAL_NORMAL || id == CSS_VAL_BREAK_WORD)
776             valid_primitive = true;
777         break;
778
779     case CSS_PROP_TEXT_INDENT:          // <length> | <percentage> | inherit
780     case CSS_PROP_PADDING_TOP:          //// <padding-width> | inherit
781     case CSS_PROP_PADDING_RIGHT:        //   Which is defined as
782     case CSS_PROP_PADDING_BOTTOM:       //   <length> | <percentage>
783     case CSS_PROP_PADDING_LEFT:         ////
784     case CSS_PROP__WEBKIT_PADDING_START:
785         valid_primitive = (!id && validUnit(value, FLength|FPercent, strict));
786         break;
787
788     case CSS_PROP_MAX_HEIGHT:           // <length> | <percentage> | none | inherit
789     case CSS_PROP_MAX_WIDTH:            // <length> | <percentage> | none | inherit
790         if (id == CSS_VAL_NONE || id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC) {
791             valid_primitive = true;
792             break;
793         }
794         /* nobreak */
795     case CSS_PROP_MIN_HEIGHT:           // <length> | <percentage> | inherit
796     case CSS_PROP_MIN_WIDTH:            // <length> | <percentage> | inherit
797         if (id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC)
798             valid_primitive = true;
799         else
800             valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, strict));
801         break;
802
803     case CSS_PROP_FONT_SIZE:
804         // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
805         if (id >= CSS_VAL_XX_SMALL && id <= CSS_VAL_LARGER)
806             valid_primitive = true;
807         else
808             valid_primitive = (validUnit(value, FLength|FPercent, strict));
809         break;
810
811     case CSS_PROP_FONT_STYLE:           // normal | italic | oblique | inherit
812         if (id == CSS_VAL_NORMAL || id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE)
813             valid_primitive = true;
814         break;
815
816     case CSS_PROP_FONT_VARIANT:         // normal | small-caps | inherit
817         if (id == CSS_VAL_NORMAL || id == CSS_VAL_SMALL_CAPS)
818             valid_primitive = true;
819         break;
820
821     case CSS_PROP_VERTICAL_ALIGN:
822         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
823         // <percentage> | <length> | inherit
824
825         if (id >= CSS_VAL_BASELINE && id <= CSS_VAL__WEBKIT_BASELINE_MIDDLE)
826             valid_primitive = true;
827         else
828             valid_primitive = (!id && validUnit(value, FLength|FPercent, strict));
829         break;
830
831     case CSS_PROP_HEIGHT:               // <length> | <percentage> | auto | inherit
832     case CSS_PROP_WIDTH:                // <length> | <percentage> | auto | inherit
833         if (id == CSS_VAL_AUTO || id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC)
834             valid_primitive = true;
835         else
836             // ### handle multilength case where we allow relative units
837             valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, strict));
838         break;
839
840     case CSS_PROP_BOTTOM:               // <length> | <percentage> | auto | inherit
841     case CSS_PROP_LEFT:                 // <length> | <percentage> | auto | inherit
842     case CSS_PROP_RIGHT:                // <length> | <percentage> | auto | inherit
843     case CSS_PROP_TOP:                  // <length> | <percentage> | auto | inherit
844     case CSS_PROP_MARGIN_TOP:           //// <margin-width> | inherit
845     case CSS_PROP_MARGIN_RIGHT:         //   Which is defined as
846     case CSS_PROP_MARGIN_BOTTOM:        //   <length> | <percentage> | auto | inherit
847     case CSS_PROP_MARGIN_LEFT:          ////
848     case CSS_PROP__WEBKIT_MARGIN_START:
849         if (id == CSS_VAL_AUTO)
850             valid_primitive = true;
851         else
852             valid_primitive = (!id && validUnit(value, FLength|FPercent, strict));
853         break;
854
855     case CSS_PROP_Z_INDEX:              // auto | <integer> | inherit
856         if (id == CSS_VAL_AUTO) {
857             valid_primitive = true;
858             break;
859         }
860         /* nobreak */
861     case CSS_PROP_ORPHANS:              // <integer> | inherit
862     case CSS_PROP_WIDOWS:               // <integer> | inherit
863         // ### not supported later on
864         valid_primitive = (!id && validUnit(value, FInteger, false));
865         break;
866
867     case CSS_PROP_LINE_HEIGHT:          // normal | <number> | <length> | <percentage> | inherit
868         if (id == CSS_VAL_NORMAL)
869             valid_primitive = true;
870         else
871             valid_primitive = (!id && validUnit(value, FNumber|FLength|FPercent, strict));
872         break;
873     case CSS_PROP_FONT_FAMILY:
874         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
875     {
876         parsedValue = parseFontFamily();
877         break;
878     }
879
880     case CSS_PROP_TEXT_DECORATION:
881     case CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT:
882         // none | [ underline || overline || line-through || blink ] | inherit
883         if (id == CSS_VAL_NONE) {
884             valid_primitive = true;
885         } else {
886             CSSValueList *list = new CSSValueList;
887             bool is_valid = true;
888             while(is_valid && value) {
889                 switch (value->id) {
890                 case CSS_VAL_BLINK:
891                     break;
892                 case CSS_VAL_UNDERLINE:
893                 case CSS_VAL_OVERLINE:
894                 case CSS_VAL_LINE_THROUGH:
895                     list->append(new CSSPrimitiveValue(value->id));
896                     break;
897                 default:
898                     is_valid = false;
899                 }
900                 value = valueList->next();
901             }
902             if(list->length() && is_valid) {
903                 parsedValue = list;
904                 valueList->next();
905             } else
906                 delete list;
907         }
908         break;
909
910     case CSS_PROP_TABLE_LAYOUT:         // auto | fixed | inherit
911         if (id == CSS_VAL_AUTO || id == CSS_VAL_FIXED)
912             valid_primitive = true;
913         break;
914
915     /* CSS3 properties */
916     case CSS_PROP__WEBKIT_APPEARANCE:
917         if ((id >= CSS_VAL_CHECKBOX && id <= CSS_VAL_TEXTAREA) || id == CSS_VAL_NONE)
918             valid_primitive = true;
919         break;
920
921     case CSS_PROP__WEBKIT_BINDING:
922 #ifdef XBL_SUPPORT
923         if (id == CSS_VAL_NONE)
924             valid_primitive = true;
925         else {
926             CSSValueList* values = new CSSValueList();
927             Value* val;
928             CSSValue* parsedValue = 0;
929             while ((val = valueList->current())) {
930                 if (val->unit == CSSPrimitiveValue::CSS_URI) {
931                     String value = parseURL(domString(val->string));
932                     parsedValue = new CSSPrimitiveValue(
933                                     String(KURL(styleElement->baseURL().deprecatedString(), value.deprecatedString()).url()), 
934                                     CSSPrimitiveValue::CSS_URI);
935                 } 
936                 
937                 if (parsedValue)
938                     values->append(parsedValue);
939                 else
940                     break;
941                 valueList->next();
942             }
943             if (values->length()) {
944                 addProperty(propId, values, important);
945                 valueList->next();
946                 return true;
947             }
948             delete values;
949             return false;
950         }
951 #endif
952         break;
953     case CSS_PROP__WEBKIT_BORDER_IMAGE:
954         if (id == CSS_VAL_NONE)
955             valid_primitive = true;
956         else
957             return parseBorderImage(propId, important);
958         break;
959     case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS:
960     case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS:
961     case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS:
962     case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS:
963     case CSS_PROP__WEBKIT_BORDER_RADIUS: {
964         if (num != 1 && num != 2)
965             return false;
966         valid_primitive = validUnit(value, FLength, strict);
967         if (!valid_primitive)
968             return false;
969         CSSPrimitiveValue* parsedValue1 = new CSSPrimitiveValue(value->fValue,
970                                                                         (CSSPrimitiveValue::UnitTypes)value->unit);
971         CSSPrimitiveValue* parsedValue2 = parsedValue1;
972         if (num == 2) {
973             value = valueList->next();
974             valid_primitive = validUnit(value, FLength, strict);
975             if (!valid_primitive) {
976                 delete parsedValue1;
977                 return false;
978             }
979             parsedValue2 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
980         }
981         
982         Pair* pair = new Pair(parsedValue1, parsedValue2);
983         CSSPrimitiveValue* val = new CSSPrimitiveValue(pair);
984         addProperty(propId, val, important);
985         return true;
986     }
987     case CSS_PROP_OUTLINE_OFFSET:
988         valid_primitive = validUnit(value, FLength, strict);
989         break;
990     case CSS_PROP_TEXT_SHADOW: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
991         if (id == CSS_VAL_NONE)
992             valid_primitive = true;
993         else
994             return parseShadow(propId, important);
995         break;
996     case CSS_PROP_OPACITY:
997         valid_primitive = validUnit(value, FNumber, strict);
998         break;
999     case CSS_PROP__WEBKIT_BOX_ALIGN:
1000         if (id == CSS_VAL_STRETCH || id == CSS_VAL_START || id == CSS_VAL_END ||
1001             id == CSS_VAL_CENTER || id == CSS_VAL_BASELINE)
1002             valid_primitive = true;
1003         break;
1004     case CSS_PROP__WEBKIT_BOX_DIRECTION:
1005         if (id == CSS_VAL_NORMAL || id == CSS_VAL_REVERSE)
1006             valid_primitive = true;
1007         break;
1008     case CSS_PROP__WEBKIT_BOX_LINES:
1009         if (id == CSS_VAL_SINGLE || id == CSS_VAL_MULTIPLE)
1010             valid_primitive = true;
1011         break;
1012     case CSS_PROP__WEBKIT_BOX_ORIENT:
1013         if (id == CSS_VAL_HORIZONTAL || id == CSS_VAL_VERTICAL ||
1014             id == CSS_VAL_INLINE_AXIS || id == CSS_VAL_BLOCK_AXIS)
1015             valid_primitive = true;
1016         break;
1017     case CSS_PROP__WEBKIT_BOX_PACK:
1018         if (id == CSS_VAL_START || id == CSS_VAL_END ||
1019             id == CSS_VAL_CENTER || id == CSS_VAL_JUSTIFY)
1020             valid_primitive = true;
1021         break;
1022     case CSS_PROP__WEBKIT_BOX_FLEX:
1023         valid_primitive = validUnit(value, FNumber, strict);
1024         break;
1025     case CSS_PROP__WEBKIT_BOX_FLEX_GROUP:
1026     case CSS_PROP__WEBKIT_BOX_ORDINAL_GROUP:
1027         valid_primitive = validUnit(value, FInteger|FNonNeg, true);
1028         break;
1029     case CSS_PROP_BOX_SIZING: {
1030         // We don't preface this with -webkit, since MacIE defined this property without the prefix.
1031         // Thus the damage has been done, and it's known that this property's definition isn't going
1032         // to fluctuate.
1033         if (id == CSS_VAL_BORDER_BOX || id == CSS_VAL_CONTENT_BOX)
1034             valid_primitive = true;
1035         break;
1036     }
1037     case CSS_PROP__WEBKIT_MARQUEE: {
1038         const int properties[5] = { CSS_PROP__WEBKIT_MARQUEE_DIRECTION, CSS_PROP__WEBKIT_MARQUEE_INCREMENT,
1039                                     CSS_PROP__WEBKIT_MARQUEE_REPETITION,
1040                                     CSS_PROP__WEBKIT_MARQUEE_STYLE, CSS_PROP__WEBKIT_MARQUEE_SPEED };
1041         return parseShorthand(propId, properties, 5, important);
1042     }
1043     case CSS_PROP__WEBKIT_MARQUEE_DIRECTION:
1044         if (id == CSS_VAL_FORWARDS || id == CSS_VAL_BACKWARDS || id == CSS_VAL_AHEAD ||
1045             id == CSS_VAL_REVERSE || id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || id == CSS_VAL_DOWN ||
1046             id == CSS_VAL_UP || id == CSS_VAL_AUTO)
1047             valid_primitive = true;
1048         break;
1049     case CSS_PROP__WEBKIT_MARQUEE_INCREMENT:
1050         if (id == CSS_VAL_SMALL || id == CSS_VAL_LARGE || id == CSS_VAL_MEDIUM)
1051             valid_primitive = true;
1052         else
1053             valid_primitive = validUnit(value, FLength|FPercent, strict);
1054         break;
1055     case CSS_PROP__WEBKIT_MARQUEE_STYLE:
1056         if (id == CSS_VAL_NONE || id == CSS_VAL_SLIDE || id == CSS_VAL_SCROLL || id == CSS_VAL_ALTERNATE ||
1057             id == CSS_VAL_UNFURL)
1058             valid_primitive = true;
1059         break;
1060     case CSS_PROP__WEBKIT_MARQUEE_REPETITION:
1061         if (id == CSS_VAL_INFINITE)
1062             valid_primitive = true;
1063         else
1064             valid_primitive = validUnit(value, FInteger|FNonNeg, strict);
1065         break;
1066     case CSS_PROP__WEBKIT_MARQUEE_SPEED:
1067         if (id == CSS_VAL_NORMAL || id == CSS_VAL_SLOW || id == CSS_VAL_FAST)
1068             valid_primitive = true;
1069         else
1070             valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict);
1071         break;
1072     case CSS_PROP__WEBKIT_USER_DRAG: // auto | none | element
1073         if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE || id == CSS_VAL_ELEMENT)
1074             valid_primitive = true;
1075         break;
1076     case CSS_PROP__WEBKIT_USER_MODIFY: // read-only | read-write
1077         if (id == CSS_VAL_READ_ONLY || id == CSS_VAL_READ_WRITE || CSS_VAL_READ_WRITE_PLAINTEXT_ONLY)
1078             valid_primitive = true;
1079         break;
1080     case CSS_PROP__WEBKIT_USER_SELECT: // auto | none | text
1081         if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE || id == CSS_VAL_TEXT || id == CSS_VAL_IGNORE)
1082             valid_primitive = true;
1083         break;
1084     case CSS_PROP_TEXT_OVERFLOW: // clip | ellipsis
1085         if (id == CSS_VAL_CLIP || id == CSS_VAL_ELLIPSIS)
1086             valid_primitive = true;
1087         break;
1088     case CSS_PROP__WEBKIT_MARGIN_COLLAPSE: {
1089         const int properties[2] = { CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE,
1090             CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE };
1091         if (num == 1) {
1092             ShorthandScope scope(this, CSS_PROP__WEBKIT_MARGIN_COLLAPSE);
1093             if (!parseValue(properties[0], important))
1094                 return false;
1095             CSSValue* value = parsedProperties[numParsedProperties-1]->value();
1096             addProperty(properties[1], value, important);
1097             return true;
1098         }
1099         else if (num == 2) {
1100             ShorthandScope scope(this, CSS_PROP__WEBKIT_MARGIN_COLLAPSE);
1101             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1102                 return false;
1103             return true;
1104         }
1105         return false;
1106     }
1107     case CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE:
1108     case CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE:
1109         if (id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE || id == CSS_VAL_DISCARD)
1110             valid_primitive = true;
1111         break;
1112     case CSS_PROP_TEXT_LINE_THROUGH_MODE:
1113     case CSS_PROP_TEXT_OVERLINE_MODE:
1114     case CSS_PROP_TEXT_UNDERLINE_MODE:
1115         if (id == CSS_VAL_CONTINUOUS || id == CSS_VAL_SKIP_WHITE_SPACE)
1116             valid_primitive = true;
1117         break;
1118     case CSS_PROP_TEXT_LINE_THROUGH_STYLE:
1119     case CSS_PROP_TEXT_OVERLINE_STYLE:
1120     case CSS_PROP_TEXT_UNDERLINE_STYLE:
1121         if (id == CSS_VAL_NONE || id == CSS_VAL_SOLID || id == CSS_VAL_DOUBLE ||
1122             id == CSS_VAL_DASHED || id == CSS_VAL_DOT_DASH || id == CSS_VAL_DOT_DOT_DASH ||
1123             id == CSS_VAL_WAVE)
1124             valid_primitive = true;
1125         break;
1126     case CSS_PROP_TEXT_LINE_THROUGH_WIDTH:
1127     case CSS_PROP_TEXT_OVERLINE_WIDTH:
1128     case CSS_PROP_TEXT_UNDERLINE_WIDTH:
1129         if (id == CSS_VAL_AUTO || id == CSS_VAL_NORMAL || id == CSS_VAL_THIN ||
1130             id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK)
1131             valid_primitive = true;
1132         else
1133             valid_primitive = !id && validUnit(value, FNumber|FLength|FPercent, strict);
1134         break;
1135     case CSS_PROP_RESIZE: // none | both | horizontal | vertical | auto
1136         if (id == CSS_VAL_NONE || id == CSS_VAL_BOTH || id == CSS_VAL_HORIZONTAL || id == CSS_VAL_VERTICAL || id == CSS_VAL_AUTO)
1137             valid_primitive = true;
1138         break;
1139     // End of CSS3 properties
1140
1141     // Apple specific properties.  These will never be standardized and are purely to
1142     // support custom WebKit-based Apple applications.
1143     case CSS_PROP__WEBKIT_LINE_CLAMP:
1144         valid_primitive = (!id && validUnit(value, FPercent, false));
1145         break;
1146     case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST:
1147         if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE)
1148             valid_primitive = true;
1149         break;
1150     case CSS_PROP__WEBKIT_RTL_ORDERING:
1151         if (id == CSS_VAL_LOGICAL || id == CSS_VAL_VISUAL)
1152             valid_primitive = true;
1153         break;
1154     
1155     case CSS_PROP__WEBKIT_FONT_SIZE_DELTA:           // <length>
1156         valid_primitive = validUnit(value, FLength, strict);
1157         break;
1158
1159     case CSS_PROP__WEBKIT_NBSP_MODE:     // normal | space
1160         if (id == CSS_VAL_NORMAL || id == CSS_VAL_SPACE)
1161             valid_primitive = true;
1162         break;
1163
1164     case CSS_PROP__WEBKIT_LINE_BREAK:   // normal | after-white-space
1165         if (id == CSS_VAL_NORMAL || id == CSS_VAL_AFTER_WHITE_SPACE)
1166             valid_primitive = true;
1167         break;
1168
1169     case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR:   // normal | match
1170         if (id == CSS_VAL_NORMAL || id == CSS_VAL_MATCH)
1171             valid_primitive = true;
1172         break;
1173
1174     case CSS_PROP__WEBKIT_HIGHLIGHT:
1175         if (id == CSS_VAL_NONE || value->unit == CSSPrimitiveValue::CSS_STRING)
1176             valid_primitive = true;
1177         break;
1178
1179     case CSS_PROP__WEBKIT_TEXT_SECURITY:
1180         // disc | circle | square | none | inherit
1181         if (id == CSS_VAL_DISC || id == CSS_VAL_CIRCLE || id == CSS_VAL_SQUARE|| id == CSS_VAL_NONE)
1182             valid_primitive = true;
1183         break;
1184
1185 #if __APPLE__
1186     case CSS_PROP__WEBKIT_DASHBOARD_REGION:                 // <dashboard-region> | <dashboard-region> 
1187         if (value->unit == Value::Function || id == CSS_VAL_NONE)
1188             return parseDashboardRegions(propId, important);
1189         break;
1190 #endif
1191     // End Apple-specific properties
1192
1193         /* shorthand properties */
1194     case CSS_PROP_BACKGROUND:
1195         // ['background-color' || 'background-image' || 'background-size' || 'background-repeat' ||
1196         // 'background-attachment' || 'background-position'] | inherit
1197         return parseBackgroundShorthand(important);
1198     case CSS_PROP_BORDER:
1199         // [ 'border-width' || 'border-style' || <color> ] | inherit
1200     {
1201         const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
1202                                     CSS_PROP_BORDER_COLOR };
1203         return parseShorthand(propId, properties, 3, important);
1204     }
1205     case CSS_PROP_BORDER_TOP:
1206         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
1207     {
1208         const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
1209                                     CSS_PROP_BORDER_TOP_COLOR};
1210         return parseShorthand(propId, properties, 3, important);
1211     }
1212     case CSS_PROP_BORDER_RIGHT:
1213         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
1214     {
1215         const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
1216                                     CSS_PROP_BORDER_RIGHT_COLOR };
1217         return parseShorthand(propId, properties, 3, important);
1218     }
1219     case CSS_PROP_BORDER_BOTTOM:
1220         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
1221     {
1222         const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
1223                                     CSS_PROP_BORDER_BOTTOM_COLOR };
1224         return parseShorthand(propId, properties, 3, important);
1225     }
1226     case CSS_PROP_BORDER_LEFT:
1227         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
1228     {
1229         const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
1230                                     CSS_PROP_BORDER_LEFT_COLOR };
1231         return parseShorthand(propId, properties, 3, important);
1232     }
1233     case CSS_PROP_OUTLINE:
1234         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
1235     {
1236         const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
1237                                     CSS_PROP_OUTLINE_COLOR };
1238         return parseShorthand(propId, properties, 3, important);
1239     }
1240     case CSS_PROP_BORDER_COLOR:
1241         // <color>{1,4} | inherit
1242     {
1243         const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
1244                                     CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
1245         return parse4Values(propId, properties, important);
1246     }
1247     case CSS_PROP_BORDER_WIDTH:
1248         // <border-width>{1,4} | inherit
1249     {
1250         const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
1251                                     CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
1252         return parse4Values(propId, properties, important);
1253     }
1254     case CSS_PROP_BORDER_STYLE:
1255         // <border-style>{1,4} | inherit
1256     {
1257         const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
1258                                     CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
1259         return parse4Values(propId, properties, important);
1260     }
1261     case CSS_PROP_MARGIN:
1262         // <margin-width>{1,4} | inherit
1263     {
1264         const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
1265                                     CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
1266         return parse4Values(propId, properties, important);
1267     }
1268     case CSS_PROP_PADDING:
1269         // <padding-width>{1,4} | inherit
1270     {
1271         const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
1272                                     CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
1273         return parse4Values(propId, properties, important);
1274     }
1275     case CSS_PROP_FONT:
1276         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
1277         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
1278         if (id >= CSS_VAL_CAPTION && id <= CSS_VAL_STATUS_BAR)
1279             valid_primitive = true;
1280         else
1281             return parseFont(important);
1282         break;
1283     case CSS_PROP_LIST_STYLE:
1284     {
1285         const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
1286                                     CSS_PROP_LIST_STYLE_IMAGE };
1287         return parseShorthand(propId, properties, 3, important);
1288     }
1289     default:
1290 #ifdef SVG_SUPPORT
1291         if (parseSVGValue(propId, important))
1292             return true;
1293 #endif
1294         break;
1295     }
1296
1297     if (valid_primitive) {
1298         if (id != 0)
1299             parsedValue = new CSSPrimitiveValue(id);
1300         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
1301             parsedValue = new CSSPrimitiveValue(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit);
1302         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1303             parsedValue = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
1304         else if (value->unit >= Value::Q_EMS)
1305             parsedValue = new CSSQuirkPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_EMS);
1306         valueList->next();
1307     }
1308     if (parsedValue) {
1309         if (!valueList->current() || inShorthand()) {
1310             addProperty(propId, parsedValue, important);
1311             return true;
1312         }
1313         delete parsedValue;
1314     }
1315     return false;
1316 }
1317
1318 void CSSParser::addBackgroundValue(CSSValue*& lval, CSSValue* rval)
1319 {
1320     if (lval) {
1321         if (lval->isValueList())
1322             static_cast<CSSValueList*>(lval)->append(rval);
1323         else {
1324             CSSValue* oldVal = lval;
1325             CSSValueList* list = new CSSValueList();
1326             lval = list;
1327             list->append(oldVal);
1328             list->append(rval);
1329         }
1330     }
1331     else
1332         lval = rval;
1333 }
1334
1335 bool CSSParser::parseBackgroundShorthand(bool important)
1336 {
1337     // Position must come before color in this array because a plain old "0" is a legal color
1338     // in quirks mode but it's usually the X coordinate of a position.
1339     // FIXME: Add CSS_PROP__KHTML_BACKGROUND_SIZE to the shorthand.
1340     const int properties[] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT, 
1341         CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, CSS_PROP__WEBKIT_BACKGROUND_CLIP,
1342         CSS_PROP__WEBKIT_BACKGROUND_ORIGIN, CSS_PROP_BACKGROUND_COLOR };
1343     const int numProperties = sizeof(properties) / sizeof(properties[0]);
1344     
1345     ShorthandScope scope(this, CSS_PROP_BACKGROUND);
1346
1347     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
1348     CSSValue* values[numProperties] = { 0 }; // compiler will repeat 0 as necessary
1349     CSSValue* positionYValue = 0;
1350     int i;
1351
1352     while (valueList->current()) {
1353         Value* val = valueList->current();
1354         if (val->unit == Value::Operator && val->iValue == ',') {
1355             // We hit the end.  Fill in all remaining values with the initial value.
1356             valueList->next();
1357             for (i = 0; i < numProperties; ++i) {
1358                 if (properties[i] == CSS_PROP_BACKGROUND_COLOR && parsedProperty[i])
1359                     // Color is not allowed except as the last item in a list.  Reject the entire
1360                     // property.
1361                     goto fail;
1362
1363                 if (!parsedProperty[i] && properties[i] != CSS_PROP_BACKGROUND_COLOR) {
1364                     addBackgroundValue(values[i], new CSSInitialValue());
1365                     if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
1366                         addBackgroundValue(positionYValue, new CSSInitialValue());
1367                 }
1368                 parsedProperty[i] = false;
1369             }
1370             if (!valueList->current())
1371                 break;
1372         }
1373         
1374         bool found = false;
1375         for (i = 0; !found && i < numProperties; ++i) {
1376             if (!parsedProperty[i]) {
1377                 CSSValue *val1 = 0, *val2 = 0;
1378                 int propId1, propId2;
1379                 if (parseBackgroundProperty(properties[i], propId1, propId2, val1, val2)) {
1380                     parsedProperty[i] = found = true;
1381                     addBackgroundValue(values[i], val1);
1382                     if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
1383                         addBackgroundValue(positionYValue, val2);
1384                 }
1385             }
1386         }
1387
1388         // if we didn't find at least one match, this is an
1389         // invalid shorthand and we have to ignore it
1390         if (!found)
1391             goto fail;
1392     }
1393     
1394     // Fill in any remaining properties with the initial value.
1395     for (i = 0; i < numProperties; ++i) {
1396         if (!parsedProperty[i]) {
1397             addBackgroundValue(values[i], new CSSInitialValue());
1398             if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
1399                 addBackgroundValue(positionYValue, new CSSInitialValue());
1400         }
1401     }
1402     
1403     // Now add all of the properties we found.
1404     for (i = 0; i < numProperties; i++) {
1405         if (properties[i] == CSS_PROP_BACKGROUND_POSITION) {
1406             addProperty(CSS_PROP_BACKGROUND_POSITION_X, values[i], important);
1407             addProperty(CSS_PROP_BACKGROUND_POSITION_Y, positionYValue, important);
1408         }
1409         else
1410             addProperty(properties[i], values[i], important);
1411     }
1412     
1413     return true;
1414
1415 fail:
1416     for (int k = 0; k < numProperties; k++)
1417         delete values[k];
1418     delete positionYValue;
1419     return false;
1420 }
1421
1422 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
1423 {
1424     // We try to match as many properties as possible
1425     // We set up an array of booleans to mark which property has been found,
1426     // and we try to search for properties until it makes no longer any sense.
1427     ShorthandScope scope(this, propId);
1428
1429     bool found = false;
1430     bool fnd[6]; // Trust me ;)
1431     for (int i = 0; i < numProperties; i++)
1432         fnd[i] = false;
1433
1434     while (valueList->current()) {
1435         found = false;
1436         for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
1437             if (!fnd[propIndex]) {
1438                 if (parseValue(properties[propIndex], important))
1439                     fnd[propIndex] = found = true;
1440             }
1441         }
1442
1443         // if we didn't find at least one match, this is an
1444         // invalid shorthand and we have to ignore it
1445         if (!found)
1446             return false;
1447     }
1448     
1449     // Fill in any remaining properties with the initial value.
1450     m_implicitShorthand = true;
1451     for (int i = 0; i < numProperties; ++i) {
1452         if (!fnd[i])
1453             addProperty(properties[i], new CSSInitialValue(), important);
1454     }
1455     m_implicitShorthand = false;
1456
1457     return true;
1458 }
1459
1460 bool CSSParser::parse4Values(int propId, const int *properties,  bool important)
1461 {
1462     /* From the CSS 2 specs, 8.3
1463      * If there is only one value, it applies to all sides. If there are two values, the top and
1464      * bottom margins are set to the first value and the right and left margins are set to the second.
1465      * If there are three values, the top is set to the first value, the left and right are set to the
1466      * second, and the bottom is set to the third. If there are four values, they apply to the top,
1467      * right, bottom, and left, respectively.
1468      */
1469     
1470     int num = inShorthand() ? 1 : valueList->size();
1471     
1472     ShorthandScope scope(this, propId);
1473
1474     // the order is top, right, bottom, left
1475     switch (num) {
1476         case 1: {
1477             if (!parseValue(properties[0], important))
1478                 return false;
1479             CSSValue *value = parsedProperties[numParsedProperties-1]->value();
1480             m_implicitShorthand = true;
1481             addProperty(properties[1], value, important);
1482             addProperty(properties[2], value, important);
1483             addProperty(properties[3], value, important);
1484             m_implicitShorthand = false;
1485             break;
1486         }
1487         case 2: {
1488             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1489                 return false;
1490             CSSValue *value = parsedProperties[numParsedProperties-2]->value();
1491             m_implicitShorthand = true;
1492             addProperty(properties[2], value, important);
1493             value = parsedProperties[numParsedProperties-2]->value();
1494             addProperty(properties[3], value, important);
1495             m_implicitShorthand = false;
1496             break;
1497         }
1498         case 3: {
1499             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
1500                 return false;
1501             CSSValue *value = parsedProperties[numParsedProperties-2]->value();
1502             m_implicitShorthand = true;
1503             addProperty(properties[3], value, important);
1504             m_implicitShorthand = false;
1505             break;
1506         }
1507         case 4: {
1508             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
1509                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
1510                 return false;
1511             break;
1512         }
1513         default: {
1514             return false;
1515         }
1516     }
1517     
1518     return true;
1519 }
1520
1521 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
1522 // in CSS 2.1 this got somewhat reduced:
1523 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
1524 bool CSSParser::parseContent(int propId, bool important)
1525 {
1526     CSSValueList* values = new CSSValueList;
1527
1528     while (Value* val = valueList->current()) {
1529         CSSValue* parsedValue = 0;
1530         if (val->unit == CSSPrimitiveValue::CSS_URI) {
1531             // url
1532             String value = parseURL(domString(val->string));
1533             parsedValue = new CSSImageValue(
1534                 String(KURL(styleElement->baseURL().deprecatedString(), value.deprecatedString()).url()), styleElement);
1535         } else if (val->unit == Value::Function) {
1536             // attr(X)
1537             ValueList *args = val->function->args;
1538             String fname = domString(val->function->name).lower();
1539             if (fname != "attr(" || !args)
1540                 return false;
1541             if (args->size() != 1)
1542                 return false;
1543             Value *a = args->current();
1544             String attrName = domString(a->string);
1545             if (document()->isHTMLDocument())
1546                 attrName = attrName.lower();
1547             parsedValue = new CSSPrimitiveValue(attrName, CSSPrimitiveValue::CSS_ATTR);
1548         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
1549             // open-quote
1550             // close-quote
1551             // no-open-quote
1552             // no-close-quote
1553             // FIXME: These are not yet implemented (http://bugzilla.opendarwin.org/show_bug.cgi?id=6503).
1554         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
1555             parsedValue = new CSSPrimitiveValue(domString(val->string), CSSPrimitiveValue::CSS_STRING);
1556         }
1557         if (!parsedValue)
1558             break;
1559         values->append(parsedValue);
1560         valueList->next();
1561     }
1562
1563     if (values->length()) {
1564         addProperty(propId, values, important);
1565         valueList->next();
1566         return true;
1567     }
1568
1569     delete values;
1570     return false;
1571 }
1572
1573 CSSValue* CSSParser::parseBackgroundColor()
1574 {
1575     int id = valueList->current()->id;
1576     if (id == CSS_VAL__WEBKIT_TEXT || (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || id == CSS_VAL_MENU ||
1577         (id >= CSS_VAL_GREY && id < CSS_VAL__WEBKIT_TEXT && !strict))
1578        return new CSSPrimitiveValue(id);
1579     return parseColor();
1580 }
1581
1582 CSSValue* CSSParser::parseBackgroundImage()
1583 {
1584     if (valueList->current()->id == CSS_VAL_NONE)
1585         return new CSSImageValue();
1586     if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
1587         String uri = parseURL(domString(valueList->current()->string));
1588         if (!uri.isEmpty())
1589             return new CSSImageValue(String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()), 
1590                                          styleElement);
1591     }
1592     return 0;
1593 }
1594
1595 CSSValue* CSSParser::parseBackgroundPositionXY(bool& xFound, bool& yFound)
1596 {
1597     int id = valueList->current()->id;
1598     if (id == CSS_VAL_LEFT || id == CSS_VAL_TOP || id == CSS_VAL_RIGHT || id == CSS_VAL_BOTTOM || id == CSS_VAL_CENTER) {
1599         int percent = 0;
1600         if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT) {
1601             if (xFound)
1602                 return 0;
1603             xFound = true;
1604             if (id == CSS_VAL_RIGHT)
1605                 percent = 100;
1606         }
1607         else if (id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) {
1608             if (yFound)
1609                 return 0;
1610             yFound = true;
1611             if (id == CSS_VAL_BOTTOM)
1612                 percent = 100;
1613         }
1614         else if (id == CSS_VAL_CENTER)
1615             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
1616             percent = 50;
1617         return new CSSPrimitiveValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
1618     }
1619     if (validUnit(valueList->current(), FPercent|FLength, strict))
1620         return new CSSPrimitiveValue(valueList->current()->fValue,
1621                                          (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
1622                 
1623     return 0;
1624 }
1625
1626 void CSSParser::parseBackgroundPosition(CSSValue*& value1, CSSValue*& value2)
1627 {
1628     value1 = value2 = 0;
1629     Value* value = valueList->current();
1630     
1631     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
1632     bool value1IsX = false, value1IsY = false;
1633     value1 = parseBackgroundPositionXY(value1IsX, value1IsY);
1634     if (!value1)
1635         return;
1636     
1637     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
1638     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
1639     // value was explicitly specified for our property.
1640     value = valueList->next();
1641     
1642     // First check for the comma.  If so, we are finished parsing this value or value pair.
1643     if (value && value->unit == Value::Operator && value->iValue == ',')
1644         value = 0;
1645     
1646     bool value2IsX = false, value2IsY = false;
1647     if (value) {
1648         value2 = parseBackgroundPositionXY(value2IsX, value2IsY);
1649         if (value2)
1650             valueList->next();
1651         else {
1652             if (!inShorthand()) {
1653                 delete value1;
1654                 value1 = 0;
1655                 return;
1656             }
1657         }
1658     }
1659     
1660     if (!value2)
1661         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
1662         // is simply 50%.  This is our default.
1663         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
1664         // For left/right/center, the default of 50% in the y is still correct.
1665         value2 = new CSSPrimitiveValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
1666
1667     if (value1IsY || value2IsX) {
1668         // Swap our two values.
1669         CSSValue* val = value2;
1670         value2 = value1;
1671         value1 = val;
1672     }
1673 }
1674
1675 CSSValue* CSSParser::parseBackgroundSize()
1676 {
1677     Value* value = valueList->current();
1678     CSSPrimitiveValue* parsedValue1;
1679     
1680     if (value->id == CSS_VAL_AUTO)
1681         parsedValue1 = new CSSPrimitiveValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
1682     else {
1683         if (!validUnit(value, FLength|FPercent, strict))
1684             return 0;
1685         parsedValue1 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1686     }
1687     
1688     CSSPrimitiveValue* parsedValue2 = parsedValue1;
1689     if ((value = valueList->next())) {
1690         if (value->id == CSS_VAL_AUTO)
1691             parsedValue2 = new CSSPrimitiveValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
1692         else {
1693             if (!validUnit(value, FLength|FPercent, strict)) {
1694                 delete parsedValue1;
1695                 return 0;
1696             }
1697             parsedValue2 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1698         }
1699     }
1700     
1701     Pair* pair = new Pair(parsedValue1, parsedValue2);
1702     return new CSSPrimitiveValue(pair);
1703 }
1704
1705 bool CSSParser::parseBackgroundProperty(int propId, int& propId1, int& propId2, 
1706                                         CSSValue*& retValue1, CSSValue*& retValue2)
1707 {
1708     CSSValueList *values = 0, *values2 = 0;
1709     Value* val;
1710     CSSValue *value = 0, *value2 = 0;
1711     bool allowComma = false;
1712     
1713     retValue1 = retValue2 = 0;
1714     propId1 = propId;
1715     propId2 = propId;
1716     if (propId == CSS_PROP_BACKGROUND_POSITION) {
1717         propId1 = CSS_PROP_BACKGROUND_POSITION_X;
1718         propId2 = CSS_PROP_BACKGROUND_POSITION_Y;
1719     }
1720
1721     while ((val = valueList->current())) {
1722         CSSValue *currValue = 0, *currValue2 = 0;
1723         if (allowComma) {
1724             if (val->unit != Value::Operator || val->iValue != ',')
1725                 goto failed;
1726             valueList->next();
1727             allowComma = false;
1728         }
1729         else {
1730             switch (propId) {
1731                 case CSS_PROP_BACKGROUND_ATTACHMENT:
1732                     if (val->id == CSS_VAL_SCROLL || val->id == CSS_VAL_FIXED) {
1733                         currValue = new CSSPrimitiveValue(val->id);
1734                         valueList->next();
1735                     }
1736                     break;
1737                 case CSS_PROP_BACKGROUND_COLOR:
1738                     currValue = parseBackgroundColor();
1739                     if (currValue)
1740                         valueList->next();
1741                     break;
1742                 case CSS_PROP_BACKGROUND_IMAGE:
1743                     currValue = parseBackgroundImage();
1744                     if (currValue)
1745                         valueList->next();
1746                     break;
1747                 case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
1748                 case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
1749                     if (val->id == CSS_VAL_BORDER || val->id == CSS_VAL_PADDING || val->id == CSS_VAL_CONTENT) {
1750                         currValue = new CSSPrimitiveValue(val->id);
1751                         valueList->next();
1752                     }
1753                     break;
1754                 case CSS_PROP_BACKGROUND_POSITION:
1755                     parseBackgroundPosition(currValue, currValue2);
1756                     // unlike the other functions, parseBackgroundPosition advances the valueList pointer
1757                     break;
1758                 case CSS_PROP_BACKGROUND_POSITION_X: {
1759                     bool xFound = false, yFound = true;
1760                     currValue = parseBackgroundPositionXY(xFound, yFound);
1761                     if (currValue)
1762                         valueList->next();
1763                     break;
1764                 }
1765                 case CSS_PROP_BACKGROUND_POSITION_Y: {
1766                     bool xFound = true, yFound = false;
1767                     currValue = parseBackgroundPositionXY(xFound, yFound);
1768                     if (currValue)
1769                         valueList->next();
1770                     break;
1771                 }
1772                 case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
1773                     if ((val->id >= CSS_VAL_CLEAR && val->id <= CSS_VAL_PLUS_LIGHTER) || val->id == CSS_VAL_HIGHLIGHT) {
1774                         currValue = new CSSPrimitiveValue(val->id);
1775                         valueList->next();
1776                     }
1777                     break;
1778                 case CSS_PROP_BACKGROUND_REPEAT:
1779                     if (val->id >= CSS_VAL_REPEAT && val->id <= CSS_VAL_NO_REPEAT) {
1780                         currValue = new CSSPrimitiveValue(val->id);
1781                         valueList->next();
1782                     }
1783                     break;
1784                 case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
1785                     currValue = parseBackgroundSize();
1786                     if (currValue)
1787                         valueList->next();
1788                     break;
1789             }
1790             
1791             if (!currValue)
1792                 goto failed;
1793             
1794             if (value && !values) {
1795                 values = new CSSValueList();
1796                 values->append(value);
1797                 value = 0;
1798             }
1799             
1800             if (value2 && !values2) {
1801                 values2 = new CSSValueList();
1802                 values2->append(value2);
1803                 value2 = 0;
1804             }
1805             
1806             if (values)
1807                 values->append(currValue);
1808             else
1809                 value = currValue;
1810             if (currValue2) {
1811                 if (values2)
1812                     values2->append(currValue2);
1813                 else
1814                     value2 = currValue2;
1815             }
1816             allowComma = true;
1817         }
1818         
1819         // When parsing the 'background' shorthand property, we let it handle building up the lists for all
1820         // properties.
1821         if (inShorthand())
1822             break;
1823     }
1824     
1825     if (values && values->length()) {
1826         retValue1 = values;
1827         if (values2 && values2->length())
1828             retValue2 = values2;
1829         return true;
1830     }
1831     if (value) {
1832         retValue1 = value;
1833         retValue2 = value2;
1834         return true;
1835     }
1836
1837 failed:
1838     delete values; delete values2;
1839     delete value; delete value2;
1840     return false;
1841 }
1842
1843 #if __APPLE__
1844 #define DASHBOARD_REGION_NUM_PARAMETERS  6
1845 #define DASHBOARD_REGION_SHORT_NUM_PARAMETERS  2
1846
1847 static Value *skipCommaInDashboardRegion (ValueList *args)
1848 {
1849     if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
1850          args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
1851         Value *current = args->current();
1852         if (current->unit == Value::Operator && current->iValue == ',')
1853             return args->next();
1854     }
1855     return args->current();
1856 }
1857
1858 bool CSSParser::parseDashboardRegions(int propId, bool important)
1859 {
1860     bool valid = true;
1861     
1862     Value *value = valueList->current();
1863
1864     if (value->id == CSS_VAL_NONE) {
1865         addProperty(propId, new CSSPrimitiveValue(value->id), important);
1866         return valid;
1867     }
1868         
1869     RefPtr<DashboardRegion> firstRegion = new DashboardRegion;
1870     DashboardRegion* region = 0;
1871
1872     while (value) {
1873         if (region == 0) {
1874             region = firstRegion.get();
1875         } else {
1876             RefPtr<DashboardRegion> nextRegion = new DashboardRegion();
1877             region->m_next = nextRegion;
1878             region = nextRegion.get();
1879         }
1880         
1881         if (value->unit != Value::Function) {
1882             valid = false;
1883             break;
1884         }
1885             
1886         // Commas count as values, so allow:
1887         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
1888         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
1889         // also allow
1890         // dashboard-region(label, type) or dashboard-region(label type)
1891         // dashboard-region(label, type) or dashboard-region(label type)
1892         ValueList* args = value->function->args;
1893         String fname = domString(value->function->name).lower();
1894         if (fname != "dashboard-region(" || !args) {
1895             valid = false;
1896             break;
1897         }
1898         
1899         int numArgs = args->size();
1900         if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
1901             (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))){
1902             valid = false;
1903             break;
1904         }
1905             
1906         // First arg is a label.
1907         Value* arg = args->current();
1908         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
1909             valid = false;
1910             break;
1911         }
1912             
1913         region->m_label = domString(arg->string);
1914
1915         // Second arg is a type.
1916         arg = args->next();
1917         arg = skipCommaInDashboardRegion (args);
1918         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
1919             valid = false;
1920             break;
1921         }
1922
1923         String geometryType = domString(arg->string).lower();
1924         if (geometryType == "circle")
1925             region->m_isCircle = true;
1926         else if (geometryType == "rectangle")
1927             region->m_isRectangle = true;
1928         else {
1929             valid = false;
1930             break;
1931         }
1932             
1933         region->m_geometryType = domString(arg->string);
1934
1935         if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
1936             CSSPrimitiveValue *amount = arg->id == CSS_VAL_AUTO ?
1937                 new CSSPrimitiveValue(CSS_VAL_AUTO) :
1938                 new CSSPrimitiveValue((double)0, (CSSPrimitiveValue::UnitTypes) arg->unit);
1939                 
1940             region->setTop(amount);
1941             region->setRight(amount);
1942             region->setBottom(amount);
1943             region->setLeft(amount);
1944         }
1945         else {
1946             // Next four arguments must be offset numbers
1947             int i;
1948             for (i = 0; i < 4; i++) {
1949                 arg = args->next();
1950                 arg = skipCommaInDashboardRegion (args);
1951
1952                 valid = arg->id == CSS_VAL_AUTO || validUnit(arg, FLength, strict);
1953                 if (!valid)
1954                     break;
1955                     
1956                 CSSPrimitiveValue *amount = arg->id == CSS_VAL_AUTO ?
1957                     new CSSPrimitiveValue(CSS_VAL_AUTO) :
1958                     new CSSPrimitiveValue(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit);
1959                     
1960                 if (i == 0)
1961                     region->setTop(amount);
1962                 else if (i == 1)
1963                     region->setRight(amount);
1964                 else if (i == 2)
1965                     region->setBottom(amount);
1966                 else
1967                     region->setLeft(amount);
1968             }
1969         }
1970
1971         value = valueList->next();
1972     }
1973
1974     if (valid)
1975         addProperty(propId, new CSSPrimitiveValue(firstRegion.release()), important);
1976         
1977     return valid;
1978 }
1979 #endif
1980
1981 bool CSSParser::parseShape(int propId, bool important)
1982 {
1983     Value *value = valueList->current();
1984     ValueList *args = value->function->args;
1985     String fname = domString(value->function->name).lower();
1986     if (fname != "rect(" || !args)
1987         return false;
1988
1989     // rect(t, r, b, l) || rect(t r b l)
1990     if (args->size() != 4 && args->size() != 7)
1991         return false;
1992     RectImpl *rect = new RectImpl();
1993     bool valid = true;
1994     int i = 0;
1995     Value *a = args->current();
1996     while (a) {
1997         valid = a->id == CSS_VAL_AUTO || validUnit(a, FLength, strict);
1998         if (!valid)
1999             break;
2000         CSSPrimitiveValue *length = a->id == CSS_VAL_AUTO ?
2001             new CSSPrimitiveValue(CSS_VAL_AUTO) :
2002             new CSSPrimitiveValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
2003         if (i == 0)
2004             rect->setTop(length);
2005         else if (i == 1)
2006             rect->setRight(length);
2007         else if (i == 2)
2008             rect->setBottom(length);
2009         else
2010             rect->setLeft(length);
2011         a = args->next();
2012         if (a && args->size() == 7) {
2013             if (a->unit == Value::Operator && a->iValue == ',') {
2014                 a = args->next();
2015             } else {
2016                 valid = false;
2017                 break;
2018             }
2019         }
2020         i++;
2021     }
2022     if (valid) {
2023         addProperty(propId, new CSSPrimitiveValue(rect), important);
2024         valueList->next();
2025         return true;
2026     }
2027     delete rect;
2028     return false;
2029 }
2030
2031 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
2032 bool CSSParser::parseFont(bool important)
2033 {
2034     bool valid = true;
2035     Value *value = valueList->current();
2036     FontValue *font = new FontValue;
2037     // optional font-style, font-variant and font-weight
2038     while (value) {
2039         int id = value->id;
2040         if (id) {
2041             if (id == CSS_VAL_NORMAL) {
2042                 // do nothing, it's the inital value for all three
2043             } else if (id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE) {
2044                 if (font->style)
2045                     goto invalid;
2046                 font->style = new CSSPrimitiveValue(id);
2047             } else if (id == CSS_VAL_SMALL_CAPS) {
2048                 if (font->variant)
2049                     goto invalid;
2050                 font->variant = new CSSPrimitiveValue(id);
2051             } else if (id >= CSS_VAL_BOLD && id <= CSS_VAL_LIGHTER) {
2052                 if (font->weight)
2053                     goto invalid;
2054                 font->weight = new CSSPrimitiveValue(id);
2055             } else {
2056                 valid = false;
2057             }
2058         } else if (!font->weight && validUnit(value, FInteger|FNonNeg, true)) {
2059             int weight = (int)value->fValue;
2060             int val = 0;
2061             if (weight == 100)
2062                 val = CSS_VAL_100;
2063             else if (weight == 200)
2064                 val = CSS_VAL_200;
2065             else if (weight == 300)
2066                 val = CSS_VAL_300;
2067             else if (weight == 400)
2068                 val = CSS_VAL_400;
2069             else if (weight == 500)
2070                 val = CSS_VAL_500;
2071             else if (weight == 600)
2072                 val = CSS_VAL_600;
2073             else if (weight == 700)
2074                 val = CSS_VAL_700;
2075             else if (weight == 800)
2076                 val = CSS_VAL_800;
2077             else if (weight == 900)
2078                 val = CSS_VAL_900;
2079
2080             if (val)
2081                 font->weight = new CSSPrimitiveValue(val);
2082             else
2083                 valid = false;
2084         } else {
2085             valid = false;
2086         }
2087         if (!valid)
2088             break;
2089         value = valueList->next();
2090     }
2091     if (!value)
2092         goto invalid;
2093
2094     // set undefined values to default
2095     if (!font->style)
2096         font->style = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2097     if (!font->variant)
2098         font->variant = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2099     if (!font->weight)
2100         font->weight = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2101
2102     // now a font size _must_ come
2103     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
2104     if (value->id >= CSS_VAL_XX_SMALL && value->id <= CSS_VAL_LARGER)
2105         font->size = new CSSPrimitiveValue(value->id);
2106     else if (validUnit(value, FLength|FPercent, strict))
2107         font->size = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2108     value = valueList->next();
2109     if (!font->size || !value)
2110         goto invalid;
2111
2112     if (value->unit == Value::Operator && value->iValue == '/') {
2113         // line-height
2114         value = valueList->next();
2115         if (!value)
2116             goto invalid;
2117         if (value->id == CSS_VAL_NORMAL) {
2118             // default value, nothing to do
2119         } else if (validUnit(value, FNumber|FLength|FPercent, strict))
2120             font->lineHeight = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2121         else
2122             goto invalid;
2123         value = valueList->next();
2124         if (!value)
2125             goto invalid;
2126     }
2127     
2128     if (!font->lineHeight)
2129         font->lineHeight = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2130
2131     // font family must come now
2132     font->family = parseFontFamily();
2133
2134     if (valueList->current() || !font->family)
2135         goto invalid;
2136
2137     addProperty(CSS_PROP_FONT, font, important);
2138     return true;
2139
2140  invalid:
2141     delete font;
2142     return false;
2143 }
2144
2145 CSSValueList* CSSParser::parseFontFamily()
2146 {
2147     CSSValueList* list = new CSSValueList;
2148     Value* value = valueList->current();
2149     FontFamilyValue* currFamily = 0;
2150     while (value) {
2151         Value* nextValue = valueList->next();
2152         bool nextValBreaksFont = !nextValue ||
2153                                  (nextValue->unit == Value::Operator && nextValue->iValue == ',');
2154         bool nextValIsFontName = nextValue &&
2155             ((nextValue->id >= CSS_VAL_SERIF && nextValue->id <= CSS_VAL__WEBKIT_BODY) ||
2156             (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
2157
2158         if (value->id >= CSS_VAL_SERIF && value->id <= CSS_VAL__WEBKIT_BODY) {
2159             if (currFamily) {
2160                 currFamily->parsedFontName += ' ';
2161                 currFamily->parsedFontName += deprecatedString(value->string);
2162             }
2163             else if (nextValBreaksFont || !nextValIsFontName)
2164                 list->append(new CSSPrimitiveValue(value->id));
2165             else
2166                 list->append(currFamily = new FontFamilyValue(deprecatedString(value->string)));
2167         }
2168         else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
2169             // Strings never share in a family name.
2170             currFamily = 0;
2171             list->append(new FontFamilyValue(deprecatedString(value->string)));
2172         }
2173         else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2174             if (currFamily) {
2175                 currFamily->parsedFontName += ' ';
2176                 currFamily->parsedFontName += deprecatedString(value->string);
2177             }
2178             else if (nextValBreaksFont || !nextValIsFontName)
2179                 list->append(new FontFamilyValue(deprecatedString(value->string)));
2180             else
2181                 list->append(currFamily = new FontFamilyValue(deprecatedString(value->string)));
2182         }
2183         else {
2184             break;
2185         }
2186         
2187         if (!nextValue)
2188             break;
2189
2190         if (nextValBreaksFont) {
2191             value = valueList->next();
2192             currFamily = 0;
2193         }
2194         else if (nextValIsFontName)
2195             value = nextValue;
2196         else
2197             break;
2198     }
2199     if (!list->length()) {
2200         delete list;
2201         list = 0;
2202     }
2203     return list;
2204 }
2205
2206
2207 bool CSSParser::parseColor(const DeprecatedString &name, RGBA32& rgb)
2208 {
2209     // FIXME: Should we move this stuff about hex digits without a "#" prefix
2210     // into the Color class along with the "#"-prefix version?
2211
2212     int len = name.length();
2213
2214     if (!len)
2215         return false;
2216
2217     bool ok;
2218
2219     if ( len == 3 || len == 6 ) {
2220         int val = name.toInt(&ok, 16);
2221         if ( ok ) {
2222             if (len == 6) {
2223                 rgb =  (0xff << 24) | val;
2224                 return true;
2225             }
2226             else if ( len == 3 ) {
2227                 // #abc converts to #aabbcc according to the specs
2228                 rgb = (0xff << 24) |
2229                     (val&0xf00)<<12 | (val&0xf00)<<8 |
2230                     (val&0xf0)<<8 | (val&0xf0)<<4 |
2231                     (val&0xf)<<4 | (val&0xf);
2232                 return true;
2233             }
2234         }
2235     }
2236
2237     // try a little harder
2238     Color tc;
2239     tc.setNamedColor(name.lower());
2240     if (tc.isValid()) {
2241         rgb = tc.rgb();
2242         return true;
2243     }
2244
2245     return false;
2246 }
2247
2248 bool CSSParser::parseColorParameters(Value* value, int* colorArray, bool parseAlpha)
2249 {
2250     ValueList* args = value->function->args;
2251     Value* v = args->current();
2252     // Get the first value
2253     if (!validUnit(v, FInteger | FPercent, true))
2254         return false;
2255     colorArray[0] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
2256     for (int i = 1; i < 3; i++) {
2257         v = args->next();
2258         if (v->unit != Value::Operator && v->iValue != ',')
2259             return false;
2260         v = args->next();
2261         if (!validUnit(v, FInteger | FPercent, true))
2262             return false;
2263         colorArray[i] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
2264     }
2265     if (parseAlpha) {
2266         v = args->next();
2267         if (v->unit != Value::Operator && v->iValue != ',')
2268             return false;
2269         v = args->next();
2270         if (!validUnit(v, FNumber, true))
2271             return false;
2272         colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * 255);
2273     }
2274     return true;
2275 }
2276
2277 // CSS3 sepcification defines the format of a HSL color as
2278 // hsl(<number>, <percent>, <percent>)
2279 // and with alpha, the format is
2280 // hsla(<number>, <percent>, <percent>, <number>)
2281 // The first value, HUE, is in an angle with a value between 0 and 360
2282 bool CSSParser::parseHSLParameters(Value* value, double* colorArray, bool parseAlpha)
2283 {
2284     ValueList* args = value->function->args;
2285     Value* v = args->current();
2286     // Get the first value
2287     if (!validUnit(v, FInteger, true))
2288         return false;
2289     // normalize the Hue value and change it to be between 0 and 1.0
2290     colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0;
2291     for (int i = 1; i < 3; i++) {
2292         v = args->next();
2293         if (v->unit != Value::Operator && v->iValue != ',')
2294             return false;
2295         v = args->next();
2296         if (!validUnit(v, FPercent, true))
2297             return false;
2298         colorArray[i] = max(0.0, min(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0
2299     }
2300     if (parseAlpha) {
2301         v = args->next();
2302         if (v->unit != Value::Operator && v->iValue != ',')
2303             return false;
2304         v = args->next();
2305         if (!validUnit(v, FNumber, true))
2306             return false;
2307         colorArray[3] = max(0.0, min(1.0, v->fValue));
2308     }
2309     return true;
2310 }
2311
2312 CSSPrimitiveValue *CSSParser::parseColor()
2313 {
2314     return parseColorFromValue(valueList->current());
2315 }
2316
2317 CSSPrimitiveValue *CSSParser::parseColorFromValue(Value* value)
2318 {
2319     RGBA32 c = Color::transparent;
2320     if (!strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
2321         value->fValue >= 0. && value->fValue < 1000000.) {
2322         DeprecatedString str;
2323         str.sprintf("%06d", (int)(value->fValue+.5));
2324         if (!CSSParser::parseColor(str, c))
2325             return 0;
2326     } else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR ||
2327                 value->unit == CSSPrimitiveValue::CSS_IDENT ||
2328                 (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
2329         if (!CSSParser::parseColor(deprecatedString(value->string), c))
2330             return 0;
2331     } else if (value->unit == Value::Function &&
2332                 value->function->args != 0 &&
2333                 value->function->args->size() == 5 /* rgb + two commas */ &&
2334                 domString(value->function->name).lower() == "rgb(") {
2335         int colorValues[3];
2336         if (!parseColorParameters(value, colorValues, false))
2337             return 0;
2338         c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
2339     } else if (value->unit == Value::Function &&
2340                 value->function->args != 0 &&
2341                 value->function->args->size() == 7 /* rgba + three commas */ &&
2342                 domString(value->function->name).lower() == "rgba(") {
2343         int colorValues[4];
2344         if (!parseColorParameters(value, colorValues, true))
2345             return 0;
2346         c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
2347     } else if (value->unit == Value::Function &&
2348                 value->function->args != 0 &&
2349                 value->function->args->size() == 5 /* hsl + two commas */ &&
2350                 domString(value->function->name).lower() == "hsl(") {
2351         double colorValues[3];
2352         if (!parseHSLParameters(value, colorValues, false))
2353             return 0;
2354         c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
2355     } else if (value->unit == Value::Function &&
2356                 value->function->args != 0 &&
2357                 value->function->args->size() == 7 /* hsla + three commas */ &&
2358                 domString(value->function->name).lower() == "hsla(") {
2359         double colorValues[4];
2360         if (!parseHSLParameters(value, colorValues, true))
2361             return 0;
2362         c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
2363     } else
2364         return 0;
2365
2366     return new CSSPrimitiveValue(c);
2367 }
2368
2369 // This class tracks parsing state for shadow values.  If it goes out of scope (e.g., due to an early return)
2370 // without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
2371 struct ShadowParseContext {
2372     ShadowParseContext()
2373     :values(0), x(0), y(0), blur(0), color(0),
2374      allowX(true), allowY(false), allowBlur(false), allowColor(true),
2375      allowBreak(true)
2376     {}
2377
2378     ~ShadowParseContext() {
2379         if (!allowBreak) {
2380             delete values;
2381             delete x;
2382             delete y;
2383             delete blur;
2384             delete color;
2385         }
2386     }
2387
2388     bool allowLength() { return allowX || allowY || allowBlur; }
2389
2390     bool failed() { return allowBreak = false; }
2391     
2392     void commitValue() {
2393         // Handle the ,, case gracefully by doing nothing.
2394         if (x || y || blur || color) {
2395             if (!values)
2396                 values = new CSSValueList();
2397             
2398             // Construct the current shadow value and add it to the list.
2399             values->append(new ShadowValue(x, y, blur, color));
2400         }
2401         
2402         // Now reset for the next shadow value.
2403         x = y = blur = color = 0;
2404         allowX = allowColor = allowBreak = true;
2405         allowY = allowBlur = false;  
2406     }
2407
2408     void commitLength(Value* v) {
2409         CSSPrimitiveValue* val = new CSSPrimitiveValue(v->fValue,
2410                                                                (CSSPrimitiveValue::UnitTypes)v->unit);
2411         if (allowX) {
2412             x = val;
2413             allowX = false; allowY = true; allowColor = false; allowBreak = false;
2414         }
2415         else if (allowY) {
2416             y = val;
2417             allowY = false; allowBlur = true; allowColor = true; allowBreak = true;
2418         }
2419         else if (allowBlur) {
2420             blur = val;
2421             allowBlur = false;
2422         }
2423     }
2424
2425     void commitColor(CSSPrimitiveValue* val) {
2426         color = val;
2427         allowColor = false;
2428         if (allowX)
2429             allowBreak = false;
2430         else
2431             allowBlur = false;
2432     }
2433     
2434     CSSValueList* values;
2435     CSSPrimitiveValue* x;
2436     CSSPrimitiveValue* y;
2437     CSSPrimitiveValue* blur;
2438     CSSPrimitiveValue* color;
2439
2440     bool allowX;
2441     bool allowY;
2442     bool allowBlur;
2443     bool allowColor;
2444     bool allowBreak;
2445 };
2446
2447 bool CSSParser::parseShadow(int propId, bool important)
2448 {
2449     ShadowParseContext context;
2450     Value* val;
2451     while ((val = valueList->current())) {
2452         // Check for a comma break first.
2453         if (val->unit == Value::Operator) {
2454             if (val->iValue != ',' || !context.allowBreak)
2455                 // Other operators aren't legal or we aren't done with the current shadow
2456                 // value.  Treat as invalid.
2457                 return context.failed();
2458             
2459             // The value is good.  Commit it.
2460             context.commitValue();
2461         }
2462         // Check to see if we're a length.
2463         else if (validUnit(val, FLength, true)) {
2464             // We required a length and didn't get one. Invalid.
2465             if (!context.allowLength())
2466                 return context.failed();
2467
2468             // A length is allowed here.  Construct the value and add it.
2469             context.commitLength(val);
2470         }
2471         else {
2472             // The only other type of value that's ok is a color value.
2473             CSSPrimitiveValue* parsedColor = 0;
2474             bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU ||
2475                             (val->id >= CSS_VAL__WEBKIT_FOCUS_RING_COLOR && val->id <= CSS_VAL__WEBKIT_TEXT && !strict));
2476             if (isColor) {
2477                 if (!context.allowColor)
2478                     return context.failed();
2479                 parsedColor = new CSSPrimitiveValue(val->id);
2480             }
2481
2482             if (!parsedColor)
2483                 // It's not built-in. Try to parse it as a color.
2484                 parsedColor = parseColorFromValue(val);
2485
2486             if (!parsedColor || !context.allowColor)
2487                 return context.failed(); // This value is not a color or length and is invalid or
2488                                          // it is a color, but a color isn't allowed at this point.
2489             
2490             context.commitColor(parsedColor);
2491         }
2492         
2493         valueList->next();
2494     }
2495
2496     if (context.allowBreak) {
2497         context.commitValue();
2498         if (context.values->length()) {
2499             addProperty(propId, context.values, important);
2500             valueList->next();
2501             return true;
2502         }
2503     }
2504     
2505     return context.failed();
2506 }
2507
2508 struct BorderImageParseContext
2509 {
2510     BorderImageParseContext()
2511     :m_allowBreak(false), m_allowNumber(false), m_allowSlash(false), m_allowWidth(false),
2512      m_allowRule(false), m_image(0), m_top(0), m_right(0), m_bottom(0), m_left(0), m_borderTop(0), m_borderRight(0), m_borderBottom(0),
2513      m_borderLeft(0), m_horizontalRule(0), m_verticalRule(0)
2514     {}
2515     
2516     ~BorderImageParseContext() {
2517         if (!m_allowBreak) {
2518             delete m_image;
2519             delete m_top; delete m_right; delete m_bottom; delete m_left;
2520             delete m_borderTop; delete m_borderRight; delete m_borderBottom; delete m_borderLeft;
2521         }
2522     }
2523
2524     bool failed() { return m_allowBreak = false; }
2525     bool allowBreak() const { return m_allowBreak; }
2526     bool allowNumber() const { return m_allowNumber; }
2527     bool allowSlash() const { return m_allowSlash; }
2528     bool allowWidth() const { return m_allowWidth; }
2529     bool allowRule() const { return m_allowRule; }
2530
2531     void commitImage(CSSImageValue* image) { m_image = image; m_allowNumber = true; }
2532     void commitNumber(Value* v) {
2533         CSSPrimitiveValue* val = new CSSPrimitiveValue(v->fValue,
2534                                                                (CSSPrimitiveValue::UnitTypes)v->unit);
2535         if (!m_top)
2536             m_top = val;
2537         else if (!m_right)
2538             m_right = val;
2539         else if (!m_bottom)
2540             m_bottom = val;
2541         else {
2542             assert(!m_left);
2543             m_left = val;
2544         }
2545         
2546         m_allowBreak = m_allowSlash = m_allowRule = true;
2547         m_allowNumber = !m_left;
2548     }
2549     void commitSlash() { m_allowBreak = m_allowSlash = m_allowNumber = false; m_allowWidth = true; }
2550     void commitWidth(Value* val) {
2551         if (!m_borderTop)
2552             m_borderTop = val;
2553         else if (!m_borderRight)
2554             m_borderRight = val;
2555         else if (!m_borderBottom)
2556             m_borderBottom = val;
2557         else {
2558             assert(!m_borderLeft);
2559             m_borderLeft = val;
2560         }
2561
2562         m_allowBreak = m_allowRule = true;
2563         m_allowWidth = !m_borderLeft;
2564     }
2565     void commitRule(int keyword) {
2566         if (!m_horizontalRule)
2567             m_horizontalRule = keyword;
2568         else if (!m_verticalRule)
2569             m_verticalRule = keyword;
2570         m_allowRule = !m_verticalRule;
2571     }
2572     void commitBorderImage(CSSParser* p, int propId, bool important) {
2573         // We need to clone and repeat values for any omissions.
2574         if (!m_right) {
2575             m_right = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2576             m_bottom = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2577             m_left = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2578         }
2579         if (!m_bottom) {
2580             m_bottom = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2581             m_left = new CSSPrimitiveValue(m_right->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
2582         }
2583         if (!m_left)
2584              m_left = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2585              
2586         // Now build a rect value to hold all four of our primitive values.
2587         RectImpl* rect = new RectImpl;
2588         rect->setTop(m_top); rect->setRight(m_right); rect->setBottom(m_bottom); rect->setLeft(m_left);
2589
2590         // Fill in STRETCH as the default if it wasn't specified.
2591         if (!m_horizontalRule)
2592             m_horizontalRule = CSS_VAL_STRETCH;
2593         if (!m_verticalRule)
2594             m_verticalRule = CSS_VAL_STRETCH;
2595
2596         // Make our new border image value now and add it as the result.
2597         CSSBorderImageValue* borderImage = new CSSBorderImageValue(m_image, rect, m_horizontalRule, m_verticalRule);
2598         p->addProperty(propId, borderImage, important);
2599             
2600         // Now we have to deal with the border widths.  The best way to deal with these is to actually put these values into a value
2601         // list and then make our parsing machinery do the parsing.
2602         if (m_borderTop) {
2603             ValueList newList;
2604             newList.addValue(*m_borderTop);
2605             if (m_borderRight)
2606                 newList.addValue(*m_borderRight);
2607             if (m_borderBottom)
2608                 newList.addValue(*m_borderBottom);
2609             if (m_borderLeft)
2610                 newList.addValue(*m_borderLeft);
2611             p->valueList = &newList;
2612             p->parseValue(CSS_PROP_BORDER_WIDTH, important);
2613             p->valueList = 0;
2614         }
2615     }
2616     
2617     bool m_allowBreak;
2618     bool m_allowNumber;
2619     bool m_allowSlash;
2620     bool m_allowWidth;
2621     bool m_allowRule;
2622     
2623     CSSImageValue* m_image;
2624     
2625     CSSPrimitiveValue* m_top;
2626     CSSPrimitiveValue* m_right;
2627     CSSPrimitiveValue* m_bottom;
2628     CSSPrimitiveValue* m_left;
2629     
2630     Value* m_borderTop;
2631     Value* m_borderRight;
2632     Value* m_borderBottom;
2633     Value* m_borderLeft;
2634     
2635     int m_horizontalRule;
2636     int m_verticalRule;
2637 };
2638
2639 bool CSSParser::parseBorderImage(int propId, bool important)
2640 {
2641     // Look for an image initially.  If the first value is not a URI, then we're done.
2642     BorderImageParseContext context;
2643     Value* val = valueList->current();
2644     if (val->unit != CSSPrimitiveValue::CSS_URI)
2645         return context.failed();
2646         
2647     String uri = parseURL(domString(val->string));
2648     if (uri.isEmpty())
2649         return context.failed();
2650     
2651     context.commitImage(new CSSImageValue(String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()),
2652                                                              styleElement));
2653     while ((val = valueList->next())) {
2654         if (context.allowNumber() && validUnit(val, FInteger|FNonNeg|FPercent, true)) {
2655             context.commitNumber(val);
2656         } else if (context.allowSlash() && val->unit == Value::Operator && val->iValue == '/') {
2657             context.commitSlash();
2658         } else if (context.allowWidth() &&
2659             (val->id == CSS_VAL_THIN || val->id == CSS_VAL_MEDIUM || val->id == CSS_VAL_THICK || validUnit(val, FLength, strict))) {
2660             context.commitWidth(val);
2661         } else if (context.allowRule() &&
2662             (val->id == CSS_VAL_STRETCH || val->id == CSS_VAL_ROUND || val->id == CSS_VAL_REPEAT)) {
2663             context.commitRule(val->id);
2664         } else {
2665             // Something invalid was encountered.
2666             return context.failed();
2667         }
2668     }
2669     
2670     if (context.allowBreak()) {
2671         // Need to fully commit as a single value.
2672         context.commitBorderImage(this, propId, important);
2673         return true;
2674     }
2675     
2676     return context.failed();
2677 }
2678
2679 #ifdef CSS_DEBUG
2680
2681 static inline int yyerror(const char *str)
2682 {
2683     kdDebug(6080) << "CSS parse error " << str << endl;
2684     return 1;
2685 }
2686
2687 #else
2688
2689 static inline int yyerror(const char*) { return 1; }
2690
2691 #endif
2692
2693 #define END_TOKEN 0
2694
2695 #include "CSSGrammar.h"
2696
2697 int CSSParser::lex(void* yylvalWithoutType)
2698 {
2699     YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType);
2700     int token = lex();
2701     int length;
2702     UChar* t = text(&length);
2703
2704     switch(token) {
2705     case WHITESPACE:
2706     case SGML_CD:
2707     case INCLUDES:
2708     case DASHMATCH:
2709         break;
2710
2711     case URI:
2712     case STRING:
2713     case IDENT:
2714     case HASH:
2715     case DIMEN:
2716     case UNICODERANGE:
2717     case FUNCTION:
2718     case NOTFUNCTION:
2719         yylval->string.characters = t;
2720         yylval->string.length = length;
2721         break;
2722
2723     case IMPORT_SYM:
2724     case PAGE_SYM:
2725     case MEDIA_SYM:
2726     case FONT_FACE_SYM:
2727     case CHARSET_SYM:
2728     case NAMESPACE_SYM:
2729
2730     case IMPORTANT_SYM:
2731         break;
2732
2733     case QEMS:
2734         length--;
2735     case GRADS:
2736         length--;
2737     case DEGS:
2738     case RADS:
2739     case KHERZ:
2740         length--;
2741     case MSECS:
2742     case HERZ:
2743     case EMS:
2744     case EXS:
2745     case PXS:
2746     case CMS:
2747     case MMS:
2748     case INS:
2749     case PTS:
2750     case PCS:
2751         length--;
2752     case SECS:
2753     case PERCENTAGE:
2754         length--;
2755     case FLOAT:
2756     case INTEGER:
2757         yylval->val = DeprecatedString((DeprecatedChar *)t, length).toDouble();
2758         break;
2759
2760     default:
2761         break;
2762     }
2763
2764     return token;
2765 }
2766
2767 static inline int toHex(char c)
2768 {
2769     if ('0' <= c && c <= '9')
2770         return c - '0';
2771     if ('a' <= c && c <= 'f')
2772         return c - 'a' + 10;
2773     if ('A' <= c && c<= 'F')
2774         return c - 'A' + 10;
2775     return 0;
2776 }
2777
2778 UChar* CSSParser::text(int *length)
2779 {
2780     UChar* start = yytext;
2781     int l = yyleng;
2782     switch(yyTok) {
2783     case STRING:
2784         l--;
2785         /* nobreak */
2786     case HASH:
2787         start++;
2788         l--;
2789         break;
2790     case URI:
2791         // "url("{w}{string}{w}")"
2792         // "url("{w}{url}{w}")"
2793
2794         // strip "url(" and ")"
2795         start += 4;
2796         l -= 5;
2797         // strip {w}
2798         while (l &&
2799                 (*start == ' ' || *start == '\t' || *start == '\r' ||
2800                  *start == '\n' || *start == '\f')) {
2801             start++; l--;
2802         }
2803         if (*start == '"' || *start == '\'') {
2804             start++; l--;
2805         }
2806         while (l &&
2807                 (start[l-1] == ' ' || start[l-1] == '\t' || start[l-1] == '\r' ||
2808                  start[l-1] == '\n' || start[l-1] == '\f')) {
2809             l--;
2810         }
2811         if (l && (start[l-1] == '\"' || start[l-1] == '\''))
2812              l--;
2813
2814     default:
2815         break;
2816     }
2817
2818     // process escapes
2819     UChar* out = start;
2820     UChar* escape = 0;
2821
2822     for (int i = 0; i < l; i++) {
2823         UChar* current = start + i;
2824         if (escape == current - 1) {
2825             if ((*current >= '0' && *current <= '9') ||
2826                  (*current >= 'a' && *current <= 'f') ||
2827                  (*current >= 'A' && *current <= 'F'))
2828                 continue;
2829             if (yyTok == STRING &&
2830                  (*current == '\n' || *current == '\r' || *current == '\f')) {
2831                 // ### handle \r\n case
2832                 if (*current != '\r')
2833                     escape = 0;
2834                 continue;
2835             }
2836             // in all other cases copy the char to output
2837             // ###
2838             *out++ = *current;
2839             escape = 0;
2840             continue;
2841         }
2842         if (escape == current - 2 && yyTok == STRING &&
2843              *(current-1) == '\r' && *current == '\n') {
2844             escape = 0;
2845             continue;
2846         }
2847         if (escape > current - 7 &&
2848              ((*current >= '0' && *current <= '9') ||
2849                (*current >= 'a' && *current <= 'f') ||
2850                (*current >= 'A' && *current <= 'F')))
2851             continue;
2852         if (escape) {
2853             // add escaped char
2854             unsigned uc = 0;
2855             escape++;
2856             while (escape < current) {
2857                 uc *= 16;
2858                 uc += toHex(*escape);
2859                 escape++;
2860             }
2861             // can't handle chars outside ucs2
2862             if (uc > 0xffff)
2863                 uc = 0xfffd;
2864             *out++ = uc;
2865             escape = 0;
2866             if (*current == ' ' ||
2867                  *current == '\t' ||
2868                  *current == '\r' ||
2869                  *current == '\n' ||
2870                  *current == '\f')
2871                 continue;
2872         }
2873         if (!escape && *current == '\\') {
2874             escape = current;
2875             continue;
2876         }
2877         *out++ = *current;
2878     }
2879     if (escape) {
2880         // add escaped char
2881         unsigned uc = 0;
2882         escape++;
2883         while (escape < start+l) {
2884             uc *= 16;
2885             uc += toHex(*escape);
2886             escape++;
2887         }
2888         // can't handle chars outside ucs2
2889         if (uc > 0xffff)
2890             uc = 0xfffd;
2891         *out++ = uc;
2892     }
2893     
2894     *length = out - start;
2895     return start;
2896 }
2897
2898 CSSSelector* CSSParser::createFloatingSelector()
2899 {
2900     CSSSelector* selector = new CSSSelector;
2901     m_floatingSelectors.add(selector);
2902     return selector;
2903 }
2904
2905 CSSSelector* CSSParser::sinkFloatingSelector(CSSSelector* selector)
2906 {
2907     if (selector) {
2908         ASSERT(m_floatingSelectors.contains(selector));
2909         m_floatingSelectors.remove(selector);
2910     }
2911     return selector;
2912 }
2913
2914 ValueList* CSSParser::createFloatingValueList()
2915 {
2916     ValueList* list = new ValueList;
2917     m_floatingValueLists.add(list);
2918     return list;
2919 }
2920
2921 ValueList* CSSParser::sinkFloatingValueList(ValueList* list)
2922 {
2923     if (list) {
2924         ASSERT(m_floatingValueLists.contains(list));
2925         m_floatingValueLists.remove(list);
2926     }
2927     return list;
2928 }
2929
2930 Function* CSSParser::createFloatingFunction()
2931 {
2932     Function* function = new Function;
2933     m_floatingFunctions.add(function);
2934     return function;
2935 }
2936
2937 Function* CSSParser::sinkFloatingFunction(Function* function)
2938 {
2939     if (function) {
2940         ASSERT(m_floatingFunctions.contains(function));
2941         m_floatingFunctions.remove(function);
2942     }
2943     return function;
2944 }
2945
2946 Value& CSSParser::sinkFloatingValue(Value& value)
2947 {
2948     if (value.unit == Value::Function) {
2949         ASSERT(m_floatingFunctions.contains(value.function));
2950         m_floatingFunctions.remove(value.function);
2951     }
2952     return value;
2953 }
2954
2955 MediaQueryExp* CSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, ValueList* values)
2956 {
2957     delete m_floatingMediaQueryExp;
2958     m_floatingMediaQueryExp = new MediaQueryExp(mediaFeature, values);
2959     return m_floatingMediaQueryExp;
2960 }
2961
2962 MediaQueryExp* CSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* e)
2963 {
2964     ASSERT(e == m_floatingMediaQueryExp);
2965     m_floatingMediaQueryExp = 0;
2966     return e;
2967 }
2968
2969 Vector<MediaQueryExp*>* CSSParser::createFloatingMediaQueryExpList()
2970 {
2971     if (m_floatingMediaQueryExpList) {
2972         deleteAllValues(*m_floatingMediaQueryExpList);
2973         delete m_floatingMediaQueryExpList;
2974     }
2975     m_floatingMediaQueryExpList = new Vector<MediaQueryExp*>;
2976     return m_floatingMediaQueryExpList;
2977 }
2978
2979 Vector<MediaQueryExp*>* CSSParser::sinkFloatingMediaQueryExpList(Vector<MediaQueryExp*>* l)
2980 {
2981     ASSERT(l == m_floatingMediaQueryExpList);
2982     m_floatingMediaQueryExpList = 0;
2983     return l;
2984 }
2985
2986 MediaQuery* CSSParser::createFloatingMediaQuery(MediaQuery::Restrictor r, const String& mediaType, Vector<MediaQueryExp*>* exprs)
2987 {
2988     delete m_floatingMediaQuery;
2989     m_floatingMediaQuery = new MediaQuery(r, mediaType, exprs);
2990     return m_floatingMediaQuery;
2991 }
2992
2993 MediaQuery* CSSParser::sinkFloatingMediaQuery(MediaQuery* mq)
2994 {
2995     ASSERT(mq == m_floatingMediaQuery);
2996     m_floatingMediaQuery = 0;
2997     return mq;
2998 }
2999
3000 MediaList* CSSParser::createMediaList()
3001 {
3002     MediaList* list = new MediaList;
3003     m_parsedStyleObjects.append(list);
3004     return list;
3005 }
3006
3007 CSSRule* CSSParser::createCharsetRule(const ParseString& charset)
3008 {
3009     if (!styleElement)
3010         return 0;
3011     if (!styleElement->isCSSStyleSheet())
3012         return 0;
3013     CSSCharsetRule* rule = new CSSCharsetRule(styleElement, domString(charset));
3014     m_parsedStyleObjects.append(rule);
3015     return rule;
3016 }
3017
3018 CSSRule* CSSParser::createImportRule(const ParseString& URL, MediaList* media)
3019 {
3020     if (!media)
3021         return 0;
3022     if (!styleElement)
3023         return 0;
3024     if (!styleElement->isCSSStyleSheet())
3025         return 0;
3026     CSSImportRule* rule = new CSSImportRule(styleElement, domString(URL), media);
3027     m_parsedStyleObjects.append(rule);
3028     return rule;
3029 }
3030
3031 CSSRule* CSSParser::createMediaRule(MediaList* media, CSSRuleList* rules)
3032 {
3033     if (!media)
3034         return 0;
3035     if (!rules)
3036         return 0;
3037     if (!styleElement)
3038         return 0;
3039     if (!styleElement->isCSSStyleSheet())
3040         return 0;
3041     CSSMediaRule* rule = new CSSMediaRule(styleElement, media, rules);
3042     m_parsedStyleObjects.append(rule);
3043     return rule;
3044 }
3045
3046 CSSRuleList* CSSParser::createRuleList()
3047 {
3048     CSSRuleList* list = new CSSRuleList;
3049     m_parsedRuleLists.append(list);
3050     return list;
3051 }
3052
3053 CSSRule* CSSParser::createStyleRule(CSSSelector* selector)
3054 {
3055     CSSStyleRule* rule = 0;
3056     if (selector) {
3057         rule = new CSSStyleRule(styleElement);
3058         m_parsedStyleObjects.append(rule);
3059         rule->setSelector(sinkFloatingSelector(selector));
3060         rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties));
3061     }
3062     clearProperties();
3063     return rule;
3064 }
3065
3066 DeprecatedString deprecatedString(const ParseString& ps)
3067 {
3068     return DeprecatedString(reinterpret_cast<const DeprecatedChar*>(ps.characters), ps.length);
3069 }
3070
3071 #define YY_DECL int CSSParser::lex()
3072 #define yyconst const
3073 typedef int yy_state_type;
3074 typedef unsigned YY_CHAR;
3075 // this line makes sure we treat all Unicode chars correctly.
3076 #define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c)
3077 #define YY_DO_BEFORE_ACTION \
3078         yytext = yy_bp; \
3079         yyleng = (int) (yy_cp - yy_bp); \
3080         yy_hold_char = *yy_cp; \
3081         *yy_cp = 0; \
3082         yy_c_buf_p = yy_cp;
3083 #define YY_BREAK break;
3084 #define ECHO
3085 #define YY_RULE_SETUP
3086 #define INITIAL 0
3087 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
3088 #define yyterminate() yyTok = END_TOKEN; return yyTok
3089 #define YY_FATAL_ERROR(a)
3090 // The line below is needed to build the tokenizer with conditon stack.
3091 // The macro is used in the tokenizer grammar with lines containing
3092 // BEGIN(mediaqueries) and BEGIN(initial). yy_start acts as index to
3093 // tokenizer transition table, and 'mediaqueries' and 'initial' are
3094 // offset multipliers that specify which transitions are active
3095 // in the tokenizer during in each condition (tokenizer state)
3096 #define BEGIN yy_start = 1 + 2 *
3097
3098 #include "tokenizer.cpp"
3099
3100 }