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