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