WebCore:
[WebKit.git] / WebCore / css / CSSParser.cpp
1 /*
2  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
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., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include "config.h"
25 #include "CSSParser.h"
26
27 #include "CString.h"
28 #include "CSSTimingFunctionValue.h"
29 #include "CSSBorderImageValue.h"
30 #include "CSSCanvasValue.h"
31 #include "CSSCharsetRule.h"
32 #include "CSSCursorImageValue.h"
33 #include "CSSHelper.h"
34 #include "CSSImageValue.h"
35 #include "CSSFontFaceRule.h"
36 #include "CSSFontFaceSrcValue.h"
37 #include "CSSGradientValue.h"
38 #include "CSSImportRule.h"
39 #include "CSSInheritedValue.h"
40 #include "CSSInitialValue.h"
41 #include "CSSMediaRule.h"
42 #include "CSSMutableStyleDeclaration.h"
43 #include "CSSPrimitiveValue.h"
44 #include "CSSProperty.h"
45 #include "CSSPropertyNames.h"
46 #include "CSSQuirkPrimitiveValue.h"
47 #include "CSSReflectValue.h"
48 #include "CSSRuleList.h"
49 #include "CSSSelector.h"
50 #include "CSSStyleRule.h"
51 #include "CSSStyleSheet.h"
52 #include "CSSTransformValue.h"
53 #include "CSSUnicodeRangeValue.h"
54 #include "CSSValueKeywords.h"
55 #include "CSSValueList.h"
56 #include "Counter.h"
57 #include "Document.h"
58 #include "FloatConversion.h"
59 #include "FontFamilyValue.h"
60 #include "FontValue.h"
61 #include "MediaList.h"
62 #include "MediaQueryExp.h"
63 #include "Pair.h"
64 #include "Rect.h"
65 #include "ShadowValue.h"
66 #include <kjs/dtoa.h>
67
68 #if ENABLE(DASHBOARD_SUPPORT)
69 #include "DashboardRegion.h"
70 #endif
71
72 #define YYDEBUG 0
73
74 #if YYDEBUG > 0
75 extern int cssyydebug;
76 #endif
77
78 extern int cssyyparse(void* parser);
79
80 using namespace std;
81 using namespace WTF;
82
83 #include "CSSPropertyNames.cpp"
84 #include "CSSValueKeywords.c"
85
86 namespace WebCore {
87
88 static bool equal(const ParseString& a, const char* b)
89 {
90     for (int i = 0; i < a.length; ++i) {
91         if (!b[i])
92             return false;
93         if (a.characters[i] != b[i])
94             return false;
95     }
96     return !b[a.length];
97 }
98
99 static bool equalIgnoringCase(const ParseString& a, const char* b)
100 {
101     for (int i = 0; i < a.length; ++i) {
102         if (!b[i])
103             return false;
104         ASSERT(!isASCIIUpper(b[i]));
105         if (toASCIILower(a.characters[i]) != b[i])
106             return false;
107     }
108     return !b[a.length];
109 }
110
111 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
112 {
113     for (unsigned i = 0; i < length; ++i) {
114         if (!prefix[i])
115             return true;
116         if (string[i] != prefix[i])
117             return false;
118     }
119     return false;
120 }
121
122 ValueList::~ValueList()
123 {
124      size_t numValues = m_values.size();
125      for (size_t i = 0; i < numValues; i++)
126          if (m_values[i].unit == Value::Function)
127              delete m_values[i].function;
128 }
129
130 CSSParser::CSSParser(bool strictParsing)
131     : m_strict(strictParsing)
132     , m_important(false)
133     , m_id(0)
134     , m_styleSheet(0)
135     , m_mediaQuery(0)
136     , m_valueList(0)
137     , m_parsedProperties(static_cast<CSSProperty**>(fastMalloc(32 * sizeof(CSSProperty*))))
138     , m_numParsedProperties(0)
139     , m_maxParsedProperties(32)
140     , m_inParseShorthand(0)
141     , m_currentShorthand(0)
142     , m_implicitShorthand(false)
143     , m_defaultNamespace(starAtom)
144     , m_data(0)
145     , yy_start(1)
146     , m_floatingMediaQuery(0)
147     , m_floatingMediaQueryExp(0)
148     , m_floatingMediaQueryExpList(0)
149 {
150 #if YYDEBUG > 0
151     cssyydebug = 1;
152 #endif
153 }
154
155 CSSParser::~CSSParser()
156 {
157     clearProperties();
158     fastFree(m_parsedProperties);
159
160     delete m_valueList;
161
162     fastFree(m_data);
163
164     if (m_floatingMediaQueryExpList) {
165         deleteAllValues(*m_floatingMediaQueryExpList);
166         delete m_floatingMediaQueryExpList;
167     }
168     delete m_floatingMediaQueryExp;
169     delete m_floatingMediaQuery;
170     deleteAllValues(m_floatingSelectors);
171     deleteAllValues(m_floatingValueLists);
172     deleteAllValues(m_floatingFunctions);
173 }
174
175 void ParseString::lower()
176 {
177     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
178     // that can potentially change the length of the string rather than the character
179     // by character kind. If we don't need Unicode lowercasing, it would be good to
180     // simplify this function.
181
182     if (charactersAreAllASCII(characters, length)) {
183         // Fast case for all-ASCII.
184         for (int i = 0; i < length; i++)
185             characters[i] = toASCIILower(characters[i]);
186     } else {
187         for (int i = 0; i < length; i++)
188             characters[i] = Unicode::toLower(characters[i]);
189     }
190 }
191
192 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
193 {
194     int length = string.length() + strlen(prefix) + strlen(suffix) + 2;
195
196     fastFree(m_data);
197     m_data = static_cast<UChar*>(fastMalloc(length * sizeof(UChar)));
198     for (unsigned i = 0; i < strlen(prefix); i++)
199         m_data[i] = prefix[i];
200     
201     memcpy(m_data + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
202
203     unsigned start = strlen(prefix) + string.length();
204     unsigned end = start + strlen(suffix);
205     for (unsigned i = start; i < end; i++)
206         m_data[i] = suffix[i - start];
207
208     m_data[length - 1] = 0;
209     m_data[length - 2] = 0;
210
211     yy_hold_char = 0;
212     yyleng = 0;
213     yytext = yy_c_buf_p = m_data;
214     yy_hold_char = *yy_c_buf_p;
215 }
216
217 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string)
218 {
219     m_styleSheet = sheet;
220     m_defaultNamespace = starAtom; // Reset the default namespace.
221     
222     setupParser("", string, "");
223     cssyyparse(this);
224     m_rule = 0;
225 }
226
227 PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
228 {
229     m_styleSheet = sheet;
230     setupParser("@-webkit-rule{", string, "} ");
231     cssyyparse(this);
232     return m_rule.release();
233 }
234
235 bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int id, const String& string, bool important)
236 {
237     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
238     m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet());
239
240     setupParser("@-webkit-value{", string, "} ");
241
242     m_id = id;
243     m_important = important;
244     
245     cssyyparse(this);
246     
247     m_rule = 0;
248
249     bool ok = false;
250     if (m_numParsedProperties) {
251         ok = true;
252         declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
253         clearProperties();
254     }
255
256     return ok;
257 }
258
259 // color will only be changed when string contains a valid css color, making it
260 // possible to set up a default color.
261 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
262 {
263     color = 0;
264     CSSParser parser(true);
265
266     // First try creating a color specified by name or the "#" syntax.
267     if (!parser.parseColor(string, color, strict)) {
268         RefPtr<CSSMutableStyleDeclaration> dummyStyleDeclaration = CSSMutableStyleDeclaration::create();
269
270         // Now try to create a color from the rgb() or rgba() syntax.
271         if (parser.parseColor(dummyStyleDeclaration.get(), string)) {
272             CSSValue* value = parser.m_parsedProperties[0]->value();
273             if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {
274                 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
275                 color = primitiveValue->getRGBColorValue();
276             }
277         } else
278             return false;
279     }
280
281     return true;
282 }
283
284 bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String& string)
285 {
286     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
287     m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet());
288
289     setupParser("@-webkit-decls{color:", string, "} ");
290     cssyyparse(this);
291     m_rule = 0;
292
293     return (m_numParsedProperties && m_parsedProperties[0]->m_id == CSSPropertyColor);
294 }
295
296 bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const String& string)
297 {
298     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
299     m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet());
300
301     setupParser("@-webkit-decls{", string, "} ");
302     cssyyparse(this);
303     m_rule = 0;
304
305     bool ok = false;
306     if (m_numParsedProperties) {
307         ok = true;
308         declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
309         clearProperties();
310     }
311
312     return ok;
313 }
314
315 bool CSSParser::parseMediaQuery(MediaList* queries, const String& string)
316 {
317     if (string.isEmpty())
318         return true;
319
320     m_mediaQuery = 0;
321     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
322     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
323     setupParser ("@-webkit-mediaquery ", string, "} ");
324     cssyyparse(this);
325
326     bool ok = false;
327     if (m_mediaQuery) {
328         ok = true;
329         queries->appendMediaQuery(m_mediaQuery);
330         m_mediaQuery = 0;
331     }
332
333     return ok;
334 }
335
336
337 void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important)
338 {
339     CSSProperty* prop = new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand);
340     if (m_numParsedProperties >= m_maxParsedProperties) {
341         m_maxParsedProperties += 32;
342         m_parsedProperties = static_cast<CSSProperty**>(fastRealloc(m_parsedProperties,
343                                                        m_maxParsedProperties * sizeof(CSSProperty*)));
344     }
345     m_parsedProperties[m_numParsedProperties++] = prop;
346 }
347
348 void CSSParser::rollbackLastProperties(int num)
349 {
350     ASSERT(num >= 0);
351     ASSERT(m_numParsedProperties >= num);
352
353     for (int i = 0; i < num; ++i)
354         delete m_parsedProperties[--m_numParsedProperties];
355 }
356
357 void CSSParser::clearProperties()
358 {
359     for (int i = 0; i < m_numParsedProperties; i++)
360         delete m_parsedProperties[i];
361     m_numParsedProperties = 0;
362 }
363
364 Document* CSSParser::document() const
365 {
366     StyleBase* root = m_styleSheet;
367     Document* doc = 0;
368     while (root->parent())
369         root = root->parent();
370     if (root->isCSSStyleSheet())
371         doc = static_cast<CSSStyleSheet*>(root)->doc();
372     return doc;
373 }
374
375 bool CSSParser::validUnit(Value* value, Units unitflags, bool strict)
376 {
377     if (unitflags & FNonNeg && value->fValue < 0)
378         return false;
379
380     bool b = false;
381     switch(value->unit) {
382     case CSSPrimitiveValue::CSS_NUMBER:
383         b = (unitflags & FNumber);
384         if (!b && ((unitflags & (FLength | FAngle)) && (value->fValue == 0 || !strict))) {
385             value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX : CSSPrimitiveValue::CSS_DEG;
386             b = true;
387         }
388         if (!b && (unitflags & FInteger) && value->isInt)
389             b = true;
390         break;
391     case CSSPrimitiveValue::CSS_PERCENTAGE:
392         b = (unitflags & FPercent);
393         break;
394     case Value::Q_EMS:
395     case CSSPrimitiveValue::CSS_EMS:
396     case CSSPrimitiveValue::CSS_EXS:
397     case CSSPrimitiveValue::CSS_PX:
398     case CSSPrimitiveValue::CSS_CM:
399     case CSSPrimitiveValue::CSS_MM:
400     case CSSPrimitiveValue::CSS_IN:
401     case CSSPrimitiveValue::CSS_PT:
402     case CSSPrimitiveValue::CSS_PC:
403         b = (unitflags & FLength);
404         break;
405     case CSSPrimitiveValue::CSS_MS:
406     case CSSPrimitiveValue::CSS_S:
407         b = (unitflags & FTime);
408         break;
409     case CSSPrimitiveValue::CSS_DEG:
410     case CSSPrimitiveValue::CSS_RAD:
411     case CSSPrimitiveValue::CSS_GRAD:
412         b = (unitflags & FAngle);
413         break;
414     case CSSPrimitiveValue::CSS_HZ:
415     case CSSPrimitiveValue::CSS_KHZ:
416     case CSSPrimitiveValue::CSS_DIMENSION:
417     default:
418         break;
419     }
420     return b;
421 }
422
423 static int unitFromString(Value* value)
424 {
425     if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
426         return 0;
427
428     if (equal(value->string, "em"))
429         return CSSPrimitiveValue::CSS_EMS;
430     if (equal(value->string, "ex"))
431         return CSSPrimitiveValue::CSS_EXS;
432     if (equal(value->string, "px"))
433         return CSSPrimitiveValue::CSS_PX;
434     if (equal(value->string, "cm"))
435         return CSSPrimitiveValue::CSS_CM;
436     if (equal(value->string, "mm"))
437         return CSSPrimitiveValue::CSS_MM;
438     if (equal(value->string, "in"))
439         return CSSPrimitiveValue::CSS_IN;
440     if (equal(value->string, "pt"))
441         return CSSPrimitiveValue::CSS_PT;
442     if (equal(value->string, "pc"))
443         return CSSPrimitiveValue::CSS_PC;
444     if (equal(value->string, "deg"))
445         return CSSPrimitiveValue::CSS_DEG;
446     if (equal(value->string, "rad"))
447         return CSSPrimitiveValue::CSS_RAD;
448     if (equal(value->string, "grad"))
449         return CSSPrimitiveValue::CSS_GRAD;
450     if (equal(value->string, "ms"))
451         return CSSPrimitiveValue::CSS_MS;
452     if (equal(value->string, "s"))
453         return CSSPrimitiveValue::CSS_S;
454     if (equal(value->string, "Hz"))
455         return CSSPrimitiveValue::CSS_HZ;
456     if (equal(value->string, "kHz"))
457         return CSSPrimitiveValue::CSS_KHZ;
458     
459     return 0;
460 }
461
462 void CSSParser::checkForOrphanedUnits()
463 {
464     if (m_strict || inShorthand())
465         return;
466         
467     // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
468     // by whitespace, so e.g., width: 20 px instead of width:20px.  This is invalid CSS, so we don't do this in strict mode.
469     Value* numericVal = 0;
470     unsigned size = m_valueList->size();
471     for (unsigned i = 0; i < size; i++) {
472         Value* value = m_valueList->valueAt(i);
473         if (numericVal) {
474             // Change the unit type of the numeric val to match.
475             int unit = unitFromString(value);
476             if (unit) {
477                 numericVal->unit = unit;
478                 numericVal = 0;
479
480                 // Now delete the bogus unit value.
481                 m_valueList->deleteValueAt(i);
482                 i--; // We're safe even though |i| is unsigned, since we only hit this code if we had a previous numeric value (so |i| is always > 0 here).
483                 size--;
484                 continue;
485             }
486         }
487         
488         numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
489     }
490 }
491
492 bool CSSParser::parseValue(int propId, bool important)
493 {
494     if (!m_valueList)
495         return false;
496
497     Value *value = m_valueList->current();
498
499     if (!value)
500         return false;
501
502     int id = value->id;
503
504     int num = inShorthand() ? 1 : m_valueList->size();
505
506     if (id == CSSValueInherit) {
507         if (num != 1)
508             return false;
509         addProperty(propId, CSSInheritedValue::create(), important);
510         return true;
511     }
512     else if (id == CSSValueInitial) {
513         if (num != 1)
514             return false;
515         addProperty(propId, CSSInitialValue::createExplicit(), important);
516         return true;
517     }
518
519     bool valid_primitive = false;
520     RefPtr<CSSValue> parsedValue;
521
522     // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
523     // by a space.  We go ahead and associate the unit with the number even though it is invalid CSS.
524     checkForOrphanedUnits();
525
526     switch (static_cast<CSSPropertyID>(propId)) {
527         /* The comment to the left defines all valid value of this properties as defined
528          * in CSS 2, Appendix F. Property index
529          */
530
531         /* All the CSS properties are not supported by the renderer at the moment.
532          * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
533          * (see parseAuralValues). As we don't support them at all this seems reasonable.
534          */
535
536     case CSSPropertySize:                 // <length>{1,2} | auto | portrait | landscape | inherit
537     case CSSPropertyQuotes:               // [<string> <string>]+ | none | inherit
538         if (id)
539             valid_primitive = true;
540         break;
541     case CSSPropertyUnicodeBidi:         // normal | embed | bidi-override | inherit
542         if (id == CSSValueNormal ||
543              id == CSSValueEmbed ||
544              id == CSSValueBidiOverride)
545             valid_primitive = true;
546         break;
547
548     case CSSPropertyPosition:             // static | relative | absolute | fixed | inherit
549         if (id == CSSValueStatic ||
550              id == CSSValueRelative ||
551              id == CSSValueAbsolute ||
552              id == CSSValueFixed)
553             valid_primitive = true;
554         break;
555
556     case CSSPropertyPageBreakAfter:     // auto | always | avoid | left | right | inherit
557     case CSSPropertyPageBreakBefore:
558     case CSSPropertyWebkitColumnBreakAfter:
559     case CSSPropertyWebkitColumnBreakBefore:
560         if (id == CSSValueAuto ||
561              id == CSSValueAlways ||
562              id == CSSValueAvoid ||
563              id == CSSValueLeft ||
564              id == CSSValueRight)
565             valid_primitive = true;
566         break;
567
568     case CSSPropertyPageBreakInside:    // avoid | auto | inherit
569     case CSSPropertyWebkitColumnBreakInside:
570         if (id == CSSValueAuto || id == CSSValueAvoid)
571             valid_primitive = true;
572         break;
573
574     case CSSPropertyEmptyCells:          // show | hide | inherit
575         if (id == CSSValueShow ||
576              id == CSSValueHide)
577             valid_primitive = true;
578         break;
579
580     case CSSPropertyContent:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
581         // close-quote | no-open-quote | no-close-quote ]+ | inherit
582         return parseContent(propId, important);
583         break;
584
585     case CSSPropertyWhiteSpace:          // normal | pre | nowrap | inherit
586         if (id == CSSValueNormal ||
587             id == CSSValuePre ||
588             id == CSSValuePreWrap ||
589             id == CSSValuePreLine ||
590             id == CSSValueNowrap)
591             valid_primitive = true;
592         break;
593
594     case CSSPropertyClip:                 // <shape> | auto | inherit
595         if (id == CSSValueAuto)
596             valid_primitive = true;
597         else if (value->unit == Value::Function)
598             return parseShape(propId, important);
599         break;
600
601     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
602      * correctly and allows optimization in WebCore::applyRule(..)
603      */
604     case CSSPropertyCaptionSide:         // top | bottom | left | right | inherit
605         if (id == CSSValueLeft || id == CSSValueRight ||
606             id == CSSValueTop || id == CSSValueBottom)
607             valid_primitive = true;
608         break;
609
610     case CSSPropertyBorderCollapse:      // collapse | separate | inherit
611         if (id == CSSValueCollapse || id == CSSValueSeparate)
612             valid_primitive = true;
613         break;
614
615     case CSSPropertyVisibility:           // visible | hidden | collapse | inherit
616         if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueCollapse)
617             valid_primitive = true;
618         break;
619
620     case CSSPropertyOverflow: {
621         ShorthandScope scope(this, propId);
622         if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
623             return false;
624         CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value();
625         addProperty(CSSPropertyOverflowY, value, important);
626         return true;
627     }
628     case CSSPropertyOverflowX:
629     case CSSPropertyOverflowY:           // visible | hidden | scroll | auto | marquee | overlay | inherit
630         if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueScroll || id == CSSValueAuto ||
631             id == CSSValueOverlay || id == CSSValueWebkitMarquee)
632             valid_primitive = true;
633         break;
634
635     case CSSPropertyListStylePosition:  // inside | outside | inherit
636         if (id == CSSValueInside || id == CSSValueOutside)
637             valid_primitive = true;
638         break;
639
640     case CSSPropertyListStyleType:
641         // disc | circle | square | decimal | decimal-leading-zero | lower-roman |
642         // upper-roman | lower-greek | lower-alpha | lower-latin | upper-alpha |
643         // upper-latin | hebrew | armenian | georgian | cjk-ideographic | hiragana |
644         // katakana | hiragana-iroha | katakana-iroha | none | inherit
645         if ((id >= CSSValueDisc && id <= CSSValueKatakanaIroha) || id == CSSValueNone)
646             valid_primitive = true;
647         break;
648
649     case CSSPropertyDisplay:
650         // inline | block | list-item | run-in | inline-block | table |
651         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
652         // table-column-group | table-column | table-cell | table-caption | box | inline-box | none | inherit
653         if ((id >= CSSValueInline && id <= CSSValueWebkitInlineBox) || id == CSSValueNone)
654             valid_primitive = true;
655         break;
656
657     case CSSPropertyDirection:            // ltr | rtl | inherit
658         if (id == CSSValueLtr || id == CSSValueRtl)
659             valid_primitive = true;
660         break;
661
662     case CSSPropertyTextTransform:       // capitalize | uppercase | lowercase | none | inherit
663         if ((id >= CSSValueCapitalize && id <= CSSValueLowercase) || id == CSSValueNone)
664             valid_primitive = true;
665         break;
666
667     case CSSPropertyFloat:                // left | right | none | inherit + center for buggy CSS
668         if (id == CSSValueLeft || id == CSSValueRight ||
669              id == CSSValueNone || id == CSSValueCenter)
670             valid_primitive = true;
671         break;
672
673     case CSSPropertyClear:                // none | left | right | both | inherit
674         if (id == CSSValueNone || id == CSSValueLeft ||
675              id == CSSValueRight|| id == CSSValueBoth)
676             valid_primitive = true;
677         break;
678
679     case CSSPropertyTextAlign:
680         // left | right | center | justify | webkit_left | webkit_right | webkit_center | start | end | <string> | inherit
681         if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitCenter) || id == CSSValueStart || id == CSSValueEnd ||
682              value->unit == CSSPrimitiveValue::CSS_STRING)
683             valid_primitive = true;
684         break;
685
686     case CSSPropertyOutlineStyle:        // <border-style> | auto | inherit
687         if (id == CSSValueAuto) {
688             valid_primitive = true;
689             break;
690         } // Fall through!
691     case CSSPropertyBorderTopStyle:     //// <border-style> | inherit
692     case CSSPropertyBorderRightStyle:   //   Defined as:    none | hidden | dotted | dashed |
693     case CSSPropertyBorderBottomStyle:  //   solid | double | groove | ridge | inset | outset
694     case CSSPropertyBorderLeftStyle:
695     case CSSPropertyWebkitColumnRuleStyle:
696         if (id >= CSSValueNone && id <= CSSValueDouble)
697             valid_primitive = true;
698         break;
699
700     case CSSPropertyFontWeight:  // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
701         if (id >= CSSValueNormal && id <= CSSValue900) {
702             // Valid weight keyword
703             valid_primitive = true;
704         } else if (validUnit(value, FInteger | FNonNeg, false)) {
705             int weight = static_cast<int>(value->fValue);
706             if (weight % 100)
707                 break;
708             weight /= 100;
709             if (weight >= 1 && weight <= 9) {
710                 id = CSSValue100 + weight - 1;
711                 valid_primitive = true;
712             }
713         }
714         break;
715
716     case CSSPropertyBorderSpacing: {
717         const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing,
718                                     CSSPropertyWebkitBorderVerticalSpacing };
719         if (num == 1) {
720             ShorthandScope scope(this, CSSPropertyBorderSpacing);
721             if (!parseValue(properties[0], important))
722                 return false;
723             CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
724             addProperty(properties[1], value, important);
725             return true;
726         }
727         else if (num == 2) {
728             ShorthandScope scope(this, CSSPropertyBorderSpacing);
729             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
730                 return false;
731             return true;
732         }
733         return false;
734     }
735     case CSSPropertyWebkitBorderHorizontalSpacing:
736     case CSSPropertyWebkitBorderVerticalSpacing:
737         valid_primitive = validUnit(value, FLength|FNonNeg, m_strict);
738         break;
739     case CSSPropertyScrollbarFaceColor:         // IE5.5
740     case CSSPropertyScrollbarShadowColor:       // IE5.5
741     case CSSPropertyScrollbarHighlightColor:    // IE5.5
742     case CSSPropertyScrollbar3dlightColor:      // IE5.5
743     case CSSPropertyScrollbarDarkshadowColor:   // IE5.5
744     case CSSPropertyScrollbarTrackColor:        // IE5.5
745     case CSSPropertyScrollbarArrowColor:        // IE5.5
746         if (m_strict)
747             break;
748         /* nobreak */
749     case CSSPropertyOutlineColor:        // <color> | invert | inherit
750         // Outline color has "invert" as additional keyword.
751         // Also, we want to allow the special focus color even in strict parsing mode.
752         if (propId == CSSPropertyOutlineColor && (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor)) {
753             valid_primitive = true;
754             break;
755         }
756         /* nobreak */
757     case CSSPropertyBackgroundColor:     // <color> | inherit
758     case CSSPropertyBorderTopColor:     // <color> | inherit
759     case CSSPropertyBorderRightColor:   // <color> | inherit
760     case CSSPropertyBorderBottomColor:  // <color> | inherit
761     case CSSPropertyBorderLeftColor:    // <color> | inherit
762     case CSSPropertyColor:                // <color> | inherit
763     case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
764     case CSSPropertyTextUnderlineColor:
765     case CSSPropertyTextOverlineColor:
766     case CSSPropertyWebkitColumnRuleColor:
767     case CSSPropertyWebkitTextFillColor:
768     case CSSPropertyWebkitTextStrokeColor:
769         if (id == CSSValueWebkitText)
770             valid_primitive = true; // Always allow this, even when strict parsing is on,
771                                     // since we use this in our UA sheets.
772         else if (id == CSSValueCurrentcolor)
773             valid_primitive = true;
774         else if (id >= CSSValueAqua && id <= CSSValueWindowtext || id == CSSValueMenu ||
775              (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && !m_strict)) {
776             valid_primitive = true;
777         } else {
778             parsedValue = parseColor();
779             if (parsedValue)
780                 m_valueList->next();
781         }
782         break;
783
784     case CSSPropertyCursor: {
785         // [<uri>,]*  [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
786         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize | 
787         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help ] ] | inherit
788         RefPtr<CSSValueList> list;
789         while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
790             if (!list)
791                 list = CSSValueList::createCommaSeparated(); 
792             String uri = parseURL(value->string);
793             Vector<int> coords;
794             value = m_valueList->next();
795             while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
796                 coords.append(int(value->fValue));
797                 value = m_valueList->next();
798             }
799             IntPoint hotspot;
800             int nrcoords = coords.size();
801             if (nrcoords > 0 && nrcoords != 2) {
802                 if (m_strict) // only support hotspot pairs in strict mode
803                     return false;
804             } else if (m_strict && nrcoords == 2)
805                 hotspot = IntPoint(coords[0], coords[1]);
806             if (m_strict || coords.size() == 0) {
807                 if (!uri.isNull())
808                     list->append(CSSCursorImageValue::create(KURL(m_styleSheet->baseURL(), uri).string(), hotspot));
809             }
810             if ((m_strict && !value) || (value && !(value->unit == Value::Operator && value->iValue == ',')))
811                 return false;
812             value = m_valueList->next(); // comma
813         }
814         if (list) {
815             if (!value) { // no value after url list (MSIE 5 compatibility)
816                 if (list->length() != 1)
817                     return false;
818             } else if (!m_strict && value->id == CSSValueHand) // MSIE 5 compatibility :/
819                 list->append(CSSPrimitiveValue::createIdentifier(CSSValuePointer));
820             else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueAllScroll) || value->id == CSSValueCopy || value->id == CSSValueNone))
821                 list->append(CSSPrimitiveValue::createIdentifier(value->id));
822             m_valueList->next();
823             parsedValue = list.release();
824             break;
825         }
826         id = value->id;
827         if (!m_strict && value->id == CSSValueHand) { // MSIE 5 compatibility :/
828             id = CSSValuePointer;
829             valid_primitive = true;
830         } else if ((value->id >= CSSValueAuto && value->id <= CSSValueAllScroll) || value->id == CSSValueCopy || value->id == CSSValueNone)
831             valid_primitive = true;
832         break;
833     }
834
835     case CSSPropertyBackgroundAttachment:
836     case CSSPropertyWebkitBackgroundClip:
837     case CSSPropertyWebkitBackgroundComposite:
838     case CSSPropertyBackgroundImage:
839     case CSSPropertyWebkitBackgroundOrigin:
840     case CSSPropertyBackgroundPosition:
841     case CSSPropertyBackgroundPositionX:
842     case CSSPropertyBackgroundPositionY:
843     case CSSPropertyWebkitBackgroundSize:
844     case CSSPropertyBackgroundRepeat:
845     case CSSPropertyWebkitMaskAttachment:
846     case CSSPropertyWebkitMaskClip:
847     case CSSPropertyWebkitMaskComposite:
848     case CSSPropertyWebkitMaskImage:
849     case CSSPropertyWebkitMaskOrigin:
850     case CSSPropertyWebkitMaskPosition:
851     case CSSPropertyWebkitMaskPositionX:
852     case CSSPropertyWebkitMaskPositionY:
853     case CSSPropertyWebkitMaskSize:
854     case CSSPropertyWebkitMaskRepeat: {
855         RefPtr<CSSValue> val1;
856         RefPtr<CSSValue> val2;
857         int propId1, propId2;
858         if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
859             addProperty(propId1, val1.release(), important);
860             if (val2)
861                 addProperty(propId2, val2.release(), important);
862             return true;
863         }
864         return false;
865     }
866     case CSSPropertyListStyleImage:     // <uri> | none | inherit
867         if (id == CSSValueNone) {
868             parsedValue = CSSImageValue::create();
869             m_valueList->next();
870         } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
871             // ### allow string in non strict mode?
872             String uri = parseURL(value->string);
873             if (!uri.isNull()) {
874                 parsedValue = CSSImageValue::create(KURL(m_styleSheet->baseURL(), uri).string());
875                 m_valueList->next();
876             }
877         } else if (value->unit == Value::Function && equalIgnoringCase(value->function->name, "-webkit-gradient(")) {
878             if (parseGradient(parsedValue))
879                 m_valueList->next();
880             else
881                 return false;
882         }
883         break;
884
885     case CSSPropertyWebkitTextStrokeWidth:
886     case CSSPropertyOutlineWidth:        // <border-width> | inherit
887     case CSSPropertyBorderTopWidth:     //// <border-width> | inherit
888     case CSSPropertyBorderRightWidth:   //   Which is defined as
889     case CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
890     case CSSPropertyBorderLeftWidth:
891     case CSSPropertyWebkitColumnRuleWidth:
892         if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
893             valid_primitive = true;
894         else
895             valid_primitive = validUnit(value, FLength, m_strict);
896         break;
897
898     case CSSPropertyLetterSpacing:       // normal | <length> | inherit
899     case CSSPropertyWordSpacing:         // normal | <length> | inherit
900         if (id == CSSValueNormal)
901             valid_primitive = true;
902         else
903             valid_primitive = validUnit(value, FLength, m_strict);
904         break;
905
906     case CSSPropertyWordBreak:          // normal | break-all | break-word (this is a custom extension)
907         if (id == CSSValueNormal || id == CSSValueBreakAll || id == CSSValueBreakWord)
908             valid_primitive = true;
909         break;
910
911     case CSSPropertyWordWrap:           // normal | break-word
912         if (id == CSSValueNormal || id == CSSValueBreakWord)
913             valid_primitive = true;
914         break;
915
916     case CSSPropertyTextIndent:          // <length> | <percentage> | inherit
917     case CSSPropertyPaddingTop:          //// <padding-width> | inherit
918     case CSSPropertyPaddingRight:        //   Which is defined as
919     case CSSPropertyPaddingBottom:       //   <length> | <percentage>
920     case CSSPropertyPaddingLeft:         ////
921     case CSSPropertyWebkitPaddingStart:
922         valid_primitive = (!id && validUnit(value, FLength|FPercent, m_strict));
923         break;
924
925     case CSSPropertyMaxHeight:           // <length> | <percentage> | none | inherit
926     case CSSPropertyMaxWidth:            // <length> | <percentage> | none | inherit
927         if (id == CSSValueNone || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic) {
928             valid_primitive = true;
929             break;
930         }
931         /* nobreak */
932     case CSSPropertyMinHeight:           // <length> | <percentage> | inherit
933     case CSSPropertyMinWidth:            // <length> | <percentage> | inherit
934         if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
935             valid_primitive = true;
936         else
937             valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, m_strict));
938         break;
939
940     case CSSPropertyFontSize:
941         // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
942         if (id >= CSSValueXxSmall && id <= CSSValueLarger)
943             valid_primitive = true;
944         else
945             valid_primitive = (validUnit(value, FLength|FPercent|FNonNeg, m_strict));
946         break;
947
948     case CSSPropertyFontStyle:           // normal | italic | oblique | inherit
949         if (id == CSSValueNormal || id == CSSValueItalic || id == CSSValueOblique)
950             valid_primitive = true;
951         break;
952
953     case CSSPropertyFontVariant:         // normal | small-caps | inherit
954         if (id == CSSValueNormal || id == CSSValueSmallCaps)
955             valid_primitive = true;
956         break;
957
958     case CSSPropertyVerticalAlign:
959         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
960         // <percentage> | <length> | inherit
961
962         if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
963             valid_primitive = true;
964         else
965             valid_primitive = (!id && validUnit(value, FLength|FPercent, m_strict));
966         break;
967
968     case CSSPropertyHeight:               // <length> | <percentage> | auto | inherit
969     case CSSPropertyWidth:                // <length> | <percentage> | auto | inherit
970         if (id == CSSValueAuto || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
971             valid_primitive = true;
972         else
973             // ### handle multilength case where we allow relative units
974             valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, m_strict));
975         break;
976
977     case CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
978     case CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
979     case CSSPropertyRight:                // <length> | <percentage> | auto | inherit
980     case CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
981     case CSSPropertyMarginTop:           //// <margin-width> | inherit
982     case CSSPropertyMarginRight:         //   Which is defined as
983     case CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
984     case CSSPropertyMarginLeft:          ////
985     case CSSPropertyWebkitMarginStart:
986         if (id == CSSValueAuto)
987             valid_primitive = true;
988         else
989             valid_primitive = (!id && validUnit(value, FLength|FPercent, m_strict));
990         break;
991
992     case CSSPropertyZIndex:              // auto | <integer> | inherit
993         if (id == CSSValueAuto) {
994             valid_primitive = true;
995             break;
996         }
997         /* nobreak */
998     case CSSPropertyOrphans:              // <integer> | inherit
999     case CSSPropertyWidows:               // <integer> | inherit
1000         // ### not supported later on
1001         valid_primitive = (!id && validUnit(value, FInteger, false));
1002         break;
1003
1004     case CSSPropertyLineHeight:          // normal | <number> | <length> | <percentage> | inherit
1005         if (id == CSSValueNormal)
1006             valid_primitive = true;
1007         else
1008             valid_primitive = (!id && validUnit(value, FNumber|FLength|FPercent|FNonNeg, m_strict));
1009         break;
1010     case CSSPropertyCounterIncrement:    // [ <identifier> <integer>? ]+ | none | inherit
1011         if (id != CSSValueNone)
1012             return parseCounter(propId, 1, important);
1013         valid_primitive = true;
1014         break;
1015      case CSSPropertyCounterReset:        // [ <identifier> <integer>? ]+ | none | inherit
1016         if (id != CSSValueNone)
1017             return parseCounter(propId, 0, important);
1018         valid_primitive = true;
1019         break;
1020     case CSSPropertyFontFamily:
1021         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
1022     {
1023         parsedValue = parseFontFamily();
1024         break;
1025     }
1026
1027     case CSSPropertyTextDecoration:
1028     case CSSPropertyWebkitTextDecorationsInEffect:
1029         // none | [ underline || overline || line-through || blink ] | inherit
1030         if (id == CSSValueNone) {
1031             valid_primitive = true;
1032         } else {
1033             RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
1034             bool is_valid = true;
1035             while(is_valid && value) {
1036                 switch (value->id) {
1037                 case CSSValueBlink:
1038                     break;
1039                 case CSSValueUnderline:
1040                 case CSSValueOverline:
1041                 case CSSValueLineThrough:
1042                     list->append(CSSPrimitiveValue::createIdentifier(value->id));
1043                     break;
1044                 default:
1045                     is_valid = false;
1046                 }
1047                 value = m_valueList->next();
1048             }
1049             if (list->length() && is_valid) {
1050                 parsedValue = list.release();
1051                 m_valueList->next();
1052             }
1053         }
1054         break;
1055
1056     case CSSPropertyZoom:          // normal | reset | <number> | <percentage> | inherit
1057         if (id == CSSValueNormal || id == CSSValueReset)
1058             valid_primitive = true;
1059         else
1060             valid_primitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, true));
1061         break;
1062         
1063     case CSSPropertyTableLayout:         // auto | fixed | inherit
1064         if (id == CSSValueAuto || id == CSSValueFixed)
1065             valid_primitive = true;
1066         break;
1067
1068     case CSSPropertySrc:  // Only used within @font-face, so cannot use inherit | initial or be !important.  This is a list of urls or local references.
1069         return parseFontFaceSrc();
1070
1071     case CSSPropertyUnicodeRange:
1072         return parseFontFaceUnicodeRange();
1073
1074     /* CSS3 properties */
1075     case CSSPropertyWebkitAppearance:
1076         if ((id >= CSSValueCheckbox && id <= CSSValueTextarea) || id == CSSValueNone)
1077             valid_primitive = true;
1078         break;
1079
1080     case CSSPropertyWebkitBinding:
1081 #if ENABLE(XBL)
1082         if (id == CSSValueNone)
1083             valid_primitive = true;
1084         else {
1085             RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
1086             Value* val;
1087             RefPtr<CSSValue> parsedValue;
1088             while ((val = m_valueList->current())) {
1089                 if (val->unit == CSSPrimitiveValue::CSS_URI) {
1090                     String value = parseURL(val->string);
1091                     parsedValue = CSSPrimitiveValue::create(KURL(m_styleSheet->baseURL(), value).string(),
1092                         CSSPrimitiveValue::CSS_URI);
1093                 }
1094                 if (!parsedValue)
1095                     break;
1096                 
1097                 // FIXME: We can't use release() here since we might hit this path twice
1098                 // but that logic seems wrong to me to begin with, we convert all non-uri values
1099                 // into the last seen URI value!?
1100                 // -webkit-binding: url(foo.xml), 1, 2; (if that were valid) is treated as:
1101                 // -webkit-binding: url(foo.xml), url(foo.xml), url(foo.xml); !?
1102                 values->append(parsedValue.get());
1103                 m_valueList->next();
1104             }
1105             if (!values->length())
1106                 return false;
1107             
1108             addProperty(propId, values.release(), important);
1109             m_valueList->next();
1110             return true;
1111         }
1112 #endif
1113         break;
1114     case CSSPropertyWebkitBorderImage:
1115     case CSSPropertyWebkitMaskBoxImage:
1116         if (id == CSSValueNone)
1117             valid_primitive = true;
1118         else {
1119             RefPtr<CSSValue> result;
1120             if (parseBorderImage(propId, important, result)) {
1121                 addProperty(propId, result, important);
1122                 return true;
1123             }
1124         }
1125         break;
1126     case CSSPropertyWebkitBorderTopRightRadius:
1127     case CSSPropertyWebkitBorderTopLeftRadius:
1128     case CSSPropertyWebkitBorderBottomLeftRadius:
1129     case CSSPropertyWebkitBorderBottomRightRadius:
1130     case CSSPropertyWebkitBorderRadius: {
1131         if (num != 1 && num != 2)
1132             return false;
1133         valid_primitive = validUnit(value, FLength, m_strict);
1134         if (!valid_primitive)
1135             return false;
1136         RefPtr<CSSPrimitiveValue> parsedValue1 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1137         RefPtr<CSSPrimitiveValue> parsedValue2;
1138         if (num == 2) {
1139             value = m_valueList->next();
1140             valid_primitive = validUnit(value, FLength, m_strict);
1141             if (!valid_primitive)
1142                 return false;
1143             parsedValue2 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1144         } else
1145             parsedValue2 = parsedValue1;
1146         
1147         RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
1148         RefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(pair.release());
1149         if (propId == CSSPropertyWebkitBorderRadius) {
1150             const int properties[4] = { CSSPropertyWebkitBorderTopRightRadius,
1151                                         CSSPropertyWebkitBorderTopLeftRadius,
1152                                         CSSPropertyWebkitBorderBottomLeftRadius,
1153                                         CSSPropertyWebkitBorderBottomRightRadius };
1154             for (int i = 0; i < 4; i++)
1155                 addProperty(properties[i], val.get(), important);
1156         } else
1157             addProperty(propId, val.release(), important);
1158         return true;
1159     }
1160     case CSSPropertyOutlineOffset:
1161         valid_primitive = validUnit(value, FLength, m_strict);
1162         break;
1163     case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
1164     case CSSPropertyWebkitBoxShadow:
1165         if (id == CSSValueNone)
1166             valid_primitive = true;
1167         else
1168             return parseShadow(propId, important);
1169         break;
1170     case CSSPropertyWebkitBoxReflect:
1171         if (id == CSSValueNone)
1172             valid_primitive = true;
1173         else
1174             return parseReflect(propId, important);
1175         break;
1176     case CSSPropertyOpacity:
1177         valid_primitive = validUnit(value, FNumber, m_strict);
1178         break;
1179     case CSSPropertyWebkitBoxAlign:
1180         if (id == CSSValueStretch || id == CSSValueStart || id == CSSValueEnd ||
1181             id == CSSValueCenter || id == CSSValueBaseline)
1182             valid_primitive = true;
1183         break;
1184     case CSSPropertyWebkitBoxDirection:
1185         if (id == CSSValueNormal || id == CSSValueReverse)
1186             valid_primitive = true;
1187         break;
1188     case CSSPropertyWebkitBoxLines:
1189         if (id == CSSValueSingle || id == CSSValueMultiple)
1190             valid_primitive = true;
1191         break;
1192     case CSSPropertyWebkitBoxOrient:
1193         if (id == CSSValueHorizontal || id == CSSValueVertical ||
1194             id == CSSValueInlineAxis || id == CSSValueBlockAxis)
1195             valid_primitive = true;
1196         break;
1197     case CSSPropertyWebkitBoxPack:
1198         if (id == CSSValueStart || id == CSSValueEnd ||
1199             id == CSSValueCenter || id == CSSValueJustify)
1200             valid_primitive = true;
1201         break;
1202     case CSSPropertyWebkitBoxFlex:
1203         valid_primitive = validUnit(value, FNumber, m_strict);
1204         break;
1205     case CSSPropertyWebkitBoxFlexGroup:
1206     case CSSPropertyWebkitBoxOrdinalGroup:
1207         valid_primitive = validUnit(value, FInteger|FNonNeg, true);
1208         break;
1209     case CSSPropertyWebkitBoxSizing:
1210         valid_primitive = id == CSSValueBorderBox || id == CSSValueContentBox;
1211         break;
1212     case CSSPropertyWebkitMarquee: {
1213         const int properties[5] = { CSSPropertyWebkitMarqueeDirection, CSSPropertyWebkitMarqueeIncrement,
1214                                     CSSPropertyWebkitMarqueeRepetition,
1215                                     CSSPropertyWebkitMarqueeStyle, CSSPropertyWebkitMarqueeSpeed };
1216         return parseShorthand(propId, properties, 5, important);
1217     }
1218     case CSSPropertyWebkitMarqueeDirection:
1219         if (id == CSSValueForwards || id == CSSValueBackwards || id == CSSValueAhead ||
1220             id == CSSValueReverse || id == CSSValueLeft || id == CSSValueRight || id == CSSValueDown ||
1221             id == CSSValueUp || id == CSSValueAuto)
1222             valid_primitive = true;
1223         break;
1224     case CSSPropertyWebkitMarqueeIncrement:
1225         if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
1226             valid_primitive = true;
1227         else
1228             valid_primitive = validUnit(value, FLength|FPercent, m_strict);
1229         break;
1230     case CSSPropertyWebkitMarqueeStyle:
1231         if (id == CSSValueNone || id == CSSValueSlide || id == CSSValueScroll || id == CSSValueAlternate)
1232             valid_primitive = true;
1233         break;
1234     case CSSPropertyWebkitMarqueeRepetition:
1235         if (id == CSSValueInfinite)
1236             valid_primitive = true;
1237         else
1238             valid_primitive = validUnit(value, FInteger|FNonNeg, m_strict);
1239         break;
1240     case CSSPropertyWebkitMarqueeSpeed:
1241         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
1242             valid_primitive = true;
1243         else
1244             valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, m_strict);
1245         break;
1246     case CSSPropertyWebkitUserDrag: // auto | none | element
1247         if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueElement)
1248             valid_primitive = true;
1249         break;
1250     case CSSPropertyWebkitUserModify: // read-only | read-write
1251         if (id == CSSValueReadOnly || id == CSSValueReadWrite || id == CSSValueReadWritePlaintextOnly)
1252             valid_primitive = true;
1253         break;
1254     case CSSPropertyWebkitUserSelect: // auto | none | text
1255         if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueText)
1256             valid_primitive = true;
1257         break;
1258     case CSSPropertyTextOverflow: // clip | ellipsis
1259         if (id == CSSValueClip || id == CSSValueEllipsis)
1260             valid_primitive = true;
1261         break;
1262     case CSSPropertyWebkitTransform:
1263         if (id == CSSValueNone)
1264             valid_primitive = true;
1265         else {
1266             PassRefPtr<CSSValue> val = parseTransform();
1267             if (val) {
1268                 addProperty(propId, val, important);
1269                 return true;
1270             }
1271             return false;
1272         }
1273         break;
1274     case CSSPropertyWebkitTransformOrigin:
1275     case CSSPropertyWebkitTransformOriginX:
1276     case CSSPropertyWebkitTransformOriginY: {
1277         RefPtr<CSSValue> val1;
1278         RefPtr<CSSValue> val2;
1279         int propId1, propId2;
1280         if (parseTransformOrigin(propId, propId1, propId2, val1, val2)) {
1281             addProperty(propId1, val1.release(), important);
1282             if (val2)
1283                 addProperty(propId2, val2.release(), important);
1284             return true;
1285         }
1286         return false;
1287     }
1288     case CSSPropertyWebkitTransitionDuration:
1289     case CSSPropertyWebkitTransitionRepeatCount:
1290     case CSSPropertyWebkitTransitionTimingFunction:
1291     case CSSPropertyWebkitTransitionProperty: {
1292         RefPtr<CSSValue> val;
1293         if (parseTransitionProperty(propId, val)) {
1294             addProperty(propId, val.release(), important);
1295             return true;
1296         }
1297         return false;
1298     }
1299     case CSSPropertyWebkitMarginCollapse: {
1300         const int properties[2] = { CSSPropertyWebkitMarginTopCollapse,
1301             CSSPropertyWebkitMarginBottomCollapse };
1302         if (num == 1) {
1303             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
1304             if (!parseValue(properties[0], important))
1305                 return false;
1306             CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
1307             addProperty(properties[1], value, important);
1308             return true;
1309         }
1310         else if (num == 2) {
1311             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
1312             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1313                 return false;
1314             return true;
1315         }
1316         return false;
1317     }
1318     case CSSPropertyWebkitMarginTopCollapse:
1319     case CSSPropertyWebkitMarginBottomCollapse:
1320         if (id == CSSValueCollapse || id == CSSValueSeparate || id == CSSValueDiscard)
1321             valid_primitive = true;
1322         break;
1323     case CSSPropertyTextLineThroughMode:
1324     case CSSPropertyTextOverlineMode:
1325     case CSSPropertyTextUnderlineMode:
1326         if (id == CSSValueContinuous || id == CSSValueSkipWhiteSpace)
1327             valid_primitive = true;
1328         break;
1329     case CSSPropertyTextLineThroughStyle:
1330     case CSSPropertyTextOverlineStyle:
1331     case CSSPropertyTextUnderlineStyle:
1332         if (id == CSSValueNone || id == CSSValueSolid || id == CSSValueDouble ||
1333             id == CSSValueDashed || id == CSSValueDotDash || id == CSSValueDotDotDash ||
1334             id == CSSValueWave)
1335             valid_primitive = true;
1336         break;
1337     case CSSPropertyTextLineThroughWidth:
1338     case CSSPropertyTextOverlineWidth:
1339     case CSSPropertyTextUnderlineWidth:
1340         if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
1341             id == CSSValueMedium || id == CSSValueThick)
1342             valid_primitive = true;
1343         else
1344             valid_primitive = !id && validUnit(value, FNumber|FLength|FPercent, m_strict);
1345         break;
1346     case CSSPropertyResize: // none | both | horizontal | vertical | auto
1347         if (id == CSSValueNone || id == CSSValueBoth || id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
1348             valid_primitive = true;
1349         break;
1350     case CSSPropertyWebkitColumnCount:
1351         if (id == CSSValueAuto)
1352             valid_primitive = true;
1353         else
1354             valid_primitive = !id && validUnit(value, FInteger | FNonNeg, false);
1355         break;
1356     case CSSPropertyWebkitColumnGap:         // normal | <length>
1357         if (id == CSSValueNormal)
1358             valid_primitive = true;
1359         else
1360             valid_primitive = validUnit(value, FLength | FNonNeg, m_strict);
1361         break;
1362     case CSSPropertyWebkitColumnWidth:         // auto | <length>
1363         if (id == CSSValueAuto)
1364             valid_primitive = true;
1365         else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
1366             valid_primitive = validUnit(value, FLength, true);
1367         break;
1368     // End of CSS3 properties
1369
1370     // Apple specific properties.  These will never be standardized and are purely to
1371     // support custom WebKit-based Apple applications.
1372     case CSSPropertyWebkitLineClamp:
1373         valid_primitive = (!id && validUnit(value, FPercent, false));
1374         break;
1375     case CSSPropertyWebkitTextSizeAdjust:
1376         if (id == CSSValueAuto || id == CSSValueNone)
1377             valid_primitive = true;
1378         break;
1379     case CSSPropertyWebkitRtlOrdering:
1380         if (id == CSSValueLogical || id == CSSValueVisual)
1381             valid_primitive = true;
1382         break;
1383     
1384     case CSSPropertyWebkitFontSizeDelta:           // <length>
1385         valid_primitive = validUnit(value, FLength, m_strict);
1386         break;
1387
1388     case CSSPropertyWebkitNbspMode:     // normal | space
1389         if (id == CSSValueNormal || id == CSSValueSpace)
1390             valid_primitive = true;
1391         break;
1392
1393     case CSSPropertyWebkitLineBreak:   // normal | after-white-space
1394         if (id == CSSValueNormal || id == CSSValueAfterWhiteSpace)
1395             valid_primitive = true;
1396         break;
1397
1398     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:   // normal | match
1399         if (id == CSSValueNormal || id == CSSValueMatch)
1400             valid_primitive = true;
1401         break;
1402
1403     case CSSPropertyWebkitHighlight:
1404         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
1405             valid_primitive = true;
1406         break;
1407     
1408     case CSSPropertyWebkitBorderFit:
1409         if (id == CSSValueBorder || id == CSSValueLines)
1410             valid_primitive = true;
1411         break;
1412         
1413     case CSSPropertyWebkitTextSecurity:
1414         // disc | circle | square | none | inherit
1415         if (id == CSSValueDisc || id == CSSValueCircle || id == CSSValueSquare|| id == CSSValueNone)
1416             valid_primitive = true;
1417         break;
1418
1419 #if ENABLE(DASHBOARD_SUPPORT)
1420     case CSSPropertyWebkitDashboardRegion:                 // <dashboard-region> | <dashboard-region> 
1421         if (value->unit == Value::Function || id == CSSValueNone)
1422             return parseDashboardRegions(propId, important);
1423         break;
1424 #endif
1425     // End Apple-specific properties
1426
1427         /* shorthand properties */
1428     case CSSPropertyBackground: {
1429         // Position must come before color in this array because a plain old "0" is a legal color
1430         // in quirks mode but it's usually the X coordinate of a position.
1431         // FIXME: Add CSSPropertyWebkitBackgroundSize to the shorthand.
1432         const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat, 
1433                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyWebkitBackgroundClip,
1434                                    CSSPropertyWebkitBackgroundOrigin, CSSPropertyBackgroundColor };
1435         return parseFillShorthand(propId, properties, 7, important);
1436     }
1437     case CSSPropertyWebkitMask: {
1438         const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat, 
1439                                    CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition, CSSPropertyWebkitMaskClip,
1440                                    CSSPropertyWebkitMaskOrigin };
1441         return parseFillShorthand(propId, properties, 6, important);
1442     }
1443     case CSSPropertyBorder:
1444         // [ 'border-width' || 'border-style' || <color> ] | inherit
1445     {
1446         const int properties[3] = { CSSPropertyBorderWidth, CSSPropertyBorderStyle,
1447                                     CSSPropertyBorderColor };
1448         return parseShorthand(propId, properties, 3, important);
1449     }
1450     case CSSPropertyBorderTop:
1451         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
1452     {
1453         const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
1454                                     CSSPropertyBorderTopColor};
1455         return parseShorthand(propId, properties, 3, important);
1456     }
1457     case CSSPropertyBorderRight:
1458         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
1459     {
1460         const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
1461                                     CSSPropertyBorderRightColor };
1462         return parseShorthand(propId, properties, 3, important);
1463     }
1464     case CSSPropertyBorderBottom:
1465         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
1466     {
1467         const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
1468                                     CSSPropertyBorderBottomColor };
1469         return parseShorthand(propId, properties, 3, important);
1470     }
1471     case CSSPropertyBorderLeft:
1472         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
1473     {
1474         const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
1475                                     CSSPropertyBorderLeftColor };
1476         return parseShorthand(propId, properties, 3, important);
1477     }
1478     case CSSPropertyOutline:
1479         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
1480     {
1481         const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
1482                                     CSSPropertyOutlineColor };
1483         return parseShorthand(propId, properties, 3, important);
1484     }
1485     case CSSPropertyBorderColor:
1486         // <color>{1,4} | inherit
1487     {
1488         const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
1489                                     CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
1490         return parse4Values(propId, properties, important);
1491     }
1492     case CSSPropertyBorderWidth:
1493         // <border-width>{1,4} | inherit
1494     {
1495         const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
1496                                     CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
1497         return parse4Values(propId, properties, important);
1498     }
1499     case CSSPropertyBorderStyle:
1500         // <border-style>{1,4} | inherit
1501     {
1502         const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
1503                                     CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
1504         return parse4Values(propId, properties, important);
1505     }
1506     case CSSPropertyMargin:
1507         // <margin-width>{1,4} | inherit
1508     {
1509         const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
1510                                     CSSPropertyMarginBottom, CSSPropertyMarginLeft };
1511         return parse4Values(propId, properties, important);
1512     }
1513     case CSSPropertyPadding:
1514         // <padding-width>{1,4} | inherit
1515     {
1516         const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
1517                                     CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
1518         return parse4Values(propId, properties, important);
1519     }
1520     case CSSPropertyFont:
1521         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
1522         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
1523         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
1524             valid_primitive = true;
1525         else
1526             return parseFont(important);
1527         break;
1528     case CSSPropertyListStyle:
1529     {
1530         const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
1531                                     CSSPropertyListStyleImage };
1532         return parseShorthand(propId, properties, 3, important);
1533     }
1534     case CSSPropertyWebkitColumns: {
1535         const int properties[2] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
1536         return parseShorthand(propId, properties, 2, important);
1537     }
1538     case CSSPropertyWebkitColumnRule: {
1539         const int properties[3] = { CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnRuleStyle,
1540                                     CSSPropertyWebkitColumnRuleColor };
1541         return parseShorthand(propId, properties, 3, important);
1542     }
1543     case CSSPropertyWebkitTextStroke: {
1544         const int properties[2] = { CSSPropertyWebkitTextStrokeWidth, CSSPropertyWebkitTextStrokeColor };
1545         return parseShorthand(propId, properties, 2, important);
1546     }
1547     case CSSPropertyWebkitTransition:
1548         return parseTransitionShorthand(important);
1549     case CSSPropertyInvalid:
1550         return false;
1551     case CSSPropertyFontStretch:
1552     case CSSPropertyPage:
1553     case CSSPropertyTextLineThrough:
1554     case CSSPropertyTextOverline:
1555     case CSSPropertyTextUnderline:
1556         return false;
1557 #if ENABLE(SVG)
1558     default:
1559         return parseSVGValue(propId, important);
1560 #endif
1561     }
1562
1563     if (valid_primitive) {
1564         if (id != 0)
1565             parsedValue = CSSPrimitiveValue::createIdentifier(id);
1566         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
1567             parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
1568         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1569             parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
1570         else if (value->unit >= Value::Q_EMS)
1571             parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS);
1572         m_valueList->next();
1573     }
1574     if (parsedValue) {
1575         if (!m_valueList->current() || inShorthand()) {
1576             addProperty(propId, parsedValue.release(), important);
1577             return true;
1578         }
1579     }
1580     return false;
1581 }
1582
1583 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
1584 {
1585     if (lval) {
1586         if (lval->isValueList())
1587             static_cast<CSSValueList*>(lval.get())->append(rval);
1588         else {
1589             PassRefPtr<CSSValue> oldlVal(lval.release());
1590             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
1591             list->append(oldlVal);
1592             list->append(rval);
1593             lval = list;
1594         }
1595     }
1596     else
1597         lval = rval;
1598 }
1599
1600 const int cMaxFillProperties = 7;
1601
1602 bool CSSParser::parseFillShorthand(int propId, const int* properties, int numProperties, bool important)
1603 {
1604     ASSERT(numProperties <= cMaxFillProperties);
1605     if (numProperties > cMaxFillProperties)
1606         return false;
1607
1608     ShorthandScope scope(this, propId);
1609
1610     bool parsedProperty[cMaxFillProperties] = { false };
1611     RefPtr<CSSValue> values[cMaxFillProperties];
1612     RefPtr<CSSValue> positionYValue;
1613     int i;
1614
1615     while (m_valueList->current()) {
1616         Value* val = m_valueList->current();
1617         if (val->unit == Value::Operator && val->iValue == ',') {
1618             // We hit the end.  Fill in all remaining values with the initial value.
1619             m_valueList->next();
1620             for (i = 0; i < numProperties; ++i) {
1621                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
1622                     // Color is not allowed except as the last item in a list for backgrounds.
1623                     // Reject the entire property.
1624                     return false;
1625
1626                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
1627                     addFillValue(values[i], CSSInitialValue::createImplicit());
1628                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1629                         addFillValue(positionYValue, CSSInitialValue::createImplicit());
1630                 }
1631                 parsedProperty[i] = false;
1632             }
1633             if (!m_valueList->current())
1634                 break;
1635         }
1636         
1637         bool found = false;
1638         for (i = 0; !found && i < numProperties; ++i) {
1639             if (!parsedProperty[i]) {
1640                 RefPtr<CSSValue> val1;
1641                 RefPtr<CSSValue> val2;
1642                 int propId1, propId2;
1643                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
1644                     parsedProperty[i] = found = true;
1645                     addFillValue(values[i], val1.release());
1646                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1647                         addFillValue(positionYValue, val2.release());
1648                 }
1649             }
1650         }
1651
1652         // if we didn't find at least one match, this is an
1653         // invalid shorthand and we have to ignore it
1654         if (!found)
1655             return false;
1656     }
1657     
1658     // Fill in any remaining properties with the initial value.
1659     for (i = 0; i < numProperties; ++i) {
1660         if (!parsedProperty[i]) {
1661             addFillValue(values[i], CSSInitialValue::createImplicit());
1662             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
1663                 addFillValue(positionYValue, CSSInitialValue::createImplicit());
1664         }
1665     }
1666     
1667     // Now add all of the properties we found.
1668     for (i = 0; i < numProperties; i++) {
1669         if (properties[i] == CSSPropertyBackgroundPosition) {
1670             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
1671             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
1672             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
1673         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
1674             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
1675             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
1676             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
1677         } else
1678             addProperty(properties[i], values[i].release(), important);
1679     }
1680     
1681     return true;
1682 }
1683
1684 void CSSParser::addTransitionValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
1685 {
1686     if (lval) {
1687         if (lval->isValueList())
1688             static_cast<CSSValueList*>(lval.get())->append(rval);
1689         else {
1690             PassRefPtr<CSSValue> oldVal(lval.release());
1691             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
1692             list->append(oldVal);
1693             list->append(rval);
1694             lval = list;
1695         }
1696     }
1697     else
1698         lval = rval;
1699 }
1700
1701 bool CSSParser::parseTransitionShorthand(bool important)
1702 {
1703     const int properties[] = { CSSPropertyWebkitTransitionProperty, CSSPropertyWebkitTransitionDuration, 
1704                                CSSPropertyWebkitTransitionTimingFunction, CSSPropertyWebkitTransitionRepeatCount };
1705     const int numProperties = sizeof(properties) / sizeof(properties[0]);
1706     
1707     ShorthandScope scope(this, CSSPropertyWebkitTransition);
1708
1709     bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
1710     RefPtr<CSSValue> values[numProperties];
1711     
1712     int i;
1713     while (m_valueList->current()) {
1714         Value* val = m_valueList->current();
1715         if (val->unit == Value::Operator && val->iValue == ',') {
1716             // We hit the end.  Fill in all remaining values with the initial value.
1717             m_valueList->next();
1718             for (i = 0; i < numProperties; ++i) {
1719                 if (!parsedProperty[i])
1720                     addTransitionValue(values[i], CSSInitialValue::createImplicit());
1721                 parsedProperty[i] = false;
1722             }
1723             if (!m_valueList->current())
1724                 break;
1725         }
1726         
1727         bool found = false;
1728         for (i = 0; !found && i < numProperties; ++i) {
1729             if (!parsedProperty[i]) {
1730                 RefPtr<CSSValue> val;
1731                 if (parseTransitionProperty(properties[i], val)) {
1732                     parsedProperty[i] = found = true;
1733                     addTransitionValue(values[i], val.release());
1734                 }
1735             }
1736         }
1737
1738         // if we didn't find at least one match, this is an
1739         // invalid shorthand and we have to ignore it
1740         if (!found)
1741             return false;
1742     }
1743     
1744     // Fill in any remaining properties with the initial value.
1745     for (i = 0; i < numProperties; ++i) {
1746         if (!parsedProperty[i])
1747             addTransitionValue(values[i], CSSInitialValue::createImplicit());
1748     }
1749     
1750     // Now add all of the properties we found.
1751     for (i = 0; i < numProperties; i++)
1752         addProperty(properties[i], values[i].release(), important);
1753     
1754     return true;
1755 }
1756
1757 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
1758 {
1759     // We try to match as many properties as possible
1760     // We set up an array of booleans to mark which property has been found,
1761     // and we try to search for properties until it makes no longer any sense.
1762     ShorthandScope scope(this, propId);
1763
1764     bool found = false;
1765     bool fnd[6]; // Trust me ;)
1766     for (int i = 0; i < numProperties; i++)
1767         fnd[i] = false;
1768
1769     while (m_valueList->current()) {
1770         found = false;
1771         for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
1772             if (!fnd[propIndex]) {
1773                 if (parseValue(properties[propIndex], important))
1774                     fnd[propIndex] = found = true;
1775             }
1776         }
1777
1778         // if we didn't find at least one match, this is an
1779         // invalid shorthand and we have to ignore it
1780         if (!found)
1781             return false;
1782     }
1783     
1784     // Fill in any remaining properties with the initial value.
1785     m_implicitShorthand = true;
1786     for (int i = 0; i < numProperties; ++i) {
1787         if (!fnd[i])
1788             addProperty(properties[i], CSSInitialValue::createImplicit(), important);
1789     }
1790     m_implicitShorthand = false;
1791
1792     return true;
1793 }
1794
1795 bool CSSParser::parse4Values(int propId, const int *properties,  bool important)
1796 {
1797     /* From the CSS 2 specs, 8.3
1798      * If there is only one value, it applies to all sides. If there are two values, the top and
1799      * bottom margins are set to the first value and the right and left margins are set to the second.
1800      * If there are three values, the top is set to the first value, the left and right are set to the
1801      * second, and the bottom is set to the third. If there are four values, they apply to the top,
1802      * right, bottom, and left, respectively.
1803      */
1804     
1805     int num = inShorthand() ? 1 : m_valueList->size();
1806     
1807     ShorthandScope scope(this, propId);
1808
1809     // the order is top, right, bottom, left
1810     switch (num) {
1811         case 1: {
1812             if (!parseValue(properties[0], important))
1813                 return false;
1814             CSSValue *value = m_parsedProperties[m_numParsedProperties-1]->value();
1815             m_implicitShorthand = true;
1816             addProperty(properties[1], value, important);
1817             addProperty(properties[2], value, important);
1818             addProperty(properties[3], value, important);
1819             m_implicitShorthand = false;
1820             break;
1821         }
1822         case 2: {
1823             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1824                 return false;
1825             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
1826             m_implicitShorthand = true;
1827             addProperty(properties[2], value, important);
1828             value = m_parsedProperties[m_numParsedProperties-2]->value();
1829             addProperty(properties[3], value, important);
1830             m_implicitShorthand = false;
1831             break;
1832         }
1833         case 3: {
1834             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
1835                 return false;
1836             CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
1837             m_implicitShorthand = true;
1838             addProperty(properties[3], value, important);
1839             m_implicitShorthand = false;
1840             break;
1841         }
1842         case 4: {
1843             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
1844                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
1845                 return false;
1846             break;
1847         }
1848         default: {
1849             return false;
1850         }
1851     }
1852     
1853     return true;
1854 }
1855
1856 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
1857 // in CSS 2.1 this got somewhat reduced:
1858 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
1859 bool CSSParser::parseContent(int propId, bool important)
1860 {
1861     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
1862
1863     while (Value* val = m_valueList->current()) {
1864         RefPtr<CSSValue> parsedValue;
1865         if (val->unit == CSSPrimitiveValue::CSS_URI) {
1866             // url
1867             String value = parseURL(val->string);
1868             parsedValue = CSSImageValue::create(KURL(m_styleSheet->baseURL(), value).string());
1869         } else if (val->unit == Value::Function) {
1870             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
1871             ValueList* args = val->function->args;
1872             if (!args)
1873                 return false;
1874             if (equalIgnoringCase(val->function->name, "attr(")) {
1875                 if (args->size() != 1)
1876                     return false;
1877                 Value* a = args->current();
1878                 String attrName = a->string;
1879                 if (document()->isHTMLDocument())
1880                     attrName = attrName.lower();
1881                 parsedValue = CSSPrimitiveValue::create(attrName, CSSPrimitiveValue::CSS_ATTR);
1882             } else if (equalIgnoringCase(val->function->name, "counter(")) {
1883                 parsedValue = parseCounterContent(args, false);
1884                 if (!parsedValue) return false;
1885             } else if (equalIgnoringCase(val->function->name, "counters(")) {
1886                 parsedValue = parseCounterContent(args, true);
1887                 if (!parsedValue)
1888                     return false;
1889             } else if (equalIgnoringCase(val->function->name, "-webkit-gradient(")) {
1890                 if (!parseGradient(parsedValue))
1891                     return false;
1892             } else if (equalIgnoringCase(val->function->name, "-webkit-canvas(")) {
1893                 if (!parseCanvas(parsedValue))
1894                     return false;
1895             } else
1896                 return false;
1897         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
1898             // open-quote
1899             // close-quote
1900             // no-open-quote
1901             // no-close-quote
1902             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
1903         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
1904             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
1905         }
1906         if (!parsedValue)
1907             break;
1908         values->append(parsedValue.release());
1909         m_valueList->next();
1910     }
1911
1912     if (values->length()) {
1913         addProperty(propId, values.release(), important);
1914         m_valueList->next();
1915         return true;
1916     }
1917
1918     return false;
1919 }
1920
1921 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
1922 {
1923     int id = m_valueList->current()->id;
1924     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
1925         (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict))
1926        return CSSPrimitiveValue::createIdentifier(id);
1927     return parseColor();
1928 }
1929
1930 bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
1931 {
1932     if (m_valueList->current()->id == CSSValueNone) {
1933         value = CSSImageValue::create();
1934         return true;
1935     }
1936     if (m_valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
1937         String uri = parseURL(m_valueList->current()->string);
1938         if (!uri.isNull())
1939             value = CSSImageValue::create(KURL(m_styleSheet->baseURL(), uri).string());
1940         return true;
1941     }
1942     if (m_valueList->current()->unit == Value::Function) {
1943         if (equalIgnoringCase(m_valueList->current()->function->name, "-webkit-gradient("))
1944             return parseGradient(value);
1945         if (equalIgnoringCase(m_valueList->current()->function->name, "-webkit-canvas("))
1946             return parseCanvas(value);
1947     }
1948     return false;
1949 }
1950
1951 PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(bool& xFound, bool& yFound)
1952 {
1953     int id = m_valueList->current()->id;
1954     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
1955         int percent = 0;
1956         if (id == CSSValueLeft || id == CSSValueRight) {
1957             if (xFound)
1958                 return 0;
1959             xFound = true;
1960             if (id == CSSValueRight)
1961                 percent = 100;
1962         }
1963         else if (id == CSSValueTop || id == CSSValueBottom) {
1964             if (yFound)
1965                 return 0;
1966             yFound = true;
1967             if (id == CSSValueBottom)
1968                 percent = 100;
1969         }
1970         else if (id == CSSValueCenter)
1971             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
1972             percent = 50;
1973         return CSSPrimitiveValue::create(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
1974     }
1975     if (validUnit(m_valueList->current(), FPercent|FLength, m_strict))
1976         return CSSPrimitiveValue::create(m_valueList->current()->fValue,
1977                                          (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
1978                 
1979     return 0;
1980 }
1981
1982 void CSSParser::parseFillPosition(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
1983 {
1984     Value* value = m_valueList->current();
1985     
1986     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
1987     bool value1IsX = false, value1IsY = false;
1988     value1 = parseFillPositionXY(value1IsX, value1IsY);
1989     if (!value1)
1990         return;
1991     
1992     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
1993     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
1994     // value was explicitly specified for our property.
1995     value = m_valueList->next();
1996     
1997     // First check for the comma.  If so, we are finished parsing this value or value pair.
1998     if (value && value->unit == Value::Operator && value->iValue == ',')
1999         value = 0;
2000     
2001     bool value2IsX = false, value2IsY = false;
2002     if (value) {
2003         value2 = parseFillPositionXY(value2IsX, value2IsY);
2004         if (value2)
2005             m_valueList->next();
2006         else {
2007             if (!inShorthand()) {
2008                 value1.clear();
2009                 return;
2010             }
2011         }
2012     }
2013     
2014     if (!value2)
2015         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
2016         // is simply 50%.  This is our default.
2017         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
2018         // For left/right/center, the default of 50% in the y is still correct.
2019         value2 = CSSPrimitiveValue::create(50, CSSPrimitiveValue::CSS_PERCENTAGE);
2020
2021     if (value1IsY || value2IsX)
2022         value1.swap(value2);
2023 }
2024
2025 PassRefPtr<CSSValue> CSSParser::parseFillSize()
2026 {
2027     Value* value = m_valueList->current();
2028     RefPtr<CSSPrimitiveValue> parsedValue1;
2029     
2030     if (value->id == CSSValueAuto)
2031         parsedValue1 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN);
2032     else {
2033         if (!validUnit(value, FLength|FPercent, m_strict))
2034             return 0;
2035         parsedValue1 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2036     }
2037     
2038     RefPtr<CSSPrimitiveValue> parsedValue2 = parsedValue1;
2039     if ((value = m_valueList->next())) {
2040         if (value->id == CSSValueAuto)
2041             parsedValue2 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN);
2042         else {
2043             if (!validUnit(value, FLength|FPercent, m_strict))
2044                 return 0;
2045             parsedValue2 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2046         }
2047     }
2048     
2049     return CSSPrimitiveValue::create(Pair::create(parsedValue1.release(), parsedValue2.release()));
2050 }
2051
2052 bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, 
2053                                   RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
2054 {
2055     RefPtr<CSSValueList> values;
2056     RefPtr<CSSValueList> values2;
2057     Value* val;
2058     RefPtr<CSSValue> value;
2059     RefPtr<CSSValue> value2;
2060     
2061     bool allowComma = false;
2062     
2063     retValue1 = retValue2 = 0;
2064     propId1 = propId;
2065     propId2 = propId;
2066     if (propId == CSSPropertyBackgroundPosition) {
2067         propId1 = CSSPropertyBackgroundPositionX;
2068         propId2 = CSSPropertyBackgroundPositionY;
2069     } else if (propId == CSSPropertyWebkitMaskPosition) {
2070         propId1 = CSSPropertyWebkitMaskPositionX;
2071         propId2 = CSSPropertyWebkitMaskPositionY;
2072     }
2073
2074     while ((val = m_valueList->current())) {
2075         RefPtr<CSSValue> currValue;
2076         RefPtr<CSSValue> currValue2;
2077         
2078         if (allowComma) {
2079             if (val->unit != Value::Operator || val->iValue != ',')
2080                 return false;
2081             m_valueList->next();
2082             allowComma = false;
2083         } else {
2084             switch (propId) {
2085                 case CSSPropertyBackgroundColor:
2086                     currValue = parseBackgroundColor();
2087                     if (currValue)
2088                         m_valueList->next();
2089                     break;
2090                 case CSSPropertyBackgroundAttachment:
2091                 case CSSPropertyWebkitMaskAttachment:
2092                     if (val->id == CSSValueScroll || val->id == CSSValueFixed) {
2093                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2094                         m_valueList->next();
2095                     }
2096                     break;
2097                 case CSSPropertyBackgroundImage:
2098                 case CSSPropertyWebkitMaskImage:
2099                     if (parseFillImage(currValue))
2100                         m_valueList->next();
2101                     break;
2102                 case CSSPropertyWebkitBackgroundClip:
2103                 case CSSPropertyWebkitBackgroundOrigin:
2104                 case CSSPropertyWebkitMaskClip:
2105                 case CSSPropertyWebkitMaskOrigin:
2106                     if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent || val->id == CSSValueText) {
2107                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2108                         m_valueList->next();
2109                     }
2110                     break;
2111                 case CSSPropertyBackgroundPosition:
2112                 case CSSPropertyWebkitMaskPosition:
2113                     parseFillPosition(currValue, currValue2);
2114                     // unlike the other functions, parseFillPosition advances the m_valueList pointer
2115                     break;
2116                 case CSSPropertyBackgroundPositionX:
2117                 case CSSPropertyWebkitMaskPositionX: {
2118                     bool xFound = false, yFound = true;
2119                     currValue = parseFillPositionXY(xFound, yFound);
2120                     if (currValue)
2121                         m_valueList->next();
2122                     break;
2123                 }
2124                 case CSSPropertyBackgroundPositionY:
2125                 case CSSPropertyWebkitMaskPositionY: {
2126                     bool xFound = true, yFound = false;
2127                     currValue = parseFillPositionXY(xFound, yFound);
2128                     if (currValue)
2129                         m_valueList->next();
2130                     break;
2131                 }
2132                 case CSSPropertyWebkitBackgroundComposite:
2133                 case CSSPropertyWebkitMaskComposite:
2134                     if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) {
2135                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2136                         m_valueList->next();
2137                     }
2138                     break;
2139                 case CSSPropertyBackgroundRepeat:
2140                 case CSSPropertyWebkitMaskRepeat:
2141                     if (val->id >= CSSValueRepeat && val->id <= CSSValueNoRepeat) {
2142                         currValue = CSSPrimitiveValue::createIdentifier(val->id);
2143                         m_valueList->next();
2144                     }
2145                     break;
2146                 case CSSPropertyWebkitBackgroundSize:
2147                 case CSSPropertyWebkitMaskSize:
2148                     currValue = parseFillSize();
2149                     if (currValue)
2150                         m_valueList->next();
2151                     break;
2152             }
2153             if (!currValue)
2154                 return false;
2155             
2156             if (value && !values) {
2157                 values = CSSValueList::createCommaSeparated();
2158                 values->append(value.release());
2159             }
2160             
2161             if (value2 && !values2) {
2162                 values2 = CSSValueList::createCommaSeparated();
2163                 values2->append(value2.release());
2164             }
2165             
2166             if (values)
2167                 values->append(currValue.release());
2168             else
2169                 value = currValue.release();
2170             if (currValue2) {
2171                 if (values2)
2172                     values2->append(currValue2.release());
2173                 else
2174                     value2 = currValue2.release();
2175             }
2176             allowComma = true;
2177         }
2178         
2179         // When parsing any fill shorthand property, we let it handle building up the lists for all
2180         // properties.
2181         if (inShorthand())
2182             break;
2183     }
2184
2185     if (values && values->length()) {
2186         retValue1 = values.release();
2187         if (values2 && values2->length())
2188             retValue2 = values2.release();
2189         return true;
2190     }
2191     if (value) {
2192         retValue1 = value.release();
2193         retValue2 = value2.release();
2194         return true;
2195     }
2196     return false;
2197 }
2198
2199 PassRefPtr<CSSValue> CSSParser::parseTransitionDuration()
2200 {
2201     Value* value = m_valueList->current();
2202     if (validUnit(value, FTime, m_strict))
2203         return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2204     return 0;
2205 }
2206
2207 PassRefPtr<CSSValue> CSSParser::parseTransitionRepeatCount()
2208 {
2209     Value* value = m_valueList->current();
2210     if (value->id == CSSValueInfinite)
2211         return CSSPrimitiveValue::createIdentifier(value->id);
2212     if (validUnit(value, FInteger|FNonNeg, m_strict))
2213         return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
2214     return 0;
2215 }
2216
2217 bool CSSParser::parseTimingFunctionValue(ValueList*& args, double& result)
2218 {
2219     Value* v = args->current();
2220     if (!validUnit(v, FNumber, m_strict))
2221         return false;
2222     result = v->fValue;
2223     if (result < 0 || result > 1.0)
2224         return false;
2225     v = args->next();
2226     if (!v)
2227         // The last number in the function has no comma after it, so we're done.
2228         return true;
2229     if (v->unit != Value::Operator && v->iValue != ',')
2230         return false;
2231     v = args->next();
2232     return true;
2233 }
2234
2235 PassRefPtr<CSSValue> CSSParser::parseTransitionTimingFunction()
2236 {
2237     Value* value = m_valueList->current();
2238     if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut || value->id == CSSValueEaseInOut)
2239         return CSSPrimitiveValue::createIdentifier(value->id);
2240     
2241     // We must be a function.
2242     if (value->unit != Value::Function)
2243         return 0;
2244     
2245     // The only timing function we accept for now is a cubic bezier function.  4 points must be specified.
2246     ValueList* args = value->function->args;
2247     if (!equalIgnoringCase(value->function->name, "cubic-bezier(") || !args || args->size() != 7)
2248         return 0;
2249
2250     // There are two points specified.  The values must be between 0 and 1.
2251     double x1, y1, x2, y2;
2252
2253     if (!parseTimingFunctionValue(args, x1))
2254         return 0;
2255     if (!parseTimingFunctionValue(args, y1))
2256         return 0;
2257     if (!parseTimingFunctionValue(args, x2))
2258         return 0;
2259     if (!parseTimingFunctionValue(args, y2))
2260         return 0;
2261
2262     return CSSTimingFunctionValue::create(x1, y1, x2, y2);
2263 }
2264
2265 PassRefPtr<CSSValue> CSSParser::parseTransitionProperty()
2266 {
2267     Value* value = m_valueList->current();
2268     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
2269         return 0;
2270     int result = cssPropertyID(value->string);
2271     if (result)
2272         return CSSPrimitiveValue::createIdentifier(result);
2273     if (equalIgnoringCase(value->string, "all"))
2274         return CSSPrimitiveValue::createIdentifier(cAnimateAll); // FIXME: Why not use CSSValueAll instead?
2275     if (equalIgnoringCase(value->string, "none"))
2276         return CSSPrimitiveValue::createIdentifier(cAnimateNone); // FIXME: Why not use CSSValueNone instead?
2277     return 0;
2278 }
2279
2280 bool CSSParser::parseTransitionProperty(int propId, RefPtr<CSSValue>& result)
2281 {
2282     RefPtr<CSSValueList> values;
2283     Value* val;
2284     RefPtr<CSSValue> value;
2285     bool allowComma = false;
2286     
2287     result = 0;
2288
2289     while ((val = m_valueList->current())) {
2290         RefPtr<CSSValue> currValue;
2291         if (allowComma) {
2292             if (val->unit != Value::Operator || val->iValue != ',')
2293                 return false;
2294             m_valueList->next();
2295             allowComma = false;
2296         }
2297         else {
2298             switch (propId) {
2299                 case CSSPropertyWebkitTransitionDuration:
2300                     currValue = parseTransitionDuration();
2301                     if (currValue)
2302                         m_valueList->next();
2303                     break;
2304                 case CSSPropertyWebkitTransitionRepeatCount:
2305                     currValue = parseTransitionRepeatCount();
2306                     if (currValue)
2307                         m_valueList->next();
2308                     break;
2309                 case CSSPropertyWebkitTransitionTimingFunction:
2310                     currValue = parseTransitionTimingFunction();
2311                     if (currValue)
2312                         m_valueList->next();
2313                     break;
2314                 case CSSPropertyWebkitTransitionProperty:
2315                     currValue = parseTransitionProperty();
2316                     if (currValue)
2317                         m_valueList->next();
2318                     break;
2319             }
2320             
2321             if (!currValue)
2322                 return false;
2323             
2324             if (value && !values) {
2325                 values = CSSValueList::createCommaSeparated();
2326                 values->append(value.release());
2327             }
2328             
2329             if (values)
2330                 values->append(currValue.release());
2331             else
2332                 value = currValue.release();
2333             
2334             allowComma = true;
2335         }
2336         
2337         // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
2338         // properties.
2339         if (inShorthand())
2340             break;
2341     }
2342     
2343     if (values && values->length()) {
2344         result = values.release();
2345         return true;
2346     }
2347     if (value) {
2348         result = value.release();
2349         return true;
2350     }
2351     return false;
2352 }
2353
2354 #if ENABLE(DASHBOARD_SUPPORT)
2355
2356 #define DASHBOARD_REGION_NUM_PARAMETERS  6
2357 #define DASHBOARD_REGION_SHORT_NUM_PARAMETERS  2
2358
2359 static Value *skipCommaInDashboardRegion (ValueList *args)
2360 {
2361     if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
2362          args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
2363         Value *current = args->current();
2364         if (current->unit == Value::Operator && current->iValue == ',')
2365             return args->next();
2366     }
2367     return args->current();
2368 }
2369
2370 bool CSSParser::parseDashboardRegions(int propId, bool important)
2371 {
2372     bool valid = true;
2373     
2374     Value *value = m_valueList->current();
2375
2376     if (value->id == CSSValueNone) {
2377         if (m_valueList->next())
2378             return false;
2379         addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important);
2380         return valid;
2381     }
2382         
2383     RefPtr<DashboardRegion> firstRegion = DashboardRegion::create();
2384     DashboardRegion* region = 0;
2385
2386     while (value) {
2387         if (region == 0) {
2388             region = firstRegion.get();
2389         } else {
2390             RefPtr<DashboardRegion> nextRegion = DashboardRegion::create();
2391             region->m_next = nextRegion;
2392             region = nextRegion.get();
2393         }
2394         
2395         if (value->unit != Value::Function) {
2396             valid = false;
2397             break;
2398         }
2399             
2400         // Commas count as values, so allow:
2401         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
2402         // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
2403         // also allow
2404         // dashboard-region(label, type) or dashboard-region(label type)
2405         // dashboard-region(label, type) or dashboard-region(label type)
2406         ValueList* args = value->function->args;
2407         if (!equalIgnoringCase(value->function->name, "dashboard-region(") || !args) {
2408             valid = false;
2409             break;
2410         }
2411         
2412         int numArgs = args->size();
2413         if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
2414             (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))){
2415             valid = false;
2416             break;
2417         }
2418             
2419         // First arg is a label.
2420         Value* arg = args->current();
2421         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
2422             valid = false;
2423             break;
2424         }
2425             
2426         region->m_label = arg->string;
2427
2428         // Second arg is a type.
2429         arg = args->next();
2430         arg = skipCommaInDashboardRegion (args);
2431         if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
2432             valid = false;
2433             break;
2434         }
2435
2436         if (equalIgnoringCase(arg->string, "circle"))
2437             region->m_isCircle = true;
2438         else if (equalIgnoringCase(arg->string, "rectangle"))
2439             region->m_isRectangle = true;
2440         else {
2441             valid = false;
2442             break;
2443         }
2444             
2445         region->m_geometryType = arg->string;
2446
2447         if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
2448             // This originally used CSSValueInvalid by accident. It might be more logical to use something else.
2449             RefPtr<CSSPrimitiveValue> amount = CSSPrimitiveValue::createIdentifier(CSSValueInvalid);
2450                 
2451             region->setTop(amount);
2452             region->setRight(amount);
2453             region->setBottom(amount);
2454             region->setLeft(amount);
2455         } else {
2456             // Next four arguments must be offset numbers
2457             int i;
2458             for (i = 0; i < 4; i++) {
2459                 arg = args->next();
2460                 arg = skipCommaInDashboardRegion (args);
2461
2462                 valid = arg->id == CSSValueAuto || validUnit(arg, FLength, m_strict);
2463                 if (!valid)
2464                     break;
2465                     
2466                 RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ?
2467                     CSSPrimitiveValue::createIdentifier(CSSValueAuto) :
2468                     CSSPrimitiveValue::create(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit);
2469                     
2470                 if (i == 0)
2471                     region->setTop(amount);
2472                 else if (i == 1)
2473                     region->setRight(amount);
2474                 else if (i == 2)
2475                     region->setBottom(amount);
2476                 else
2477                     region->setLeft(amount);
2478             }
2479         }
2480
2481         if (args->next())
2482             return false;
2483
2484         value = m_valueList->next();
2485     }
2486
2487     if (valid)
2488         addProperty(propId, CSSPrimitiveValue::create(firstRegion.release()), important);
2489         
2490     return valid;
2491 }
2492
2493 #endif /* ENABLE(DASHBOARD_SUPPORT) */
2494
2495 PassRefPtr<CSSValue> CSSParser::parseCounterContent(ValueList* args, bool counters)
2496 {
2497     unsigned numArgs = args->size();
2498     if (counters && numArgs != 3 && numArgs != 5)
2499         return 0;
2500     if (!counters && numArgs != 1 && numArgs != 3)
2501         return 0;
2502     
2503     Value* i = args->current();
2504     RefPtr<CSSPrimitiveValue> identifier = CSSPrimitiveValue::create(i->string, CSSPrimitiveValue::CSS_STRING);
2505
2506     RefPtr<CSSPrimitiveValue> separator;
2507     if (!counters)
2508         separator = CSSPrimitiveValue::create(String(), CSSPrimitiveValue::CSS_STRING);
2509     else {
2510         i = args->next();
2511         if (i->unit != Value::Operator || i->iValue != ',')
2512             return 0;
2513         
2514         i = args->next();
2515         if (i->unit != CSSPrimitiveValue::CSS_STRING)
2516             return 0;
2517         
2518         separator = CSSPrimitiveValue::create(i->string, (CSSPrimitiveValue::UnitTypes) i->unit);
2519     }
2520
2521     RefPtr<CSSPrimitiveValue> listStyle;
2522     i = args->next();
2523     if (!i) // Make the list style default decimal
2524         listStyle = CSSPrimitiveValue::create(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER);
2525     else {
2526         if (i->unit != Value::Operator || i->iValue != ',')
2527             return 0;
2528         
2529         i = args->next();
2530         if (i->unit != CSSPrimitiveValue::CSS_IDENT)
2531             return 0;
2532         
2533         short ls = 0;
2534         if (i->id == CSSValueNone)
2535             ls = CSSValueKatakanaIroha - CSSValueDisc + 1;
2536         else if (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha)
2537             ls = i->id - CSSValueDisc;
2538         else
2539             return 0;
2540
2541         listStyle = CSSPrimitiveValue::create(ls, (CSSPrimitiveValue::UnitTypes) i->unit);
2542     }
2543
2544     return CSSPrimitiveValue::create(Counter::create(identifier.release(), listStyle.release(), separator.release()));
2545 }
2546
2547 bool CSSParser::parseShape(int propId, bool important)
2548 {
2549     Value* value = m_valueList->current();
2550     ValueList* args = value->function->args;
2551     if (!equalIgnoringCase(value->function->name, "rect(") || !args)
2552         return false;
2553
2554     // rect(t, r, b, l) || rect(t r b l)
2555     if (args->size() != 4 && args->size() != 7)
2556         return false;
2557     RefPtr<Rect> rect = Rect::create();
2558     bool valid = true;
2559     int i = 0;
2560     Value *a = args->current();
2561     while (a) {
2562         valid = a->id == CSSValueAuto || validUnit(a, FLength, m_strict);
2563         if (!valid)
2564             break;
2565         RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ?
2566             CSSPrimitiveValue::createIdentifier(CSSValueAuto) :
2567             CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
2568         if (i == 0)
2569             rect->setTop(length);
2570         else if (i == 1)
2571             rect->setRight(length);
2572         else if (i == 2)
2573             rect->setBottom(length);
2574         else
2575             rect->setLeft(length);
2576         a = args->next();
2577         if (a && args->size() == 7) {
2578             if (a->unit == Value::Operator && a->iValue == ',') {
2579                 a = args->next();
2580             } else {
2581                 valid = false;
2582                 break;
2583             }
2584         }
2585         i++;
2586     }
2587     if (valid) {
2588         addProperty(propId, CSSPrimitiveValue::create(rect.release()), important);
2589         m_valueList->next();
2590         return true;
2591     }
2592     return false;
2593 }
2594
2595 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
2596 bool CSSParser::parseFont(bool important)
2597 {
2598     bool valid = true;
2599     Value *value = m_valueList->current();
2600     RefPtr<FontValue> font = FontValue::create();
2601     // optional font-style, font-variant and font-weight
2602     while (value) {
2603         int id = value->id;
2604         if (id) {
2605             if (id == CSSValueNormal) {
2606                 // do nothing, it's the inital value for all three
2607             } else if (id == CSSValueItalic || id == CSSValueOblique) {
2608                 if (font->style)
2609                     return false;
2610                 font->style = CSSPrimitiveValue::createIdentifier(id);
2611             } else if (id == CSSValueSmallCaps) {
2612                 if (font->variant)
2613                     return false;
2614                 font->variant = CSSPrimitiveValue::createIdentifier(id);
2615             } else if (id >= CSSValueBold && id <= CSSValueLighter) {
2616                 if (font->weight)
2617                     return false;
2618                 font->weight = CSSPrimitiveValue::createIdentifier(id);
2619             } else {
2620                 valid = false;
2621             }
2622         } else if (!font->weight && validUnit(value, FInteger|FNonNeg, true)) {
2623             int weight = (int)value->fValue;
2624             int val = 0;
2625             if (weight == 100)
2626                 val = CSSValue100;
2627             else if (weight == 200)
2628                 val = CSSValue200;
2629             else if (weight == 300)
2630                 val = CSSValue300;
2631             else if (weight == 400)
2632                 val = CSSValue400;
2633             else if (weight == 500)
2634                 val = CSSValue500;
2635             else if (weight == 600)
2636                 val = CSSValue600;
2637             else if (weight == 700)
2638                 val = CSSValue700;
2639             else if (weight == 800)
2640                 val = CSSValue800;
2641             else if (weight == 900)
2642                 val = CSSValue900;
2643
2644             if (val)
2645                 font->weight = CSSPrimitiveValue::createIdentifier(val);
2646             else
2647                 valid = false;
2648         } else {
2649             valid = false;
2650         }
2651         if (!valid)
2652             break;
2653         value = m_valueList->next();
2654     }
2655     if (!value)
2656         return false;
2657
2658     // set undefined values to default
2659     if (!font->style)
2660         font->style = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2661     if (!font->variant)
2662         font->variant = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2663     if (!font->weight)
2664         font->weight = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2665
2666     // now a font size _must_ come
2667     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
2668     if (value->id >= CSSValueXxSmall && value->id <= CSSValueLarger)
2669         font->size = CSSPrimitiveValue::createIdentifier(value->id);
2670     else if (validUnit(value, FLength|FPercent|FNonNeg, m_strict))
2671         font->size = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2672     value = m_valueList->next();
2673     if (!font->size || !value)
2674         return false;
2675
2676     if (value->unit == Value::Operator && value->iValue == '/') {
2677         // line-height
2678         value = m_valueList->next();
2679         if (!value)
2680             return false;
2681         if (value->id == CSSValueNormal) {
2682             // default value, nothing to do
2683         } else if (validUnit(value, FNumber|FLength|FPercent|FNonNeg, m_strict))
2684             font->lineHeight = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2685         else
2686             return false;
2687         value = m_valueList->next();
2688         if (!value)
2689             return false;
2690     }
2691     
2692     if (!font->lineHeight)
2693         font->lineHeight = CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2694
2695     // font family must come now
2696     font->family = parseFontFamily();
2697
2698     if (m_valueList->current() || !font->family)
2699         return false;
2700
2701     addProperty(CSSPropertyFont, font.release(), important);
2702     return true;
2703 }
2704
2705 PassRefPtr<CSSValueList> CSSParser::parseFontFamily()
2706 {
2707     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2708     Value* value = m_valueList->current();
2709     FontFamilyValue* currFamily = 0;
2710     while (value) {
2711         Value* nextValue = m_valueList->next();
2712         bool nextValBreaksFont = !nextValue ||
2713                                  (nextValue->unit == Value::Operator && nextValue->iValue == ',');
2714         bool nextValIsFontName = nextValue &&
2715             ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) ||
2716             (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
2717
2718         if (value->id >= CSSValueSerif && value->id <= CSSValueWebkitBody) {
2719             if (currFamily)
2720                 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
2721             else if (nextValBreaksFont || !nextValIsFontName)
2722                 list->append(CSSPrimitiveValue::createIdentifier(value->id));
2723             else {
2724                 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
2725                 currFamily = newFamily.get();
2726                 list->append(newFamily.release());
2727             }
2728         } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
2729             // Strings never share in a family name.
2730             currFamily = 0;
2731             list->append(FontFamilyValue::create(value->string));
2732         } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2733             if (currFamily)
2734                 currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
2735             else if (nextValBreaksFont || !nextValIsFontName)
2736                 list->append(FontFamilyValue::create(value->string));
2737             else {
2738                 RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
2739                 currFamily = newFamily.get();
2740                 list->append(newFamily.release());
2741             }
2742         } else {
2743             break;
2744         }
2745         
2746         if (!nextValue)
2747             break;
2748
2749         if (nextValBreaksFont) {
2750             value = m_valueList->next();
2751             currFamily = 0;
2752         }
2753         else if (nextValIsFontName)
2754             value = nextValue;
2755         else
2756             break;
2757     }
2758     if (!list->length())
2759         list = 0;
2760     return list.release();
2761 }
2762
2763 bool CSSParser::parseFontFaceSrc()
2764 {
2765     RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
2766     Value* val;
2767     bool expectComma = false;
2768     bool allowFormat = false;
2769     bool failed = false;
2770     RefPtr<CSSFontFaceSrcValue> uriValue;
2771     while ((val = m_valueList->current())) {
2772         RefPtr<CSSFontFaceSrcValue> parsedValue;
2773         if (val->unit == CSSPrimitiveValue::CSS_URI && !expectComma) {
2774             String value = parseURL(val->string);
2775             parsedValue = CSSFontFaceSrcValue::create(KURL(m_styleSheet->baseURL(), value).string());
2776             uriValue = parsedValue;
2777             allowFormat = true;
2778             expectComma = true;
2779         } else if (val->unit == Value::Function) {
2780             // There are two allowed functions: local() and format().             
2781             ValueList* args = val->function->args;
2782             if (args && args->size() == 1) {
2783                 if (equalIgnoringCase(val->function->name, "local(") && !expectComma) {
2784                     expectComma = true;
2785                     allowFormat = false;
2786                     Value* a = args->current();
2787                     uriValue.clear();
2788                     parsedValue = CSSFontFaceSrcValue::createLocal(a->string);
2789                 } else if (equalIgnoringCase(val->function->name, "format(") && allowFormat && uriValue) {
2790                     expectComma = true;
2791                     allowFormat = false;
2792                     uriValue->setFormat(args->current()->string);
2793                     uriValue.clear();
2794                     m_valueList->next();
2795                     continue;
2796                 }
2797             }
2798         } else if (val->unit == Value::Operator && val->iValue == ',' && expectComma) {
2799             expectComma = false;
2800             allowFormat = false;
2801             uriValue.clear();
2802             m_valueList->next();
2803             continue;
2804         }
2805     
2806         if (parsedValue)
2807             values->append(parsedValue.release());
2808         else {
2809             failed = true;
2810             break;
2811         }
2812         m_valueList->next();
2813     }
2814     
2815     if (values->length() && !failed) {
2816         addProperty(CSSPropertySrc, values.release(), m_important);
2817         m_valueList->next();
2818         return true;
2819     }
2820
2821     return false;
2822 }
2823
2824 bool CSSParser::parseFontFaceUnicodeRange()
2825 {
2826     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
2827     Value* currentValue;
2828     bool failed = false;
2829     while ((currentValue = m_valueList->current())) {
2830         if (m_valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) {
2831             failed = true;
2832             break;
2833         }
2834
2835         String rangeString = m_valueList->current()->string;
2836         UChar32 from = 0;
2837         UChar32 to = 0;
2838         unsigned length = rangeString.length();
2839
2840         if (length < 3) {
2841             failed = true;
2842             break;
2843         }
2844
2845         unsigned i = 2;
2846         while (i < length) {
2847             UChar c = rangeString[i];
2848             if (c == '-' || c == '?')
2849                 break;
2850             from *= 16;
2851             if (c >= '0' && c <= '9')
2852                 from += c - '0';
2853             else if (c >= 'A' && c <= 'F')
2854                 from += 10 + c - 'A';
2855             else if (c >= 'a' && c <= 'f')
2856                 from += 10 + c - 'a';
2857             else {
2858                 failed = true;
2859                 break;
2860             }
2861             i++;
2862         }
2863         if (failed)
2864             break;
2865
2866         if (i == length)
2867             to = from;
2868         else if (rangeString[i] == '?') {
2869             unsigned span = 1;
2870             while (i < length && rangeString[i] == '?') {
2871                 span *= 16;
2872                 from *= 16;
2873                 i++;
2874             }
2875             if (i < length)
2876                 failed = true;
2877             to = from + span - 1;
2878         } else {
2879             if (length < i + 2) {
2880                 failed = true;
2881                 break;
2882             }
2883             i++;
2884             while (i < length) {
2885                 UChar c = rangeString[i];
2886                 to *= 16;
2887                 if (c >= '0' && c <= '9')
2888                     to += c - '0';
2889                 else if (c >= 'A' && c <= 'F')
2890                     to += 10 + c - 'A';
2891                 else if (c >= 'a' && c <= 'f')
2892                     to += 10 + c - 'a';
2893                 else {
2894                     failed = true;
2895                     break;
2896                 }
2897                 i++;
2898             }
2899             if (failed)
2900                 break;
2901         }
2902         values->append(CSSUnicodeRangeValue::create(from, to));
2903         m_valueList->next();
2904     }
2905     if (failed || !values->length())
2906         return false;
2907     addProperty(CSSPropertyUnicodeRange, values.release(), m_important);
2908     return true;
2909 }
2910
2911 bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict)
2912 {
2913     if (!strict && Color::parseHexColor(name, rgb))
2914         return true;
2915
2916     // try a little harder
2917     Color tc;
2918     tc.setNamedColor(name);
2919     if (tc.isValid()) {
2920         rgb = tc.rgb();
2921         return true;
2922     }
2923
2924     return false;
2925 }
2926
2927 bool CSSParser::parseColorParameters(Value* value, int* colorArray, bool parseAlpha)
2928 {
2929     ValueList* args = value->function->args;
2930     Value* v = args->current();
2931     Units unitType = FUnknown;
2932     // Get the first value and its type
2933     if (validUnit(v, FInteger, true))
2934         unitType = FInteger;
2935     else if (validUnit(v, FPercent, true))
2936         unitType = FPercent;
2937     else
2938         return false;
2939     colorArray[0] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
2940     for (int i = 1; i < 3; i++) {
2941         v = args->next();
2942         if (v->unit != Value::Operator && v->iValue != ',')
2943             return false;
2944         v = args->next();
2945         if (!validUnit(v, unitType, true))
2946             return false;
2947         colorArray[i] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
2948     }
2949     if (parseAlpha) {
2950         v = args->next();
2951         if (v->unit != Value::Operator && v->iValue != ',')
2952             return false;
2953         v = args->next();
2954         if (!validUnit(v, FNumber, true))
2955             return false;
2956         colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * 255);
2957     }
2958     return true;
2959 }
2960
2961 // CSS3 sepcification defines the format of a HSL color as
2962 // hsl(<number>, <percent>, <percent>)
2963 // and with alpha, the format is
2964 // hsla(<number>, <percent>, <percent>, <number>)
2965 // The first value, HUE, is in an angle with a value between 0 and 360
2966 bool CSSParser::parseHSLParameters(Value* value, double* colorArray, bool parseAlpha)
2967 {
2968     ValueList* args = value->function->args;
2969     Value* v = args->current();
2970     // Get the first value
2971     if (!validUnit(v, FNumber, true))
2972         return false;
2973     // normalize the Hue value and change it to be between 0 and 1.0
2974     colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0;
2975     for (int i = 1; i < 3; i++) {
2976         v = args->next();
2977         if (v->unit != Value::Operator && v->iValue != ',')
2978             return false;
2979         v = args->next();
2980         if (!validUnit(v, FPercent, true))
2981             return false;
2982         colorArray[i] = max(0.0, min(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0
2983     }
2984     if (parseAlpha) {
2985         v = args->next();
2986         if (v->unit != Value::Operator && v->iValue != ',')
2987             return false;
2988         v = args->next();
2989         if (!validUnit(v, FNumber, true))
2990             return false;
2991         colorArray[3] = max(0.0, min(1.0, v->fValue));
2992     }
2993     return true;
2994 }
2995
2996 PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(Value* value)
2997 {
2998     RGBA32 c = Color::transparent;
2999     if (!parseColorFromValue(value ? value : m_valueList->current(), c))
3000         return 0;
3001     return CSSPrimitiveValue::createColor(c);
3002 }
3003
3004 bool CSSParser::parseColorFromValue(Value* value, RGBA32& c, bool svg)
3005 {
3006     if (!m_strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
3007         value->fValue >= 0. && value->fValue < 1000000.) {
3008         String str = String::format("%06d", (int)(value->fValue+.5));
3009         if (!CSSParser::parseColor(str, c, m_strict))
3010             return false;
3011     } else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR ||
3012                 value->unit == CSSPrimitiveValue::CSS_IDENT ||
3013                 (!m_strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
3014         if (!CSSParser::parseColor(value->string, c, m_strict && value->unit == CSSPrimitiveValue::CSS_IDENT))
3015             return false;
3016     } else if (value->unit == Value::Function &&
3017                 value->function->args != 0 &&
3018                 value->function->args->size() == 5 /* rgb + two commas */ &&
3019                 equalIgnoringCase(value->function->name, "rgb(")) {
3020         int colorValues[3];
3021         if (!parseColorParameters(value, colorValues, false))
3022             return false;
3023         c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
3024     } else if (!svg) {
3025         if (value->unit == Value::Function &&
3026                 value->function->args != 0 &&
3027                 value->function->args->size() == 7 /* rgba + three commas */ &&
3028                 equalIgnoringCase(value->function->name, "rgba(")) {
3029             int colorValues[4];
3030             if (!parseColorParameters(value, colorValues, true))
3031                 return false;
3032             c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
3033         } else if (value->unit == Value::Function &&
3034                     value->function->args != 0 &&
3035                     value->function->args->size() == 5 /* hsl + two commas */ &&
3036                     equalIgnoringCase(value->function->name, "hsl(")) {
3037             double colorValues[3];
3038             if (!parseHSLParameters(value, colorValues, false))
3039                 return false;
3040             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
3041         } else if (value->unit == Value::Function &&
3042                     value->function->args != 0 &&
3043                     value->function->args->size() == 7 /* hsla + three commas */ &&
3044                     equalIgnoringCase(value->function->name, "hsla(")) {
3045             double colorValues[4];
3046             if (!parseHSLParameters(value, colorValues, true))
3047                 return false;
3048             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
3049         } else
3050             return false;
3051     } else
3052         return false;
3053
3054     return true;
3055 }
3056
3057 // This class tracks parsing state for shadow values.  If it goes out of scope (e.g., due to an early return)
3058 // without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
3059 struct ShadowParseContext {
3060     ShadowParseContext()
3061     : allowX(true)
3062     , allowY(false)
3063     , allowBlur(false)
3064     , allowColor(true)
3065     , allowBreak(true)
3066     {}
3067
3068     bool allowLength() { return allowX || allowY || allowBlur; }
3069
3070     void commitValue() {
3071         // Handle the ,, case gracefully by doing nothing.
3072         if (x || y || blur || color) {
3073             if (!values)
3074                 values = CSSValueList::createCommaSeparated();
3075             
3076             // Construct the current shadow value and add it to the list.
3077             values->append(ShadowValue::create(x.release(), y.release(), blur.release(), color.release()));
3078         }
3079         
3080         // Now reset for the next shadow value.
3081         x = y = blur = color = 0;
3082         allowX = allowColor = allowBreak = true;
3083         allowY = allowBlur = false;  
3084     }
3085
3086     void commitLength(Value* v) {
3087         RefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
3088
3089         if (allowX) {
3090             x = val.release();
3091             allowX = false; allowY = true; allowColor = false; allowBreak = false;
3092         }
3093         else if (allowY) {
3094             y = val.release();
3095             allowY = false; allowBlur = true; allowColor = true; allowBreak = true;
3096         }
3097         else if (allowBlur) {
3098             blur = val.release();
3099             allowBlur = false;
3100         }
3101     }
3102
3103     void commitColor(PassRefPtr<CSSPrimitiveValue> val) {
3104         color = val;
3105         allowColor = false;
3106         if (allowX)
3107             allowBreak = false;
3108         else
3109             allowBlur = false;
3110     }
3111     
3112     RefPtr<CSSValueList> values;
3113     RefPtr<CSSPrimitiveValue> x;
3114     RefPtr<CSSPrimitiveValue> y;
3115     RefPtr<CSSPrimitiveValue> blur;
3116     RefPtr<CSSPrimitiveValue> color;
3117
3118     bool allowX;
3119     bool allowY;
3120     bool allowBlur;
3121     bool allowColor;
3122     bool allowBreak;
3123 };
3124
3125 bool CSSParser::parseShadow(int propId, bool important)
3126 {
3127     ShadowParseContext context;
3128     Value* val;
3129     while ((val = m_valueList->current())) {
3130         // Check for a comma break first.
3131         if (val->unit == Value::Operator) {
3132             if (val->iValue != ',' || !context.allowBreak)
3133                 // Other operators aren't legal or we aren't done with the current shadow
3134                 // value.  Treat as invalid.
3135                 return false;
3136             
3137             // The value is good.  Commit it.
3138             context.commitValue();
3139         }
3140         // Check to see if we're a length.
3141         else if (validUnit(val, FLength, true)) {
3142             // We required a length and didn't get one. Invalid.
3143             if (!context.allowLength())
3144                 return false;
3145
3146             // A length is allowed here.  Construct the value and add it.
3147             context.commitLength(val);
3148         }
3149         else {
3150             // The only other type of value that's ok is a color value.
3151             RefPtr<CSSPrimitiveValue> parsedColor;
3152             bool isColor = (val->id >= CSSValueAqua && val->id <= CSSValueWindowtext || val->id == CSSValueMenu ||
3153                             (val->id >= CSSValueWebkitFocusRingColor && val->id <= CSSValueWebkitText && !m_strict));
3154             if (isColor) {
3155                 if (!context.allowColor)
3156                     return false;
3157                 parsedColor = CSSPrimitiveValue::createIdentifier(val->id);
3158             }
3159
3160             if (!parsedColor)
3161                 // It's not built-in. Try to parse it as a color.
3162                 parsedColor = parseColor(val);
3163
3164             if (!parsedColor || !context.allowColor)
3165                 return false; // This value is not a color or length and is invalid or
3166                               // it is a color, but a color isn't allowed at this point.
3167             
3168             context.commitColor(parsedColor.release());
3169         }
3170         
3171         m_valueList->next();
3172     }
3173
3174     if (context.allowBreak) {
3175         context.commitValue();
3176         if (context.values->length()) {
3177             addProperty(propId, context.values.release(), important);
3178             m_valueList->next();
3179             return true;
3180         }
3181     }
3182     
3183     return false;
3184 }
3185
3186 bool CSSParser::parseReflect(int propId, bool important)
3187 {
3188     // box-reflect: <direction> <offset> <mask>
3189     
3190     // Direction comes first.
3191     Value* val = m_valueList->current();
3192     CSSReflectionDirection direction;
3193     switch (val->id) {
3194         case CSSValueAbove:
3195             direction = ReflectionAbove;
3196             break;
3197         case CSSValueBelow:
3198             direction = ReflectionBelow;
3199             break;
3200         case CSSValueLeft:
3201             direction = ReflectionLeft;
3202             break;
3203         case CSSValueRight:
3204             direction = ReflectionRight;
3205             break;
3206         default:
3207             return false;
3208     }
3209
3210     // The offset comes next.
3211     val = m_valueList->next();
3212     RefPtr<CSSPrimitiveValue> offset;
3213     if (!val)
3214         offset = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX);
3215     else {
3216         if (!validUnit(val, FLength | FPercent, m_strict))
3217             return false;
3218         offset = CSSPrimitiveValue::create(val->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(val->unit));
3219     }
3220
3221     // Now for the mask.
3222     RefPtr<CSSValue> mask;
3223     val = m_valueList->next();
3224     if (val) {
3225         if (!parseBorderImage(propId, important, mask))
3226             return false;
3227     }
3228
3229     RefPtr<CSSReflectValue> reflectValue = CSSReflectValue::create(direction, offset.release(), mask.release());
3230     addProperty(propId, reflectValue.release(), important);
3231     m_valueList->next();
3232     return true;
3233 }
3234
3235 struct BorderImageParseContext
3236 {
3237     BorderImageParseContext()
3238     : m_allowBreak(false)
3239     , m_allowNumber(false)
3240     , m_allowSlash(false)
3241     , m_allowWidth(false)
3242     , m_allowRule(false)
3243     , m_borderTop(0)
3244     , m_borderRight(0)
3245     , m_borderBottom(0)
3246     , m_borderLeft(0)
3247     , m_horizontalRule(0)
3248     , m_verticalRule(0)
3249     {}
3250     
3251     bool allowBreak() const { return m_allowBreak; }
3252     bool allowNumber() const { return m_allowNumber; }
3253     bool allowSlash() const { return m_allowSlash; }
3254     bool allowWidth() const { return m_allowWidth; }
3255     bool allowRule() const { return m_allowRule; }
3256
3257     void commitImage(PassRefPtr<CSSValue> image) { m_image = image; m_allowNumber = true; }
3258     void commitNumber(Value* v) {
3259         PassRefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
3260         if (!m_top)
3261             m_top = val;
3262         else if (!m_right)
3263             m_right = val;
3264         else if (!m_bottom)
3265             m_bottom = val;
3266         else {
3267             ASSERT(!m_left);
3268             m_left = val;
3269         }
3270         
3271         m_allowBreak = m_allowSlash = m_allowRule = true;
3272         m_allowNumber = !m_left;
3273     }
3274     void commitSlash() { m_allowBreak = m_allowSlash = m_allowNumber = false; m_allowWidth = true; }
3275     void commitWidth(Value* val) {
3276         if (!m_borderTop)
3277             m_borderTop = val;
3278         else if (!m_borderRight)
3279             m_borderRight = val;
3280         else if (!m_borderBottom)
3281             m_borderBottom = val;
3282         else {
3283             ASSERT(!m_borderLeft);
3284             m_borderLeft = val;
3285         }
3286
3287         m_allowBreak = m_allowRule = true;
3288         m_allowWidth = !m_borderLeft;
3289     }
3290     void commitRule(int keyword) {
3291         if (!m_horizontalRule)
3292             m_horizontalRule = keyword;
3293         else if (!m_verticalRule)
3294             m_verticalRule = keyword;
3295         m_allowRule = !m_verticalRule;
3296     }
3297     PassRefPtr<CSSValue> commitBorderImage(CSSParser* p, bool important) {
3298         // We need to clone and repeat values for any omissions.
3299         if (!m_right) {
3300             m_right = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
3301             m_bottom = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
3302             m_left = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
3303         }
3304         if (!m_bottom) {
3305             m_bottom = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
3306             m_left = CSSPrimitiveValue::create(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
3307         }
3308         if (!m_left)
3309              m_left = CSSPrimitiveValue::create(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
3310              
3311         // Now build a rect value to hold all four of our primitive values.
3312         RefPtr<Rect> rect = Rect::create();
3313         rect->setTop(m_top);
3314         rect->setRight(m_right);
3315         rect->setBottom(m_bottom);
3316         rect->setLeft(m_left);
3317
3318         // Fill in STRETCH as the default if it wasn't specified.
3319         if (!m_horizontalRule)
3320             m_horizontalRule = CSSValueStretch;
3321             
3322         // The vertical rule should match the horizontal rule if unspecified.
3323         if (!m_verticalRule)
3324             m_verticalRule = m_horizontalRule;
3325
3326         // 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
3327         // list and then make our parsing machinery do the parsing.
3328         if (m_borderTop) {
3329             ValueList newList;
3330             newList.addValue(*m_borderTop);
3331             if (m_borderRight)
3332                 newList.addValue(*m_borderRight);
3333             if (m_borderBottom)
3334                 newList.addValue(*m_borderBottom);
3335             if (m_borderLeft)
3336                 newList.addValue(*m_borderLeft);
3337             p->m_valueList = &newList;
3338             p->parseValue(CSSPropertyBorderWidth, important);
3339             p->m_valueList = 0;
3340         }
3341
3342         // Make our new border image value now.
3343         return CSSBorderImageValue::create(m_image, rect.release(), m_horizontalRule, m_verticalRule);
3344     }
3345     
3346     bool m_allowBreak;
3347     bool m_allowNumber;
3348     bool m_allowSlash;
3349     bool m_allowWidth;
3350     bool m_allowRule;
3351     
3352     RefPtr<CSSValue> m_image;
3353
3354     RefPtr<CSSPrimitiveValue> m_top;
3355     RefPtr<CSSPrimitiveValue> m_right;
3356     RefPtr<CSSPrimitiveValue> m_bottom;
3357     RefPtr<CSSPrimitiveValue> m_left;
3358     
3359     Value* m_borderTop;
3360     Value* m_borderRight;
3361     Value* m_borderBottom;
3362     Value* m_borderLeft;
3363     
3364     int m_horizontalRule;
3365     int m_verticalRule;
3366 };
3367
3368 bool CSSParser::parseBorderImage(int propId, bool important, RefPtr<CSSValue>& result)
3369 {
3370     // Look for an image initially.  If the first value is not a URI, then we're done.
3371     BorderImageParseContext context;
3372     Value* val = m_valueList->current();
3373     if (val->unit == CSSPrimitiveValue::CSS_URI) {        
3374         String uri = parseURL(val->string);
3375         if (uri.isNull())
3376             return false;
3377         context.commitImage(CSSImageValue::create(KURL(m_styleSheet->baseURL(), uri).string()));
3378     } else if (val->unit == Value::Function) {
3379         RefPtr<CSSValue> value;
3380         if ((equalIgnoringCase(val->function->name, "-webkit-gradient(") && parseGradient(value)) ||
3381             (equalIgnoringCase(val->function->name, "-webkit-canvas(") && parseCanvas(value)))
3382             context.commitImage(value);
3383         else
3384             return false;
3385     } else
3386         return false;
3387
3388     while ((val = m_valueList->next())) {
3389         if (context.allowNumber() && validUnit(val, FInteger|FNonNeg|FPercent, true)) {
3390             context.commitNumber(val);
3391         } else if (propId == CSSPropertyWebkitBorderImage && context.allowSlash() && val->unit == Value::Operator && val->iValue == '/') {
3392             context.commitSlash();
3393         } else if (context.allowWidth() &&
3394             (val->id == CSSValueThin || val->id == CSSValueMedium || val->id == CSSValueThick || validUnit(val, FLength, m_strict))) {
3395             context.commitWidth(val);
3396         } else if (context.allowRule() &&
3397             (val->id == CSSValueStretch || val->id == CSSValueRound || val->id == CSSValueRepeat)) {
3398             context.commitRule(val->id);
3399         } else {
3400             // Something invalid was encountered.
3401             return false;
3402         }
3403     }
3404     
3405     if (context.allowNumber() && propId != CSSPropertyWebkitBorderImage) {
3406         // Allow the slices to be omitted for images that don't fit to a border.  We just set the slices to be 0.
3407         context.m_top = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER);
3408         context.m_allowBreak = true;
3409     }
3410
3411     if (context.allowBreak()) {
3412         // Need to fully commit as a single value.
3413         result = context.commitBorderImage(this, important);
3414         return true;
3415     }
3416     
3417     return false;
3418 }
3419
3420 bool CSSParser::parseCounter(int propId, int defaultValue, bool important)
3421 {
3422     enum { ID, VAL } state = ID;
3423
3424     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
3425     RefPtr<CSSPrimitiveValue> counterName;
3426     
3427     while (true) {
3428         Value* val = m_valueList->current();
3429         switch (state) {
3430             case ID:
3431                 if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
3432                     counterName = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
3433                     state = VAL;
3434                     m_valueList->next();
3435                     continue;
3436                 }
3437                 break;
3438             case VAL: {
3439                 int i = defaultValue;
3440                 if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
3441                     i = (int)val->fValue;
3442                     m_valueList->next();
3443                 }
3444
3445                 list->append(CSSPrimitiveValue::create(Pair::create(counterName.release(),
3446                     CSSPrimitiveValue::create(i, CSSPrimitiveValue::CSS_NUMBER))));