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