2 * This file is part of the DOM implementation for KDE.
4 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
5 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
6 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
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.
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.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 #include "cssparser.h"
27 #include "CSSBorderImageValue.h"
28 #include "CSSCursorImageValue.h"
29 #include "CSSImageValue.h"
30 #include "CSSCharsetRule.h"
31 #include "CSSImportRule.h"
32 #include "CSSInheritedValue.h"
33 #include "CSSInitialValue.h"
34 #include "CSSMediaRule.h"
35 #include "CSSMutableStyleDeclaration.h"
36 #include "CSSPrimitiveValue.h"
37 #include "CSSProperty.h"
38 #include "CSSPropertyNames.h"
39 #include "CSSRuleList.h"
40 #include "CSSSelector.h"
41 #include "CSSStyleRule.h"
42 #include "CSSStyleSheet.h"
43 #include "CSSQuirkPrimitiveValue.h"
44 #include "CSSValueKeywords.h"
45 #include "CSSValueList.h"
47 #include "DashboardRegion.h"
49 #include "FontFamilyValue.h"
50 #include "FontValue.h"
52 #include "MediaList.h"
54 #include "ShadowValue.h"
55 #include "csshelper.h"
56 #include "MediaQueryExp.h"
61 extern int cssyydebug;
64 extern int cssyyparse(void* parser);
70 ValueList::~ValueList()
72 size_t numValues = m_values.size();
73 for (size_t i = 0; i < numValues; i++)
74 if (m_values[i].unit == Value::Function)
75 delete m_values[i].function;
79 class ShorthandScope {
81 ShorthandScope(CSSParser* parser, int propId) : m_parser(parser)
83 if (!(m_parser->m_inParseShorthand++))
84 m_parser->m_currentShorthand = propId;
88 if (!(--m_parser->m_inParseShorthand))
89 m_parser->m_currentShorthand = 0;
97 CSSParser* CSSParser::currentParser = 0;
99 CSSParser::CSSParser(bool strictParsing)
100 : m_floatingMediaQuery(0)
101 , m_floatingMediaQueryExp(0)
102 , m_floatingMediaQueryExpList(0)
105 kdDebug(6080) << "CSSParser::CSSParser this=" << this << endl;
107 strict = strictParsing;
109 parsedProperties = (CSSProperty **)fastMalloc(32 * sizeof(CSSProperty *));
110 numParsedProperties = 0;
111 maxParsedProperties = 32;
117 m_inParseShorthand = 0;
118 m_currentShorthand = 0;
119 m_implicitShorthand = false;
121 defaultNamespace = starAtom;
130 CSSParser::~CSSParser()
133 fastFree(parsedProperties);
139 if (m_floatingMediaQueryExpList) {
140 deleteAllValues(*m_floatingMediaQueryExpList);
141 delete m_floatingMediaQueryExpList;
143 delete m_floatingMediaQueryExp;
144 delete m_floatingMediaQuery;
145 deleteAllValues(m_floatingSelectors);
146 deleteAllValues(m_floatingValueLists);
147 deleteAllValues(m_floatingFunctions);
150 void ParseString::lower()
152 // Fast case for all-ASCII.
154 for (int i = 0; i < length; i++)
155 ored |= characters[i];
157 for (int i = 0; i < length; i++)
158 characters[i] = u_tolower(characters[i]);
160 for (int i = 0; i < length; i++)
161 characters[i] = tolower(characters[i]);
164 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
166 int length = string.length() + strlen(prefix) + strlen(suffix) + 2;
171 data = static_cast<UChar*>(fastMalloc(length * sizeof(UChar)));
172 for (unsigned i = 0; i < strlen(prefix); i++)
175 memcpy(data + strlen(prefix), string.characters(), string.length() * sizeof(UChar));
177 unsigned start = strlen(prefix) + string.length();
178 unsigned end = start + strlen(suffix);
179 for (unsigned i = start; i < end; i++)
180 data[i] = suffix[i - start];
182 data[length - 1] = 0;
183 data[length - 2] = 0;
187 yytext = yy_c_buf_p = data;
188 yy_hold_char = *yy_c_buf_p;
191 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string)
193 styleElement = sheet;
194 defaultNamespace = starAtom; // Reset the default namespace.
196 setupParser("", string, "");
198 CSSParser* old = currentParser;
199 currentParser = this;
206 PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet *sheet, const String &string)
208 styleElement = sheet;
210 setupParser("@-webkit-rule{", string, "} ");
212 CSSParser* old = currentParser;
213 currentParser = this;
217 return rule.release();
220 bool CSSParser::parseValue(CSSMutableStyleDeclaration *declaration, int _id, const String &string, bool _important)
222 styleElement = declaration->stylesheet();
224 setupParser("@-webkit-value{", string, "} ");
227 important = _important;
229 CSSParser* old = currentParser;
230 currentParser = this;
237 if (numParsedProperties) {
239 declaration->addParsedProperties(parsedProperties, numParsedProperties);
246 RGBA32 CSSParser::parseColor(const String &string)
249 RefPtr<CSSMutableStyleDeclaration>dummyStyleDeclaration = new CSSMutableStyleDeclaration;
251 CSSParser parser(true);
253 // First try creating a color specified by name or the "#" syntax.
254 if (!parser.parseColor(string.deprecatedString(), color)) {
256 // Now try to create a color from the rgb() or rgba() syntax.
257 if (parser.parseColor(dummyStyleDeclaration.get(), string)) {
258 CSSValue* value = parser.parsedProperties[0]->value();
259 if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {
260 CSSPrimitiveValue *primitiveValue = static_cast<CSSPrimitiveValue *>(value);
261 color = primitiveValue->getRGBColorValue();
269 bool CSSParser::parseColor(CSSMutableStyleDeclaration *declaration, const String &string)
271 styleElement = declaration->stylesheet();
273 setupParser("@-webkit-decls{color:", string, "} ");
275 CSSParser* old = currentParser;
276 currentParser = this;
283 if (numParsedProperties && parsedProperties[0]->m_id == CSS_PROP_COLOR)
289 bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration *declaration, const String &string)
291 styleElement = declaration->stylesheet();
293 setupParser("@-webkit-decls{", string, "} ");
295 CSSParser* old = currentParser;
296 currentParser = this;
303 if (numParsedProperties) {
305 declaration->addParsedProperties(parsedProperties, numParsedProperties);
312 bool CSSParser::parseMediaQuery(MediaList* queries, const String& string)
314 if (string.isEmpty() || string.isNull()) {
319 // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
320 // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
321 setupParser ("@-webkit-mediaquery ", string, "} ");
323 CSSParser* old = currentParser;
324 currentParser = this;
331 queries->appendMediaQuery(mediaQuery);
339 void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important)
341 CSSProperty *prop = new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand);
342 if (numParsedProperties >= maxParsedProperties) {
343 maxParsedProperties += 32;
344 parsedProperties = (CSSProperty **)fastRealloc(parsedProperties,
345 maxParsedProperties*sizeof(CSSProperty *));
347 parsedProperties[numParsedProperties++] = prop;
350 void CSSParser::rollbackLastProperties(int num)
353 ASSERT(numParsedProperties >= num);
355 for (int i = 0; i < num; ++i)
356 delete parsedProperties[--numParsedProperties];
359 void CSSParser::clearProperties()
361 for (int i = 0; i < numParsedProperties; i++)
362 delete parsedProperties[i];
363 numParsedProperties = 0;
366 Document *CSSParser::document() const
368 StyleBase *root = styleElement;
370 while (root->parent())
371 root = root->parent();
372 if (root->isCSSStyleSheet())
373 doc = static_cast<CSSStyleSheet*>(root)->doc();
377 bool CSSParser::validUnit(Value* value, Units unitflags, bool strict)
379 if (unitflags & FNonNeg && value->fValue < 0)
383 switch(value->unit) {
384 case CSSPrimitiveValue::CSS_NUMBER:
385 b = (unitflags & FNumber);
386 if (!b && ((unitflags & FLength) && (value->fValue == 0 || !strict))) {
387 value->unit = CSSPrimitiveValue::CSS_PX;
390 if (!b && (unitflags & FInteger) && value->isInt)
393 case CSSPrimitiveValue::CSS_PERCENTAGE:
394 b = (unitflags & FPercent);
397 case CSSPrimitiveValue::CSS_EMS:
398 case CSSPrimitiveValue::CSS_EXS:
399 case CSSPrimitiveValue::CSS_PX:
400 case CSSPrimitiveValue::CSS_CM:
401 case CSSPrimitiveValue::CSS_MM:
402 case CSSPrimitiveValue::CSS_IN:
403 case CSSPrimitiveValue::CSS_PT:
404 case CSSPrimitiveValue::CSS_PC:
405 b = (unitflags & FLength);
407 case CSSPrimitiveValue::CSS_MS:
408 case CSSPrimitiveValue::CSS_S:
409 b = (unitflags & FTime);
411 case CSSPrimitiveValue::CSS_DEG:
412 case CSSPrimitiveValue::CSS_RAD:
413 case CSSPrimitiveValue::CSS_GRAD:
414 case CSSPrimitiveValue::CSS_HZ:
415 case CSSPrimitiveValue::CSS_KHZ:
416 case CSSPrimitiveValue::CSS_DIMENSION:
423 bool CSSParser::parseValue(int propId, bool important)
428 Value *value = valueList->current();
435 int num = inShorthand() ? 1 : valueList->size();
437 if (id == CSS_VAL_INHERIT) {
440 addProperty(propId, new CSSInheritedValue(), important);
443 else if (id == CSS_VAL_INITIAL) {
446 addProperty(propId, new CSSInitialValue(), important);
450 bool valid_primitive = false;
451 CSSValue *parsedValue = 0;
454 /* The comment to the left defines all valid value of this properties as defined
455 * in CSS 2, Appendix F. Property index
458 /* All the CSS properties are not supported by the renderer at the moment.
459 * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
460 * (see parseAuralValues). As we don't support them at all this seems reasonable.
463 case CSS_PROP_SIZE: // <length>{1,2} | auto | portrait | landscape | inherit
464 case CSS_PROP_QUOTES: // [<string> <string>]+ | none | inherit
465 // case CSS_PROP_PAGE: // <identifier> | auto // ### CHECK
468 valid_primitive = true;
470 case CSS_PROP_UNICODE_BIDI: // normal | embed | bidi-override | inherit
471 if (id == CSS_VAL_NORMAL ||
472 id == CSS_VAL_EMBED ||
473 id == CSS_VAL_BIDI_OVERRIDE)
474 valid_primitive = true;
477 case CSS_PROP_POSITION: // static | relative | absolute | fixed | inherit
478 if (id == CSS_VAL_STATIC ||
479 id == CSS_VAL_RELATIVE ||
480 id == CSS_VAL_ABSOLUTE ||
482 valid_primitive = true;
485 case CSS_PROP_PAGE_BREAK_AFTER: // auto | always | avoid | left | right | inherit
486 case CSS_PROP_PAGE_BREAK_BEFORE: // auto | always | avoid | left | right | inherit
487 if (id == CSS_VAL_AUTO ||
488 id == CSS_VAL_ALWAYS ||
489 id == CSS_VAL_AVOID ||
490 id == CSS_VAL_LEFT ||
492 valid_primitive = true;
495 case CSS_PROP_PAGE_BREAK_INSIDE: // avoid | auto | inherit
496 if (id == CSS_VAL_AUTO ||
498 valid_primitive = true;
501 case CSS_PROP_EMPTY_CELLS: // show | hide | inherit
502 if (id == CSS_VAL_SHOW ||
504 valid_primitive = true;
507 case CSS_PROP_CONTENT: // [ <string> | <uri> | <counter> | attr(X) | open-quote |
508 // close-quote | no-open-quote | no-close-quote ]+ | inherit
509 return parseContent(propId, important);
512 case CSS_PROP_WHITE_SPACE: // normal | pre | nowrap | inherit
513 if (id == CSS_VAL_NORMAL ||
515 id == CSS_VAL_PRE_WRAP ||
516 id == CSS_VAL_PRE_LINE ||
517 id == CSS_VAL_NOWRAP)
518 valid_primitive = true;
521 case CSS_PROP_CLIP: // <shape> | auto | inherit
522 if (id == CSS_VAL_AUTO)
523 valid_primitive = true;
524 else if (value->unit == Value::Function)
525 return parseShape(propId, important);
528 /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
529 * correctly and allows optimization in WebCore::applyRule(..)
531 case CSS_PROP_CAPTION_SIDE: // top | bottom | left | right | inherit
532 if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT ||
533 id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM)
534 valid_primitive = true;
537 case CSS_PROP_BORDER_COLLAPSE: // collapse | separate | inherit
538 if (id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE)
539 valid_primitive = true;
542 case CSS_PROP_VISIBILITY: // visible | hidden | collapse | inherit
543 if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_COLLAPSE)
544 valid_primitive = true;
547 case CSS_PROP_OVERFLOW: // visible | hidden | scroll | auto | marquee | overlay | inherit
548 case CSS_PROP_OVERFLOW_X:
549 case CSS_PROP_OVERFLOW_Y:
550 if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_SCROLL || id == CSS_VAL_AUTO ||
551 id == CSS_VAL_OVERLAY || id == CSS_VAL__WEBKIT_MARQUEE)
552 valid_primitive = true;
555 case CSS_PROP_LIST_STYLE_POSITION: // inside | outside | inherit
556 if (id == CSS_VAL_INSIDE || id == CSS_VAL_OUTSIDE)
557 valid_primitive = true;
560 case CSS_PROP_LIST_STYLE_TYPE:
561 // disc | circle | square | decimal | decimal-leading-zero | lower-roman |
562 // upper-roman | lower-greek | lower-alpha | lower-latin | upper-alpha |
563 // upper-latin | hebrew | armenian | georgian | cjk-ideographic | hiragana |
564 // katakana | hiragana-iroha | katakana-iroha | none | inherit
565 if ((id >= CSS_VAL_DISC && id <= CSS_VAL_KATAKANA_IROHA) || id == CSS_VAL_NONE)
566 valid_primitive = true;
569 case CSS_PROP_DISPLAY:
570 // inline | block | list-item | run-in | inline-block | table |
571 // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
572 // table-column-group | table-column | table-cell | table-caption | box | inline-box | none | inherit
573 if ((id >= CSS_VAL_INLINE && id <= CSS_VAL__WEBKIT_INLINE_BOX) || id == CSS_VAL_NONE)
574 valid_primitive = true;
577 case CSS_PROP_DIRECTION: // ltr | rtl | inherit
578 if (id == CSS_VAL_LTR || id == CSS_VAL_RTL)
579 valid_primitive = true;
582 case CSS_PROP_TEXT_TRANSFORM: // capitalize | uppercase | lowercase | none | inherit
583 if ((id >= CSS_VAL_CAPITALIZE && id <= CSS_VAL_LOWERCASE) || id == CSS_VAL_NONE)
584 valid_primitive = true;
587 case CSS_PROP_FLOAT: // left | right | none | inherit + center for buggy CSS
588 if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT ||
589 id == CSS_VAL_NONE || id == CSS_VAL_CENTER)
590 valid_primitive = true;
593 case CSS_PROP_CLEAR: // none | left | right | both | inherit
594 if (id == CSS_VAL_NONE || id == CSS_VAL_LEFT ||
595 id == CSS_VAL_RIGHT|| id == CSS_VAL_BOTH)
596 valid_primitive = true;
599 case CSS_PROP_TEXT_ALIGN:
600 // left | right | center | justify | khtml_left | khtml_right | khtml_center | <string> | inherit
601 if ((id >= CSS_VAL__WEBKIT_AUTO && id <= CSS_VAL__WEBKIT_CENTER) ||
602 value->unit == CSSPrimitiveValue::CSS_STRING)
603 valid_primitive = true;
606 case CSS_PROP_OUTLINE_STYLE: // <border-style> | auto | inherit
607 if (id == CSS_VAL_AUTO) {
608 valid_primitive = true;
611 case CSS_PROP_BORDER_TOP_STYLE: //// <border-style> | inherit
612 case CSS_PROP_BORDER_RIGHT_STYLE: // Defined as: none | hidden | dotted | dashed |
613 case CSS_PROP_BORDER_BOTTOM_STYLE: // solid | double | groove | ridge | inset | outset
614 case CSS_PROP_BORDER_LEFT_STYLE: ////
615 if (id >= CSS_VAL_NONE && id <= CSS_VAL_DOUBLE)
616 valid_primitive = true;
619 case CSS_PROP_FONT_WEIGHT: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 |
620 // 500 | 600 | 700 | 800 | 900 | inherit
621 if (id >= CSS_VAL_NORMAL && id <= CSS_VAL_900) {
622 // Allready correct id
623 valid_primitive = true;
624 } else if (validUnit(value, FInteger|FNonNeg, false)) {
625 int weight = (int)value->fValue;
629 if (weight >= 1 && weight <= 9) {
630 id = CSS_VAL_100 + weight - 1;
631 valid_primitive = true;
636 case CSS_PROP_BORDER_SPACING: {
637 const int properties[2] = { CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING,
638 CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING };
640 ShorthandScope scope(this, CSS_PROP_BORDER_SPACING);
641 if (!parseValue(properties[0], important))
643 CSSValue* value = parsedProperties[numParsedProperties-1]->value();
644 addProperty(properties[1], value, important);
648 ShorthandScope scope(this, CSS_PROP_BORDER_SPACING);
649 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
655 case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING:
656 case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING:
657 valid_primitive = validUnit(value, FLength|FNonNeg, strict);
659 case CSS_PROP_SCROLLBAR_FACE_COLOR: // IE5.5
660 case CSS_PROP_SCROLLBAR_SHADOW_COLOR: // IE5.5
661 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: // IE5.5
662 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: // IE5.5
663 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: // IE5.5
664 case CSS_PROP_SCROLLBAR_TRACK_COLOR: // IE5.5
665 case CSS_PROP_SCROLLBAR_ARROW_COLOR: // IE5.5
669 case CSS_PROP_OUTLINE_COLOR: // <color> | invert | inherit
670 // Outline color has "invert" as additional keyword.
671 // Also, we want to allow the special focus color even in strict parsing mode.
672 if (propId == CSS_PROP_OUTLINE_COLOR && (id == CSS_VAL_INVERT || id == CSS_VAL__WEBKIT_FOCUS_RING_COLOR)) {
673 valid_primitive = true;
677 case CSS_PROP_BACKGROUND_COLOR: // <color> | inherit
678 case CSS_PROP_BORDER_TOP_COLOR: // <color> | inherit
679 case CSS_PROP_BORDER_RIGHT_COLOR: // <color> | inherit
680 case CSS_PROP_BORDER_BOTTOM_COLOR: // <color> | inherit
681 case CSS_PROP_BORDER_LEFT_COLOR: // <color> | inherit
682 case CSS_PROP_COLOR: // <color> | inherit
683 case CSS_PROP_TEXT_LINE_THROUGH_COLOR: // CSS3 text decoration colors
684 case CSS_PROP_TEXT_UNDERLINE_COLOR:
685 case CSS_PROP_TEXT_OVERLINE_COLOR:
686 if (id == CSS_VAL__WEBKIT_TEXT)
687 valid_primitive = true; // Always allow this, even when strict parsing is on,
688 // since we use this in our UA sheets.
689 else if (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT || id == CSS_VAL_MENU ||
690 (id >= CSS_VAL__WEBKIT_FOCUS_RING_COLOR && id < CSS_VAL__WEBKIT_TEXT && !strict)) {
691 valid_primitive = true;
693 parsedValue = parseColor();
699 case CSS_PROP_CURSOR: {
700 // [<uri>,]* [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
701 // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
702 // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help ] ] | inherit
703 CSSValueList* list = 0;
704 while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
705 String uri = parseURL(domString(value->string));
707 value = valueList->next();
708 while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
709 coords.append(int(value->fValue));
710 value = valueList->next();
713 int nrcoords = coords.size();
714 if (nrcoords > 0 && nrcoords != 2) {
715 if (strict) { // only support hotspot pairs in strict mode
719 } else if(strict && nrcoords == 2)
720 hotspot = IntPoint(coords[0], coords[1]);
721 if (strict || coords.size() == 0) {
723 if (uri.startsWith("#")) {
725 list = new CSSValueList;
726 list->append(new CSSPrimitiveValue(uri, CSSPrimitiveValue::CSS_URI));
729 if (!uri.isEmpty()) {
731 list = new CSSValueList;
732 list->append(new CSSCursorImageValue(
733 String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()),
734 hotspot, styleElement));
737 if ((strict && !value) || (value && !(value->unit == Value::Operator && value->iValue == ',')))
739 value = valueList->next(); // comma
742 if (!value) { // no value after url list (MSIE 5 compatibility)
743 if (list->length() > 1)
745 } else if (!strict && value->id == CSS_VAL_HAND) // MSIE 5 compatibility :/
746 list->append(new CSSPrimitiveValue(CSS_VAL_POINTER));
747 else if (value && value->id >= CSS_VAL_AUTO && value->id <= CSS_VAL_HELP)
748 list->append(new CSSPrimitiveValue(value->id));
754 if (!strict && value->id == CSS_VAL_HAND) { // MSIE 5 compatibility :/
755 id = CSS_VAL_POINTER;
756 valid_primitive = true;
757 } else if (value->id >= CSS_VAL_AUTO && value->id <= CSS_VAL_HELP)
758 valid_primitive = true;
762 case CSS_PROP_BACKGROUND_ATTACHMENT:
763 case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
764 case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
765 case CSS_PROP_BACKGROUND_IMAGE:
766 case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
767 case CSS_PROP_BACKGROUND_POSITION:
768 case CSS_PROP_BACKGROUND_POSITION_X:
769 case CSS_PROP_BACKGROUND_POSITION_Y:
770 case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
771 case CSS_PROP_BACKGROUND_REPEAT: {
772 CSSValue *val1 = 0, *val2 = 0;
773 int propId1, propId2;
774 if (parseBackgroundProperty(propId, propId1, propId2, val1, val2)) {
775 addProperty(propId1, val1, important);
777 addProperty(propId2, val2, important);
782 case CSS_PROP_LIST_STYLE_IMAGE: // <uri> | none | inherit
783 if (id == CSS_VAL_NONE) {
784 parsedValue = new CSSImageValue();
787 else if (value->unit == CSSPrimitiveValue::CSS_URI) {
788 // ### allow string in non strict mode?
789 String uri = parseURL(domString(value->string));
790 if (!uri.isEmpty()) {
791 parsedValue = new CSSImageValue(
792 String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()),
799 case CSS_PROP_OUTLINE_WIDTH: // <border-width> | inherit
800 case CSS_PROP_BORDER_TOP_WIDTH: //// <border-width> | inherit
801 case CSS_PROP_BORDER_RIGHT_WIDTH: // Which is defined as
802 case CSS_PROP_BORDER_BOTTOM_WIDTH: // thin | medium | thick | <length>
803 case CSS_PROP_BORDER_LEFT_WIDTH: ////
804 if (id == CSS_VAL_THIN || id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK)
805 valid_primitive = true;
807 valid_primitive = validUnit(value, FLength, strict);
810 case CSS_PROP_LETTER_SPACING: // normal | <length> | inherit
811 case CSS_PROP_WORD_SPACING: // normal | <length> | inherit
812 if (id == CSS_VAL_NORMAL)
813 valid_primitive = true;
815 valid_primitive = validUnit(value, FLength, strict);
818 case CSS_PROP_WORD_WRAP: // normal | break-word
819 if (id == CSS_VAL_NORMAL || id == CSS_VAL_BREAK_WORD)
820 valid_primitive = true;
823 case CSS_PROP_TEXT_INDENT: // <length> | <percentage> | inherit
824 case CSS_PROP_PADDING_TOP: //// <padding-width> | inherit
825 case CSS_PROP_PADDING_RIGHT: // Which is defined as
826 case CSS_PROP_PADDING_BOTTOM: // <length> | <percentage>
827 case CSS_PROP_PADDING_LEFT: ////
828 case CSS_PROP__WEBKIT_PADDING_START:
829 valid_primitive = (!id && validUnit(value, FLength|FPercent, strict));
832 case CSS_PROP_MAX_HEIGHT: // <length> | <percentage> | none | inherit
833 case CSS_PROP_MAX_WIDTH: // <length> | <percentage> | none | inherit
834 if (id == CSS_VAL_NONE || id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC) {
835 valid_primitive = true;
839 case CSS_PROP_MIN_HEIGHT: // <length> | <percentage> | inherit
840 case CSS_PROP_MIN_WIDTH: // <length> | <percentage> | inherit
841 if (id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC)
842 valid_primitive = true;
844 valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, strict));
847 case CSS_PROP_FONT_SIZE:
848 // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
849 if (id >= CSS_VAL_XX_SMALL && id <= CSS_VAL_LARGER)
850 valid_primitive = true;
852 valid_primitive = (validUnit(value, FLength|FPercent, strict));
855 case CSS_PROP_FONT_STYLE: // normal | italic | oblique | inherit
856 if (id == CSS_VAL_NORMAL || id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE)
857 valid_primitive = true;
860 case CSS_PROP_FONT_VARIANT: // normal | small-caps | inherit
861 if (id == CSS_VAL_NORMAL || id == CSS_VAL_SMALL_CAPS)
862 valid_primitive = true;
865 case CSS_PROP_VERTICAL_ALIGN:
866 // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
867 // <percentage> | <length> | inherit
869 if (id >= CSS_VAL_BASELINE && id <= CSS_VAL__WEBKIT_BASELINE_MIDDLE)
870 valid_primitive = true;
872 valid_primitive = (!id && validUnit(value, FLength|FPercent, strict));
875 case CSS_PROP_HEIGHT: // <length> | <percentage> | auto | inherit
876 case CSS_PROP_WIDTH: // <length> | <percentage> | auto | inherit
877 if (id == CSS_VAL_AUTO || id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC)
878 valid_primitive = true;
880 // ### handle multilength case where we allow relative units
881 valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, strict));
884 case CSS_PROP_BOTTOM: // <length> | <percentage> | auto | inherit
885 case CSS_PROP_LEFT: // <length> | <percentage> | auto | inherit
886 case CSS_PROP_RIGHT: // <length> | <percentage> | auto | inherit
887 case CSS_PROP_TOP: // <length> | <percentage> | auto | inherit
888 case CSS_PROP_MARGIN_TOP: //// <margin-width> | inherit
889 case CSS_PROP_MARGIN_RIGHT: // Which is defined as
890 case CSS_PROP_MARGIN_BOTTOM: // <length> | <percentage> | auto | inherit
891 case CSS_PROP_MARGIN_LEFT: ////
892 case CSS_PROP__WEBKIT_MARGIN_START:
893 if (id == CSS_VAL_AUTO)
894 valid_primitive = true;
896 valid_primitive = (!id && validUnit(value, FLength|FPercent, strict));
899 case CSS_PROP_Z_INDEX: // auto | <integer> | inherit
900 if (id == CSS_VAL_AUTO) {
901 valid_primitive = true;
905 case CSS_PROP_ORPHANS: // <integer> | inherit
906 case CSS_PROP_WIDOWS: // <integer> | inherit
907 // ### not supported later on
908 valid_primitive = (!id && validUnit(value, FInteger, false));
911 case CSS_PROP_LINE_HEIGHT: // normal | <number> | <length> | <percentage> | inherit
912 if (id == CSS_VAL_NORMAL)
913 valid_primitive = true;
915 valid_primitive = (!id && validUnit(value, FNumber|FLength|FPercent, strict));
917 case CSS_PROP_COUNTER_INCREMENT: // [ <identifier> <integer>? ]+ | none | inherit
918 if (id != CSS_VAL_NONE)
919 return parseCounter(propId, 1, important);
920 valid_primitive = true;
922 case CSS_PROP_COUNTER_RESET: // [ <identifier> <integer>? ]+ | none | inherit
923 if (id != CSS_VAL_NONE)
924 return parseCounter(propId, 0, important);
925 valid_primitive = true;
927 case CSS_PROP_FONT_FAMILY:
928 // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
930 parsedValue = parseFontFamily();
934 case CSS_PROP_TEXT_DECORATION:
935 case CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT:
936 // none | [ underline || overline || line-through || blink ] | inherit
937 if (id == CSS_VAL_NONE) {
938 valid_primitive = true;
940 CSSValueList *list = new CSSValueList;
941 bool is_valid = true;
942 while(is_valid && value) {
946 case CSS_VAL_UNDERLINE:
947 case CSS_VAL_OVERLINE:
948 case CSS_VAL_LINE_THROUGH:
949 list->append(new CSSPrimitiveValue(value->id));
954 value = valueList->next();
956 if(list->length() && is_valid) {
964 case CSS_PROP_TABLE_LAYOUT: // auto | fixed | inherit
965 if (id == CSS_VAL_AUTO || id == CSS_VAL_FIXED)
966 valid_primitive = true;
969 /* CSS3 properties */
970 case CSS_PROP__WEBKIT_APPEARANCE:
971 if ((id >= CSS_VAL_CHECKBOX && id <= CSS_VAL_TEXTAREA) || id == CSS_VAL_NONE)
972 valid_primitive = true;
975 case CSS_PROP__WEBKIT_BINDING:
977 if (id == CSS_VAL_NONE)
978 valid_primitive = true;
980 CSSValueList* values = new CSSValueList();
982 CSSValue* parsedValue = 0;
983 while ((val = valueList->current())) {
984 if (val->unit == CSSPrimitiveValue::CSS_URI) {
985 String value = parseURL(domString(val->string));
986 parsedValue = new CSSPrimitiveValue(
987 String(KURL(styleElement->baseURL().deprecatedString(), value.deprecatedString()).url()),
988 CSSPrimitiveValue::CSS_URI);
992 values->append(parsedValue);
997 if (values->length()) {
998 addProperty(propId, values, important);
1007 case CSS_PROP__WEBKIT_BORDER_IMAGE:
1008 if (id == CSS_VAL_NONE)
1009 valid_primitive = true;
1011 return parseBorderImage(propId, important);
1013 case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS:
1014 case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS:
1015 case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS:
1016 case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS:
1017 case CSS_PROP__WEBKIT_BORDER_RADIUS: {
1018 if (num != 1 && num != 2)
1020 valid_primitive = validUnit(value, FLength, strict);
1021 if (!valid_primitive)
1023 CSSPrimitiveValue* parsedValue1 = new CSSPrimitiveValue(value->fValue,
1024 (CSSPrimitiveValue::UnitTypes)value->unit);
1025 CSSPrimitiveValue* parsedValue2 = parsedValue1;
1027 value = valueList->next();
1028 valid_primitive = validUnit(value, FLength, strict);
1029 if (!valid_primitive) {
1030 delete parsedValue1;
1033 parsedValue2 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1036 Pair* pair = new Pair(parsedValue1, parsedValue2);
1037 CSSPrimitiveValue* val = new CSSPrimitiveValue(pair);
1038 addProperty(propId, val, important);
1041 case CSS_PROP_OUTLINE_OFFSET:
1042 valid_primitive = validUnit(value, FLength, strict);
1044 case CSS_PROP_TEXT_SHADOW: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
1045 if (id == CSS_VAL_NONE)
1046 valid_primitive = true;
1048 return parseShadow(propId, important);
1050 case CSS_PROP_OPACITY:
1051 valid_primitive = validUnit(value, FNumber, strict);
1053 case CSS_PROP__WEBKIT_BOX_ALIGN:
1054 if (id == CSS_VAL_STRETCH || id == CSS_VAL_START || id == CSS_VAL_END ||
1055 id == CSS_VAL_CENTER || id == CSS_VAL_BASELINE)
1056 valid_primitive = true;
1058 case CSS_PROP__WEBKIT_BOX_DIRECTION:
1059 if (id == CSS_VAL_NORMAL || id == CSS_VAL_REVERSE)
1060 valid_primitive = true;
1062 case CSS_PROP__WEBKIT_BOX_LINES:
1063 if (id == CSS_VAL_SINGLE || id == CSS_VAL_MULTIPLE)
1064 valid_primitive = true;
1066 case CSS_PROP__WEBKIT_BOX_ORIENT:
1067 if (id == CSS_VAL_HORIZONTAL || id == CSS_VAL_VERTICAL ||
1068 id == CSS_VAL_INLINE_AXIS || id == CSS_VAL_BLOCK_AXIS)
1069 valid_primitive = true;
1071 case CSS_PROP__WEBKIT_BOX_PACK:
1072 if (id == CSS_VAL_START || id == CSS_VAL_END ||
1073 id == CSS_VAL_CENTER || id == CSS_VAL_JUSTIFY)
1074 valid_primitive = true;
1076 case CSS_PROP__WEBKIT_BOX_FLEX:
1077 valid_primitive = validUnit(value, FNumber, strict);
1079 case CSS_PROP__WEBKIT_BOX_FLEX_GROUP:
1080 case CSS_PROP__WEBKIT_BOX_ORDINAL_GROUP:
1081 valid_primitive = validUnit(value, FInteger|FNonNeg, true);
1083 case CSS_PROP_BOX_SIZING: {
1084 // We don't preface this with -webkit, since MacIE defined this property without the prefix.
1085 // Thus the damage has been done, and it's known that this property's definition isn't going
1087 if (id == CSS_VAL_BORDER_BOX || id == CSS_VAL_CONTENT_BOX)
1088 valid_primitive = true;
1091 case CSS_PROP__WEBKIT_MARQUEE: {
1092 const int properties[5] = { CSS_PROP__WEBKIT_MARQUEE_DIRECTION, CSS_PROP__WEBKIT_MARQUEE_INCREMENT,
1093 CSS_PROP__WEBKIT_MARQUEE_REPETITION,
1094 CSS_PROP__WEBKIT_MARQUEE_STYLE, CSS_PROP__WEBKIT_MARQUEE_SPEED };
1095 return parseShorthand(propId, properties, 5, important);
1097 case CSS_PROP__WEBKIT_MARQUEE_DIRECTION:
1098 if (id == CSS_VAL_FORWARDS || id == CSS_VAL_BACKWARDS || id == CSS_VAL_AHEAD ||
1099 id == CSS_VAL_REVERSE || id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || id == CSS_VAL_DOWN ||
1100 id == CSS_VAL_UP || id == CSS_VAL_AUTO)
1101 valid_primitive = true;
1103 case CSS_PROP__WEBKIT_MARQUEE_INCREMENT:
1104 if (id == CSS_VAL_SMALL || id == CSS_VAL_LARGE || id == CSS_VAL_MEDIUM)
1105 valid_primitive = true;
1107 valid_primitive = validUnit(value, FLength|FPercent, strict);
1109 case CSS_PROP__WEBKIT_MARQUEE_STYLE:
1110 if (id == CSS_VAL_NONE || id == CSS_VAL_SLIDE || id == CSS_VAL_SCROLL || id == CSS_VAL_ALTERNATE ||
1111 id == CSS_VAL_UNFURL)
1112 valid_primitive = true;
1114 case CSS_PROP__WEBKIT_MARQUEE_REPETITION:
1115 if (id == CSS_VAL_INFINITE)
1116 valid_primitive = true;
1118 valid_primitive = validUnit(value, FInteger|FNonNeg, strict);
1120 case CSS_PROP__WEBKIT_MARQUEE_SPEED:
1121 if (id == CSS_VAL_NORMAL || id == CSS_VAL_SLOW || id == CSS_VAL_FAST)
1122 valid_primitive = true;
1124 valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict);
1126 case CSS_PROP__WEBKIT_USER_DRAG: // auto | none | element
1127 if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE || id == CSS_VAL_ELEMENT)
1128 valid_primitive = true;
1130 case CSS_PROP__WEBKIT_USER_MODIFY: // read-only | read-write
1131 if (id == CSS_VAL_READ_ONLY || id == CSS_VAL_READ_WRITE || CSS_VAL_READ_WRITE_PLAINTEXT_ONLY)
1132 valid_primitive = true;
1134 case CSS_PROP__WEBKIT_USER_SELECT: // auto | none | text
1135 if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE || id == CSS_VAL_TEXT || id == CSS_VAL_IGNORE)
1136 valid_primitive = true;
1138 case CSS_PROP_TEXT_OVERFLOW: // clip | ellipsis
1139 if (id == CSS_VAL_CLIP || id == CSS_VAL_ELLIPSIS)
1140 valid_primitive = true;
1142 case CSS_PROP__WEBKIT_MARGIN_COLLAPSE: {
1143 const int properties[2] = { CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE,
1144 CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE };
1146 ShorthandScope scope(this, CSS_PROP__WEBKIT_MARGIN_COLLAPSE);
1147 if (!parseValue(properties[0], important))
1149 CSSValue* value = parsedProperties[numParsedProperties-1]->value();
1150 addProperty(properties[1], value, important);
1153 else if (num == 2) {
1154 ShorthandScope scope(this, CSS_PROP__WEBKIT_MARGIN_COLLAPSE);
1155 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1161 case CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE:
1162 case CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE:
1163 if (id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE || id == CSS_VAL_DISCARD)
1164 valid_primitive = true;
1166 case CSS_PROP_TEXT_LINE_THROUGH_MODE:
1167 case CSS_PROP_TEXT_OVERLINE_MODE:
1168 case CSS_PROP_TEXT_UNDERLINE_MODE:
1169 if (id == CSS_VAL_CONTINUOUS || id == CSS_VAL_SKIP_WHITE_SPACE)
1170 valid_primitive = true;
1172 case CSS_PROP_TEXT_LINE_THROUGH_STYLE:
1173 case CSS_PROP_TEXT_OVERLINE_STYLE:
1174 case CSS_PROP_TEXT_UNDERLINE_STYLE:
1175 if (id == CSS_VAL_NONE || id == CSS_VAL_SOLID || id == CSS_VAL_DOUBLE ||
1176 id == CSS_VAL_DASHED || id == CSS_VAL_DOT_DASH || id == CSS_VAL_DOT_DOT_DASH ||
1178 valid_primitive = true;
1180 case CSS_PROP_TEXT_LINE_THROUGH_WIDTH:
1181 case CSS_PROP_TEXT_OVERLINE_WIDTH:
1182 case CSS_PROP_TEXT_UNDERLINE_WIDTH:
1183 if (id == CSS_VAL_AUTO || id == CSS_VAL_NORMAL || id == CSS_VAL_THIN ||
1184 id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK)
1185 valid_primitive = true;
1187 valid_primitive = !id && validUnit(value, FNumber|FLength|FPercent, strict);
1189 case CSS_PROP_RESIZE: // none | both | horizontal | vertical | auto
1190 if (id == CSS_VAL_NONE || id == CSS_VAL_BOTH || id == CSS_VAL_HORIZONTAL || id == CSS_VAL_VERTICAL || id == CSS_VAL_AUTO)
1191 valid_primitive = true;
1193 // End of CSS3 properties
1195 // Apple specific properties. These will never be standardized and are purely to
1196 // support custom WebKit-based Apple applications.
1197 case CSS_PROP__WEBKIT_LINE_CLAMP:
1198 valid_primitive = (!id && validUnit(value, FPercent, false));
1200 case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST:
1201 if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE)
1202 valid_primitive = true;
1204 case CSS_PROP__WEBKIT_RTL_ORDERING:
1205 if (id == CSS_VAL_LOGICAL || id == CSS_VAL_VISUAL)
1206 valid_primitive = true;
1209 case CSS_PROP__WEBKIT_FONT_SIZE_DELTA: // <length>
1210 valid_primitive = validUnit(value, FLength, strict);
1213 case CSS_PROP__WEBKIT_NBSP_MODE: // normal | space
1214 if (id == CSS_VAL_NORMAL || id == CSS_VAL_SPACE)
1215 valid_primitive = true;
1218 case CSS_PROP__WEBKIT_LINE_BREAK: // normal | after-white-space
1219 if (id == CSS_VAL_NORMAL || id == CSS_VAL_AFTER_WHITE_SPACE)
1220 valid_primitive = true;
1223 case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR: // normal | match
1224 if (id == CSS_VAL_NORMAL || id == CSS_VAL_MATCH)
1225 valid_primitive = true;
1228 case CSS_PROP__WEBKIT_HIGHLIGHT:
1229 if (id == CSS_VAL_NONE || value->unit == CSSPrimitiveValue::CSS_STRING)
1230 valid_primitive = true;
1233 case CSS_PROP__WEBKIT_TEXT_SECURITY:
1234 // disc | circle | square | none | inherit
1235 if (id == CSS_VAL_DISC || id == CSS_VAL_CIRCLE || id == CSS_VAL_SQUARE|| id == CSS_VAL_NONE)
1236 valid_primitive = true;
1240 case CSS_PROP__WEBKIT_DASHBOARD_REGION: // <dashboard-region> | <dashboard-region>
1241 if (value->unit == Value::Function || id == CSS_VAL_NONE)
1242 return parseDashboardRegions(propId, important);
1245 // End Apple-specific properties
1247 /* shorthand properties */
1248 case CSS_PROP_BACKGROUND:
1249 // ['background-color' || 'background-image' || 'background-size' || 'background-repeat' ||
1250 // 'background-attachment' || 'background-position'] | inherit
1251 return parseBackgroundShorthand(important);
1252 case CSS_PROP_BORDER:
1253 // [ 'border-width' || 'border-style' || <color> ] | inherit
1255 const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
1256 CSS_PROP_BORDER_COLOR };
1257 return parseShorthand(propId, properties, 3, important);
1259 case CSS_PROP_BORDER_TOP:
1260 // [ 'border-top-width' || 'border-style' || <color> ] | inherit
1262 const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
1263 CSS_PROP_BORDER_TOP_COLOR};
1264 return parseShorthand(propId, properties, 3, important);
1266 case CSS_PROP_BORDER_RIGHT:
1267 // [ 'border-right-width' || 'border-style' || <color> ] | inherit
1269 const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
1270 CSS_PROP_BORDER_RIGHT_COLOR };
1271 return parseShorthand(propId, properties, 3, important);
1273 case CSS_PROP_BORDER_BOTTOM:
1274 // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
1276 const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
1277 CSS_PROP_BORDER_BOTTOM_COLOR };
1278 return parseShorthand(propId, properties, 3, important);
1280 case CSS_PROP_BORDER_LEFT:
1281 // [ 'border-left-width' || 'border-style' || <color> ] | inherit
1283 const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
1284 CSS_PROP_BORDER_LEFT_COLOR };
1285 return parseShorthand(propId, properties, 3, important);
1287 case CSS_PROP_OUTLINE:
1288 // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
1290 const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
1291 CSS_PROP_OUTLINE_COLOR };
1292 return parseShorthand(propId, properties, 3, important);
1294 case CSS_PROP_BORDER_COLOR:
1295 // <color>{1,4} | inherit
1297 const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
1298 CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
1299 return parse4Values(propId, properties, important);
1301 case CSS_PROP_BORDER_WIDTH:
1302 // <border-width>{1,4} | inherit
1304 const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
1305 CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
1306 return parse4Values(propId, properties, important);
1308 case CSS_PROP_BORDER_STYLE:
1309 // <border-style>{1,4} | inherit
1311 const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
1312 CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
1313 return parse4Values(propId, properties, important);
1315 case CSS_PROP_MARGIN:
1316 // <margin-width>{1,4} | inherit
1318 const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
1319 CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
1320 return parse4Values(propId, properties, important);
1322 case CSS_PROP_PADDING:
1323 // <padding-width>{1,4} | inherit
1325 const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
1326 CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
1327 return parse4Values(propId, properties, important);
1330 // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
1331 // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
1332 if (id >= CSS_VAL_CAPTION && id <= CSS_VAL_STATUS_BAR)
1333 valid_primitive = true;
1335 return parseFont(important);
1337 case CSS_PROP_LIST_STYLE:
1339 const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
1340 CSS_PROP_LIST_STYLE_IMAGE };
1341 return parseShorthand(propId, properties, 3, important);
1345 if (parseSVGValue(propId, important))
1351 if (valid_primitive) {
1353 parsedValue = new CSSPrimitiveValue(id); }
1354 else if (value->unit == CSSPrimitiveValue::CSS_STRING)
1355 parsedValue = new CSSPrimitiveValue(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit);
1356 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1357 parsedValue = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
1358 else if (value->unit >= Value::Q_EMS)
1359 parsedValue = new CSSQuirkPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_EMS);
1363 if (!valueList->current() || inShorthand()) {
1364 addProperty(propId, parsedValue, important);
1372 void CSSParser::addBackgroundValue(CSSValue*& lval, CSSValue* rval)
1375 if (lval->isValueList())
1376 static_cast<CSSValueList*>(lval)->append(rval);
1378 CSSValue* oldVal = lval;
1379 CSSValueList* list = new CSSValueList();
1381 list->append(oldVal);
1389 bool CSSParser::parseBackgroundShorthand(bool important)
1391 // Position must come before color in this array because a plain old "0" is a legal color
1392 // in quirks mode but it's usually the X coordinate of a position.
1393 // FIXME: Add CSS_PROP__KHTML_BACKGROUND_SIZE to the shorthand.
1394 const int properties[] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,
1395 CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, CSS_PROP__WEBKIT_BACKGROUND_CLIP,
1396 CSS_PROP__WEBKIT_BACKGROUND_ORIGIN, CSS_PROP_BACKGROUND_COLOR };
1397 const int numProperties = sizeof(properties) / sizeof(properties[0]);
1399 ShorthandScope scope(this, CSS_PROP_BACKGROUND);
1401 bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
1402 CSSValue* values[numProperties] = { 0 }; // compiler will repeat 0 as necessary
1403 CSSValue* positionYValue = 0;
1406 while (valueList->current()) {
1407 Value* val = valueList->current();
1408 if (val->unit == Value::Operator && val->iValue == ',') {
1409 // We hit the end. Fill in all remaining values with the initial value.
1411 for (i = 0; i < numProperties; ++i) {
1412 if (properties[i] == CSS_PROP_BACKGROUND_COLOR && parsedProperty[i])
1413 // Color is not allowed except as the last item in a list. Reject the entire
1417 if (!parsedProperty[i] && properties[i] != CSS_PROP_BACKGROUND_COLOR) {
1418 addBackgroundValue(values[i], new CSSInitialValue());
1419 if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
1420 addBackgroundValue(positionYValue, new CSSInitialValue());
1422 parsedProperty[i] = false;
1424 if (!valueList->current())
1429 for (i = 0; !found && i < numProperties; ++i) {
1430 if (!parsedProperty[i]) {
1431 CSSValue *val1 = 0, *val2 = 0;
1432 int propId1, propId2;
1433 if (parseBackgroundProperty(properties[i], propId1, propId2, val1, val2)) {
1434 parsedProperty[i] = found = true;
1435 addBackgroundValue(values[i], val1);
1436 if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
1437 addBackgroundValue(positionYValue, val2);
1442 // if we didn't find at least one match, this is an
1443 // invalid shorthand and we have to ignore it
1448 // Fill in any remaining properties with the initial value.
1449 for (i = 0; i < numProperties; ++i) {
1450 if (!parsedProperty[i]) {
1451 addBackgroundValue(values[i], new CSSInitialValue());
1452 if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
1453 addBackgroundValue(positionYValue, new CSSInitialValue());
1457 // Now add all of the properties we found.
1458 for (i = 0; i < numProperties; i++) {
1459 if (properties[i] == CSS_PROP_BACKGROUND_POSITION) {
1460 addProperty(CSS_PROP_BACKGROUND_POSITION_X, values[i], important);
1461 addProperty(CSS_PROP_BACKGROUND_POSITION_Y, positionYValue, important);
1464 addProperty(properties[i], values[i], important);
1470 for (int k = 0; k < numProperties; k++)
1472 delete positionYValue;
1476 bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
1478 // We try to match as many properties as possible
1479 // We set up an array of booleans to mark which property has been found,
1480 // and we try to search for properties until it makes no longer any sense.
1481 ShorthandScope scope(this, propId);
1484 bool fnd[6]; // Trust me ;)
1485 for (int i = 0; i < numProperties; i++)
1488 while (valueList->current()) {
1490 for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
1491 if (!fnd[propIndex]) {
1492 if (parseValue(properties[propIndex], important))
1493 fnd[propIndex] = found = true;
1497 // if we didn't find at least one match, this is an
1498 // invalid shorthand and we have to ignore it
1503 // Fill in any remaining properties with the initial value.
1504 m_implicitShorthand = true;
1505 for (int i = 0; i < numProperties; ++i) {
1507 addProperty(properties[i], new CSSInitialValue(), important);
1509 m_implicitShorthand = false;
1514 bool CSSParser::parse4Values(int propId, const int *properties, bool important)
1516 /* From the CSS 2 specs, 8.3
1517 * If there is only one value, it applies to all sides. If there are two values, the top and
1518 * bottom margins are set to the first value and the right and left margins are set to the second.
1519 * If there are three values, the top is set to the first value, the left and right are set to the
1520 * second, and the bottom is set to the third. If there are four values, they apply to the top,
1521 * right, bottom, and left, respectively.
1524 int num = inShorthand() ? 1 : valueList->size();
1526 ShorthandScope scope(this, propId);
1528 // the order is top, right, bottom, left
1531 if (!parseValue(properties[0], important))
1533 CSSValue *value = parsedProperties[numParsedProperties-1]->value();
1534 m_implicitShorthand = true;
1535 addProperty(properties[1], value, important);
1536 addProperty(properties[2], value, important);
1537 addProperty(properties[3], value, important);
1538 m_implicitShorthand = false;
1542 if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
1544 CSSValue *value = parsedProperties[numParsedProperties-2]->value();
1545 m_implicitShorthand = true;
1546 addProperty(properties[2], value, important);
1547 value = parsedProperties[numParsedProperties-2]->value();
1548 addProperty(properties[3], value, important);
1549 m_implicitShorthand = false;
1553 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
1555 CSSValue *value = parsedProperties[numParsedProperties-2]->value();
1556 m_implicitShorthand = true;
1557 addProperty(properties[3], value, important);
1558 m_implicitShorthand = false;
1562 if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
1563 !parseValue(properties[2], important) || !parseValue(properties[3], important))
1575 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
1576 // in CSS 2.1 this got somewhat reduced:
1577 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
1578 bool CSSParser::parseContent(int propId, bool important)
1580 RefPtr<CSSValueList> values = new CSSValueList;
1582 while (Value* val = valueList->current()) {
1583 RefPtr<CSSValue> parsedValue;
1584 if (val->unit == CSSPrimitiveValue::CSS_URI) {
1586 String value = parseURL(domString(val->string));
1587 parsedValue = new CSSImageValue(
1588 String(KURL(styleElement->baseURL().deprecatedString(), value.deprecatedString()).url()), styleElement);
1589 } else if (val->unit == Value::Function) {
1590 // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z])
1591 ValueList *args = val->function->args;
1592 String fname = domString(val->function->name).lower();
1595 if (fname == "attr(") {
1596 if (args->size() != 1)
1598 Value* a = args->current();
1599 String attrName = domString(a->string);
1600 if (document()->isHTMLDocument())
1601 attrName = attrName.lower();
1602 parsedValue = new CSSPrimitiveValue(attrName, CSSPrimitiveValue::CSS_ATTR);
1603 } else if (fname == "counter(") {
1604 parsedValue = parseCounterContent(args, false);
1605 if (!parsedValue) return false;
1606 } else if (fname == "counters(") {
1607 parsedValue = parseCounterContent(args, true);
1612 } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
1617 // FIXME: These are not yet implemented (http://bugzilla.opendarwin.org/show_bug.cgi?id=6503).
1618 } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
1619 parsedValue = new CSSPrimitiveValue(domString(val->string), CSSPrimitiveValue::CSS_STRING);
1623 values->append(parsedValue.release());
1627 if (values->length()) {
1628 addProperty(propId, values.release(), important);
1636 CSSValue* CSSParser::parseBackgroundColor()
1638 int id = valueList->current()->id;
1639 if (id == CSS_VAL__WEBKIT_TEXT || (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || id == CSS_VAL_MENU ||
1640 (id >= CSS_VAL_GREY && id < CSS_VAL__WEBKIT_TEXT && !strict))
1641 return new CSSPrimitiveValue(id);
1642 return parseColor();
1645 CSSValue* CSSParser::parseBackgroundImage()
1647 if (valueList->current()->id == CSS_VAL_NONE)
1648 return new CSSImageValue();
1649 if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
1650 String uri = parseURL(domString(valueList->current()->string));
1652 return new CSSImageValue(String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()),
1658 CSSValue* CSSParser::parseBackgroundPositionXY(bool& xFound, bool& yFound)
1660 int id = valueList->current()->id;
1661 if (id == CSS_VAL_LEFT || id == CSS_VAL_TOP || id == CSS_VAL_RIGHT || id == CSS_VAL_BOTTOM || id == CSS_VAL_CENTER) {
1663 if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT) {
1667 if (id == CSS_VAL_RIGHT)
1670 else if (id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) {
1674 if (id == CSS_VAL_BOTTOM)
1677 else if (id == CSS_VAL_CENTER)
1678 // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
1680 return new CSSPrimitiveValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
1682 if (validUnit(valueList->current(), FPercent|FLength, strict))
1683 return new CSSPrimitiveValue(valueList->current()->fValue,
1684 (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
1689 void CSSParser::parseBackgroundPosition(CSSValue*& value1, CSSValue*& value2)
1691 value1 = value2 = 0;
1692 Value* value = valueList->current();
1694 // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
1695 bool value1IsX = false, value1IsY = false;
1696 value1 = parseBackgroundPositionXY(value1IsX, value1IsY);
1700 // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
1701 // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
1702 // value was explicitly specified for our property.
1703 value = valueList->next();
1705 // First check for the comma. If so, we are finished parsing this value or value pair.
1706 if (value && value->unit == Value::Operator && value->iValue == ',')
1709 bool value2IsX = false, value2IsY = false;
1711 value2 = parseBackgroundPositionXY(value2IsX, value2IsY);
1715 if (!inShorthand()) {
1724 // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
1725 // is simply 50%. This is our default.
1726 // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
1727 // For left/right/center, the default of 50% in the y is still correct.
1728 value2 = new CSSPrimitiveValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
1730 if (value1IsY || value2IsX) {
1731 // Swap our two values.
1732 CSSValue* val = value2;
1738 CSSValue* CSSParser::parseBackgroundSize()
1740 Value* value = valueList->current();
1741 CSSPrimitiveValue* parsedValue1;
1743 if (value->id == CSS_VAL_AUTO)
1744 parsedValue1 = new CSSPrimitiveValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
1746 if (!validUnit(value, FLength|FPercent, strict))
1748 parsedValue1 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1751 CSSPrimitiveValue* parsedValue2 = parsedValue1;
1752 if ((value = valueList->next())) {
1753 if (value->id == CSS_VAL_AUTO)
1754 parsedValue2 = new CSSPrimitiveValue(0, CSSPrimitiveValue::CSS_UNKNOWN);
1756 if (!validUnit(value, FLength|FPercent, strict)) {
1757 delete parsedValue1;
1760 parsedValue2 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
1764 Pair* pair = new Pair(parsedValue1, parsedValue2);
1765 return new CSSPrimitiveValue(pair);
1768 bool CSSParser::parseBackgroundProperty(int propId, int& propId1, int& propId2,
1769 CSSValue*& retValue1, CSSValue*& retValue2)
1771 CSSValueList *values = 0, *values2 = 0;
1773 CSSValue *value = 0, *value2 = 0;
1774 bool allowComma = false;
1776 retValue1 = retValue2 = 0;
1779 if (propId == CSS_PROP_BACKGROUND_POSITION) {
1780 propId1 = CSS_PROP_BACKGROUND_POSITION_X;
1781 propId2 = CSS_PROP_BACKGROUND_POSITION_Y;
1784 while ((val = valueList->current())) {
1785 CSSValue *currValue = 0, *currValue2 = 0;
1787 if (val->unit != Value::Operator || val->iValue != ',')
1794 case CSS_PROP_BACKGROUND_ATTACHMENT:
1795 if (val->id == CSS_VAL_SCROLL || val->id == CSS_VAL_FIXED) {
1796 currValue = new CSSPrimitiveValue(val->id);
1800 case CSS_PROP_BACKGROUND_COLOR:
1801 currValue = parseBackgroundColor();
1805 case CSS_PROP_BACKGROUND_IMAGE:
1806 currValue = parseBackgroundImage();
1810 case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
1811 case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
1812 if (val->id == CSS_VAL_BORDER || val->id == CSS_VAL_PADDING || val->id == CSS_VAL_CONTENT) {
1813 currValue = new CSSPrimitiveValue(val->id);
1817 case CSS_PROP_BACKGROUND_POSITION:
1818 parseBackgroundPosition(currValue, currValue2);
1819 // unlike the other functions, parseBackgroundPosition advances the valueList pointer
1821 case CSS_PROP_BACKGROUND_POSITION_X: {
1822 bool xFound = false, yFound = true;
1823 currValue = parseBackgroundPositionXY(xFound, yFound);
1828 case CSS_PROP_BACKGROUND_POSITION_Y: {
1829 bool xFound = true, yFound = false;
1830 currValue = parseBackgroundPositionXY(xFound, yFound);
1835 case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
1836 if ((val->id >= CSS_VAL_CLEAR && val->id <= CSS_VAL_PLUS_LIGHTER) || val->id == CSS_VAL_HIGHLIGHT) {
1837 currValue = new CSSPrimitiveValue(val->id);
1841 case CSS_PROP_BACKGROUND_REPEAT:
1842 if (val->id >= CSS_VAL_REPEAT && val->id <= CSS_VAL_NO_REPEAT) {
1843 currValue = new CSSPrimitiveValue(val->id);
1847 case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
1848 currValue = parseBackgroundSize();
1857 if (value && !values) {
1858 values = new CSSValueList();
1859 values->append(value);
1863 if (value2 && !values2) {
1864 values2 = new CSSValueList();
1865 values2->append(value2);
1870 values->append(currValue);
1875 values2->append(currValue2);
1877 value2 = currValue2;
1882 // When parsing the 'background' shorthand property, we let it handle building up the lists for all
1888 if (values && values->length()) {
1890 if (values2 && values2->length())
1891 retValue2 = values2;
1901 delete values; delete values2;
1902 delete value; delete value2;
1907 #define DASHBOARD_REGION_NUM_PARAMETERS 6
1908 #define DASHBOARD_REGION_SHORT_NUM_PARAMETERS 2
1910 static Value *skipCommaInDashboardRegion (ValueList *args)
1912 if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
1913 args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
1914 Value *current = args->current();
1915 if (current->unit == Value::Operator && current->iValue == ',')
1916 return args->next();
1918 return args->current();
1921 bool CSSParser::parseDashboardRegions(int propId, bool important)
1925 Value *value = valueList->current();
1927 if (value->id == CSS_VAL_NONE) {
1928 addProperty(propId, new CSSPrimitiveValue(value->id), important);
1932 RefPtr<DashboardRegion> firstRegion = new DashboardRegion;
1933 DashboardRegion* region = 0;
1937 region = firstRegion.get();
1939 RefPtr<DashboardRegion> nextRegion = new DashboardRegion();
1940 region->m_next = nextRegion;
1941 region = nextRegion.get();
1944 if (value->unit != Value::Function) {
1949 // Commas count as values, so allow:
1950 // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
1951 // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
1953 // dashboard-region(label, type) or dashboard-region(label type)
1954 // dashboard-region(label, type) or dashboard-region(label type)
1955 ValueList* args = value->function->args;
1956 String fname = domString(value->function->name).lower();
1957 if (fname != "dashboard-region(" || !args) {
1962 int numArgs = args->size();
1963 if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
1964 (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))){
1969 // First arg is a label.
1970 Value* arg = args->current();
1971 if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
1976 region->m_label = domString(arg->string);
1978 // Second arg is a type.
1980 arg = skipCommaInDashboardRegion (args);
1981 if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
1986 String geometryType = domString(arg->string).lower();
1987 if (geometryType == "circle")
1988 region->m_isCircle = true;
1989 else if (geometryType == "rectangle")
1990 region->m_isRectangle = true;
1996 region->m_geometryType = domString(arg->string);
1998 if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
1999 CSSPrimitiveValue *amount = arg->id == CSS_VAL_AUTO ?
2000 new CSSPrimitiveValue(CSS_VAL_AUTO) :
2001 new CSSPrimitiveValue((double)0, (CSSPrimitiveValue::UnitTypes) arg->unit);
2003 region->setTop(amount);
2004 region->setRight(amount);
2005 region->setBottom(amount);
2006 region->setLeft(amount);
2009 // Next four arguments must be offset numbers
2011 for (i = 0; i < 4; i++) {
2013 arg = skipCommaInDashboardRegion (args);
2015 valid = arg->id == CSS_VAL_AUTO || validUnit(arg, FLength, strict);
2019 CSSPrimitiveValue *amount = arg->id == CSS_VAL_AUTO ?
2020 new CSSPrimitiveValue(CSS_VAL_AUTO) :
2021 new CSSPrimitiveValue(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit);
2024 region->setTop(amount);
2026 region->setRight(amount);
2028 region->setBottom(amount);
2030 region->setLeft(amount);
2034 value = valueList->next();
2038 addProperty(propId, new CSSPrimitiveValue(firstRegion.release()), important);
2044 PassRefPtr<CSSValue> CSSParser::parseCounterContent(ValueList* args, bool counters)
2046 unsigned numArgs = args->size();
2047 if (counters && numArgs != 3 && numArgs != 5)
2049 if (!counters && numArgs != 1 && numArgs != 3)
2052 Value* i = args->current();
2053 RefPtr<CSSPrimitiveValue> identifier = new CSSPrimitiveValue(domString(i->string),
2054 CSSPrimitiveValue::CSS_STRING);
2056 RefPtr<CSSPrimitiveValue> separator;
2058 separator = new CSSPrimitiveValue(String(), CSSPrimitiveValue::CSS_STRING);
2061 if (i->unit != Value::Operator || i->iValue != ',')
2065 if (i->unit != CSSPrimitiveValue::CSS_STRING)
2068 separator = new CSSPrimitiveValue(domString(i->string), (CSSPrimitiveValue::UnitTypes) i->unit);
2071 RefPtr<CSSPrimitiveValue> listStyle;
2073 if (!i) // Make the list style default decimal
2074 listStyle = new CSSPrimitiveValue(CSS_VAL_DECIMAL - CSS_VAL_DISC, CSSPrimitiveValue::CSS_NUMBER);
2076 if (i->unit != Value::Operator || i->iValue != ',')
2080 if (i->unit != CSSPrimitiveValue::CSS_IDENT)
2084 if (i->id == CSS_VAL_NONE)
2085 ls = CSS_VAL_KATAKANA_IROHA - CSS_VAL_DISC + 1;
2086 else if (i->id >= CSS_VAL_DISC && i->id <= CSS_VAL_KATAKANA_IROHA)
2087 ls = i->id - CSS_VAL_DISC;
2091 listStyle = new CSSPrimitiveValue(ls, (CSSPrimitiveValue::UnitTypes) i->unit);
2094 return new CSSPrimitiveValue(new Counter(identifier.release(), listStyle.release(), separator.release()));
2097 bool CSSParser::parseShape(int propId, bool important)
2099 Value *value = valueList->current();
2100 ValueList *args = value->function->args;
2101 String fname = domString(value->function->name).lower();
2102 if (fname != "rect(" || !args)
2105 // rect(t, r, b, l) || rect(t r b l)
2106 if (args->size() != 4 && args->size() != 7)
2108 RectImpl *rect = new RectImpl();
2111 Value *a = args->current();
2113 valid = a->id == CSS_VAL_AUTO || validUnit(a, FLength, strict);
2116 CSSPrimitiveValue *length = a->id == CSS_VAL_AUTO ?
2117 new CSSPrimitiveValue(CSS_VAL_AUTO) :
2118 new CSSPrimitiveValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
2120 rect->setTop(length);
2122 rect->setRight(length);
2124 rect->setBottom(length);
2126 rect->setLeft(length);
2128 if (a && args->size() == 7) {
2129 if (a->unit == Value::Operator && a->iValue == ',') {
2139 addProperty(propId, new CSSPrimitiveValue(rect), important);
2147 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
2148 bool CSSParser::parseFont(bool important)
2151 Value *value = valueList->current();
2152 FontValue *font = new FontValue;
2153 // optional font-style, font-variant and font-weight
2157 if (id == CSS_VAL_NORMAL) {
2158 // do nothing, it's the inital value for all three
2159 } else if (id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE) {
2162 font->style = new CSSPrimitiveValue(id);
2163 } else if (id == CSS_VAL_SMALL_CAPS) {
2166 font->variant = new CSSPrimitiveValue(id);
2167 } else if (id >= CSS_VAL_BOLD && id <= CSS_VAL_LIGHTER) {
2170 font->weight = new CSSPrimitiveValue(id);
2174 } else if (!font->weight && validUnit(value, FInteger|FNonNeg, true)) {
2175 int weight = (int)value->fValue;
2179 else if (weight == 200)
2181 else if (weight == 300)
2183 else if (weight == 400)
2185 else if (weight == 500)
2187 else if (weight == 600)
2189 else if (weight == 700)
2191 else if (weight == 800)
2193 else if (weight == 900)
2197 font->weight = new CSSPrimitiveValue(val);
2205 value = valueList->next();
2210 // set undefined values to default
2212 font->style = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2214 font->variant = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2216 font->weight = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2218 // now a font size _must_ come
2219 // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
2220 if (value->id >= CSS_VAL_XX_SMALL && value->id <= CSS_VAL_LARGER)
2221 font->size = new CSSPrimitiveValue(value->id);
2222 else if (validUnit(value, FLength|FPercent, strict))
2223 font->size = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2224 value = valueList->next();
2225 if (!font->size || !value)
2228 if (value->unit == Value::Operator && value->iValue == '/') {
2230 value = valueList->next();
2233 if (value->id == CSS_VAL_NORMAL) {
2234 // default value, nothing to do
2235 } else if (validUnit(value, FNumber|FLength|FPercent, strict))
2236 font->lineHeight = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
2239 value = valueList->next();
2244 if (!font->lineHeight)
2245 font->lineHeight = new CSSPrimitiveValue(CSS_VAL_NORMAL);
2247 // font family must come now
2248 font->family = parseFontFamily();
2250 if (valueList->current() || !font->family)
2253 addProperty(CSS_PROP_FONT, font, important);
2261 CSSValueList* CSSParser::parseFontFamily()
2263 CSSValueList* list = new CSSValueList;
2264 Value* value = valueList->current();
2265 FontFamilyValue* currFamily = 0;
2267 Value* nextValue = valueList->next();
2268 bool nextValBreaksFont = !nextValue ||
2269 (nextValue->unit == Value::Operator && nextValue->iValue == ',');
2270 bool nextValIsFontName = nextValue &&
2271 ((nextValue->id >= CSS_VAL_SERIF && nextValue->id <= CSS_VAL__WEBKIT_BODY) ||
2272 (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
2274 if (value->id >= CSS_VAL_SERIF && value->id <= CSS_VAL__WEBKIT_BODY) {
2276 currFamily->parsedFontName += ' ';
2277 currFamily->parsedFontName += deprecatedString(value->string);
2279 else if (nextValBreaksFont || !nextValIsFontName)
2280 list->append(new CSSPrimitiveValue(value->id));
2282 list->append(currFamily = new FontFamilyValue(deprecatedString(value->string)));
2284 else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
2285 // Strings never share in a family name.
2287 list->append(new FontFamilyValue(deprecatedString(value->string)));
2289 else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2291 currFamily->parsedFontName += ' ';
2292 currFamily->parsedFontName += deprecatedString(value->string);
2294 else if (nextValBreaksFont || !nextValIsFontName)
2295 list->append(new FontFamilyValue(deprecatedString(value->string)));
2297 list->append(currFamily = new FontFamilyValue(deprecatedString(value->string)));
2306 if (nextValBreaksFont) {
2307 value = valueList->next();
2310 else if (nextValIsFontName)
2315 if (!list->length()) {
2323 bool CSSParser::parseColor(const DeprecatedString &name, RGBA32& rgb)
2325 // FIXME: Should we move this stuff about hex digits without a "#" prefix
2326 // into the Color class along with the "#"-prefix version?
2328 int len = name.length();
2335 if ( len == 3 || len == 6 ) {
2336 int val = name.toInt(&ok, 16);
2339 rgb = (0xff << 24) | val;
2342 else if ( len == 3 ) {
2343 // #abc converts to #aabbcc according to the specs
2344 rgb = (0xff << 24) |
2345 (val&0xf00)<<12 | (val&0xf00)<<8 |
2346 (val&0xf0)<<8 | (val&0xf0)<<4 |
2347 (val&0xf)<<4 | (val&0xf);
2353 // try a little harder
2355 tc.setNamedColor(name.lower());
2364 bool CSSParser::parseColorParameters(Value* value, int* colorArray, bool parseAlpha)
2366 ValueList* args = value->function->args;
2367 Value* v = args->current();
2368 // Get the first value
2369 if (!validUnit(v, FInteger | FPercent, true))
2371 colorArray[0] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
2372 for (int i = 1; i < 3; i++) {
2374 if (v->unit != Value::Operator && v->iValue != ',')
2377 if (!validUnit(v, FInteger | FPercent, true))
2379 colorArray[i] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
2383 if (v->unit != Value::Operator && v->iValue != ',')
2386 if (!validUnit(v, FNumber, true))
2388 colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * 255);
2393 // CSS3 sepcification defines the format of a HSL color as
2394 // hsl(<number>, <percent>, <percent>)
2395 // and with alpha, the format is
2396 // hsla(<number>, <percent>, <percent>, <number>)
2397 // The first value, HUE, is in an angle with a value between 0 and 360
2398 bool CSSParser::parseHSLParameters(Value* value, double* colorArray, bool parseAlpha)
2400 ValueList* args = value->function->args;
2401 Value* v = args->current();
2402 // Get the first value
2403 if (!validUnit(v, FInteger, true))
2405 // normalize the Hue value and change it to be between 0 and 1.0
2406 colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0;
2407 for (int i = 1; i < 3; i++) {
2409 if (v->unit != Value::Operator && v->iValue != ',')
2412 if (!validUnit(v, FPercent, true))
2414 colorArray[i] = max(0.0, min(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0
2418 if (v->unit != Value::Operator && v->iValue != ',')
2421 if (!validUnit(v, FNumber, true))
2423 colorArray[3] = max(0.0, min(1.0, v->fValue));
2428 CSSPrimitiveValue *CSSParser::parseColor()
2430 return parseColorFromValue(valueList->current());
2433 CSSPrimitiveValue *CSSParser::parseColorFromValue(Value* value)
2435 RGBA32 c = Color::transparent;
2436 if (!strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
2437 value->fValue >= 0. && value->fValue < 1000000.) {
2438 DeprecatedString str;
2439 str.sprintf("%06d", (int)(value->fValue+.5));
2440 if (!CSSParser::parseColor(str, c))
2442 } else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR ||
2443 value->unit == CSSPrimitiveValue::CSS_IDENT ||
2444 (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
2445 if (!CSSParser::parseColor(deprecatedString(value->string), c))
2447 } else if (value->unit == Value::Function &&
2448 value->function->args != 0 &&
2449 value->function->args->size() == 5 /* rgb + two commas */ &&
2450 domString(value->function->name).lower() == "rgb(") {
2452 if (!parseColorParameters(value, colorValues, false))
2454 c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
2455 } else if (value->unit == Value::Function &&
2456 value->function->args != 0 &&
2457 value->function->args->size() == 7 /* rgba + three commas */ &&
2458 domString(value->function->name).lower() == "rgba(") {
2460 if (!parseColorParameters(value, colorValues, true))
2462 c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
2463 } else if (value->unit == Value::Function &&
2464 value->function->args != 0 &&
2465 value->function->args->size() == 5 /* hsl + two commas */ &&
2466 domString(value->function->name).lower() == "hsl(") {
2467 double colorValues[3];
2468 if (!parseHSLParameters(value, colorValues, false))
2470 c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
2471 } else if (value->unit == Value::Function &&
2472 value->function->args != 0 &&
2473 value->function->args->size() == 7 /* hsla + three commas */ &&
2474 domString(value->function->name).lower() == "hsla(") {
2475 double colorValues[4];
2476 if (!parseHSLParameters(value, colorValues, true))
2478 c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
2482 return new CSSPrimitiveValue(c);
2485 // This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return)
2486 // without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
2487 struct ShadowParseContext {
2488 ShadowParseContext()
2489 :values(0), x(0), y(0), blur(0), color(0),
2490 allowX(true), allowY(false), allowBlur(false), allowColor(true),
2494 ~ShadowParseContext() {
2504 bool allowLength() { return allowX || allowY || allowBlur; }
2506 bool failed() { return allowBreak = false; }
2508 void commitValue() {
2509 // Handle the ,, case gracefully by doing nothing.
2510 if (x || y || blur || color) {
2512 values = new CSSValueList();
2514 // Construct the current shadow value and add it to the list.
2515 values->append(new ShadowValue(x, y, blur, color));
2518 // Now reset for the next shadow value.
2519 x = y = blur = color = 0;
2520 allowX = allowColor = allowBreak = true;
2521 allowY = allowBlur = false;
2524 void commitLength(Value* v) {
2525 CSSPrimitiveValue* val = new CSSPrimitiveValue(v->fValue,
2526 (CSSPrimitiveValue::UnitTypes)v->unit);
2529 allowX = false; allowY = true; allowColor = false; allowBreak = false;
2533 allowY = false; allowBlur = true; allowColor = true; allowBreak = true;
2535 else if (allowBlur) {
2541 void commitColor(CSSPrimitiveValue* val) {
2550 CSSValueList* values;
2551 CSSPrimitiveValue* x;
2552 CSSPrimitiveValue* y;
2553 CSSPrimitiveValue* blur;
2554 CSSPrimitiveValue* color;
2563 bool CSSParser::parseShadow(int propId, bool important)
2565 ShadowParseContext context;
2567 while ((val = valueList->current())) {
2568 // Check for a comma break first.
2569 if (val->unit == Value::Operator) {
2570 if (val->iValue != ',' || !context.allowBreak)
2571 // Other operators aren't legal or we aren't done with the current shadow
2572 // value. Treat as invalid.
2573 return context.failed();
2575 // The value is good. Commit it.
2576 context.commitValue();
2578 // Check to see if we're a length.
2579 else if (validUnit(val, FLength, true)) {
2580 // We required a length and didn't get one. Invalid.
2581 if (!context.allowLength())
2582 return context.failed();
2584 // A length is allowed here. Construct the value and add it.
2585 context.commitLength(val);
2588 // The only other type of value that's ok is a color value.
2589 CSSPrimitiveValue* parsedColor = 0;
2590 bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU ||
2591 (val->id >= CSS_VAL__WEBKIT_FOCUS_RING_COLOR && val->id <= CSS_VAL__WEBKIT_TEXT && !strict));
2593 if (!context.allowColor)
2594 return context.failed();
2595 parsedColor = new CSSPrimitiveValue(val->id);
2599 // It's not built-in. Try to parse it as a color.
2600 parsedColor = parseColorFromValue(val);
2602 if (!parsedColor || !context.allowColor)
2603 return context.failed(); // This value is not a color or length and is invalid or
2604 // it is a color, but a color isn't allowed at this point.
2606 context.commitColor(parsedColor);
2612 if (context.allowBreak) {
2613 context.commitValue();
2614 if (context.values->length()) {
2615 addProperty(propId, context.values, important);
2621 return context.failed();
2624 struct BorderImageParseContext
2626 BorderImageParseContext()
2627 :m_allowBreak(false), m_allowNumber(false), m_allowSlash(false), m_allowWidth(false),
2628 m_allowRule(false), m_image(0), m_top(0), m_right(0), m_bottom(0), m_left(0), m_borderTop(0), m_borderRight(0), m_borderBottom(0),
2629 m_borderLeft(0), m_horizontalRule(0), m_verticalRule(0)
2632 ~BorderImageParseContext() {
2633 if (!m_allowBreak) {
2635 delete m_top; delete m_right; delete m_bottom; delete m_left;
2636 delete m_borderTop; delete m_borderRight; delete m_borderBottom; delete m_borderLeft;
2640 bool failed() { return m_allowBreak = false; }
2641 bool allowBreak() const { return m_allowBreak; }
2642 bool allowNumber() const { return m_allowNumber; }
2643 bool allowSlash() const { return m_allowSlash; }
2644 bool allowWidth() const { return m_allowWidth; }
2645 bool allowRule() const { return m_allowRule; }
2647 void commitImage(CSSImageValue* image) { m_image = image; m_allowNumber = true; }
2648 void commitNumber(Value* v) {
2649 CSSPrimitiveValue* val = new CSSPrimitiveValue(v->fValue,
2650 (CSSPrimitiveValue::UnitTypes)v->unit);
2662 m_allowBreak = m_allowSlash = m_allowRule = true;
2663 m_allowNumber = !m_left;
2665 void commitSlash() { m_allowBreak = m_allowSlash = m_allowNumber = false; m_allowWidth = true; }
2666 void commitWidth(Value* val) {
2669 else if (!m_borderRight)
2670 m_borderRight = val;
2671 else if (!m_borderBottom)
2672 m_borderBottom = val;
2674 assert(!m_borderLeft);
2678 m_allowBreak = m_allowRule = true;
2679 m_allowWidth = !m_borderLeft;
2681 void commitRule(int keyword) {
2682 if (!m_horizontalRule)
2683 m_horizontalRule = keyword;
2684 else if (!m_verticalRule)
2685 m_verticalRule = keyword;
2686 m_allowRule = !m_verticalRule;
2688 void commitBorderImage(CSSParser* p, int propId, bool important) {
2689 // We need to clone and repeat values for any omissions.
2691 m_right = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2692 m_bottom = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2693 m_left = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2696 m_bottom = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2697 m_left = new CSSPrimitiveValue(m_right->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
2700 m_left = new CSSPrimitiveValue(m_top->getFloatValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType());
2702 // Now build a rect value to hold all four of our primitive values.
2703 RectImpl* rect = new RectImpl;
2704 rect->setTop(m_top); rect->setRight(m_right); rect->setBottom(m_bottom); rect->setLeft(m_left);
2706 // Fill in STRETCH as the default if it wasn't specified.
2707 if (!m_horizontalRule)
2708 m_horizontalRule = CSS_VAL_STRETCH;
2709 if (!m_verticalRule)
2710 m_verticalRule = CSS_VAL_STRETCH;
2712 // Make our new border image value now and add it as the result.
2713 CSSBorderImageValue* borderImage = new CSSBorderImageValue(m_image, rect, m_horizontalRule, m_verticalRule);
2714 p->addProperty(propId, borderImage, important);
2716 // 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
2717 // list and then make our parsing machinery do the parsing.
2720 newList.addValue(*m_borderTop);
2722 newList.addValue(*m_borderRight);
2724 newList.addValue(*m_borderBottom);
2726 newList.addValue(*m_borderLeft);
2727 p->valueList = &newList;
2728 p->parseValue(CSS_PROP_BORDER_WIDTH, important);
2739 CSSImageValue* m_image;
2741 CSSPrimitiveValue* m_top;
2742 CSSPrimitiveValue* m_right;
2743 CSSPrimitiveValue* m_bottom;
2744 CSSPrimitiveValue* m_left;
2747 Value* m_borderRight;
2748 Value* m_borderBottom;
2749 Value* m_borderLeft;
2751 int m_horizontalRule;
2755 bool CSSParser::parseBorderImage(int propId, bool important)
2757 // Look for an image initially. If the first value is not a URI, then we're done.
2758 BorderImageParseContext context;
2759 Value* val = valueList->current();
2760 if (val->unit != CSSPrimitiveValue::CSS_URI)
2761 return context.failed();
2763 String uri = parseURL(domString(val->string));
2765 return context.failed();
2767 context.commitImage(new CSSImageValue(String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()),
2769 while ((val = valueList->next())) {
2770 if (context.allowNumber() && validUnit(val, FInteger|FNonNeg|FPercent, true)) {
2771 context.commitNumber(val);
2772 } else if (context.allowSlash() && val->unit == Value::Operator && val->iValue == '/') {
2773 context.commitSlash();
2774 } else if (context.allowWidth() &&
2775 (val->id == CSS_VAL_THIN || val->id == CSS_VAL_MEDIUM || val->id == CSS_VAL_THICK || validUnit(val, FLength, strict))) {
2776 context.commitWidth(val);
2777 } else if (context.allowRule() &&
2778 (val->id == CSS_VAL_STRETCH || val->id == CSS_VAL_ROUND || val->id == CSS_VAL_REPEAT)) {
2779 context.commitRule(val->id);
2781 // Something invalid was encountered.
2782 return context.failed();
2786 if (context.allowBreak()) {
2787 // Need to fully commit as a single value.
2788 context.commitBorderImage(this, propId, important);
2792 return context.failed();
2795 bool CSSParser::parseCounter(int propId, int defaultValue, bool important)
2797 enum { ID, VAL } state = ID;
2799 RefPtr<CSSValueList> list = new CSSValueList;
2800 RefPtr<CSSPrimitiveValue> counterName;
2803 Value* val = valueList->current();
2806 if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
2807 counterName = new CSSPrimitiveValue(domString(val->string), CSSPrimitiveValue::CSS_STRING);
2814 int i = defaultValue;
2815 if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
2816 i = (int)val->fValue;
2820 list->append(new CSSPrimitiveValue(new Pair(counterName.release(),
2821 new CSSPrimitiveValue(i, CSSPrimitiveValue::CSS_NUMBER))));
2829 if (list->length() > 0) {
2830 addProperty(propId, list.release(), important);
2839 static inline int yyerror(const char *str)
2841 kdDebug(6080) << "CSS parse error " << str << endl;
2847 static inline int yyerror(const char*) { return 1; }
2853 #include "CSSGrammar.h"
2855 int CSSParser::lex(void* yylvalWithoutType)
2857 YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType);
2860 UChar* t = text(&length);
2877 yylval->string.characters = t;
2878 yylval->string.length = length;
2915 yylval->val = DeprecatedString((DeprecatedChar *)t, length).toDouble();
2925 static inline int toHex(char c)
2927 if ('0' <= c && c <= '9')
2929 if ('a' <= c && c <= 'f')
2930 return c - 'a' + 10;
2931 if ('A' <= c && c<= 'F')
2932 return c - 'A' + 10;
2936 UChar* CSSParser::text(int *length)
2938 UChar* start = yytext;
2949 // "url("{w}{string}{w}")"
2950 // "url("{w}{url}{w}")"
2952 // strip "url(" and ")"
2957 (*start == ' ' || *start == '\t' || *start == '\r' ||
2958 *start == '\n' || *start == '\f')) {
2961 if (*start == '"' || *start == '\'') {
2965 (start[l-1] == ' ' || start[l-1] == '\t' || start[l-1] == '\r' ||
2966 start[l-1] == '\n' || start[l-1] == '\f')) {
2969 if (l && (start[l-1] == '\"' || start[l-1] == '\''))
2980 for (int i = 0; i < l; i++) {
2981 UChar* current = start + i;
2982 if (escape == current - 1) {
2983 if ((*current >= '0' && *current <= '9') ||
2984 (*current >= 'a' && *current <= 'f') ||
2985 (*current >= 'A' && *current <= 'F'))
2987 if (yyTok == STRING &&
2988 (*current == '\n' || *current == '\r' || *current == '\f')) {
2989 // ### handle \r\n case
2990 if (*current != '\r')
2994 // in all other cases copy the char to output
3000 if (escape == current - 2 && yyTok == STRING &&
3001 *(current-1) == '\r' && *current == '\n') {
3005 if (escape > current - 7 &&
3006 ((*current >= '0' && *current <= '9') ||
3007 (*current >= 'a' && *current <= 'f') ||
3008 (*current >= 'A' && *current <= 'F')))
3014 while (escape < current) {
3016 uc += toHex(*escape);
3019 // can't handle chars outside ucs2
3024 if (*current == ' ' ||
3031 if (!escape && *current == '\\') {
3041 while (escape < start+l) {
3043 uc += toHex(*escape);
3046 // can't handle chars outside ucs2
3052 *length = out - start;
3056 CSSSelector* CSSParser::createFloatingSelector()
3058 CSSSelector* selector = new CSSSelector;
3059 m_floatingSelectors.add(selector);
3063 CSSSelector* CSSParser::sinkFloatingSelector(CSSSelector* selector)
3066 ASSERT(m_floatingSelectors.contains(selector));
3067 m_floatingSelectors.remove(selector);
3072 ValueList* CSSParser::createFloatingValueList()
3074 ValueList* list = new ValueList;
3075 m_floatingValueLists.add(list);
3079 ValueList* CSSParser::sinkFloatingValueList(ValueList* list)
3082 ASSERT(m_floatingValueLists.contains(list));
3083 m_floatingValueLists.remove(list);
3088 Function* CSSParser::createFloatingFunction()
3090 Function* function = new Function;
3091 m_floatingFunctions.add(function);
3095 Function* CSSParser::sinkFloatingFunction(Function* function)
3098 ASSERT(m_floatingFunctions.contains(function));
3099 m_floatingFunctions.remove(function);
3104 Value& CSSParser::sinkFloatingValue(Value& value)
3106 if (value.unit == Value::Function) {
3107 ASSERT(m_floatingFunctions.contains(value.function));
3108 m_floatingFunctions.remove(value.function);
3113 MediaQueryExp* CSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, ValueList* values)
3115 delete m_floatingMediaQueryExp;
3116 m_floatingMediaQueryExp = new MediaQueryExp(mediaFeature, values);
3117 return m_floatingMediaQueryExp;
3120 MediaQueryExp* CSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* e)
3122 ASSERT(e == m_floatingMediaQueryExp);
3123 m_floatingMediaQueryExp = 0;
3127 Vector<MediaQueryExp*>* CSSParser::createFloatingMediaQueryExpList()
3129 if (m_floatingMediaQueryExpList) {
3130 deleteAllValues(*m_floatingMediaQueryExpList);
3131 delete m_floatingMediaQueryExpList;
3133 m_floatingMediaQueryExpList = new Vector<MediaQueryExp*>;
3134 return m_floatingMediaQueryExpList;
3137 Vector<MediaQueryExp*>* CSSParser::sinkFloatingMediaQueryExpList(Vector<MediaQueryExp*>* l)
3139 ASSERT(l == m_floatingMediaQueryExpList);
3140 m_floatingMediaQueryExpList = 0;
3144 MediaQuery* CSSParser::createFloatingMediaQuery(MediaQuery::Restrictor r, const String& mediaType, Vector<MediaQueryExp*>* exprs)
3146 delete m_floatingMediaQuery;
3147 m_floatingMediaQuery = new MediaQuery(r, mediaType, exprs);
3148 return m_floatingMediaQuery;
3151 MediaQuery* CSSParser::sinkFloatingMediaQuery(MediaQuery* mq)
3153 ASSERT(mq == m_floatingMediaQuery);
3154 m_floatingMediaQuery = 0;
3158 MediaList* CSSParser::createMediaList()
3160 MediaList* list = new MediaList;
3161 m_parsedStyleObjects.append(list);
3165 CSSRule* CSSParser::createCharsetRule(const ParseString& charset)
3169 if (!styleElement->isCSSStyleSheet())
3171 CSSCharsetRule* rule = new CSSCharsetRule(styleElement, domString(charset));
3172 m_parsedStyleObjects.append(rule);
3176 CSSRule* CSSParser::createImportRule(const ParseString& URL, MediaList* media)
3182 if (!styleElement->isCSSStyleSheet())
3184 CSSImportRule* rule = new CSSImportRule(styleElement, domString(URL), media);
3185 m_parsedStyleObjects.append(rule);
3189 CSSRule* CSSParser::createMediaRule(MediaList* media, CSSRuleList* rules)
3197 if (!styleElement->isCSSStyleSheet())
3199 CSSMediaRule* rule = new CSSMediaRule(styleElement, media, rules);
3200 m_parsedStyleObjects.append(rule);
3204 CSSRuleList* CSSParser::createRuleList()
3206 CSSRuleList* list = new CSSRuleList;
3207 m_parsedRuleLists.append(list);
3211 CSSRule* CSSParser::createStyleRule(CSSSelector* selector)
3213 CSSStyleRule* rule = 0;
3215 rule = new CSSStyleRule(styleElement);
3216 m_parsedStyleObjects.append(rule);
3217 rule->setSelector(sinkFloatingSelector(selector));
3218 rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties));
3224 DeprecatedString deprecatedString(const ParseString& ps)
3226 return DeprecatedString(reinterpret_cast<const DeprecatedChar*>(ps.characters), ps.length);
3229 #define YY_DECL int CSSParser::lex()
3230 #define yyconst const
3231 typedef int yy_state_type;
3232 typedef unsigned YY_CHAR;
3233 // this line makes sure we treat all Unicode chars correctly.
3234 #define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c)
3235 #define YY_DO_BEFORE_ACTION \
3237 yyleng = (int) (yy_cp - yy_bp); \
3238 yy_hold_char = *yy_cp; \
3241 #define YY_BREAK break;
3243 #define YY_RULE_SETUP
3245 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
3246 #define yyterminate() yyTok = END_TOKEN; return yyTok
3247 #define YY_FATAL_ERROR(a)
3248 // The line below is needed to build the tokenizer with conditon stack.
3249 // The macro is used in the tokenizer grammar with lines containing
3250 // BEGIN(mediaqueries) and BEGIN(initial). yy_start acts as index to
3251 // tokenizer transition table, and 'mediaqueries' and 'initial' are
3252 // offset multipliers that specify which transitions are active
3253 // in the tokenizer during in each condition (tokenizer state)
3254 #define BEGIN yy_start = 1 + 2 *
3256 #include "tokenizer.cpp"