be7999f8c297c2d5043601ed0c3643028c3aefd0
[WebKit-https.git] / WebCore / css / cssstyleselector.cpp
1 /**
2  * This file is part of the CSS implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
6  *           (C) 2006 Nicholas Shanks (webkit@nickshanks.com)
7  * Copyright (C) 2005, 2006 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "config.h"
26 #include "cssstyleselector.h"
27
28 #include "CSSBorderImageValue.h"
29 #include "CSSCursorImageValue.h"
30 #include "CSSImageValue.h"
31 #include "CSSImportRule.h"
32 #include "CSSMediaRule.h"
33 #include "CSSProperty.h"
34 #include "CSSPropertyNames.h"
35 #include "CSSRuleList.h"
36 #include "CSSSelector.h"
37 #include "CSSStyleRule.h"
38 #include "CSSStyleSheet.h"
39 #include "CSSValueKeywords.h"
40 #include "CSSValueList.h"
41 #include "Counter.h"
42 #include "CachedImage.h"
43 #include "DashboardRegion.h"
44 #include "FontFamilyValue.h"
45 #include "FontValue.h"
46 #include "Frame.h"
47 #include "HTMLDocument.h"
48 #include "HTMLElement.h"
49 #include "HTMLInputElement.h"
50 #include "HTMLNames.h"
51 #include "History.h"
52 #include "Settings.h"
53 #include "MediaList.h"
54 #include "MediaQueryEvaluator.h"
55 #include "Pair.h"
56 #include "RectImpl.h"
57 #include "RenderTheme.h"
58 #include "StyleSheetList.h"
59 #include "UserAgentStyleSheets.h"
60 #include "loader.h"
61 #include "ShadowValue.h"
62
63 #ifdef SVG_SUPPORT
64 #include "XLinkNames.h"
65 #endif
66
67 using namespace std;
68
69 namespace WebCore {
70
71 using namespace HTMLNames;
72
73 // #define STYLE_SHARING_STATS 1
74
75 #define HANDLE_INHERIT(prop, Prop) \
76 if (isInherit) { \
77     style->set##Prop(parentStyle->prop()); \
78     return; \
79 }
80
81 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
82 HANDLE_INHERIT(prop, Prop) \
83 if (isInitial) { \
84     style->set##Prop(RenderStyle::initial##Prop()); \
85     return; \
86 }
87
88 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
89 HANDLE_INHERIT(prop, Prop) \
90 if (isInitial) { \
91     style->set##Prop(RenderStyle::initial##Value());\
92     return;\
93 }
94
95 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
96 if (isInherit) { \
97     BackgroundLayer* currChild = style->accessBackgroundLayers(); \
98     BackgroundLayer* prevChild = 0; \
99     const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \
100     while (currParent && currParent->is##Prop##Set()) { \
101         if (!currChild) { \
102             /* Need to make a new layer.*/ \
103             currChild = new BackgroundLayer(); \
104             prevChild->setNext(currChild); \
105         } \
106         currChild->set##Prop(currParent->prop()); \
107         prevChild = currChild; \
108         currChild = prevChild->next(); \
109         currParent = currParent->next(); \
110     } \
111     \
112     while (currChild) { \
113         /* Reset any remaining layers to not have the property set. */ \
114         currChild->clear##Prop(); \
115         currChild = currChild->next(); \
116     } \
117     return; \
118 } \
119 if (isInitial) { \
120     BackgroundLayer* currChild = style->accessBackgroundLayers(); \
121     currChild->set##Prop(RenderStyle::initial##Prop()); \
122     for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
123         currChild->clear##Prop(); \
124     return; \
125 }
126
127 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \
128 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
129 if (!value->isPrimitiveValue() && !value->isValueList()) \
130     return; \
131 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
132 BackgroundLayer* prevChild = 0; \
133 if (value->isPrimitiveValue()) { \
134     map##Prop(currChild, value); \
135     currChild = currChild->next(); \
136 } \
137 else { \
138     /* Walk each value and put it into a layer, creating new layers as needed. */ \
139     CSSValueList* valueList = static_cast<CSSValueList*>(value); \
140     for (unsigned int i = 0; i < valueList->length(); i++) { \
141         if (!currChild) { \
142             /* Need to make a new layer to hold this value */ \
143             currChild = new BackgroundLayer(); \
144             prevChild->setNext(currChild); \
145         } \
146         map##Prop(currChild, valueList->item(i)); \
147         prevChild = currChild; \
148         currChild = currChild->next(); \
149     } \
150 } \
151 while (currChild) { \
152     /* Reset all remaining layers to not have the property set. */ \
153     currChild->clear##Prop(); \
154     currChild = currChild->next(); \
155 } }
156
157 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
158 if (id == propID) { \
159     style->set##Prop(parentStyle->prop()); \
160     return; \
161 }
162
163 #define HANDLE_INITIAL_COND(propID, Prop) \
164 if (id == propID) { \
165     style->set##Prop(RenderStyle::initial##Prop()); \
166     return; \
167 }
168
169 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
170 if (id == propID) { \
171     style->set##Prop(RenderStyle::initial##Value()); \
172     return; \
173 }
174
175 class CSSRuleSet
176 {
177 public:
178     CSSRuleSet();
179     ~CSSRuleSet();
180     
181     typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;
182     
183     void addRulesFromSheet(CSSStyleSheet* sheet, MediaQueryEvaluator* medium);
184     
185     void addRule(CSSStyleRule* rule, CSSSelector* sel);
186     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
187                       CSSStyleRule* rule, CSSSelector* sel);
188     
189     CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
190     CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
191     CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
192     CSSRuleDataList* getUniversalRules() { return m_universalRules; }
193     
194 public:
195     AtomRuleMap m_idRules;
196     AtomRuleMap m_classRules;
197     AtomRuleMap m_tagRules;
198     CSSRuleDataList* m_universalRules;
199     
200     unsigned m_ruleCount;
201 };
202
203 CSSRuleSet* CSSStyleSelector::defaultStyle = 0;
204 CSSRuleSet* CSSStyleSelector::defaultQuirksStyle = 0;
205 CSSRuleSet* CSSStyleSelector::defaultPrintStyle = 0;
206 CSSRuleSet* CSSStyleSelector::defaultViewSourceStyle = 0;
207
208 CSSStyleSheet* CSSStyleSelector::defaultSheet = 0;
209 RenderStyle* CSSStyleSelector::styleNotYetAvailable = 0;
210 CSSStyleSheet* CSSStyleSelector::quirksSheet = 0;
211 CSSStyleSheet* CSSStyleSelector::viewSourceSheet = 0;
212
213 #ifdef SVG_SUPPORT
214 CSSStyleSheet *CSSStyleSelector::svgSheet = 0;
215 #endif
216
217 static CSSStyleSelector::Encodedurl *currentEncodedURL = 0;
218 static PseudoState pseudoState;
219
220 CSSStyleSelector::CSSStyleSelector(Document* doc, const String& userStyleSheet, StyleSheetList *styleSheets, bool _strictParsing)
221 {
222     init();
223
224     view = doc->view();
225     strictParsing = _strictParsing;
226     settings = view ? view->frame()->settings() : 0;
227     if (!defaultStyle)
228         loadDefaultStyle();
229
230     m_userStyle = 0;
231     m_userSheet = 0;
232
233     // construct document root element default style. this is needed
234     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
235     // This is here instead of constructor, because when constructor is run,
236     // document doesn't have documentElement
237     // NOTE: this assumes that element that gets passed to styleForElement -call
238     // is always from the document that owns the style selector
239     if (view)
240         m_medium = new MediaQueryEvaluator(view->mediaType());
241     else
242         m_medium = new MediaQueryEvaluator("all");
243
244     Element* root = doc->documentElement();
245
246     if (root)
247         m_rootDefaultStyle = styleForElement(root, 0, false, true); // dont ref, because the RenderStyle is allocated from global heap
248
249     if (m_rootDefaultStyle && view) {
250         delete m_medium;
251         m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame()->page(), m_rootDefaultStyle);
252     }
253
254     // FIXME: This sucks! The user sheet is reparsed every time!
255     if (!userStyleSheet.isEmpty()) {
256         m_userSheet = new CSSStyleSheet(doc);
257         m_userSheet->parseString(userStyleSheet, strictParsing);
258
259         m_userStyle = new CSSRuleSet();
260         m_userStyle->addRulesFromSheet(m_userSheet, m_medium);
261     }
262
263     // add stylesheets from document
264     m_authorStyle = new CSSRuleSet();
265
266     DeprecatedPtrListIterator<StyleSheet> it(styleSheets->styleSheets);
267     for (; it.current(); ++it)
268         if (it.current()->isCSSStyleSheet() && !it.current()->disabled())
269             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(it.current()), m_medium);
270
271 }
272
273 CSSStyleSelector::CSSStyleSelector(CSSStyleSheet *sheet)
274 {
275     init();
276
277     if (!defaultStyle)
278         loadDefaultStyle();
279     FrameView *view = sheet->doc()->view();
280
281     if (view)
282         m_medium = new MediaQueryEvaluator(view->mediaType());
283     else
284         m_medium = new MediaQueryEvaluator("all");
285
286     Element* root = sheet->doc()->documentElement();
287     if (root)
288         m_rootDefaultStyle = styleForElement(root, 0, false, true);
289
290     if (m_rootDefaultStyle && view) {
291         delete m_medium;
292         m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame()->page(), m_rootDefaultStyle);
293     }
294
295     m_authorStyle = new CSSRuleSet();
296     m_authorStyle->addRulesFromSheet(sheet, m_medium);
297 }
298
299 void CSSStyleSelector::init()
300 {
301     element = 0;
302     settings = 0;
303     m_matchedRules.clear();
304     m_matchedDecls.clear();
305     m_ruleList = 0;
306     m_collectRulesOnly = false;
307     m_rootDefaultStyle = 0;
308     m_medium = 0;
309 }
310
311 void CSSStyleSelector::setEncodedURL(const KURL& url)
312 {
313     KURL u = url;
314
315     u.setQuery(DeprecatedString::null);
316     u.setRef(DeprecatedString::null);
317     encodedurl.file = u.url();
318     int pos = encodedurl.file.findRev('/');
319     encodedurl.path = encodedurl.file;
320     if (pos > 0) {
321         encodedurl.path.truncate(pos);
322         encodedurl.path += '/';
323     }
324     u.setPath(DeprecatedString::null);
325     encodedurl.host = u.url();
326 }
327
328 CSSStyleSelector::~CSSStyleSelector()
329 {
330     delete m_medium;
331     ::delete m_rootDefaultStyle;
332
333     delete m_authorStyle;
334     delete m_userStyle;
335     delete m_userSheet;
336 }
337
338 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
339 {
340     CSSStyleSheet* const parent = 0;
341     CSSStyleSheet* sheet = new CSSStyleSheet(parent);
342     sheet->ref(); // leak the sheet on purpose since it will be stored in a global variable
343     sheet->parseString(String(characters, size));
344     return sheet;
345 }
346
347 template<typename T> CSSStyleSheet* parseUASheet(const T& array)
348 {
349     return parseUASheet(array, sizeof(array));
350 }
351
352 void CSSStyleSelector::loadDefaultStyle()
353 {
354     if (defaultStyle)
355         return;
356
357     defaultStyle = new CSSRuleSet;
358     defaultPrintStyle = new CSSRuleSet;
359     defaultQuirksStyle = new CSSRuleSet;
360     defaultViewSourceStyle = new CSSRuleSet;
361
362     MediaQueryEvaluator screenEval("screen");
363     MediaQueryEvaluator printEval("print");
364
365     // Strict-mode rules.
366     defaultSheet = parseUASheet(html4UserAgentStyleSheet);
367     defaultStyle->addRulesFromSheet(defaultSheet, &screenEval);
368     defaultPrintStyle->addRulesFromSheet(defaultSheet, &printEval);
369
370 #ifdef SVG_SUPPORT
371     // SVG rules.
372     svgSheet = parseUASheet(svgUserAgentStyleSheet);
373     defaultStyle->addRulesFromSheet(svgSheet, &screenEval);
374     defaultPrintStyle->addRulesFromSheet(svgSheet, &printEval);
375 #endif
376
377     // Quirks-mode rules.
378     quirksSheet = parseUASheet(quirksUserAgentStyleSheet);
379     defaultQuirksStyle->addRulesFromSheet(quirksSheet, &screenEval);
380     
381     // View source rules.
382     viewSourceSheet = parseUASheet(sourceUserAgentStyleSheet);
383     defaultViewSourceStyle->addRulesFromSheet(viewSourceSheet, &screenEval);
384 }
385
386 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
387 {
388     m_matchedRules.clear();
389
390     if (!rules || !element)
391         return;
392     
393     // We need to collect the rules for id, class, tag, and everything else into a buffer and
394     // then sort the buffer.
395     if (element->hasID())
396         matchRulesForList(rules->getIDRules(element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex);
397     if (element->hasClass()) {
398         for (const AtomicStringList* singleClass = element->getClassList(); singleClass; singleClass = singleClass->next())
399             matchRulesForList(rules->getClassRules(singleClass->string().impl()), firstRuleIndex, lastRuleIndex);
400     }
401     matchRulesForList(rules->getTagRules(element->localName().impl()), firstRuleIndex, lastRuleIndex);
402     matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
403     
404     // If we didn't match any rules, we're done.
405     if (m_matchedRules.isEmpty())
406         return;
407     
408     // Sort the set of matched rules.
409     sortMatchedRules(0, m_matchedRules.size());
410     
411     // Now transfer the set of matched rules over to our list of decls.
412     if (!m_collectRulesOnly) {
413         for (unsigned i = 0; i < m_matchedRules.size(); i++)
414             addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
415     } else {
416         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
417             if (!m_ruleList)
418                 m_ruleList = new CSSRuleList();
419             m_ruleList->append(m_matchedRules[i]->rule());
420         }
421     }
422 }
423
424 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex)
425 {
426     if (!rules)
427         return;
428
429     for (CSSRuleData* d = rules->first(); d; d = d->next()) {
430         CSSStyleRule* rule = d->rule();
431         const AtomicString& localName = element->localName();
432         const AtomicString& selectorLocalName = d->selector()->tag.localName();
433         if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector(), element)) {
434             // If the rule has no properties to apply, then ignore it.
435             CSSMutableStyleDeclaration* decl = rule->declaration();
436             if (!decl || !decl->length())
437                 continue;
438             
439             // If we're matching normal rules, set a pseudo bit if 
440             // we really just matched a pseudo-element.
441             if (dynamicPseudo != RenderStyle::NOPSEUDO && pseudoStyle == RenderStyle::NOPSEUDO) {
442                 if (m_collectRulesOnly)
443                     return;
444                 style->setHasPseudoStyle(dynamicPseudo);
445             } else {
446                 // Update our first/last rule indices in the matched rules array.
447                 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
448                 if (firstRuleIndex == -1)
449                     firstRuleIndex = lastRuleIndex;
450
451                 // Add this rule to our list of matched rules.
452                 addMatchedRule(d);
453             }
454         }
455     }
456 }
457
458 bool operator >(CSSRuleData& r1, CSSRuleData& r2)
459 {
460     int spec1 = r1.selector()->specificity();
461     int spec2 = r2.selector()->specificity();
462     return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; 
463 }
464 bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
465 {
466     return !(r1 > r2);
467 }
468
469 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
470 {
471     if (start >= end || (end - start == 1))
472         return; // Sanity check.
473
474     if (end - start <= 6) {
475         // Apply a bubble sort for smaller lists.
476         for (unsigned i = end - 1; i > start; i--) {
477             bool sorted = true;
478             for (unsigned j = start; j < i; j++) {
479                 CSSRuleData* elt = m_matchedRules[j];
480                 CSSRuleData* elt2 = m_matchedRules[j + 1];
481                 if (*elt > *elt2) {
482                     sorted = false;
483                     m_matchedRules[j] = elt2;
484                     m_matchedRules[j + 1] = elt;
485                 }
486             }
487             if (sorted)
488                 return;
489         }
490         return;
491     }
492
493     // Peform a merge sort for larger lists.
494     unsigned mid = (start + end) / 2;
495     sortMatchedRules(start, mid);
496     sortMatchedRules(mid, end);
497     
498     CSSRuleData* elt = m_matchedRules[mid - 1];
499     CSSRuleData* elt2 = m_matchedRules[mid];
500     
501     // Handle the fast common case (of equal specificity).  The list may already
502     // be completely sorted.
503     if (*elt <= *elt2)
504         return;
505     
506     // We have to merge sort.  Ensure our merge buffer is big enough to hold
507     // all the items.
508     Vector<CSSRuleData*> rulesMergeBuffer;
509     rulesMergeBuffer.reserveCapacity(end - start); 
510
511     unsigned i1 = start;
512     unsigned i2 = mid;
513     
514     elt = m_matchedRules[i1];
515     elt2 = m_matchedRules[i2];
516     
517     while (i1 < mid || i2 < end) {
518         if (i1 < mid && (i2 == end || *elt <= *elt2)) {
519             rulesMergeBuffer.append(elt);
520             if (++i1 < mid)
521                 elt = m_matchedRules[i1];
522         } else {
523             rulesMergeBuffer.append(elt2);
524             if (++i2 < end)
525                 elt2 = m_matchedRules[i2];
526         }
527     }
528     
529     for (unsigned i = start; i < end; i++)
530         m_matchedRules[i] = rulesMergeBuffer[i - start];
531 }
532
533 void CSSStyleSelector::initElementAndPseudoState(Element* e)
534 {
535     element = e;
536     if (element && element->isStyledElement())
537         styledElement = static_cast<StyledElement*>(element);
538     else
539         styledElement = 0;
540     currentEncodedURL = &encodedurl;
541     pseudoState = PseudoUnknown;
542 }
543
544 void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParent)
545 {
546     // set some variables we will need
547     pseudoStyle = RenderStyle::NOPSEUDO;
548
549     parentNode = e->parentNode();
550     if (defaultParent)
551         parentStyle = defaultParent;
552     else
553         parentStyle = parentNode ? parentNode->renderStyle() : 0;
554     view = element->document()->view();
555     isXMLDoc = !element->document()->isHTMLDocument();
556     frame = element->document()->frame();
557     settings = frame ? frame->settings() : 0;
558
559     style = 0;
560     
561     m_matchedRules.clear();
562     m_matchedDecls.clear();
563
564     m_ruleList = 0;
565
566     fontDirty = false;
567 }
568
569 // modified version of the one in kurl.cpp
570 static void cleanpath(DeprecatedString &path)
571 {
572     int pos;
573     while ((pos = path.find("/../")) != -1) {
574         int prev = 0;
575         if (pos > 0)
576             prev = path.findRev("/", pos -1);
577         // don't remove the host, i.e. http://foo.org/../foo.html
578         if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2))
579             path.remove(pos, 3);
580         else
581             // matching directory found ?
582             path.remove(prev, pos- prev + 3);
583     }
584     pos = 0;
585     
586     // Don't remove "//" from an anchor identifier. -rjw
587     // Set refPos to -2 to mean "I haven't looked for the anchor yet".
588     // We don't want to waste a function call on the search for the the anchor
589     // in the vast majority of cases where there is no "//" in the path.
590     int refPos = -2;
591     while ((pos = path.find("//", pos)) != -1) {
592         if (refPos == -2)
593             refPos = path.find("#");
594         if (refPos > 0 && pos >= refPos)
595             break;
596         
597         if (pos == 0 || path[pos-1] != ':')
598             path.remove(pos, 1);
599         else
600             pos += 2;
601     }
602     while ((pos = path.find("/./")) != -1)
603         path.remove(pos, 2);
604 }
605
606 static void checkPseudoState(Element *e, bool checkVisited = true)
607 {
608     if (!e->isLink()) {
609         pseudoState = PseudoNone;
610         return;
611     }
612     
613     AtomicString attr;
614     if (e->isHTMLElement())
615         attr = e->getAttribute(hrefAttr);
616 #ifdef SVG_SUPPORT
617     else if (e->isSVGElement())
618         attr = e->getAttribute(XLinkNames::hrefAttr);
619 #endif
620     if (attr.isNull()) {
621         pseudoState = PseudoNone;
622         return;
623     }
624     
625     if (!checkVisited) {
626         pseudoState = PseudoAnyLink;
627         return;
628     }
629     
630     DeprecatedConstString cu(reinterpret_cast<const DeprecatedChar*>(attr.characters()), attr.length());
631     DeprecatedString u = cu.string();
632     if (!u.contains("://")) {
633         if (u[0] == '/')
634             u.prepend(currentEncodedURL->host);
635         else if (u[0] == '#')
636             u.prepend(currentEncodedURL->file);
637         else
638             u.prepend(currentEncodedURL->path);
639         cleanpath(u);
640     }
641     pseudoState = historyContains(u) ? PseudoVisited : PseudoLink;
642 }
643
644 #ifdef STYLE_SHARING_STATS
645 static int fraction = 0;
646 static int total = 0;
647 #endif
648
649 const int siblingThreshold = 10;
650
651 Node* CSSStyleSelector::locateCousinList(Element* parent)
652 {
653     if (parent && parent->isStyledElement()) {
654         StyledElement* p = static_cast<StyledElement*>(parent);
655         if (!p->inlineStyleDecl() && !p->hasID()) {
656             Node* r = p->previousSibling();
657             int subcount = 0;
658             RenderStyle* st = p->renderStyle();
659             while (r) {
660                 if (r->renderStyle() == st)
661                     return r->lastChild();
662                 if (subcount++ == siblingThreshold)
663                     return 0;
664                 r = r->previousSibling();
665             }
666             if (!r)
667                 r = locateCousinList(static_cast<Element*>(parent->parentNode()));
668             while (r) {
669                 if (r->renderStyle() == st)
670                     return r->lastChild();
671                 if (subcount++ == siblingThreshold)
672                     return 0;
673                 r = r->previousSibling();
674             }
675         }
676     }
677     return 0;
678 }
679
680 bool CSSStyleSelector::canShareStyleWithElement(Node* n)
681 {
682     if (n->isStyledElement()) {
683         StyledElement* s = static_cast<StyledElement*>(n);
684         RenderStyle* style = s->renderStyle();
685         if (style && !style->unique() &&
686             (s->tagQName() == element->tagQName()) && !s->hasID() &&
687             (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() &&
688             (s->hasMappedAttributes() == styledElement->hasMappedAttributes()) &&
689             (s->isLink() == element->isLink()) && 
690             !style->affectedByAttributeSelectors() &&
691             (s->hovered() == element->hovered()) &&
692             (s->active() == element->active()) &&
693             (s->focused() == element->focused()) &&
694             (s->isEnabled() == element->isEnabled()) &&
695             (s->isIndeterminate() == element->isIndeterminate()) &&
696             (s->isChecked() == element->isChecked()) &&
697             (s != s->document()->getCSSTarget() && element != element->document()->getCSSTarget()) &&
698             (s->getAttribute(typeAttr) == element->getAttribute(typeAttr))) {
699             bool classesMatch = true;
700             if (s->hasClass()) {
701                 const AtomicString& class1 = element->getAttribute(classAttr);
702                 const AtomicString& class2 = s->getAttribute(classAttr);
703                 classesMatch = (class1 == class2);
704             }
705             
706             if (classesMatch) {
707                 bool mappedAttrsMatch = true;
708                 if (s->hasMappedAttributes())
709                     mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(styledElement->mappedAttributes());
710                 if (mappedAttrsMatch) {
711                     bool linksMatch = true;
712                     if (s->isLink()) {
713                         // We need to check to see if the visited state matches.
714                         Color linkColor = element->document()->linkColor();
715                         Color visitedColor = element->document()->visitedLinkColor();
716                         if (pseudoState == PseudoUnknown)
717                             checkPseudoState(element, style->pseudoState() != PseudoAnyLink ||
718                                              linkColor != visitedColor);
719                         linksMatch = (pseudoState == style->pseudoState());
720                     }
721                     
722                     if (linksMatch)
723                         return true;
724                 }
725             }
726         }
727     }
728     return false;
729 }
730
731 RenderStyle* CSSStyleSelector::locateSharedStyle()
732 {
733     if (styledElement && !styledElement->inlineStyleDecl() && !styledElement->hasID() &&
734         !styledElement->document()->usesSiblingRules()) {
735         // Check previous siblings.
736         int count = 0;
737         Node* n;
738         for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
739         while (n) {
740             if (canShareStyleWithElement(n))
741                 return n->renderStyle();
742             if (count++ == siblingThreshold)
743                 return 0;
744             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
745         }
746         if (!n) 
747             n = locateCousinList(static_cast<Element*>(element->parentNode()));
748         while (n) {
749             if (canShareStyleWithElement(n))
750                 return n->renderStyle();
751             if (count++ == siblingThreshold)
752                 return 0;
753             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
754         }        
755     }
756     return 0;
757 }
758
759 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
760 {
761     // First we match rules from the user agent sheet.
762     CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatch("print")
763         ? defaultPrintStyle : defaultStyle;
764     matchRules(userAgentStyleSheet, firstUARule, lastUARule);
765
766     // In quirks mode, we match rules from the quirks user agent sheet.
767     if (!strictParsing)
768         matchRules(defaultQuirksStyle, firstUARule, lastUARule);
769         
770     // If we're in view source mode, then we match rules from the view source style sheet.
771     if (view && view->frame() && view->frame()->inViewSourceMode())
772         matchRules(defaultViewSourceStyle, firstUARule, lastUARule);
773 }
774
775 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
776 // relative units are interpreted according to document root element style, styled only with UA stylesheet
777
778 RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
779 {
780     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
781     // will vanish if a style recalc happens during loading.
782     if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
783         if (!styleNotYetAvailable) {
784             styleNotYetAvailable = ::new RenderStyle();
785             styleNotYetAvailable->setDisplay(NONE);
786             styleNotYetAvailable->ref();
787         }
788         styleNotYetAvailable->ref();
789         return styleNotYetAvailable;
790     }
791     
792     initElementAndPseudoState(e);
793     if (allowSharing) {
794         style = locateSharedStyle();
795 #ifdef STYLE_SHARING_STATS
796         fraction += style != 0;
797         total++;
798         printf("Sharing %d out of %d\n", fraction, total);
799 #endif
800         if (style) {
801             style->ref();
802             return style;
803         }
804     }
805     initForStyleResolve(e, defaultParent);
806
807     if (resolveForRootDefault) {
808         style = ::new RenderStyle();
809         // don't ref, because we want to delete this, but we cannot unref it
810     } else {
811         style = new (e->document()->renderArena()) RenderStyle();
812         style->ref();
813     }
814     if (parentStyle)
815         style->inheritFrom(parentStyle);
816     else
817         parentStyle = style;
818
819     int firstUARule = -1, lastUARule = -1;
820     int firstUserRule = -1, lastUserRule = -1;
821     int firstAuthorRule = -1, lastAuthorRule = -1;
822     matchUARules(firstUARule, lastUARule);
823
824     if (!resolveForRootDefault) {
825         // 4. Now we check user sheet rules.
826         matchRules(m_userStyle, firstUserRule, lastUserRule);
827
828         // 5. Now check author rules, beginning first with presentational attributes
829         // mapped from HTML.
830         if (styledElement) {
831             // Ask if the HTML element has mapped attributes.
832             if (styledElement->hasMappedAttributes()) {
833                 // Walk our attribute list and add in each decl.
834                 const NamedMappedAttrMap* map = styledElement->mappedAttributes();
835                 for (unsigned i = 0; i < map->length(); i++) {
836                     MappedAttribute* attr = map->attributeItem(i);
837                     if (attr->decl()) {
838                         lastAuthorRule = m_matchedDecls.size();
839                         if (firstAuthorRule == -1)
840                             firstAuthorRule = lastAuthorRule;
841                         addMatchedDeclaration(attr->decl());
842                     }
843                 }
844             }
845
846             // Now we check additional mapped declarations.
847             // Tables and table cells share an additional mapped rule that must be applied
848             // after all attributes, since their mapped style depends on the values of multiple attributes.
849             CSSMutableStyleDeclaration* attributeDecl = styledElement->additionalAttributeStyleDecl();
850             if (attributeDecl) {
851                 lastAuthorRule = m_matchedDecls.size();
852                 if (firstAuthorRule == -1)
853                     firstAuthorRule = lastAuthorRule;
854                 addMatchedDeclaration(attributeDecl);
855             }
856         }
857     
858         // 6. Check the rules in author sheets next.
859         matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
860     
861         // 7. Now check our inline style attribute.
862         if (styledElement) {
863             CSSMutableStyleDeclaration* inlineDecl = styledElement->inlineStyleDecl();
864             if (inlineDecl) {
865                 lastAuthorRule = m_matchedDecls.size();
866                 if (firstAuthorRule == -1)
867                     firstAuthorRule = lastAuthorRule;
868                 addMatchedDeclaration(inlineDecl);
869             }
870         }
871     }
872
873     // Now we have all of the matched rules in the appropriate order.  Walk the rules and apply
874     // high-priority properties first, i.e., those properties that other properties depend on.
875     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
876     // and (4) normal important.
877     applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
878     if (!resolveForRootDefault) {
879         applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
880         applyDeclarations(true, true, firstUserRule, lastUserRule);
881     }
882     applyDeclarations(true, true, firstUARule, lastUARule);
883     
884     // If our font got dirtied, go ahead and update it now.
885     if (fontDirty)
886         updateFont();
887     
888     // Now do the normal priority UA properties.
889     applyDeclarations(false, false, firstUARule, lastUARule);
890     
891     // Cache our border and background so that we can examine them later.
892     cacheBorderAndBackground();
893     
894     // Now do the author and user normal priority properties and all the !important properties.
895     if (!resolveForRootDefault) {
896         applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
897         applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
898         applyDeclarations(false, true, firstUserRule, lastUserRule);
899     }
900     applyDeclarations(false, true, firstUARule, lastUARule);
901     
902     // If our font got dirtied by one of the non-essential font props, 
903     // go ahead and update it a second time.
904     if (fontDirty)
905         updateFont();
906     
907     // Clean up our style object's display and text decorations (among other fixups).
908     adjustRenderStyle(style, e);
909
910     // If we are a link, cache the determined pseudo-state.
911     if (e->isLink())
912         style->setPseudoState(pseudoState);
913
914     // Now return the style.
915     return style;
916 }
917
918 RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, Element* e, RenderStyle* parentStyle)
919 {
920     if (!e)
921         return 0;
922
923     initElementAndPseudoState(e);
924     initForStyleResolve(e, parentStyle);
925     pseudoStyle = pseudo;
926     
927     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
928     // those rules.
929     
930     // Check UA, user and author rules.
931     int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
932     matchRules(defaultStyle, firstUARule, lastUARule);
933     matchRules(m_userStyle, firstUserRule, lastUserRule);
934     matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
935     
936     if (m_matchedDecls.isEmpty())
937         return 0;
938     
939     style = new (e->document()->renderArena()) RenderStyle();
940     style->ref();
941     if (parentStyle)
942         style->inheritFrom(parentStyle);
943     else
944         parentStyle = style;
945     style->noninherited_flags._styleType = pseudoStyle;
946     
947     // High-priority properties.
948     applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
949     applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
950     applyDeclarations(true, true, firstUserRule, lastUserRule);
951     applyDeclarations(true, true, firstUARule, lastUARule);
952     
953     // If our font got dirtied, go ahead and update it now.
954     if (fontDirty)
955         updateFont();
956     
957     // Now do the normal priority properties.
958     applyDeclarations(false, false, firstUARule, lastUARule);
959     
960     // Cache our border and background so that we can examine them later.
961     cacheBorderAndBackground();
962     
963     applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
964     applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
965     applyDeclarations(false, true, firstUserRule, lastUserRule);
966     applyDeclarations(false, true, firstUARule, lastUARule);
967     
968     // If our font got dirtied by one of the non-essential font props, 
969     // go ahead and update it a second time.
970     if (fontDirty)
971         updateFont();
972     // Clean up our style object's display and text decorations (among other fixups).
973     adjustRenderStyle(style, 0);
974
975     // Now return the style.
976     return style;
977 }
978
979 static void addIntrinsicMargins(RenderStyle* style)
980 {
981     // Intrinsic margin value.
982     const int intrinsicMargin = 2;
983     
984     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
985     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
986     if (style->width().isIntrinsicOrAuto()) {
987         if (style->marginLeft().quirk())
988             style->setMarginLeft(Length(intrinsicMargin, Fixed));
989         if (style->marginRight().quirk())
990             style->setMarginRight(Length(intrinsicMargin, Fixed));
991     }
992
993     if (style->height().isAuto()) {
994         if (style->marginTop().quirk())
995             style->setMarginTop(Length(intrinsicMargin, Fixed));
996         if (style->marginBottom().quirk())
997             style->setMarginBottom(Length(intrinsicMargin, Fixed));
998     }
999 }
1000
1001 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e)
1002 {
1003     // Cache our original display.
1004     style->setOriginalDisplay(style->display());
1005
1006     if (style->display() != NONE) {
1007         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1008         // property.
1009         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
1010         // these tags to retain their display types.
1011         if (!strictParsing && e) {
1012             if (e->hasTagName(tdTag)) {
1013                 style->setDisplay(TABLE_CELL);
1014                 style->setFloating(FNONE);
1015             }
1016             else if (e->hasTagName(tableTag))
1017                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1018         }
1019
1020         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
1021         // fix a crash where a site tries to position these objects.  They also never honor display.
1022         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1023             style->setPosition(StaticPosition);
1024             style->setDisplay(BLOCK);
1025         }
1026
1027         // Table headers with a text-align of auto will change the text-align to center.
1028         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1029             style->setTextAlign(CENTER);
1030         
1031         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1032         // position or float an inline, compact, or run-in.  Cache the original display, since it
1033         // may be needed for positioned elements that have to compute their static normal flow
1034         // positions.  We also force inline-level roots to be block-level.
1035         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1036             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
1037              (e && e->document()->documentElement() == e))) {
1038             if (style->display() == INLINE_TABLE)
1039                 style->setDisplay(TABLE);
1040             else if (style->display() == INLINE_BOX)
1041                 style->setDisplay(BOX);
1042             else if (style->display() == LIST_ITEM) {
1043                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1044                 // but only in quirks mode.
1045                 if (!strictParsing && style->floating() != FNONE)
1046                     style->setDisplay(BLOCK);
1047             }
1048             else
1049                 style->setDisplay(BLOCK);
1050         }
1051         
1052         // After performing the display mutation, check table rows.  We do not honor position:relative on
1053         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
1054         // on some sites).
1055         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP ||
1056              style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) &&
1057              style->position() == RelativePosition)
1058             style->setPosition(StaticPosition);
1059     }
1060
1061     // Make sure our z-index value is only applied if the object is positioned,
1062     // relatively positioned, or transparent.
1063     if (style->position() == StaticPosition && style->opacity() == 1.0f)
1064         style->setHasAutoZIndex();
1065
1066     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
1067     // cases where objects that should be blended as a single unit end up with a non-transparent
1068     // object wedged in between them.
1069     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f))
1070         style->setZIndex(0);
1071     
1072     // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'.
1073     // This will be important when we use block flows for all form controls.
1074     if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) ||
1075               e->hasTagName(selectTag) || e->hasTagName(textareaTag))) {
1076         if (style->width().isAuto())
1077             style->setWidth(Length(Intrinsic));
1078     }
1079
1080     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1081     // tables, inline blocks, inline tables, or run-ins.
1082     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1083         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
1084         style->setTextDecorationsInEffect(style->textDecoration());
1085     else
1086         style->addToTextDecorationsInEffect(style->textDecoration());
1087     
1088     // If either overflow value is not visible, change to auto.
1089     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1090         style->setOverflowY(OMARQUEE);
1091     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1092         style->setOverflowX(OMARQUEE);
1093     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1094         style->setOverflowX(OAUTO);
1095     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1096         style->setOverflowY(OAUTO);
1097
1098     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1099     // FIXME: Eventually table sections will support auto and scroll.
1100     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1101         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1102         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) 
1103             style->setOverflowX(OVISIBLE);
1104         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) 
1105             style->setOverflowY(OVISIBLE);
1106     }
1107
1108     // Links should be user selectable when content editable
1109     if (e && e->isLink() && (e->document()->frame()->isContentEditable() || style->userModify() == READ_WRITE || style->userModify() == READ_WRITE_PLAINTEXT_ONLY))
1110         style->setUserSelect(SELECT_AUTO);
1111
1112     // Cull out any useless layers and also repeat patterns into additional layers.
1113     style->adjustBackgroundLayers();
1114
1115     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1116     // alter fonts and heights/widths.
1117     if (e && e->isControl() && style->fontSize() >= 11) {
1118         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
1119         // so we have to treat all image buttons as though they were explicitly sized.
1120         if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE)
1121             addIntrinsicMargins(style);
1122     }
1123
1124     // Let the theme also have a crack at adjusting the style.
1125     if (style->hasAppearance())
1126         theme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1127
1128 #ifdef SVG_SUPPORT
1129     if (e && e->isSVGElement()) {
1130         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1131         if (style->overflowY() == OSCROLL)
1132             style->setOverflowY(OHIDDEN);
1133         else if (style->overflowY() == OAUTO)
1134             style->setOverflowY(OVISIBLE);
1135         
1136         if (style->overflowX() == OSCROLL)
1137             style->setOverflowX(OHIDDEN);
1138         else if (style->overflowX() == OAUTO)
1139             style->setOverflowX(OVISIBLE);
1140     }
1141 #endif
1142 }
1143
1144 void CSSStyleSelector::updateFont()
1145 {
1146     checkForTextSizeAdjust();
1147     checkForGenericFamilyChange(style, parentStyle);
1148     style->font().update();
1149     fontDirty = false;
1150 }
1151
1152 void CSSStyleSelector::cacheBorderAndBackground()
1153 {
1154     m_hasUAAppearance = style->hasAppearance();
1155     if (m_hasUAAppearance) {
1156         m_borderData = style->border();
1157         m_backgroundData = *style->backgroundLayers();
1158         m_backgroundColor = style->backgroundColor();
1159     }
1160 }
1161
1162 RefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly)
1163 {
1164     if (!e->document()->haveStylesheetsLoaded())
1165         return 0;
1166
1167     m_collectRulesOnly = true;
1168     
1169     initElementAndPseudoState(e);
1170     initForStyleResolve(e, 0);
1171     
1172     if (!authorOnly) {
1173         int firstUARule = -1, lastUARule = -1;
1174         // First we match rules from the user agent sheet.
1175         matchUARules(firstUARule, lastUARule);
1176
1177         // Now we check user sheet rules.
1178         int firstUserRule = -1, lastUserRule = -1;
1179         matchRules(m_userStyle, firstUserRule, lastUserRule);
1180     }
1181
1182     // Check the rules in author sheets.
1183     int firstAuthorRule = -1, lastAuthorRule = -1;
1184     matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
1185     
1186     m_collectRulesOnly = false;
1187     
1188     return m_ruleList;
1189 }
1190
1191 RefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, StringImpl* pseudoStyle, bool authorOnly)
1192 {
1193     // FIXME: Implement this.
1194     return 0;
1195 }
1196
1197 static bool subject;
1198
1199 bool CSSStyleSelector::checkSelector(CSSSelector* sel, Element *e)
1200 {
1201     dynamicPseudo = RenderStyle::NOPSEUDO;
1202     
1203     Node *n = e;
1204
1205     // we have the subject part of the selector
1206     subject = true;
1207
1208     // We track whether or not the rule contains only :hover and :active in a simple selector. If
1209     // so, we can't allow that to apply to every element on the page.  We assume the author intended
1210     // to apply the rules only to links.
1211     bool onlyHoverActive = (!sel->hasTag() &&
1212                             (sel->match == CSSSelector::PseudoClass &&
1213                               (sel->pseudoType() == CSSSelector::PseudoHover ||
1214                                sel->pseudoType() == CSSSelector::PseudoActive)));
1215     bool affectedByHover = style ? style->affectedByHoverRules() : false;
1216     bool affectedByActive = style ? style->affectedByActiveRules() : false;
1217     bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO;
1218     
1219     // first selector has to match
1220     if (!checkOneSelector(sel, e))
1221         return false;
1222
1223     // check the subselectors
1224     CSSSelector::Relation relation = sel->relation();
1225     while((sel = sel->tagHistory)) {
1226         if (!n->isElementNode())
1227             return false;
1228         if (relation != CSSSelector::SubSelector) {
1229             subject = false;
1230             if (havePseudo && dynamicPseudo != pseudoStyle)
1231                 return false;
1232         }
1233         
1234         switch(relation)
1235         {
1236         case CSSSelector::Descendant:
1237             // FIXME: This match needs to know how to backtrack and be non-deterministic.
1238             do {
1239                 n = n->parentNode();
1240                 if (!n || !n->isElementNode())
1241                     return false;
1242             } while (!checkOneSelector(sel, static_cast<Element*>(n)));
1243             break;
1244         case CSSSelector::Child:
1245         {
1246             n = n->parentNode();
1247             if (!strictParsing)
1248                 while (n && n->implicitNode())
1249                     n = n->parentNode();
1250             if (!n || !n->isElementNode())
1251                 return false;
1252             if (!checkOneSelector(sel, static_cast<Element*>(n)))
1253                 return false;
1254             break;
1255         }
1256         case CSSSelector::DirectAdjacent:
1257         {
1258             n = n->previousSibling();
1259             while (n && !n->isElementNode())
1260                 n = n->previousSibling();
1261             if (!n)
1262                 return false;
1263             if (!checkOneSelector(sel, static_cast<Element*>(n)))
1264                 return false;
1265             break;
1266         }
1267         case CSSSelector::IndirectAdjacent:
1268             // FIXME: This match needs to know how to backtrack and be non-deterministic.
1269             do {
1270                 n = n->previousSibling();
1271                 while (n && !n->isElementNode())
1272                     n = n->previousSibling();
1273                 if (!n)
1274                     return false;
1275             } while (!checkOneSelector(sel, static_cast<Element*>(n)));
1276             break;
1277        case CSSSelector::SubSelector:
1278        {
1279             if (onlyHoverActive)
1280                 onlyHoverActive = (sel->match == CSSSelector::PseudoClass &&
1281                                    (sel->pseudoType() == CSSSelector::PseudoHover ||
1282                                     sel->pseudoType() == CSSSelector::PseudoActive));
1283             
1284             Element *elem = static_cast<Element*>(n);
1285             // a selector is invalid if something follows :first-xxx
1286             if (elem == element && dynamicPseudo != RenderStyle::NOPSEUDO)
1287                 return false;
1288             if (!checkOneSelector(sel, elem, true))
1289                 return false;
1290             break;
1291         }
1292         }
1293         relation = sel->relation();
1294     }
1295
1296     if (subject && havePseudo && dynamicPseudo != pseudoStyle)
1297         return false;
1298     
1299     // disallow *:hover, *:active, and *:hover:active except for links
1300     if (!strictParsing && onlyHoverActive && subject) {
1301         if (pseudoState == PseudoUnknown)
1302             checkPseudoState(e);
1303
1304         if (pseudoState == PseudoNone) {
1305             if (!affectedByHover && style->affectedByHoverRules())
1306                 style->setAffectedByHoverRules(false);
1307             if (!affectedByActive && style->affectedByActiveRules())
1308                 style->setAffectedByActiveRules(false);
1309             return false;
1310         }
1311     }
1312
1313     return true;
1314 }
1315
1316 bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isSubSelector)
1317 {
1318     if(!e)
1319         return false;
1320
1321     if (sel->hasTag()) {
1322         const AtomicString& localName = e->localName();
1323         const AtomicString& ns = e->namespaceURI();
1324         const AtomicString& selLocalName = sel->tag.localName();
1325         const AtomicString& selNS = sel->tag.namespaceURI();
1326     
1327         if ((selLocalName != starAtom && localName != selLocalName) ||
1328             (selNS != starAtom && ns != selNS))
1329             return false;
1330     }
1331
1332     if (sel->hasAttribute()) {
1333         if (sel->match == CSSSelector::Class) {
1334             if (!e->hasClass())
1335                 return false;
1336             for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
1337                 if (c->string() == sel->value)
1338                     return true;
1339             return false;
1340         }
1341         else if (sel->match == CSSSelector::Id)
1342             return e->hasID() && e->getIDAttribute() == sel->value;
1343         else if (style && (e != element || !styledElement || (!styledElement->isMappedAttribute(sel->attr) && sel->attr != typeAttr))) {
1344             style->setAffectedByAttributeSelectors(); // Special-case the "type" attribute so input form controls can share style.
1345             m_selectorAttrs.add(sel->attr.localName().impl());
1346         }
1347
1348         const AtomicString& value = e->getAttribute(sel->attr);
1349         if (value.isNull())
1350             return false; // attribute is not set
1351
1352         switch(sel->match) {
1353         case CSSSelector::Exact:
1354             if ((isXMLDoc && sel->value != value) || (!isXMLDoc && !equalIgnoringCase(sel->value, value)))
1355                 return false;
1356             break;
1357         case CSSSelector::List:
1358         {
1359             // The selector's value can't contain a space, or it's totally bogus.
1360             if (sel->value.contains(' '))
1361                 return false;
1362
1363             int startSearchAt = 0;
1364             while (true) {
1365                 int foundPos = value.find(sel->value, startSearchAt, isXMLDoc);
1366                 if (foundPos == -1)
1367                     return false;
1368                 if (foundPos == 0 || value[foundPos-1] == ' ') {
1369                     unsigned endStr = foundPos + sel->value.length();
1370                     if (endStr == value.length() || value[endStr] == ' ')
1371                         break; // We found a match.
1372                 }
1373                 
1374                 // No match.  Keep looking.
1375                 startSearchAt = foundPos + 1;
1376             }
1377             break;
1378         }
1379         case CSSSelector::Contain:
1380             if (!value.contains(sel->value, isXMLDoc))
1381                 return false;
1382             break;
1383         case CSSSelector::Begin:
1384             if (!value.startsWith(sel->value, isXMLDoc))
1385                 return false;
1386             break;
1387         case CSSSelector::End:
1388             if (!value.endsWith(sel->value, isXMLDoc))
1389                 return false;
1390             break;
1391         case CSSSelector::Hyphen:
1392             if (value.length() < sel->value.length())
1393                 return false;
1394             if (!value.startsWith(sel->value, isXMLDoc))
1395                 return false;
1396             // It they start the same, check for exact match or following '-':
1397             if (value.length() != sel->value.length() && value[sel->value.length()] != '-')
1398                 return false;
1399             break;
1400         case CSSSelector::PseudoClass:
1401         case CSSSelector::PseudoElement:
1402         default:
1403             break;
1404         }
1405     }
1406     if(sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement)
1407     {
1408         // Pseudo elements. We need to check first child here. No dynamic pseudo
1409         // elements for the moment
1410             switch (sel->pseudoType()) {
1411                 // Pseudo classes:
1412             case CSSSelector::PseudoEmpty:
1413                 if (!e->firstChild())
1414                     return true;
1415                 break;
1416             case CSSSelector::PseudoFirstChild: {
1417                 // first-child matches the first child that is an element!
1418                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1419                     Node *n = e->previousSibling();
1420                     while (n && !n->isElementNode())
1421                         n = n->previousSibling();
1422                     if (!n)
1423                         return true;
1424                 }
1425                 break;
1426             }
1427             case CSSSelector::PseudoFirstOfType: {
1428                 // first-of-type matches the first element of its type!
1429                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1430                     const QualifiedName& type = e->tagQName();
1431                     Node *n = e->previousSibling();
1432                     while (n) {
1433                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1434                             break;
1435                         n = n->previousSibling();
1436                     }
1437                     if (!n)
1438                         return true;
1439                 }
1440                 break;
1441             }
1442             case CSSSelector::PseudoLastChild: {
1443                 // last-child matches the last child that is an element!
1444                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1445                     Node *n = e->nextSibling();
1446                     while (n && !n->isElementNode())
1447                         n = n->nextSibling();
1448                     if (!n)
1449                         return true;
1450                 }
1451                 break;
1452             }
1453             case CSSSelector::PseudoLastOfType: {
1454                 // last-of-type matches the last element of its type!
1455                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1456                     const QualifiedName& type = e->tagQName();
1457                     Node *n = e->nextSibling();
1458                     while (n) {
1459                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1460                             break;
1461                         n = n->nextSibling();
1462                     }
1463                     if (!n)
1464                         return true;
1465                 }
1466                 break;
1467             }
1468             case CSSSelector::PseudoOnlyChild: {
1469                 // If both first-child and last-child apply, then only-child applies.
1470                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1471                     Node *n = e->previousSibling();
1472                     while (n && !n->isElementNode())
1473                         n = n->previousSibling();
1474                     if (!n) {
1475                         n = e->nextSibling();
1476                         while (n && !n->isElementNode())
1477                             n = n->nextSibling();
1478                         if (!n)
1479                             return true;
1480                     }
1481                 }
1482                 break;
1483             }
1484             case CSSSelector::PseudoOnlyOfType: {
1485                 // If both first-of-type and last-of-type apply, then only-of-type applies.
1486                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1487                     const QualifiedName& type = e->tagQName();
1488                     Node *n = e->previousSibling();
1489                     while (n && !static_cast<Element*>(n)->hasTagName(type))
1490                         n = n->previousSibling();
1491                     if (!n) {
1492                         n = e->nextSibling();
1493                         while (n && !static_cast<Element*>(n)->hasTagName(type))
1494                             n = n->nextSibling();
1495                         if (!n)
1496                             return true;
1497                     }
1498                 }
1499                 break;
1500             }
1501             case CSSSelector::PseudoTarget:
1502                 if (e == e->document()->getCSSTarget())
1503                     return true;
1504                 break;
1505             case CSSSelector::PseudoAnyLink:
1506                 if (pseudoState == PseudoUnknown)
1507                     checkPseudoState(e, false);
1508                 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
1509                     return true;
1510                 break;
1511             case CSSSelector::PseudoAutofill:
1512                 if (e && e->hasTagName(inputTag))
1513                     return static_cast<HTMLInputElement*>(e)->autofilled();
1514                 break;
1515             case CSSSelector::PseudoLink:
1516                 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1517                     checkPseudoState(e);
1518                 if (pseudoState == PseudoLink)
1519                     return true;
1520                 break;
1521             case CSSSelector::PseudoVisited:
1522                 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1523                     checkPseudoState(e);
1524                 if (pseudoState == PseudoVisited)
1525                     return true;
1526                 break;
1527             case CSSSelector::PseudoHover: {
1528                 // If we're in quirks mode, then hover should never match anchors with no
1529                 // href and *:hover should not match anything.  This is important for sites like wsj.com.
1530                 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1531                     if (element == e && style)
1532                         style->setAffectedByHoverRules(true);
1533                         if (element != e && e->renderStyle())
1534                             e->renderStyle()->setAffectedByHoverRules(true);
1535                         if (e->hovered())
1536                             return true;
1537                 }
1538                 break;
1539             }
1540             case CSSSelector::PseudoDrag: {
1541                 if (element == e && style)
1542                     style->setAffectedByDragRules(true);
1543                     if (element != e && e->renderStyle())
1544                         e->renderStyle()->setAffectedByDragRules(true);
1545                     if (e->renderer() && e->renderer()->isDragging())
1546                         return true;
1547                 break;
1548             }
1549             case CSSSelector::PseudoFocus:
1550                 if (e && e->focused() && e->document()->frame()->isActive())
1551                     return true;
1552                 break;
1553             case CSSSelector::PseudoActive:
1554                 // If we're in quirks mode, then :active should never match anchors with no
1555                 // href and *:active should not match anything. 
1556                 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1557                     if (element == e && style)
1558                         style->setAffectedByActiveRules(true);
1559                     else if (e->renderStyle())
1560                         e->renderStyle()->setAffectedByActiveRules(true);
1561                     if (e->active())
1562                         return true;
1563                 }
1564                 break;
1565             case CSSSelector::PseudoEnabled:
1566                 if (e && e->isControl())
1567                     // The UI spec states that you can't match :enabled unless you are an object that can
1568                     // "receive focus and be activated."  We will limit matching of this pseudo-class to elements
1569                     // that are controls.
1570                     return e->isEnabled();                    
1571                 break;
1572             case CSSSelector::PseudoDisabled:
1573                 if (e && e->isControl())
1574                     // The UI spec states that you can't match :enabled unless you are an object that can
1575                     // "receive focus and be activated."  We will limit matching of this pseudo-class to elements
1576                     // that are controls.
1577                     return !e->isEnabled();                    
1578                 break;
1579             case CSSSelector::PseudoChecked:
1580                 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
1581                 // you can't be both checked and indeterminate.  We will behave like WinIE behind the scenes and just
1582                 // obey the CSS spec here in the test for matching the pseudo.
1583                 if (e && e->isChecked() && !e->isIndeterminate())
1584                     return true;
1585                 break;
1586             case CSSSelector::PseudoIndeterminate:
1587                 if (e && e->isIndeterminate())
1588                     return true;
1589                 break;
1590             case CSSSelector::PseudoRoot:
1591                 if (e == e->document()->documentElement())
1592                     return true;
1593                 break;
1594             case CSSSelector::PseudoLang: {
1595                 const AtomicString& value = e->getAttribute(langAttr);
1596                 if (value.isEmpty() || !value.startsWith(sel->argument, false))
1597                     break;
1598                 if (value.length() != sel->argument.length() && value[sel->argument.length()] != '-')
1599                     break;
1600                 return true;
1601             }
1602             case CSSSelector::PseudoNot: {
1603                 // check the simple selector
1604                 for (CSSSelector* subSel = sel->simpleSelector; subSel; subSel = subSel->tagHistory) {
1605                     // :not cannot nest. I don't really know why this is a
1606                     // restriction in CSS3, but it is, so let's honour it.
1607                     if (subSel->simpleSelector)
1608                         break;
1609                     if (!checkOneSelector(subSel, e))
1610                         return true;
1611                 }
1612                 break;
1613             }
1614             case CSSSelector::PseudoOther:
1615                 break;
1616             
1617             // Pseudo-elements:
1618             case CSSSelector::PseudoFirstLine:
1619                 if (subject) {
1620                     dynamicPseudo=RenderStyle::FIRST_LINE;
1621                     return true;
1622                 }
1623                 break;
1624             case CSSSelector::PseudoFirstLetter:
1625                 if (subject) {
1626                     dynamicPseudo=RenderStyle::FIRST_LETTER;
1627                     return true;
1628                 }
1629                 break;
1630             case CSSSelector::PseudoSelection:
1631                 dynamicPseudo = RenderStyle::SELECTION;
1632                 return true;
1633             case CSSSelector::PseudoBefore:
1634                 dynamicPseudo = RenderStyle::BEFORE;
1635                 return true;
1636             case CSSSelector::PseudoAfter:
1637                 dynamicPseudo = RenderStyle::AFTER;
1638                 return true;
1639             case CSSSelector::PseudoFileUploadButton:
1640                 dynamicPseudo = RenderStyle::FILE_UPLOAD_BUTTON;
1641                 return true;
1642                 
1643             case CSSSelector::PseudoNotParsed:
1644                 assert(false);
1645                 break;
1646         }
1647         return false;
1648     }
1649     // ### add the rest of the checks...
1650     return true;
1651 }
1652
1653 // -----------------------------------------------------------------
1654
1655 CSSRuleSet::CSSRuleSet()
1656 {
1657     m_universalRules = 0;
1658     m_ruleCount = 0;
1659 }
1660
1661 CSSRuleSet::~CSSRuleSet()
1662
1663     deleteAllValues(m_idRules);
1664     deleteAllValues(m_classRules);
1665     deleteAllValues(m_tagRules);
1666
1667     delete m_universalRules; 
1668 }
1669
1670
1671 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
1672                               CSSStyleRule* rule, CSSSelector* sel)
1673 {
1674     if (!key) return;
1675     CSSRuleDataList* rules = map.get(key);
1676     if (!rules) {
1677         rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1678         map.set(key, rules);
1679     } else
1680         rules->append(m_ruleCount++, rule, sel);
1681 }
1682
1683 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
1684 {
1685     if (sel->match == CSSSelector::Id) {
1686         addToRuleSet(sel->value.impl(), m_idRules, rule, sel);
1687         return;
1688     }
1689     if (sel->match == CSSSelector::Class) {
1690         addToRuleSet(sel->value.impl(), m_classRules, rule, sel);
1691         return;
1692     }
1693      
1694     const AtomicString& localName = sel->tag.localName();
1695     if (localName != starAtom) {
1696         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
1697         return;
1698     }
1699     
1700     // Just put it in the universal rule set.
1701     if (!m_universalRules)
1702         m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1703     else
1704         m_universalRules->append(m_ruleCount++, rule, sel);
1705 }
1706
1707 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet,  MediaQueryEvaluator* medium)
1708 {
1709     if (!sheet || !sheet->isCSSStyleSheet())
1710         return;
1711
1712     // No media implies "all", but if a media list exists it must
1713     // contain our current medium
1714     if (sheet->media() && !medium->eval(sheet->media()))
1715         return; // the style sheet doesn't apply
1716
1717     int len = sheet->length();
1718
1719     for (int i = 0; i < len; i++) {
1720         StyleBase* item = sheet->item(i);
1721         if (item->isStyleRule()) {
1722             CSSStyleRule* rule = static_cast<CSSStyleRule*>(item);
1723             for (CSSSelector* s = rule->selector(); s; s = s->next())
1724                 addRule(rule, s);
1725         }
1726         else if(item->isImportRule()) {
1727             CSSImportRule* import = static_cast<CSSImportRule*>(item);
1728             if (!import->media() || medium->eval(import->media()))
1729                 addRulesFromSheet(import->styleSheet(), medium);
1730         }
1731         else if(item->isMediaRule()) {
1732             CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
1733             CSSRuleList* rules = r->cssRules();
1734
1735             if ((!r->media() || medium->eval(r->media())) && rules) {
1736                 // Traverse child elements of the @media rule.
1737                 for (unsigned j = 0; j < rules->length(); j++) {
1738                     CSSRule *childItem = rules->item(j);
1739                     if (childItem->isStyleRule()) {
1740                         // It is a StyleRule, so append it to our list
1741                         CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem);
1742                         for (CSSSelector* s = rule->selector(); s; s = s->next())
1743                             addRule(rule, s);
1744                         
1745                     }
1746                 }   // for rules
1747             }   // if rules
1748         }
1749     }
1750 }
1751
1752 // -------------------------------------------------------------------------------------
1753 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1754
1755 static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0)
1756 {
1757     Length l;
1758     if (!primitiveValue) {
1759         if (ok)
1760             *ok = false;
1761     } else {
1762         int type = primitiveValue->primitiveType();
1763         if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
1764             l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
1765         else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
1766             l = Length(int(primitiveValue->getFloatValue()), Percent);
1767         else if(type == CSSPrimitiveValue::CSS_NUMBER)
1768             l = Length(int(primitiveValue->getFloatValue() * 100), Percent);
1769         else if (ok)
1770             *ok = false;
1771     }
1772     return l;
1773 }
1774
1775 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
1776                                          int startIndex, int endIndex)
1777 {
1778     if (startIndex == -1) return;
1779     for (int i = startIndex; i <= endIndex; i++) {
1780         CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
1781         DeprecatedValueListConstIterator<CSSProperty> end;
1782         for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
1783             const CSSProperty& current = *it;
1784             // give special priority to font-xxx, color properties
1785             if (isImportant == current.isImportant()) {
1786                 bool first;
1787                 switch(current.id()) {
1788                     case CSS_PROP_COLOR:
1789                     case CSS_PROP_DIRECTION:
1790                     case CSS_PROP_DISPLAY:
1791                     case CSS_PROP_FONT:
1792                     case CSS_PROP_FONT_SIZE:
1793                     case CSS_PROP_FONT_STYLE:
1794                     case CSS_PROP_FONT_FAMILY:
1795                     case CSS_PROP_FONT_WEIGHT:
1796                     case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST:
1797                     case CSS_PROP_FONT_VARIANT:
1798                         // these have to be applied first, because other properties use the computed
1799                         // values of these porperties.
1800                         first = true;
1801                         break;
1802                     default:
1803                         first = false;
1804                         break;
1805                 }
1806                 
1807                 if (first == applyFirst)
1808                     applyProperty(current.id(), current.value());
1809             }
1810         }
1811     }
1812 }
1813
1814 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
1815 {
1816     CSSPrimitiveValue *primitiveValue = 0;
1817     if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValue*>(value);
1818
1819     Length l;
1820     bool apply = false;
1821
1822     unsigned short valueType = value->cssValueType();
1823
1824     bool isInherit = parentNode && valueType == CSSValue::CSS_INHERIT;
1825     bool isInitial = valueType == CSSValue::CSS_INITIAL || (!parentNode && valueType == CSSValue::CSS_INHERIT);
1826
1827     // These properties are used to set the correct margins/padding on RTL lists.
1828     if (id == CSS_PROP__WEBKIT_MARGIN_START)
1829         id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
1830     else if (id == CSS_PROP__WEBKIT_PADDING_START)
1831         id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
1832
1833     // What follows is a list that maps the CSS properties into their corresponding front-end
1834     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
1835     // are only hit when mapping "inherit" or "initial" into front-end values.
1836     switch(id)
1837     {
1838 // ident only properties
1839     case CSS_PROP_BACKGROUND_ATTACHMENT:
1840         HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
1841         break;
1842     case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
1843         HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
1844         break;
1845     case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
1846         HANDLE_BACKGROUND_VALUE(backgroundComposite, BackgroundComposite, value)
1847         break;
1848     case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
1849         HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
1850         break;
1851     case CSS_PROP_BACKGROUND_REPEAT:
1852         HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
1853         break;
1854     case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
1855         HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
1856         break;
1857     case CSS_PROP_BORDER_COLLAPSE:
1858         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
1859         if(!primitiveValue) break;
1860         switch(primitiveValue->getIdent())
1861         {
1862         case CSS_VAL_COLLAPSE:
1863             style->setBorderCollapse(true);
1864             break;
1865         case CSS_VAL_SEPARATE:
1866             style->setBorderCollapse(false);
1867             break;
1868         default:
1869             return;
1870         }
1871         break;
1872         
1873     case CSS_PROP_BORDER_TOP_STYLE:
1874         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
1875         if (!primitiveValue) return;
1876         style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1877         break;
1878     case CSS_PROP_BORDER_RIGHT_STYLE:
1879         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
1880         if (!primitiveValue) return;
1881         style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1882         break;
1883     case CSS_PROP_BORDER_BOTTOM_STYLE:
1884         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
1885         if (!primitiveValue) return;
1886         style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1887         break;
1888     case CSS_PROP_BORDER_LEFT_STYLE:
1889         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
1890         if (!primitiveValue) return;
1891         style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1892         break;
1893     case CSS_PROP_OUTLINE_STYLE:
1894         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
1895         if (!primitiveValue) return;
1896         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
1897             style->setOutlineStyle(DOTTED, true);
1898         else
1899             style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1900         break;
1901     case CSS_PROP_CAPTION_SIDE:
1902     {
1903         HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
1904         if(!primitiveValue) break;
1905         ECaptionSide c = RenderStyle::initialCaptionSide();
1906         switch(primitiveValue->getIdent())
1907         {
1908         case CSS_VAL_LEFT:
1909             c = CAPLEFT; break;
1910         case CSS_VAL_RIGHT:
1911             c = CAPRIGHT; break;
1912         case CSS_VAL_TOP:
1913             c = CAPTOP; break;
1914         case CSS_VAL_BOTTOM:
1915             c = CAPBOTTOM; break;
1916         default:
1917             return;
1918         }
1919         style->setCaptionSide(c);
1920         return;
1921     }
1922     case CSS_PROP_CLEAR:
1923     {
1924         HANDLE_INHERIT_AND_INITIAL(clear, Clear)
1925         if(!primitiveValue) break;
1926         EClear c;
1927         switch(primitiveValue->getIdent())
1928         {
1929         case CSS_VAL_NONE:
1930             c = CNONE; break;
1931         case CSS_VAL_LEFT:
1932             c = CLEFT; break;
1933         case CSS_VAL_RIGHT:
1934             c = CRIGHT; break;
1935         case CSS_VAL_BOTH:
1936             c = CBOTH; break;
1937         default:
1938             return;
1939         }
1940         style->setClear(c);
1941         return;
1942     }
1943     case CSS_PROP_DIRECTION:
1944     {
1945         HANDLE_INHERIT_AND_INITIAL(direction, Direction)
1946         if(!primitiveValue) break;
1947         style->setDirection(primitiveValue->getIdent() == CSS_VAL_LTR ? LTR : RTL);
1948         return;
1949     }
1950     case CSS_PROP_DISPLAY:
1951     {
1952         HANDLE_INHERIT_AND_INITIAL(display, Display)
1953         if(!primitiveValue) break;
1954         int id = primitiveValue->getIdent();
1955         EDisplay d;
1956         if (id == CSS_VAL_NONE)
1957             d = NONE;
1958         else
1959             d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE);
1960
1961         style->setDisplay(d);
1962         break;
1963     }
1964
1965     case CSS_PROP_EMPTY_CELLS:
1966     {
1967         HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
1968         if (!primitiveValue) break;
1969         int id = primitiveValue->getIdent();
1970         if (id == CSS_VAL_SHOW)
1971             style->setEmptyCells(SHOW);
1972         else if (id == CSS_VAL_HIDE)
1973             style->setEmptyCells(HIDE);
1974         break;
1975     }
1976     case CSS_PROP_FLOAT:
1977     {
1978         HANDLE_INHERIT_AND_INITIAL(floating, Floating)
1979         if(!primitiveValue) return;
1980         EFloat f;
1981         switch(primitiveValue->getIdent())
1982         {
1983         case CSS_VAL_LEFT:
1984             f = FLEFT; break;
1985         case CSS_VAL_RIGHT:
1986             f = FRIGHT; break;
1987         case CSS_VAL_NONE:
1988         case CSS_VAL_CENTER:  //Non standart CSS-Value
1989             f = FNONE; break;
1990         default:
1991             return;
1992         }
1993         
1994         style->setFloating(f);
1995         break;
1996     }
1997
1998         break;
1999     case CSS_PROP_FONT_STRETCH:
2000         break; /* Not supported. */
2001
2002     case CSS_PROP_FONT_STYLE:
2003     {
2004         FontDescription fontDescription = style->fontDescription();
2005         if (isInherit)
2006             fontDescription.setItalic(parentStyle->fontDescription().italic());
2007         else if (isInitial)
2008             fontDescription.setItalic(false);
2009         else {
2010             if (!primitiveValue) return;
2011             switch (primitiveValue->getIdent()) {
2012                 case CSS_VAL_OBLIQUE:
2013                 // FIXME: oblique is the same as italic for the moment...
2014                 case CSS_VAL_ITALIC:
2015                     fontDescription.setItalic(true);
2016                     break;
2017                 case CSS_VAL_NORMAL:
2018                     fontDescription.setItalic(false);
2019                     break;
2020                 default:
2021                     return;
2022             }
2023         }
2024         if (style->setFontDescription(fontDescription))
2025             fontDirty = true;
2026         break;
2027     }
2028
2029     case CSS_PROP_FONT_VARIANT:
2030     {
2031         FontDescription fontDescription = style->fontDescription();
2032         if (isInherit) 
2033             fontDescription.setSmallCaps(parentStyle->fontDescription().smallCaps());
2034         else if (isInitial)
2035             fontDescription.setSmallCaps(false);
2036         else {
2037             if (!primitiveValue) return;
2038             int id = primitiveValue->getIdent();
2039             if (id == CSS_VAL_NORMAL)
2040                 fontDescription.setSmallCaps(false);
2041             else if (id == CSS_VAL_SMALL_CAPS)
2042                 fontDescription.setSmallCaps(true);
2043             else
2044                 return;
2045         }
2046         if (style->setFontDescription(fontDescription))
2047             fontDirty = true;
2048         break;        
2049     }
2050
2051     case CSS_PROP_FONT_WEIGHT:
2052     {
2053         FontDescription fontDescription = style->fontDescription();
2054         if (isInherit)
2055             fontDescription.setWeight(parentStyle->fontDescription().weight());
2056         else if (isInitial)
2057             fontDescription.setWeight(cNormalWeight);
2058         else {
2059             if (!primitiveValue) return;
2060             if (primitiveValue->getIdent()) {
2061                 switch (primitiveValue->getIdent()) {
2062                     // FIXME: We aren't genuinely supporting specific weight values.
2063                     case CSS_VAL_BOLD:
2064                     case CSS_VAL_BOLDER:
2065                     case CSS_VAL_600:
2066                     case CSS_VAL_700:
2067                     case CSS_VAL_800:
2068                     case CSS_VAL_900:
2069                         fontDescription.setWeight(cBoldWeight);
2070                         break;
2071                     case CSS_VAL_NORMAL:
2072                     case CSS_VAL_LIGHTER:
2073                     case CSS_VAL_100:
2074                     case CSS_VAL_200:
2075                     case CSS_VAL_300:
2076                     case CSS_VAL_400:
2077                     case CSS_VAL_500:
2078                         fontDescription.setWeight(cNormalWeight);
2079                         break;
2080                     default:
2081                         return;
2082                 }
2083             }
2084             else
2085             {
2086                 // ### fix parsing of 100-900 values in parser, apply them here
2087             }
2088         }
2089         if (style->setFontDescription(fontDescription))
2090             fontDirty = true;
2091         break;
2092     }
2093         
2094     case CSS_PROP_LIST_STYLE_POSITION:
2095     {
2096         HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
2097         if (!primitiveValue) return;
2098         if (primitiveValue->getIdent())
2099             style->setListStylePosition((EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE));
2100         return;
2101     }
2102
2103     case CSS_PROP_LIST_STYLE_TYPE:
2104     {
2105         HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2106         if (!primitiveValue) return;
2107         if (primitiveValue->getIdent())
2108         {
2109             EListStyleType t;
2110             int id = primitiveValue->getIdent();
2111             if (id == CSS_VAL_NONE) { // important!!
2112               t = LNONE;
2113             } else {
2114               t = EListStyleType(id - CSS_VAL_DISC);
2115             }
2116             style->setListStyleType(t);
2117         }
2118         return;
2119     }
2120
2121     case CSS_PROP_OVERFLOW:
2122     {
2123         if (isInherit) {
2124             style->setOverflowX(parentStyle->overflowX());
2125             style->setOverflowY(parentStyle->overflowY());
2126             return;
2127         }
2128         
2129         if (isInitial) {
2130             style->setOverflowX(RenderStyle::initialOverflowX());
2131             style->setOverflowY(RenderStyle::initialOverflowY());
2132             return;
2133         }
2134             
2135         EOverflow o;
2136         switch(primitiveValue->getIdent()) {
2137             case CSS_VAL_VISIBLE:
2138                 o = OVISIBLE; break;
2139             case CSS_VAL_HIDDEN:
2140                 o = OHIDDEN; break;
2141             case CSS_VAL_SCROLL:
2142                 o = OSCROLL; break;
2143             case CSS_VAL_AUTO:
2144                 o = OAUTO; break;
2145             case CSS_VAL__WEBKIT_MARQUEE:
2146                 o = OMARQUEE; break;
2147             case CSS_VAL_OVERLAY:
2148                 o = OOVERLAY; break;
2149             default:
2150                 return;
2151         }
2152         style->setOverflowX(o);
2153         style->setOverflowY(o);
2154         return;
2155     }
2156
2157     case CSS_PROP_OVERFLOW_X:
2158     {
2159         HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX)
2160         EOverflow o;
2161         switch(primitiveValue->getIdent())
2162         {
2163         case CSS_VAL_VISIBLE:
2164             o = OVISIBLE; break;
2165         case CSS_VAL_HIDDEN:
2166             o = OHIDDEN; break;
2167         case CSS_VAL_SCROLL:
2168             o = OSCROLL; break;
2169         case CSS_VAL_AUTO:
2170             o = OAUTO; break;
2171         case CSS_VAL_OVERLAY:
2172             o = OOVERLAY; break;
2173         default:
2174             return;
2175         }
2176         style->setOverflowX(o);
2177         return;
2178     }
2179
2180     case CSS_PROP_OVERFLOW_Y:
2181     {
2182         HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY)
2183         EOverflow o;
2184         switch(primitiveValue->getIdent())
2185         {
2186         case CSS_VAL_VISIBLE:
2187             o = OVISIBLE; break;
2188         case CSS_VAL_HIDDEN:
2189             o = OHIDDEN; break;
2190         case CSS_VAL_SCROLL:
2191             o = OSCROLL; break;
2192         case CSS_VAL_AUTO:
2193             o = OAUTO; break;
2194         case CSS_VAL_OVERLAY:
2195             o = OOVERLAY; break;
2196         default:
2197             return;
2198         }
2199         style->setOverflowY(o);
2200         return;
2201     }
2202
2203     case CSS_PROP_PAGE_BREAK_BEFORE:
2204     {
2205         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2206         if (!primitiveValue) return;
2207         switch (primitiveValue->getIdent()) {
2208             case CSS_VAL_AUTO:
2209                 style->setPageBreakBefore(PBAUTO);
2210                 break;
2211             case CSS_VAL_LEFT:
2212             case CSS_VAL_RIGHT:
2213             case CSS_VAL_ALWAYS:
2214                 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2215                 break;
2216             case CSS_VAL_AVOID:
2217                 style->setPageBreakBefore(PBAVOID);
2218                 break;
2219         }
2220         break;
2221     }
2222
2223     case CSS_PROP_PAGE_BREAK_AFTER:
2224     {
2225         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2226         if (!primitiveValue) return;
2227         switch (primitiveValue->getIdent()) {
2228             case CSS_VAL_AUTO:
2229                 style->setPageBreakAfter(PBAUTO);
2230                 break;
2231             case CSS_VAL_LEFT:
2232             case CSS_VAL_RIGHT:
2233             case CSS_VAL_ALWAYS:
2234                 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2235                 break;
2236             case CSS_VAL_AVOID:
2237                 style->setPageBreakAfter(PBAVOID);
2238                 break;
2239         }
2240         break;
2241     }
2242
2243     case CSS_PROP_PAGE_BREAK_INSIDE: {
2244         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2245         if (!primitiveValue) return;
2246         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
2247             style->setPageBreakInside(PBAUTO);
2248         else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
2249             style->setPageBreakInside(PBAVOID);
2250         return;
2251     }
2252         
2253     case CSS_PROP_PAGE:
2254         break; /* FIXME: Not even sure what this is...  -dwh */
2255
2256     case CSS_PROP_POSITION:
2257     {
2258         HANDLE_INHERIT_AND_INITIAL(position, Position)
2259         if(!primitiveValue) return;
2260         EPosition p;
2261         switch(primitiveValue->getIdent())
2262         {
2263         case CSS_VAL_STATIC:
2264             p = StaticPosition;
2265             break;
2266         case CSS_VAL_RELATIVE:
2267             p = RelativePosition;
2268             break;
2269         case CSS_VAL_ABSOLUTE:
2270             p = AbsolutePosition;
2271             break;
2272         case CSS_VAL_FIXED:
2273             p = FixedPosition;
2274             break;
2275         default:
2276             return;
2277         }
2278         style->setPosition(p);
2279         return;
2280     }
2281
2282     case CSS_PROP_TABLE_LAYOUT: {
2283         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2284
2285         if (!primitiveValue->getIdent())
2286             return;
2287
2288         ETableLayout l = RenderStyle::initialTableLayout();
2289         switch(primitiveValue->getIdent()) {
2290             case CSS_VAL_FIXED:
2291                 l = TFIXED;
2292                 // fall through
2293             case CSS_VAL_AUTO:
2294                 style->setTableLayout(l);
2295             default:
2296                 break;
2297         }
2298         break;
2299     }
2300         
2301     case CSS_PROP_UNICODE_BIDI: {
2302         HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2303         switch (primitiveValue->getIdent()) {
2304             case CSS_VAL_NORMAL:
2305                 style->setUnicodeBidi(UBNormal); 
2306                 break;
2307             case CSS_VAL_EMBED:
2308                 style->setUnicodeBidi(Embed); 
2309                 break;
2310             case CSS_VAL_BIDI_OVERRIDE:
2311                 style->setUnicodeBidi(Override);
2312                 break;
2313             default:
2314                 return;
2315         }
2316         break;
2317     }
2318     case CSS_PROP_TEXT_TRANSFORM: {
2319         HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2320         
2321         if(!primitiveValue->getIdent()) return;
2322
2323         ETextTransform tt;
2324         switch(primitiveValue->getIdent()) {
2325         case CSS_VAL_CAPITALIZE:  tt = CAPITALIZE;  break;
2326         case CSS_VAL_UPPERCASE:   tt = UPPERCASE;   break;
2327         case CSS_VAL_LOWERCASE:   tt = LOWERCASE;   break;
2328         case CSS_VAL_NONE:
2329         default:                  tt = TTNONE;      break;
2330         }
2331         style->setTextTransform(tt);
2332         break;
2333         }
2334
2335     case CSS_PROP_VISIBILITY:
2336     {
2337         HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2338
2339         switch(primitiveValue->getIdent()) {
2340         case CSS_VAL_HIDDEN:
2341             style->setVisibility(HIDDEN);
2342             break;
2343         case CSS_VAL_VISIBLE:
2344             style->setVisibility(VISIBLE);
2345             break;
2346         case CSS_VAL_COLLAPSE:
2347             style->setVisibility(COLLAPSE);
2348         default:
2349             break;
2350         }
2351         break;
2352     }
2353     case CSS_PROP_WHITE_SPACE:
2354         HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2355
2356         if(!primitiveValue->getIdent()) return;
2357
2358         EWhiteSpace s;
2359         switch(primitiveValue->getIdent()) {
2360         case CSS_VAL__WEBKIT_NOWRAP:
2361             s = KHTML_NOWRAP;
2362             break;
2363         case CSS_VAL_NOWRAP:
2364             s = NOWRAP;
2365             break;
2366         case CSS_VAL_PRE:
2367             s = PRE;
2368             break;
2369         case CSS_VAL_PRE_WRAP:
2370             s = PRE_WRAP;
2371             break;
2372         case CSS_VAL_PRE_LINE:
2373             s = PRE_LINE;
2374             break;
2375         case CSS_VAL_NORMAL:
2376         default:
2377             s = NORMAL;
2378             break;
2379         }
2380         style->setWhiteSpace(s);
2381         break;
2382
2383     case CSS_PROP_BACKGROUND_POSITION:
2384         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
2385         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
2386         break;
2387     case CSS_PROP_BACKGROUND_POSITION_X: {
2388         HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
2389         break;
2390     }
2391     case CSS_PROP_BACKGROUND_POSITION_Y: {
2392         HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
2393         break;
2394     }
2395     case CSS_PROP_BORDER_SPACING: {
2396         if (isInherit) {
2397             style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing());
2398             style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing());
2399         }
2400         else if (isInitial) {
2401             style->setHorizontalBorderSpacing(0);
2402             style->setVerticalBorderSpacing(0);
2403         }
2404         break;
2405     }
2406     case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: {
2407         HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2408         if (!primitiveValue) break;
2409         short spacing =  primitiveValue->computeLengthShort(style);
2410         style->setHorizontalBorderSpacing(spacing);
2411         break;
2412     }
2413     case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: {
2414         HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2415         if (!primitiveValue) break;
2416         short spacing =  primitiveValue->computeLengthShort(style);
2417         style->setVerticalBorderSpacing(spacing);
2418         break;
2419     }
2420     case CSS_PROP_CURSOR:
2421         if (isInherit) {
2422             style->setCursor(parentStyle->cursor());
2423             style->setCursorList(parentStyle->cursors());
2424             return;
2425         }
2426         style->clearCursorList();
2427         if (isInitial) {
2428             style->setCursor(RenderStyle::initialCursor());
2429             return;
2430         }
2431         if (value->isValueList()) {
2432             CSSValueList* list = static_cast<CSSValueList*>(value);
2433             int len = list->length();
2434             style->setCursor(CURSOR_AUTO);
2435             for (int i = 0; i < len; i++) {
2436                 CSSValue* item = list->item(i);
2437                 if (!item->isPrimitiveValue())
2438                     continue;
2439                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
2440                 int type = primitiveValue->primitiveType();
2441                 if (type == CSSPrimitiveValue::CSS_URI) {
2442 #ifdef SVG_SUPPORT
2443                     if (primitiveValue->getStringValue().find("#") == 0)
2444                         style->addSVGCursor(primitiveValue->getStringValue().substring(1));
2445                     else
2446 #endif
2447                     {
2448                         CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
2449                         style->addCursor(image->image(element->document()->docLoader()), image->hotspot());
2450                     }
2451                 } else if (type == CSSPrimitiveValue::CSS_IDENT)
2452                     style->setCursor((ECursor)(primitiveValue->getIdent() - CSS_VAL_AUTO));
2453             }
2454         } else if (primitiveValue) {
2455             int type = primitiveValue->primitiveType();
2456             if (type == CSSPrimitiveValue::CSS_IDENT)
2457                 style->setCursor((ECursor)(primitiveValue->getIdent() - CSS_VAL_AUTO));
2458         }
2459         break;
2460 // colors || inherit
2461     case CSS_PROP_BACKGROUND_COLOR:
2462     case CSS_PROP_BORDER_TOP_COLOR:
2463     case CSS_PROP_BORDER_RIGHT_COLOR:
2464     case CSS_PROP_BORDER_BOTTOM_COLOR:
2465     case CSS_PROP_BORDER_LEFT_COLOR:
2466     case CSS_PROP_COLOR:
2467     case CSS_PROP_OUTLINE_COLOR:
2468         // this property is an extension used to get HTML4 <font> right.
2469     {
2470         Color col;
2471         if (isInherit) {
2472             HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
2473             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
2474             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
2475             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
2476             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
2477             HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
2478             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
2479             return;
2480         }
2481         if (isInitial) {
2482             // The border/outline colors will just map to the invalid color |col| above.  This will have the
2483             // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2484             // not painting the background since the color won't be valid).
2485             if (id == CSS_PROP_COLOR)
2486                 col = RenderStyle::initialColor();
2487         } else {
2488             if (!primitiveValue)
2489                 return;
2490             col = getColorFromPrimitiveValue(primitiveValue);
2491         }
2492
2493         switch(id) {
2494         case CSS_PROP_BACKGROUND_COLOR:
2495             style->setBackgroundColor(col); break;
2496         case CSS_PROP_BORDER_TOP_COLOR:
2497             style->setBorderTopColor(col); break;
2498         case CSS_PROP_BORDER_RIGHT_COLOR:
2499             style->setBorderRightColor(col); break;
2500         case CSS_PROP_BORDER_BOTTOM_COLOR:
2501             style->setBorderBottomColor(col); break;
2502         case CSS_PROP_BORDER_LEFT_COLOR:
2503             style->setBorderLeftColor(col); break;
2504         case CSS_PROP_COLOR:
2505             style->setColor(col); break;
2506         case CSS_PROP_OUTLINE_COLOR:
2507             style->setOutlineColor(col); break;
2508         }
2509         return;
2510     }
2511     break;
2512     
2513 // uri || inherit
2514     case CSS_PROP_BACKGROUND_IMAGE:
2515         HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
2516         break;
2517     case CSS_PROP_LIST_STYLE_IMAGE:
2518     {
2519         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2520         if (!primitiveValue)
2521             return;
2522         style->setListStyleImage(static_cast<CSSImageValue*>(primitiveValue)->image(element->document()->docLoader()));
2523         break;
2524     }
2525
2526 // length
2527     case CSS_PROP_BORDER_TOP_WIDTH:
2528     case CSS_PROP_BORDER_RIGHT_WIDTH:
2529     case CSS_PROP_BORDER_BOTTOM_WIDTH:
2530     case CSS_PROP_BORDER_LEFT_WIDTH:
2531     case CSS_PROP_OUTLINE_WIDTH:
2532     {
2533         if (isInherit) {
2534             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
2535             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
2536             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
2537             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
2538             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
2539             return;
2540         }
2541         else if (isInitial) {
2542             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
2543             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
2544             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
2545             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
2546             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
2547             return;
2548         }
2549
2550         if(!primitiveValue) break;
2551         short width = 3;
2552         switch(primitiveValue->getIdent())
2553         {
2554         case CSS_VAL_THIN:
2555             width = 1;
2556             break;
2557         case CSS_VAL_MEDIUM:
2558             width = 3;
2559             break;
2560         case CSS_VAL_THICK:
2561             width = 5;
2562             break;
2563         case CSS_VAL_INVALID:
2564             width = primitiveValue->computeLengthShort(style);
2565             break;
2566         default:
2567             return;
2568         }
2569
2570         if(width < 0) return;
2571         switch(id)
2572         {
2573         case CSS_PROP_BORDER_TOP_WIDTH:
2574             style->setBorderTopWidth(width);
2575             break;
2576         case CSS_PROP_BORDER_RIGHT_WIDTH:
2577             style->setBorderRightWidth(width);
2578             break;
2579         case CSS_PROP_BORDER_BOTTOM_WIDTH:
2580             style->setBorderBottomWidth(width);
2581             break;
2582         case CSS_PROP_BORDER_LEFT_WIDTH:
2583             style->setBorderLeftWidth(width);
2584             break;
2585         case CSS_PROP_OUTLINE_WIDTH:
2586             style->setOutlineWidth(width);
2587             break;
2588         default:
2589             return;
2590         }
2591         return;
2592     }
2593
2594     case CSS_PROP_LETTER_SPACING:
2595     case CSS_PROP_WORD_SPACING:
2596     {
2597         
2598         if (isInherit) {
2599             HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
2600             HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
2601             return;
2602         }
2603         else if (isInitial) {
2604             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
2605             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
2606             return;
2607         }
2608         
2609         int width = 0;
2610         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){
2611             width = 0;
2612         } else {
2613             if(!primitiveValue) return;
2614             width = primitiveValue->computeLengthInt(style);
2615         }
2616         switch(id)
2617         {
2618         case CSS_PROP_LETTER_SPACING:
2619             style->setLetterSpacing(width);
2620             break;
2621         case CSS_PROP_WORD_SPACING:
2622             style->setWordSpacing(width);
2623             break;
2624             // ### needs the definitions in renderstyle
2625         default: break;
2626         }
2627         return;
2628     }
2629
2630     case CSS_PROP_WORD_WRAP:
2631     {
2632         HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap)
2633
2634         if(!primitiveValue->getIdent()) return;
2635
2636         EWordWrap s;
2637         switch(primitiveValue->getIdent()) {
2638         case CSS_VAL_BREAK_WORD:
2639             s = BREAK_WORD;
2640             break;
2641         case CSS_VAL_NORMAL:
2642         default:
2643             s = WBNORMAL;
2644             break;
2645         }
2646         style->setWordWrap(s);
2647         break;
2648     }
2649
2650     case CSS_PROP__WEBKIT_NBSP_MODE:
2651     {
2652         HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode)
2653
2654         if (!primitiveValue->getIdent()) return;
2655
2656         ENBSPMode m;
2657         switch(primitiveValue->getIdent()) {
2658         case CSS_VAL_SPACE:
2659             m = SPACE;
2660             break;
2661         case CSS_VAL_NORMAL:
2662         default:
2663             m = NBNORMAL;
2664             break;
2665         }
2666         style->setNBSPMode(m);
2667         break;
2668     }
2669
2670     case CSS_PROP__WEBKIT_LINE_BREAK:
2671     {
2672         HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak)
2673
2674         if (!primitiveValue->getIdent()) return;
2675
2676         EKHTMLLineBreak b;
2677         switch(primitiveValue->getIdent()) {
2678         case CSS_VAL_AFTER_WHITE_SPACE:
2679             b = AFTER_WHITE_SPACE;
2680             break;
2681         case CSS_VAL_NORMAL:
2682         default:
2683             b = LBNORMAL;
2684             break;
2685         }
2686         style->setKHTMLLineBreak(b);
2687         break;
2688     }
2689
2690     case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR:
2691     {
2692         HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2693
2694         if (!primitiveValue->getIdent()) return;
2695
2696         EMatchNearestMailBlockquoteColor c;
2697         switch(primitiveValue->getIdent()) {
2698         case CSS_VAL_NORMAL:
2699             c = BCNORMAL;
2700             break;
2701         case CSS_VAL_MATCH:
2702         default:
2703             c = MATCH;
2704             break;
2705         }
2706         style->setMatchNearestMailBlockquoteColor(c);
2707         break;
2708     }
2709
2710     case CSS_PROP_RESIZE:
2711     {
2712         HANDLE_INHERIT_AND_INITIAL(resize, Resize)
2713
2714         if (!primitiveValue->getIdent()) return;
2715
2716         EResize r;
2717         switch(primitiveValue->getIdent()) {
2718         case CSS_VAL_BOTH:
2719             r = RESIZE_BOTH;
2720             break;
2721         case CSS_VAL_HORIZONTAL:
2722             r = RESIZE_HORIZONTAL;
2723             break;
2724         case CSS_VAL_VERTICAL:
2725             r = RESIZE_VERTICAL;
2726             break;
2727         case CSS_VAL_AUTO:
2728             r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
2729             break;
2730         case CSS_VAL_NONE:
2731         default:
2732             r = RESIZE_NONE;
2733             break;
2734         }
2735         style->setResize(r);
2736         break;
2737     }
2738     
2739     // length, percent
2740     case CSS_PROP_MAX_WIDTH:
2741         // +none +inherit
2742         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2743             apply = true;
2744     case CSS_PROP_TOP:
2745     case CSS_PROP_LEFT:
2746     case CSS_PROP_RIGHT:
2747     case CSS_PROP_BOTTOM:
2748     case CSS_PROP_WIDTH:
2749     case CSS_PROP_MIN_WIDTH:
2750     case CSS_PROP_MARGIN_TOP:
2751     case CSS_PROP_MARGIN_RIGHT:
2752     case CSS_PROP_MARGIN_BOTTOM:
2753     case CSS_PROP_MARGIN_LEFT:
2754         // +inherit +auto
2755         if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) {
2756             if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2757                 l = Length(Intrinsic);
2758                 apply = true;
2759             }
2760             else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2761                 l = Length(MinIntrinsic);
2762                 apply = true;
2763             }
2764         }
2765         if (id != CSS_PROP_MAX_WIDTH && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2766             apply = true;
2767     case CSS_PROP_PADDING_TOP:
2768     case CSS_PROP_PADDING_RIGHT:
2769     case CSS_PROP_PADDING_BOTTOM:
2770     case CSS_PROP_PADDING_LEFT:
2771     case CSS_PROP_TEXT_INDENT:
2772         // +inherit
2773     {
2774         if (isInherit) {
2775             HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
2776             HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
2777             HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
2778             HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
2779             HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
2780             HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
2781             HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
2782             HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
2783             HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
2784             HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
2785             HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
2786             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
2787             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
2788             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
2789             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
2790             HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
2791             return;
2792         }
2793         else if (isInitial) {
2794             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
2795             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
2796             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
2797             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
2798             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
2799             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
2800             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
2801             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
2802             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
2803             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
2804             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
2805             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
2806             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
2807             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
2808             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
2809             HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
2810             return;
2811         } 
2812
2813         if (primitiveValue && !apply) {
2814             int type = primitiveValue->primitiveType();
2815             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2816                 // Handle our quirky margin units if we have them.
2817                 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed, 
2818                            primitiveValue->isQuirkValue());
2819             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2820                 l = Length((int)primitiveValue->getFloatValue(), Percent);
2821             else
2822                 return;
2823             if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT ||
2824                 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM)
2825                 // Padding can't be negative
2826                 apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0);
2827             else
2828                 apply = true;
2829         }
2830         if(!apply) return;
2831         switch(id)
2832             {
2833             case CSS_PROP_MAX_WIDTH:
2834                 style->setMaxWidth(l); break;
2835             case CSS_PROP_BOTTOM:
2836                 style->setBottom(l); break;
2837             case CSS_PROP_TOP:
2838                 style->setTop(l); break;
2839             case CSS_PROP_LEFT:
2840                 style->setLeft(l); break;
2841             case CSS_PROP_RIGHT:
2842                 style->setRight(l); break;
2843             case CSS_PROP_WIDTH:
2844                 style->setWidth(l); break;
2845             case CSS_PROP_MIN_WIDTH:
2846                 style->setMinWidth(l); break;
2847             case CSS_PROP_PADDING_TOP:
2848                 style->setPaddingTop(l); break;
2849             case CSS_PROP_PADDING_RIGHT:
2850                 style->setPaddingRight(l); break;
2851             case CSS_PROP_PADDING_BOTTOM:
2852                 style->setPaddingBottom(l); break;
2853             case CSS_PROP_PADDING_LEFT:
2854                 style->setPaddingLeft(l); break;
2855             case CSS_PROP_MARGIN_TOP:
2856                 style->setMarginTop(l); break;
2857             case CSS_PROP_MARGIN_RIGHT:
2858                 style->setMarginRight(l); break;
2859             case CSS_PROP_MARGIN_BOTTOM:
2860                 style->setMarginBottom(l); break;
2861             case CSS_PROP_MARGIN_LEFT:
2862                 style->setMarginLeft(l); break;
2863             case CSS_PROP_TEXT_INDENT:
2864                 style->setTextIndent(l); break;
2865             default: break;
2866             }
2867         return;
2868     }
2869
2870     case CSS_PROP_MAX_HEIGHT:
2871         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
2872             l = Length(undefinedLength, Fixed);
2873             apply = true;
2874         }
2875     case CSS_PROP_HEIGHT:
2876     case CSS_PROP_MIN_HEIGHT:
2877         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2878             l = Length(Intrinsic);
2879             apply = true;
2880         } else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2881             l = Length(MinIntrinsic);
2882             apply = true;
2883         } else if (id != CSS_PROP_MAX_HEIGHT && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2884             apply = true;
2885         if (isInherit) {
2886             HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
2887             HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
2888             HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
2889             return;
2890         }
2891         if (isInitial) {
2892             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
2893             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
2894             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
2895             return;
2896         }
2897
2898         if (primitiveValue && !apply) {
2899             unsigned short type = primitiveValue->primitiveType();
2900             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2901                 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2902             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2903                 l = Length((int)primitiveValue->getFloatValue(), Percent);
2904             else
2905                 return;
2906             apply = true;
2907         }
2908         if (apply)
2909             switch (id) {
2910                 case CSS_PROP_MAX_HEIGHT:
2911                     style->setMaxHeight(l);
2912                     break;
2913                 case CSS_PROP_HEIGHT:
2914                     style->setHeight(l);
2915                     break;
2916                 case CSS_PROP_MIN_HEIGHT:
2917                     style->setMinHeight(l);
2918                     break;
2919             }
2920         break;
2921
2922     case CSS_PROP_VERTICAL_ALIGN:
2923         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2924         if (!primitiveValue) return;
2925         if (primitiveValue->getIdent()) {
2926           EVerticalAlign align;
2927
2928           switch(primitiveValue->getIdent())
2929             {
2930                 case CSS_VAL_TOP:
2931                     align = TOP; break;
2932                 case CSS_VAL_BOTTOM:
2933                     align = BOTTOM; break;
2934                 case CSS_VAL_MIDDLE:
2935                     align = MIDDLE; break;
2936                 case CSS_VAL_BASELINE:
2937                     align = BASELINE; break;
2938                 case CSS_VAL_TEXT_BOTTOM:
2939                     align = TEXT_BOTTOM; break;
2940                 case CSS_VAL_TEXT_TOP:
2941                     align = TEXT_TOP; break;
2942                 case CSS_VAL_SUB:
2943                     align = SUB; break;
2944                 case CSS_VAL_SUPER:
2945                     align = SUPER; break;
2946                 case CSS_VAL__WEBKIT_BASELINE_MIDDLE:
2947                     align = BASELINE_MIDDLE; break;
2948                 default:
2949                     return;
2950             }
2951           style->setVerticalAlign(align);
2952           return;
2953         } else {
2954           int type = primitiveValue->primitiveType();
2955           Length l;
2956           if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2957             l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2958           else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2959             l = Length(int(primitiveValue->getFloatValue()), Percent);
2960
2961           style->setVerticalAlign(LENGTH);
2962           style->setVerticalAlignLength(l);
2963         }
2964         break;
2965
2966     case CSS_PROP_FONT_SIZE:
2967     {
2968         FontDescription fontDescription = style->fontDescription();
2969         fontDescription.setKeywordSize(0);
2970         bool familyIsFixed = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
2971         float oldSize = 0;
2972         float size = 0;
2973         
2974         bool parentIsAbsoluteSize = false;
2975         if (parentNode) {
2976             oldSize = parentStyle->fontDescription().specifiedSize();
2977             parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize();
2978         }
2979
2980         if (isInherit) {
2981             size = oldSize;
2982             if (parentNode)
2983                 fontDescription.setKeywordSize(parentStyle->fontDescription().keywordSize());
2984         } else if (isInitial) {
2985             size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks(), familyIsFixed);
2986             fontDescription.setKeywordSize(CSS_VAL_MEDIUM - CSS_VAL_XX_SMALL + 1);
2987         } else if (primitiveValue->getIdent()) {
2988             // Keywords are being used.
2989             switch (primitiveValue->getIdent()) {
2990                 case CSS_VAL_XX_SMALL:
2991                 case CSS_VAL_X_SMALL:
2992                 case CSS_VAL_SMALL:
2993                 case CSS_VAL_MEDIUM:
2994                 case CSS_VAL_LARGE:
2995                 case CSS_VAL_X_LARGE:
2996                 case CSS_VAL_XX_LARGE:
2997                 case CSS_VAL__WEBKIT_XXX_LARGE:
2998                     size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks(), familyIsFixed);
2999                     fontDescription.setKeywordSize(primitiveValue->getIdent() - CSS_VAL_XX_SMALL + 1);
3000                     break;
3001                 case CSS_VAL_LARGER:
3002                     size = largerFontSize(oldSize, style->htmlHacks());
3003                     break;
3004                 case CSS_VAL_SMALLER:
3005                     size = smallerFontSize(oldSize, style->htmlHacks());
3006                     break;
3007                 default:
3008                     return;
3009             }
3010
3011             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && 
3012                                               (primitiveValue->getIdent() == CSS_VAL_LARGER ||
3013                                                primitiveValue->getIdent() == CSS_VAL_SMALLER));
3014         } else {
3015             int type = primitiveValue->primitiveType();
3016             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
3017                                               (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
3018                                                type != CSSPrimitiveValue::CSS_EMS && 
3019                                                type != CSSPrimitiveValue::CSS_EXS));
3020             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
3021                 size = primitiveValue->computeLengthFloat(parentStyle, false);
3022             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
3023                 size = (primitiveValue->getFloatValue() * oldSize) / 100;
3024             else
3025                 return;
3026         }
3027
3028         if (size < 0)
3029             return;
3030
3031         setFontSize(fontDescription, size);
3032         if (style->setFontDescription(fontDescription))
3033             fontDirty = true;
3034         return;
3035     }
3036         break;
3037     case CSS_PROP_Z_INDEX:
3038     {
3039         HANDLE_INHERIT(zIndex, ZIndex)
3040         else if (isInitial) {
3041             style->setHasAutoZIndex();
3042             return;
3043         }
3044         
3045         if (!primitiveValue)
3046             return;
3047
3048         if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
3049             style->setHasAutoZIndex();
3050             return;
3051         }
3052         
3053         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3054             return; // Error case.
3055         
3056         style->setZIndex((int)primitiveValue->getFloatValue());
3057         
3058         return;
3059     }
3060         
3061     case CSS_PROP_WIDOWS:
3062     {
3063         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
3064         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3065             return;
3066         style->setWidows((int)primitiveValue->getFloatValue());
3067         break;
3068     }
3069         
3070     case CSS_PROP_ORPHANS:
3071     {
3072         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
3073         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3074             return;
3075         style->setOrphans((int)primitiveValue->getFloatValue());
3076         break;
3077     }        
3078
3079 // length, percent, number
3080     case CSS_PROP_LINE_HEIGHT:
3081     {
3082         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
3083         if(!primitiveValue) return;
3084         Length lineHeight;
3085         int type = primitiveValue->primitiveType();
3086         if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
3087             lineHeight = Length(-100, Percent);
3088         else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3089             double multiplier = 1.0;
3090             // Scale for the font zoom factor only for types other than "em" and "ex", since those are
3091             // already based on the font size.
3092             if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->frame()) {
3093                 multiplier = view->frame()->zoomFactor() / 100.0;
3094             }
3095             lineHeight = Length(primitiveValue->computeLengthIntForLength(style, multiplier), Fixed);
3096         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3097             lineHeight = Length((style->fontSize() * int(primitiveValue->getFloatValue())) / 100, Fixed);
3098         else if (type == CSSPrimitiveValue::CSS_NUMBER)
3099             lineHeight = Length(int(primitiveValue->getFloatValue() * 100), Percent);
3100         else
3101             return;
3102         style->setLineHeight(lineHeight);
3103         return;
3104     }
3105
3106 // string
3107     case CSS_PROP_TEXT_ALIGN:
3108     {
3109         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
3110         if (!primitiveValue) return;
3111         if (primitiveValue->getIdent())
3112             style->setTextAlign((ETextAlign) (primitiveValue->getIdent() - CSS_VAL__WEBKIT_AUTO));
3113         return;
3114     }
3115
3116 // rect
3117     case CSS_PROP_CLIP:
3118     {
3119         Length top;
3120         Length right;
3121         Length bottom;
3122         Length left;
3123         bool hasClip = true;
3124         if (isInherit) {
3125             if (parentStyle->hasClip()) {
3126                 top = parentStyle->clipTop();
3127                 right = parentStyle->clipRight();
3128                 bottom = parentStyle->clipBottom();
3129                 left = parentStyle->clipLeft();
3130             }
3131             else {
3132                 hasClip = false;
3133                 top = right = bottom = left = Length();
3134             }
3135         } else if (isInitial) {
3136             hasClip = false;
3137             top = right = bottom = left = Length();
3138         } else if (!primitiveValue) {
3139             break;
3140         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
3141             RectImpl* rect = primitiveValue->getRectValue();
3142             if (!rect)
3143                 break;
3144             top = convertToLength(rect->top(), style);
3145             right = convertToLength(rect->right(), style);
3146             bottom = convertToLength(rect->bottom(), style);
3147             left = convertToLength(rect->left(), style);
3148
3149         } else if (primitiveValue->getIdent() != CSS_VAL_AUTO) {
3150             break;
3151         }
3152         style->setClip(top, right, bottom, left);
3153         style->setHasClip(hasClip);
3154     
3155         // rect, ident
3156         break;
3157     }
3158
3159 // lists
3160     case CSS_PROP_CONTENT:
3161         // list of string, uri, counter, attr, i
3162     {
3163         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
3164         // note is a reminder that eventually "inherit" needs to be supported.
3165
3166         if (isInitial) {
3167             if (style->contentData())
3168                 style->contentData()->clearContent();
3169             return;
3170         }
3171         
3172         if (!value->isValueList()) return;
3173         CSSValueList *list = static_cast<CSSValueList*>(value);
3174         int len = list->length();
3175
3176         for (int i = 0; i < len; i++) {
3177             CSSValue *item = list->item(i);
3178             if (!item->isPrimitiveValue())
3179                 continue;
3180             
3181             CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3182             if (val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
3183                 style->setContent(val->getStringValue().impl(), i != 0);
3184             else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR) {
3185                 // FIXME: Can a namespace be specified for an attr(foo)?
3186                 if (style->styleType() == RenderStyle::NOPSEUDO)
3187                     style->setUnique();
3188                 else
3189                     parentStyle->setUnique();
3190                 QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom);
3191                 style->setContent(element->getAttribute(attr).impl(), i != 0);
3192                 // register the fact that the attribute value affects the style
3193                 m_selectorAttrs.add(attr.localName().impl());
3194             } else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI) {
3195                 CSSImageValue *image = static_cast<CSSImageValue*>(val);
3196                 style->setContent(image->image(element->document()->docLoader()), i != 0);
3197             } else if (val->primitiveType()==CSSPrimitiveValue::CSS_COUNTER) {
3198                 Counter* counterValue = val->getCounterValue();
3199                 CounterData counter(counterValue->identifier(),
3200                     (EListStyleType)counterValue->listStyleNumber(), counterValue->separator());
3201                 style->setContent(new CounterData(counter), i != 0);
3202            }
3203         }
3204         break;
3205     }
3206
3207     case CSS_PROP_COUNTER_INCREMENT:
3208         if (!value->isValueList())
3209             return;
3210         style->setCounterIncrementList(static_cast<CSSValueList*>(value));
3211         break;
3212     case CSS_PROP_COUNTER_RESET:
3213         if (!value->isValueList())
3214             return;
3215         style->setCounterResetList(static_cast<CSSValueList*>(value));
3216         break;
3217     case CSS_PROP_FONT_FAMILY: {
3218         // list of strings and ids
3219         if (isInherit) {
3220             FontDescription parentFontDescription = parentStyle->fontDescription();
3221             FontDescription fontDescription = style->fontDescription();
3222             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
3223             fontDescription.setFamily(parentFontDescription.firstFamily());
3224             if (style->setFontDescription(fontDescription))
3225                 fontDirty = true;
3226             return;
3227         }
3228         else if (isInitial) {
3229             FontDescription initialDesc = FontDescription();
3230             FontDescription fontDescription = style->fontDescription();
3231             // We need to adjust the size to account for the generic family change from monospace
3232             // to non-monospace.
3233             if (fontDescription.keywordSize() && fontDescription.genericFamily() == FontDescription::MonospaceFamily)
3234                 setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, style->htmlHacks(), false));
3235             fontDescription.setGenericFamily(initialDesc.genericFamily());
3236             fontDescription.setFamily(initialDesc.firstFamily());
3237             if (style->setFontDescription(fontDescription))
3238                 fontDirty = true;
3239             return;
3240         }
3241         
3242         if (!value->isValueList()) return;
3243         FontDescription fontDescription = style->fontDescription();
3244         CSSValueList *list = static_cast<CSSValueList*>(value);
3245         int len = list->length();
3246         FontFamily& firstFamily = fontDescription.firstFamily();
3247         FontFamily *currFamily = 0;
3248         
3249         // Before mapping in a new font-family property, we should reset the generic family.
3250         bool oldFamilyIsMonospace = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
3251         fontDescription.setGenericFamily(FontDescription::NoFamily);
3252
3253         for(int i = 0; i < len; i++) {
3254             CSSValue *item = list->item(i);
3255             if(!item->isPrimitiveValue()) continue;
3256             CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3257             AtomicString face;
3258             if(val->primitiveType() == CSSPrimitiveValue::CSS_STRING)
3259                 face = static_cast<FontFamilyValue*>(val)->fontName();
3260             else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3261                 switch (val->getIdent()) {
3262                     case CSS_VAL__WEBKIT_BODY:
3263                         face = settings->stdFontName();
3264                         break;
3265                     case CSS_VAL_SERIF:
3266                         face = settings->serifFontName();
3267                         fontDescription.setGenericFamily(FontDescription::SerifFamily);
3268                         break;
3269                     case CSS_VAL_SANS_SERIF:
3270                         face = settings->sansSerifFontName();
3271                         fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3272                         break;
3273                     case CSS_VAL_CURSIVE:
3274                         face = settings->cursiveFontName();
3275                         fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3276                         break;
3277                     case CSS_VAL_FANTASY:
3278                         face = settings->fantasyFontName();
3279                         fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3280                         break;
3281                     case CSS_VAL_MONOSPACE:
3282                         face = settings->fixedFontName();
3283                         fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3284                         break;
3285                 }
3286             }
3287     
3288             if (!face.isEmpty()) {
3289                 if (!currFamily) {
3290                     // Filling in the first family.
3291                     firstFamily.setFamily(face);
3292                     currFamily = &firstFamily;
3293                 }
3294                 else {
3295                     FontFamily *newFamily = new FontFamily;
3296                     newFamily->setFamily(face);
3297                     currFamily->appendFamily(newFamily);
3298                     currFamily = newFamily;
3299                 }
3300     
3301                 if (fontDescription.keywordSize() && (fontDescription.genericFamily() == FontDescription::MonospaceFamily) != oldFamilyIsMonospace)
3302                     setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, style->htmlHacks(), !oldFamilyIsMonospace));
3303             
3304                 if (style->setFontDescription(fontDescription))
3305                     fontDirty = true;
3306             }
3307         }
3308       break;
3309     }
3310     case CSS_PROP_QUOTES:
3311         // list of strings or i
3312     case CSS_PROP_SIZE:
3313         // ### look up
3314       break;
3315     case CSS_PROP_TEXT_DECORATION: {
3316         // list of ident
3317         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3318         int t = RenderStyle::initialTextDecoration();
3319         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3320             // do nothing
3321         } else {
3322             if(!value->isValueList()) return;
3323             CSSValueList *list = static_cast<CSSValueList*>(value);
3324             int len = list->length();
3325             for(int i = 0; i < len; i++)
3326             {
3327                 CSSValue *item = list->item(i);
3328                 if(!item->isPrimitiveValue()) continue;
3329                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
3330                 switch(primitiveValue->getIdent())
3331                 {
3332                     case CSS_VAL_NONE:
3333                         t = TDNONE; break;
3334                     case CSS_VAL_UNDERLINE:
3335                         t |= UNDERLINE; break;
3336                     case CSS_VAL_OVERLINE:
3337                         t |= OVERLINE; break;
3338                     case CSS_VAL_LINE_THROUGH:
3339                         t |= LINE_THROUGH; break;
3340                     case CSS_VAL_BLINK:
3341                         t |= BLINK; break;
3342                     default:
3343                         return;
3344                 }
3345             }
3346         }
3347
3348         style->setTextDecoration(t);
3349         break;
3350     }
3351
3352 // shorthand properties
3353     case CSS_PROP_BACKGROUND:
3354         if (isInitial) {
3355             style->clearBackgroundLayers();
3356             return;
3357         }
3358         else if (isInherit) {
3359             if (parentStyle)
3360                 style->inheritBackgroundLayers(*parentStyle->backgroundLayers());
3361             else
3362                 style->clearBackgroundLayers();
3363             return;
3364         }
3365         break;
3366     case CSS_PROP_BORDER:
3367     case CSS_PROP_BORDER_STYLE:
3368     case CSS_PROP_BORDER_WIDTH:
3369     case CSS_PROP_BORDER_COLOR:
3370         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
3371         {
3372             if (isInherit) {
3373                 style->setBorderTopColor(parentStyle->borderTopColor());
3374                 style->setBorderBottomColor(parentStyle->borderBottomColor());
3375                 style->setBorderLeftColor(parentStyle->borderLeftColor());
3376                 style->setBorderRightColor(parentStyle->borderRightColor());
3377             }
3378             else if (isInitial) {
3379                 style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead.
3380                 style->setBorderBottomColor(Color());
3381                 style->setBorderLeftColor(Color());
3382                 style->setBorderRightColor(Color());
3383             }
3384         }
3385         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
3386         {
3387             if (isInherit) {
3388                 style->setBorderTopStyle(parentStyle->borderTopStyle());
3389                 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
3390                 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
3391                 style->setBorderRightStyle(parentStyle->borderRightStyle());
3392             }
3393             else if (isInitial) {
3394                 style->setBorderTopStyle(RenderStyle::initialBorderStyle());
3395                 style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
3396                 style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
3397                 style->setBorderRightStyle(RenderStyle::initialBorderStyle());
3398             }
3399         }
3400         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH)
3401         {
3402             if (isInherit) {
3403                 style->setBorderTopWidth(parentStyle->borderTopWidth());
3404                 style->setBorderBottomWidth(parentStyle->borderBottomWidth());
3405                 style->setBorderLeftWidth(parentStyle->borderLeftWidth());
3406                 style->setBorderRightWidth(parentStyle->borderRightWidth());
3407             }
3408             else if (isInitial) {
3409                 style->setBorderTopWidth(RenderStyle::initialBorderWidth());
3410                 style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
3411                 style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
3412                 style->setBorderRightWidth(RenderStyle::initialBorderWidth());
3413             }
3414         }
3415         return;
3416     case CSS_PROP_BORDER_TOP:
3417         if (isInherit) {
3418             style->setBorderTopColor(parentStyle->borderTopColor());
3419             style->setBorderTopStyle(parentStyle->borderTopStyle());
3420             style->setBorderTopWidth(parentStyle->borderTopWidth());
3421         }
3422         else if (isInitial)
3423             style->resetBorderTop();
3424         return;
3425     case CSS_PROP_BORDER_RIGHT:
3426         if (isInherit) {
3427             style->setBorderRightColor(parentStyle->borderRightColor());
3428             style->setBorderRightStyle(parentStyle->borderRightStyle());
3429             style->setBorderRightWidth(parentStyle->borderRightWidth());
3430         }
3431         else if (isInitial)
3432             style->resetBorderRight();
3433         return;
3434     case CSS_PROP_BORDER_BOTTOM:
3435         if (isInherit) {
3436             style->setBorderBottomColor(parentStyle->borderBottomColor());
3437             style->setBorderBottomStyle(parentStyle->borderBottomStyle());
3438             style->setBorderBottomWidth(parentStyle->borderBottomWidth());
3439         }
3440         else if (isInitial)
3441             style->resetBorderBottom();
3442         return;
3443     case CSS_PROP_BORDER_LEFT:
3444         if (isInherit) {
3445             style->setBorderLeftColor(parentStyle->borderLeftColor());
3446             style->setBorderLeftStyle(parentStyle->borderLeftStyle());
3447             style->setBorderLeftWidth(parentStyle->borderLeftWidth());
3448         }
3449         else if (isInitial)
3450             style->resetBorderLeft();
3451         return;
3452     case CSS_PROP_MARGIN:
3453         if (isInherit) {
3454             style->setMarginTop(parentStyle->marginTop());
3455             style->setMarginBottom(parentStyle->marginBottom());
3456             style->setMarginLeft(parentStyle->marginLeft());
3457             style->setMarginRight(parentStyle->marginRight());
3458         }
3459         else if (isInitial)
3460             style->resetMargin();
3461         return;
3462     case CSS_PROP_PADDING:
3463         if (isInherit) {
3464             style->setPaddingTop(parentStyle->paddingTop());
3465             style->setPaddingBottom(parentStyle->paddingBottom());
3466             style->setPaddingLeft(parentStyle->paddingLeft());
3467             style->setPaddingRight(parentStyle->paddingRight());
3468         }
3469         else if (isInitial)
3470             style->resetPadding();
3471         return;
3472     case CSS_PROP_FONT:
3473         if (isInherit) {
3474             FontDescription fontDescription = parentStyle->fontDescription();
3475             style->setLineHeight(parentStyle->lineHeight());
3476             if (style->setFontDescription(fontDescription))
3477                 fontDirty = true;
3478         } else if (isInitial) {
3479             FontDescription fontDescription;
3480             style->setLineHeight(RenderStyle::initialLineHeight());
3481             if (style->setFontDescription(fontDescription))
3482                 fontDirty = true;
3483         } else if (primitiveValue) {
3484             style->setLineHeight(RenderStyle::initialLineHeight());
3485             FontDescription fontDescription;
3486             theme()->systemFont(primitiveValue->getIdent(), fontDescription);
3487             // Double-check and see if the theme did anything.  If not, don't bother updating the font.
3488             if (fontDescription.isAbsoluteSize()) {
3489                 // Handle the zoom factor.
3490                 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription.isAbsoluteSize(), fontDescription.specifiedSize()));
3491                 if (style->setFontDescription(fontDescription))
3492                     fontDirty = true;
3493             }
3494         } else if (value->isFontValue()) {
3495             FontValue *font = static_cast<FontValue*>(value);
3496             if (!font->style || !font->variant || !font->weight ||
3497                  !font->size || !font->lineHeight || !font->family)
3498                 return;
3499             applyProperty(CSS_PROP_FONT_STYLE, font->style.get());
3500             applyProperty(CSS_PROP_FONT_VARIANT, font->variant.get());
3501             applyProperty(CSS_PROP_FONT_WEIGHT, font->weight.get());
3502             applyProperty(CSS_PROP_FONT_SIZE, font->size.get());
3503
3504             // Line-height can depend on font().pixelSize(), so we have to update the font
3505             // before we evaluate line-height, e.g., font: 1em/1em.  FIXME: Still not
3506             // good enough: style="font:1em/1em; font-size:36px" should have a line-height of 36px.
3507             if (fontDirty)
3508                 CSSStyleSelector::style->font().update();
3509             
3510             applyProperty(CSS_PROP_LINE_HEIGHT, font->lineHeight.get());
3511             applyProperty(CSS_PROP_FONT_FAMILY, font->family.get());
3512         }
3513         return;
3514         
3515     case CSS_PROP_LIST_STYLE:
3516         if (isInherit) {
3517             style->setListStyleType(parentStyle->listStyleType());
3518             style->setListStyleImage(parentStyle->listStyleImage());
3519             style->setListStylePosition(parentStyle->listStylePosition());
3520         }
3521         else if (isInitial) {
3522             style->setListStyleType(RenderStyle::initialListStyleType());
3523             style->setListStyleImage(RenderStyle::initialListStyleImage());
3524             style->setListStylePosition(RenderStyle::initialListStylePosition());
3525         }
3526         break;
3527     case CSS_PROP_OUTLINE:
3528         if (isInherit) {
3529             style->setOutlineWidth(parentStyle->outlineWidth());
3530             style->setOutlineColor(parentStyle->outlineColor());
3531             style->setOutlineStyle(parentStyle->outlineStyle());
3532         }
3533         else if (isInitial)
3534             style->resetOutline();
3535         break;
3536
3537     // CSS3 Properties
3538     case CSS_PROP__WEBKIT_APPEARANCE: {
3539         HANDLE_INHERIT_AND_INITIAL(appearance, Appearance)
3540         if (!primitiveValue) break;
3541         int id = primitiveValue->getIdent();
3542         EAppearance appearance;
3543         if (id == CSS_VAL_NONE)
3544             appearance = NoAppearance;
3545         else
3546             appearance = EAppearance(id - CSS_VAL_CHECKBOX + 1);
3547         style->setAppearance(appearance);
3548     }
3549     case CSS_PROP__WEBKIT_BINDING: {
3550 #ifdef XBL_SUPPORT
3551         if (isInitial || (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)) {
3552             style->deleteBindingURIs();
3553             return;
3554         }
3555         else if (isInherit) {
3556             if (parentStyle->bindingURIs())
3557                 style->inheritBindingURIs(parentStyle->bindingURIs());
3558             else
3559                 style->deleteBindingURIs();
3560             return;
3561         }
3562
3563         if (!value->isValueList()) return;
3564         CSSValueList* list = static_cast<CSSValueList*>(value);
3565         bool firstBinding = true;
3566         for (unsigned int i = 0; i < list->length(); i++) {
3567             CSSValue *item = list->item(i);
3568             CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3569             if (val->primitiveType() == CSSPrimitiveValue::CSS_URI) {
3570                 if (firstBinding) {
3571                     firstBinding = false;
3572                     style->deleteBindingURIs();
3573                 }
3574                 style->addBindingURI(val->getStringValue());
3575             }
3576         }
3577 #endif
3578         break;
3579     }
3580
3581     case CSS_PROP__WEBKIT_BORDER_IMAGE: {
3582         HANDLE_INHERIT_AND_INITIAL(borderImage, BorderImage)
3583         BorderImage image;
3584         if (primitiveValue) {
3585             if (primitiveValue->getIdent() == CSS_VAL_NONE)
3586                 style->setBorderImage(image);
3587         } else {
3588             // Retrieve the border image value.
3589             CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value);
3590             
3591             // Set the image (this kicks off the load).
3592             image.m_image = borderImage->m_image->image(element->document()->docLoader());
3593             
3594             // Set up a length box to represent our image slices.
3595             LengthBox& l = image.m_slices;
3596             RectImpl* r = borderImage->m_imageSliceRect.get();
3597             if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
3598                 l.top = Length((int)r->top()->getFloatValue(), Percent);
3599             else
3600                 l.top = Length((int)r->top()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
3601             if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
3602                 l.bottom = Length((int)r->bottom()->getFloatValue(), Percent);
3603             else
3604                 l.bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
3605             if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
3606                 l.left = Length((int)r->left()->getFloatValue(), Percent);
3607             else
3608                 l.left = Length((int)r->left()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
3609             if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
3610                 l.right = Length((int)r->right()->getFloatValue(), Percent);
3611             else
3612                 l.right = Length((int)r->right()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
3613             
3614             // Set the appropriate rules for stretch/round/repeat of the slices
3615             switch (borderImage->m_horizontalSizeRule) {
3616                 case CSS_VAL_STRETCH:
3617                     image.m_horizontalRule = BI_STRETCH;
3618                     break;
3619                 case CSS_VAL_ROUND:
3620                     image.m_horizontalRule = BI_ROUND;
3621                     break;
3622                 default: // CSS_VAL_REPEAT
3623                     image.m_horizontalRule = BI_REPEAT;
3624                     break;
3625             }
3626
3627             switch (borderImage->m_verticalSizeRule) {
3628                 case CSS_VAL_STRETCH:
3629                     image.m_verticalRule = BI_STRETCH;
3630                     break;
3631                 case CSS_VAL_ROUND:
3632                     image.m_verticalRule = BI_ROUND;
3633                     break;
3634                 default: // CSS_VAL_REPEAT
3635                     image.m_verticalRule = BI_REPEAT;
3636                     break;
3637             }
3638
3639             style->setBorderImage(image);
3640         }
3641         break;
3642     }
3643
3644     case CSS_PROP__WEBKIT_BORDER_RADIUS:
3645         if (isInherit) {
3646             style->setBorderTopLeftRadius(parentStyle->borderTopLeftRadius());
3647             style->setBorderTopRightRadius(parentStyle->borderTopRightRadius());
3648             style->setBorderBottomLeftRadius(parentStyle->borderBottomLeftRadius());
3649             style->setBorderBottomRightRadius(parentStyle->borderBottomRightRadius());
3650             return;
3651         }
3652         if (isInitial) {
3653             style->resetBorderRadius();
3654             return;
3655         }
3656         // Fall through
3657     case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS:
3658     case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS:
3659     case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS:
3660     case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS: {
3661         if (isInherit) {
3662             HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, borderTopLeftRadius, BorderTopLeftRadius)
3663             HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, borderTopRightRadius, BorderTopRightRadius)
3664             HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, borderBottomLeftRadius, BorderBottomLeftRadius)
3665             HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS, borderBottomRightRadius, BorderBottomRightRadius)
3666             return;
3667         }
3668         
3669         if (isInitial) {
3670             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, BorderTopLeftRadius, BorderRadius)
3671             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, BorderTopRightRadius, BorderRadius)
3672             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, BorderBottomLeftRadius, BorderRadius)
3673             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS, BorderBottomRightRadius, BorderRadius)
3674             return;
3675         }
3676
3677         if (!primitiveValue)
3678             return;
3679
3680         Pair* pair = primitiveValue->getPairValue();
3681         if (!pair)
3682             return;
3683
3684         int width = pair->first()->computeLengthInt(style);
3685         int height = pair->second()->computeLengthInt(style);
3686         if (width < 0 || height < 0)
3687             return;
3688
3689         if (width == 0)
3690             height = 0; // Null out the other value.
3691         else if (height == 0)
3692             width = 0; // Null out the other value.
3693
3694         IntSize size(width, height);
3695         switch (id) {
3696             case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS:
3697                 style->setBorderTopLeftRadius(size);
3698                 break;
3699             case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS:
3700                 style->setBorderTopRightRadius(size);
3701                 break;
3702             case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS:
3703                 style->setBorderBottomLeftRadius(size);
3704                 break;
3705             case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS:
3706                 style->setBorderBottomRightRadius(size);
3707                 break;
3708             default:
3709                 style->setBorderRadius(size);
3710                 break;
3711         }
3712     }
3713
3714     case CSS_PROP_OUTLINE_OFFSET:
3715         HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
3716         style->setOutlineOffset(primitiveValue->computeLengthInt(style));
3717         break;
3718
3719     case CSS_PROP_TEXT_SHADOW: {
3720         if (isInherit) {
3721             style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : 0);
3722             return;
3723         }
3724         if (isInitial) {
3725             style->setTextShadow(0);
3726             return;
3727         }
3728
3729         if (primitiveValue) { // none
3730             style->setTextShadow(0);
3731             return;
3732         }
3733
3734         if (!value->isValueList())
3735             return;
3736         CSSValueList *list = static_cast<CSSValueList*>(value);
3737         int len = list->length();
3738         for (int i = 0; i < len; i++) {
3739             ShadowValue* item = static_cast<ShadowValue*>(list->item(i));
3740             int x = item->x->computeLengthInt(style);
3741             int y = item->y->computeLengthInt(style);
3742             int blur = item->blur ? item->blur->computeLengthInt(style) : 0;
3743             Color color;
3744             if (item->color)
3745                 color = getColorFromPrimitiveValue(item->color.get());
3746             ShadowData* shadowData = new ShadowData(x, y, blur, color.isValid() ? color : Color::transparent);
3747             style->setTextShadow(shadowData, i != 0);
3748         }
3749         return;
3750     }
3751     case CSS_PROP_OPACITY:
3752         HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
3753         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3754             return; // Error case.
3755         // Clamp opacity to the range 0-1
3756         style->setOpacity(min(1.0, max(0.0, primitiveValue->getFloatValue())));
3757         return;
3758     case CSS_PROP__WEBKIT_BOX_ALIGN:
3759         HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign)
3760         if (!primitiveValue) return;
3761         switch (primitiveValue->getIdent()) {
3762             case CSS_VAL_STRETCH:
3763                 style->setBoxAlign(BSTRETCH);
3764                 break;
3765             case CSS_VAL_START:
3766                 style->setBoxAlign(BSTART);
3767                 break;
3768             case CSS_VAL_END:
3769                 style->setBoxAlign(BEND);
3770                 break;
3771             case CSS_VAL_CENTER:
3772                 style->setBoxAlign(BCENTER);
3773                 break;
3774             case CSS_VAL_BASELINE:
3775                 style->setBoxAlign(BBASELINE);
3776                 break;
3777             default:
3778                 return;
3779         }
3780         return;        
3781     case CSS_PROP__WEBKIT_BOX_DIRECTION:
3782         HANDLE_INHERIT_AND_INITIAL(boxDirection, BoxDirection)
3783         if (!primitiveValue) return;
3784         if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
3785             style->setBoxDirection(BNORMAL);
3786         else
3787             style->setBoxDirection(BREVERSE);
3788         return;        
3789     case CSS_PROP__WEBKIT_BOX_LINES:
3790         HANDLE_INHERIT_AND_INITIAL(boxLines, BoxLines)
3791         if(!primitiveValue) return;
3792         if (primitiveValue->getIdent() == CSS_VAL_SINGLE)
3793             style->setBoxLines(SINGLE);
3794         else
3795             style->setBoxLines(MULTIPLE);
3796         return;     
3797     case CSS_PROP__WEBKIT_BOX_ORIENT:
3798         HANDLE_INHERIT_AND_INITIAL(boxOrient, BoxOrient)
3799         if (!primitiveValue) return;
3800         if (primitiveValue->getIdent() == CSS_VAL_HORIZONTAL ||
3801             primitiveValue->getIdent() == CSS_VAL_INLINE_AXIS)
3802             style->setBoxOrient(HORIZONTAL);
3803         else
3804             style->setBoxOrient(VERTICAL);
3805         return;     
3806     case CSS_PROP__WEBKIT_BOX_PACK:
3807         HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack)
3808         if (!primitiveValue) return;
3809         switch (primitiveValue->getIdent()) {
3810             case CSS_VAL_START:
3811              &nb