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::PseudoSearchCancelButton:
1647                 dynamicPseudo = RenderStyle::SEARCH_CANCEL_BUTTON;
1648                 return true; 
1649             case CSSSelector::PseudoSearchDecoration:
1650                 dynamicPseudo = RenderStyle::SEARCH_DECORATION;
1651                 return true;
1652             case CSSSelector::PseudoSearchResultsDecoration:
1653                 dynamicPseudo = RenderStyle::SEARCH_RESULTS_DECORATION;
1654                 return true;
1655             case CSSSelector::PseudoSearchResultsButton:
1656                 dynamicPseudo = RenderStyle::SEARCH_RESULTS_BUTTON;
1657                 return true;
1658             case CSSSelector::PseudoNotParsed:
1659                 assert(false);
1660                 break;
1661         }
1662         return false;
1663     }
1664     // ### add the rest of the checks...
1665     return true;
1666 }
1667
1668 // -----------------------------------------------------------------
1669
1670 CSSRuleSet::CSSRuleSet()
1671 {
1672     m_universalRules = 0;
1673     m_ruleCount = 0;
1674 }
1675
1676 CSSRuleSet::~CSSRuleSet()
1677
1678     deleteAllValues(m_idRules);
1679     deleteAllValues(m_classRules);
1680     deleteAllValues(m_tagRules);
1681
1682     delete m_universalRules; 
1683 }
1684
1685
1686 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
1687                               CSSStyleRule* rule, CSSSelector* sel)
1688 {
1689     if (!key) return;
1690     CSSRuleDataList* rules = map.get(key);
1691     if (!rules) {
1692         rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1693         map.set(key, rules);
1694     } else
1695         rules->append(m_ruleCount++, rule, sel);
1696 }
1697
1698 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
1699 {
1700     if (sel->match == CSSSelector::Id) {
1701         addToRuleSet(sel->value.impl(), m_idRules, rule, sel);
1702         return;
1703     }
1704     if (sel->match == CSSSelector::Class) {
1705         addToRuleSet(sel->value.impl(), m_classRules, rule, sel);
1706         return;
1707     }
1708      
1709     const AtomicString& localName = sel->tag.localName();
1710     if (localName != starAtom) {
1711         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
1712         return;
1713     }
1714     
1715     // Just put it in the universal rule set.
1716     if (!m_universalRules)
1717         m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1718     else
1719         m_universalRules->append(m_ruleCount++, rule, sel);
1720 }
1721
1722 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet,  MediaQueryEvaluator* medium)
1723 {
1724     if (!sheet || !sheet->isCSSStyleSheet())
1725         return;
1726
1727     // No media implies "all", but if a media list exists it must
1728     // contain our current medium
1729     if (sheet->media() && !medium->eval(sheet->media()))
1730         return; // the style sheet doesn't apply
1731
1732     int len = sheet->length();
1733
1734     for (int i = 0; i < len; i++) {
1735         StyleBase* item = sheet->item(i);
1736         if (item->isStyleRule()) {
1737             CSSStyleRule* rule = static_cast<CSSStyleRule*>(item);
1738             for (CSSSelector* s = rule->selector(); s; s = s->next())
1739                 addRule(rule, s);
1740         }
1741         else if(item->isImportRule()) {
1742             CSSImportRule* import = static_cast<CSSImportRule*>(item);
1743             if (!import->media() || medium->eval(import->media()))
1744                 addRulesFromSheet(import->styleSheet(), medium);
1745         }
1746         else if(item->isMediaRule()) {
1747             CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
1748             CSSRuleList* rules = r->cssRules();
1749
1750             if ((!r->media() || medium->eval(r->media())) && rules) {
1751                 // Traverse child elements of the @media rule.
1752                 for (unsigned j = 0; j < rules->length(); j++) {
1753                     CSSRule *childItem = rules->item(j);
1754                     if (childItem->isStyleRule()) {
1755                         // It is a StyleRule, so append it to our list
1756                         CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem);
1757                         for (CSSSelector* s = rule->selector(); s; s = s->next())
1758                             addRule(rule, s);
1759                         
1760                     }
1761                 }   // for rules
1762             }   // if rules
1763         }
1764     }
1765 }
1766
1767 // -------------------------------------------------------------------------------------
1768 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1769
1770 static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0)
1771 {
1772     Length l;
1773     if (!primitiveValue) {
1774         if (ok)
1775             *ok = false;
1776     } else {
1777         int type = primitiveValue->primitiveType();
1778         if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
1779             l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
1780         else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
1781             l = Length(int(primitiveValue->getFloatValue()), Percent);
1782         else if(type == CSSPrimitiveValue::CSS_NUMBER)
1783             l = Length(int(primitiveValue->getFloatValue() * 100), Percent);
1784         else if (ok)
1785             *ok = false;
1786     }
1787     return l;
1788 }
1789
1790 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
1791                                          int startIndex, int endIndex)
1792 {
1793     if (startIndex == -1) return;
1794     for (int i = startIndex; i <= endIndex; i++) {
1795         CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
1796         DeprecatedValueListConstIterator<CSSProperty> end;
1797         for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
1798             const CSSProperty& current = *it;
1799             // give special priority to font-xxx, color properties
1800             if (isImportant == current.isImportant()) {
1801                 bool first;
1802                 switch(current.id()) {
1803                     case CSS_PROP_COLOR:
1804                     case CSS_PROP_DIRECTION:
1805                     case CSS_PROP_DISPLAY:
1806                     case CSS_PROP_FONT:
1807                     case CSS_PROP_FONT_SIZE:
1808                     case CSS_PROP_FONT_STYLE:
1809                     case CSS_PROP_FONT_FAMILY:
1810                     case CSS_PROP_FONT_WEIGHT:
1811                     case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST:
1812                     case CSS_PROP_FONT_VARIANT:
1813                         // these have to be applied first, because other properties use the computed
1814                         // values of these porperties.
1815                         first = true;
1816                         break;
1817                     default:
1818                         first = false;
1819                         break;
1820                 }
1821                 
1822                 if (first == applyFirst)
1823                     applyProperty(current.id(), current.value());
1824             }
1825         }
1826     }
1827 }
1828
1829 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
1830 {
1831     CSSPrimitiveValue *primitiveValue = 0;
1832     if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValue*>(value);
1833
1834     Length l;
1835     bool apply = false;
1836
1837     unsigned short valueType = value->cssValueType();
1838
1839     bool isInherit = parentNode && valueType == CSSValue::CSS_INHERIT;
1840     bool isInitial = valueType == CSSValue::CSS_INITIAL || (!parentNode && valueType == CSSValue::CSS_INHERIT);
1841
1842     // These properties are used to set the correct margins/padding on RTL lists.
1843     if (id == CSS_PROP__WEBKIT_MARGIN_START)
1844         id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
1845     else if (id == CSS_PROP__WEBKIT_PADDING_START)
1846         id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
1847
1848     // What follows is a list that maps the CSS properties into their corresponding front-end
1849     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
1850     // are only hit when mapping "inherit" or "initial" into front-end values.
1851     switch(id)
1852     {
1853 // ident only properties
1854     case CSS_PROP_BACKGROUND_ATTACHMENT:
1855         HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
1856         break;
1857     case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
1858         HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
1859         break;
1860     case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
1861         HANDLE_BACKGROUND_VALUE(backgroundComposite, BackgroundComposite, value)
1862         break;
1863     case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
1864         HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
1865         break;
1866     case CSS_PROP_BACKGROUND_REPEAT:
1867         HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
1868         break;
1869     case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
1870         HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
1871         break;
1872     case CSS_PROP_BORDER_COLLAPSE:
1873         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
1874         if(!primitiveValue) break;
1875         switch(primitiveValue->getIdent())
1876         {
1877         case CSS_VAL_COLLAPSE:
1878             style->setBorderCollapse(true);
1879             break;
1880         case CSS_VAL_SEPARATE:
1881             style->setBorderCollapse(false);
1882             break;
1883         default:
1884             return;
1885         }
1886         break;
1887         
1888     case CSS_PROP_BORDER_TOP_STYLE:
1889         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
1890         if (!primitiveValue) return;
1891         style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1892         break;
1893     case CSS_PROP_BORDER_RIGHT_STYLE:
1894         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
1895         if (!primitiveValue) return;
1896         style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1897         break;
1898     case CSS_PROP_BORDER_BOTTOM_STYLE:
1899         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
1900         if (!primitiveValue) return;
1901         style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1902         break;
1903     case CSS_PROP_BORDER_LEFT_STYLE:
1904         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
1905         if (!primitiveValue) return;
1906         style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1907         break;
1908     case CSS_PROP_OUTLINE_STYLE:
1909         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
1910         if (!primitiveValue) return;
1911         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
1912             style->setOutlineStyle(DOTTED, true);
1913         else
1914             style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1915         break;
1916     case CSS_PROP_CAPTION_SIDE:
1917     {
1918         HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
1919         if(!primitiveValue) break;
1920         ECaptionSide c = RenderStyle::initialCaptionSide();
1921         switch(primitiveValue->getIdent())
1922         {
1923         case CSS_VAL_LEFT:
1924             c = CAPLEFT; break;
1925         case CSS_VAL_RIGHT:
1926             c = CAPRIGHT; break;
1927         case CSS_VAL_TOP:
1928             c = CAPTOP; break;
1929         case CSS_VAL_BOTTOM:
1930             c = CAPBOTTOM; break;
1931         default:
1932             return;
1933         }
1934         style->setCaptionSide(c);
1935         return;
1936     }
1937     case CSS_PROP_CLEAR:
1938     {
1939         HANDLE_INHERIT_AND_INITIAL(clear, Clear)
1940         if(!primitiveValue) break;
1941         EClear c;
1942         switch(primitiveValue->getIdent())
1943         {
1944         case CSS_VAL_NONE:
1945             c = CNONE; break;
1946         case CSS_VAL_LEFT:
1947             c = CLEFT; break;
1948         case CSS_VAL_RIGHT:
1949             c = CRIGHT; break;
1950         case CSS_VAL_BOTH:
1951             c = CBOTH; break;
1952         default:
1953             return;
1954         }
1955         style->setClear(c);
1956         return;
1957     }
1958     case CSS_PROP_DIRECTION:
1959     {
1960         HANDLE_INHERIT_AND_INITIAL(direction, Direction)
1961         if(!primitiveValue) break;
1962         style->setDirection(primitiveValue->getIdent() == CSS_VAL_LTR ? LTR : RTL);
1963         return;
1964     }
1965     case CSS_PROP_DISPLAY:
1966     {
1967         HANDLE_INHERIT_AND_INITIAL(display, Display)
1968         if(!primitiveValue) break;
1969         int id = primitiveValue->getIdent();
1970         EDisplay d;
1971         if (id == CSS_VAL_NONE)
1972             d = NONE;
1973         else
1974             d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE);
1975
1976         style->setDisplay(d);
1977         break;
1978     }
1979
1980     case CSS_PROP_EMPTY_CELLS:
1981     {
1982         HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
1983         if (!primitiveValue) break;
1984         int id = primitiveValue->getIdent();
1985         if (id == CSS_VAL_SHOW)
1986             style->setEmptyCells(SHOW);
1987         else if (id == CSS_VAL_HIDE)
1988             style->setEmptyCells(HIDE);
1989         break;
1990     }
1991     case CSS_PROP_FLOAT:
1992     {
1993         HANDLE_INHERIT_AND_INITIAL(floating, Floating)
1994         if(!primitiveValue) return;
1995         EFloat f;
1996         switch(primitiveValue->getIdent())
1997         {
1998         case CSS_VAL_LEFT:
1999             f = FLEFT; break;
2000         case CSS_VAL_RIGHT:
2001             f = FRIGHT; break;
2002         case CSS_VAL_NONE:
2003         case CSS_VAL_CENTER:  //Non standart CSS-Value
2004             f = FNONE; break;
2005         default:
2006             return;
2007         }
2008         
2009         style->setFloating(f);
2010         break;
2011     }
2012
2013         break;
2014     case CSS_PROP_FONT_STRETCH:
2015         break; /* Not supported. */
2016
2017     case CSS_PROP_FONT_STYLE:
2018     {
2019         FontDescription fontDescription = style->fontDescription();
2020         if (isInherit)
2021             fontDescription.setItalic(parentStyle->fontDescription().italic());
2022         else if (isInitial)
2023             fontDescription.setItalic(false);
2024         else {
2025             if (!primitiveValue) return;
2026             switch (primitiveValue->getIdent()) {
2027                 case CSS_VAL_OBLIQUE:
2028                 // FIXME: oblique is the same as italic for the moment...
2029                 case CSS_VAL_ITALIC:
2030                     fontDescription.setItalic(true);
2031                     break;
2032                 case CSS_VAL_NORMAL:
2033                     fontDescription.setItalic(false);
2034                     break;
2035                 default:
2036                     return;
2037             }
2038         }
2039         if (style->setFontDescription(fontDescription))
2040             fontDirty = true;
2041         break;
2042     }
2043
2044     case CSS_PROP_FONT_VARIANT:
2045     {
2046         FontDescription fontDescription = style->fontDescription();
2047         if (isInherit) 
2048             fontDescription.setSmallCaps(parentStyle->fontDescription().smallCaps());
2049         else if (isInitial)
2050             fontDescription.setSmallCaps(false);
2051         else {
2052             if (!primitiveValue) return;
2053             int id = primitiveValue->getIdent();
2054             if (id == CSS_VAL_NORMAL)
2055                 fontDescription.setSmallCaps(false);
2056             else if (id == CSS_VAL_SMALL_CAPS)
2057                 fontDescription.setSmallCaps(true);
2058             else
2059                 return;
2060         }
2061         if (style->setFontDescription(fontDescription))
2062             fontDirty = true;
2063         break;        
2064     }
2065
2066     case CSS_PROP_FONT_WEIGHT:
2067     {
2068         FontDescription fontDescription = style->fontDescription();
2069         if (isInherit)
2070             fontDescription.setWeight(parentStyle->fontDescription().weight());
2071         else if (isInitial)
2072             fontDescription.setWeight(cNormalWeight);
2073         else {
2074             if (!primitiveValue) return;
2075             if (primitiveValue->getIdent()) {
2076                 switch (primitiveValue->getIdent()) {
2077                     // FIXME: We aren't genuinely supporting specific weight values.
2078                     case CSS_VAL_BOLD:
2079                     case CSS_VAL_BOLDER:
2080                     case CSS_VAL_600:
2081                     case CSS_VAL_700:
2082                     case CSS_VAL_800:
2083                     case CSS_VAL_900:
2084                         fontDescription.setWeight(cBoldWeight);
2085                         break;
2086                     case CSS_VAL_NORMAL:
2087                     case CSS_VAL_LIGHTER:
2088                     case CSS_VAL_100:
2089                     case CSS_VAL_200:
2090                     case CSS_VAL_300:
2091                     case CSS_VAL_400:
2092                     case CSS_VAL_500:
2093                         fontDescription.setWeight(cNormalWeight);
2094                         break;
2095                     default:
2096                         return;
2097                 }
2098             }
2099             else
2100             {
2101                 // ### fix parsing of 100-900 values in parser, apply them here
2102             }
2103         }
2104         if (style->setFontDescription(fontDescription))
2105             fontDirty = true;
2106         break;
2107     }
2108         
2109     case CSS_PROP_LIST_STYLE_POSITION:
2110     {
2111         HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
2112         if (!primitiveValue) return;
2113         if (primitiveValue->getIdent())
2114             style->setListStylePosition((EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE));
2115         return;
2116     }
2117
2118     case CSS_PROP_LIST_STYLE_TYPE:
2119     {
2120         HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2121         if (!primitiveValue) return;
2122         if (primitiveValue->getIdent())
2123         {
2124             EListStyleType t;
2125             int id = primitiveValue->getIdent();
2126             if (id == CSS_VAL_NONE) { // important!!
2127               t = LNONE;
2128             } else {
2129               t = EListStyleType(id - CSS_VAL_DISC);
2130             }
2131             style->setListStyleType(t);
2132         }
2133         return;
2134     }
2135
2136     case CSS_PROP_OVERFLOW:
2137     {
2138         if (isInherit) {
2139             style->setOverflowX(parentStyle->overflowX());
2140             style->setOverflowY(parentStyle->overflowY());
2141             return;
2142         }
2143         
2144         if (isInitial) {
2145             style->setOverflowX(RenderStyle::initialOverflowX());
2146             style->setOverflowY(RenderStyle::initialOverflowY());
2147             return;
2148         }
2149             
2150         EOverflow o;
2151         switch(primitiveValue->getIdent()) {
2152             case CSS_VAL_VISIBLE:
2153                 o = OVISIBLE; break;
2154             case CSS_VAL_HIDDEN:
2155                 o = OHIDDEN; break;
2156             case CSS_VAL_SCROLL:
2157                 o = OSCROLL; break;
2158             case CSS_VAL_AUTO:
2159                 o = OAUTO; break;
2160             case CSS_VAL__WEBKIT_MARQUEE:
2161                 o = OMARQUEE; break;
2162             case CSS_VAL_OVERLAY:
2163                 o = OOVERLAY; break;
2164             default:
2165                 return;
2166         }
2167         style->setOverflowX(o);
2168         style->setOverflowY(o);
2169         return;
2170     }
2171
2172     case CSS_PROP_OVERFLOW_X:
2173     {
2174         HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX)
2175         EOverflow o;
2176         switch(primitiveValue->getIdent())
2177         {
2178         case CSS_VAL_VISIBLE:
2179             o = OVISIBLE; break;
2180         case CSS_VAL_HIDDEN:
2181             o = OHIDDEN; break;
2182         case CSS_VAL_SCROLL:
2183             o = OSCROLL; break;
2184         case CSS_VAL_AUTO:
2185             o = OAUTO; break;
2186         case CSS_VAL_OVERLAY:
2187             o = OOVERLAY; break;
2188         default:
2189             return;
2190         }
2191         style->setOverflowX(o);
2192         return;
2193     }
2194
2195     case CSS_PROP_OVERFLOW_Y:
2196     {
2197         HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY)
2198         EOverflow o;
2199         switch(primitiveValue->getIdent())
2200         {
2201         case CSS_VAL_VISIBLE:
2202             o = OVISIBLE; break;
2203         case CSS_VAL_HIDDEN:
2204             o = OHIDDEN; break;
2205         case CSS_VAL_SCROLL:
2206             o = OSCROLL; break;
2207         case CSS_VAL_AUTO:
2208             o = OAUTO; break;
2209         case CSS_VAL_OVERLAY:
2210             o = OOVERLAY; break;
2211         default:
2212             return;
2213         }
2214         style->setOverflowY(o);
2215         return;
2216     }
2217
2218     case CSS_PROP_PAGE_BREAK_BEFORE:
2219     {
2220         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2221         if (!primitiveValue) return;
2222         switch (primitiveValue->getIdent()) {
2223             case CSS_VAL_AUTO:
2224                 style->setPageBreakBefore(PBAUTO);
2225                 break;
2226             case CSS_VAL_LEFT:
2227             case CSS_VAL_RIGHT:
2228             case CSS_VAL_ALWAYS:
2229                 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2230                 break;
2231             case CSS_VAL_AVOID:
2232                 style->setPageBreakBefore(PBAVOID);
2233                 break;
2234         }
2235         break;
2236     }
2237
2238     case CSS_PROP_PAGE_BREAK_AFTER:
2239     {
2240         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2241         if (!primitiveValue) return;
2242         switch (primitiveValue->getIdent()) {
2243             case CSS_VAL_AUTO:
2244                 style->setPageBreakAfter(PBAUTO);
2245                 break;
2246             case CSS_VAL_LEFT:
2247             case CSS_VAL_RIGHT:
2248             case CSS_VAL_ALWAYS:
2249                 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2250                 break;
2251             case CSS_VAL_AVOID:
2252                 style->setPageBreakAfter(PBAVOID);
2253                 break;
2254         }
2255         break;
2256     }
2257
2258     case CSS_PROP_PAGE_BREAK_INSIDE: {
2259         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2260         if (!primitiveValue) return;
2261         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
2262             style->setPageBreakInside(PBAUTO);
2263         else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
2264             style->setPageBreakInside(PBAVOID);
2265         return;
2266     }
2267         
2268     case CSS_PROP_PAGE:
2269         break; /* FIXME: Not even sure what this is...  -dwh */
2270
2271     case CSS_PROP_POSITION:
2272     {
2273         HANDLE_INHERIT_AND_INITIAL(position, Position)
2274         if(!primitiveValue) return;
2275         EPosition p;
2276         switch(primitiveValue->getIdent())
2277         {
2278         case CSS_VAL_STATIC:
2279             p = StaticPosition;
2280             break;
2281         case CSS_VAL_RELATIVE:
2282             p = RelativePosition;
2283             break;
2284         case CSS_VAL_ABSOLUTE:
2285             p = AbsolutePosition;
2286             break;
2287         case CSS_VAL_FIXED:
2288             p = FixedPosition;
2289             break;
2290         default:
2291             return;
2292         }
2293         style->setPosition(p);
2294         return;
2295     }
2296
2297     case CSS_PROP_TABLE_LAYOUT: {
2298         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2299
2300         if (!primitiveValue->getIdent())
2301             return;
2302
2303         ETableLayout l = RenderStyle::initialTableLayout();
2304         switch(primitiveValue->getIdent()) {
2305             case CSS_VAL_FIXED:
2306                 l = TFIXED;
2307                 // fall through
2308             case CSS_VAL_AUTO:
2309                 style->setTableLayout(l);
2310             default:
2311                 break;
2312         }
2313         break;
2314     }
2315         
2316     case CSS_PROP_UNICODE_BIDI: {
2317         HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2318         switch (primitiveValue->getIdent()) {
2319             case CSS_VAL_NORMAL:
2320                 style->setUnicodeBidi(UBNormal); 
2321                 break;
2322             case CSS_VAL_EMBED:
2323                 style->setUnicodeBidi(Embed); 
2324                 break;
2325             case CSS_VAL_BIDI_OVERRIDE:
2326                 style->setUnicodeBidi(Override);
2327                 break;
2328             default:
2329                 return;
2330         }
2331         break;
2332     }
2333     case CSS_PROP_TEXT_TRANSFORM: {
2334         HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2335         
2336         if(!primitiveValue->getIdent()) return;
2337
2338         ETextTransform tt;
2339         switch(primitiveValue->getIdent()) {
2340         case CSS_VAL_CAPITALIZE:  tt = CAPITALIZE;  break;
2341         case CSS_VAL_UPPERCASE:   tt = UPPERCASE;   break;
2342         case CSS_VAL_LOWERCASE:   tt = LOWERCASE;   break;
2343         case CSS_VAL_NONE:
2344         default:                  tt = TTNONE;      break;
2345         }
2346         style->setTextTransform(tt);
2347         break;
2348         }
2349
2350     case CSS_PROP_VISIBILITY:
2351     {
2352         HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2353
2354         switch(primitiveValue->getIdent()) {
2355         case CSS_VAL_HIDDEN:
2356             style->setVisibility(HIDDEN);
2357             break;
2358         case CSS_VAL_VISIBLE:
2359             style->setVisibility(VISIBLE);
2360             break;
2361         case CSS_VAL_COLLAPSE:
2362             style->setVisibility(COLLAPSE);
2363         default:
2364             break;
2365         }
2366         break;
2367     }
2368     case CSS_PROP_WHITE_SPACE:
2369         HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2370
2371         if(!primitiveValue->getIdent()) return;
2372
2373         EWhiteSpace s;
2374         switch(primitiveValue->getIdent()) {
2375         case CSS_VAL__WEBKIT_NOWRAP:
2376             s = KHTML_NOWRAP;
2377             break;
2378         case CSS_VAL_NOWRAP:
2379             s = NOWRAP;
2380             break;
2381         case CSS_VAL_PRE:
2382             s = PRE;
2383             break;
2384         case CSS_VAL_PRE_WRAP:
2385             s = PRE_WRAP;
2386             break;
2387         case CSS_VAL_PRE_LINE:
2388             s = PRE_LINE;
2389             break;
2390         case CSS_VAL_NORMAL:
2391         default:
2392             s = NORMAL;
2393             break;
2394         }
2395         style->setWhiteSpace(s);
2396         break;
2397
2398     case CSS_PROP_BACKGROUND_POSITION:
2399         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
2400         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
2401         break;
2402     case CSS_PROP_BACKGROUND_POSITION_X: {
2403         HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
2404         break;
2405     }
2406     case CSS_PROP_BACKGROUND_POSITION_Y: {
2407         HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
2408         break;
2409     }
2410     case CSS_PROP_BORDER_SPACING: {
2411         if (isInherit) {
2412             style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing());
2413             style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing());
2414         }
2415         else if (isInitial) {
2416             style->setHorizontalBorderSpacing(0);
2417             style->setVerticalBorderSpacing(0);
2418         }
2419         break;
2420     }
2421     case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: {
2422         HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2423         if (!primitiveValue) break;
2424         short spacing =  primitiveValue->computeLengthShort(style);
2425         style->setHorizontalBorderSpacing(spacing);
2426         break;
2427     }
2428     case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: {
2429         HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2430         if (!primitiveValue) break;
2431         short spacing =  primitiveValue->computeLengthShort(style);
2432         style->setVerticalBorderSpacing(spacing);
2433         break;
2434     }
2435     case CSS_PROP_CURSOR:
2436         if (isInherit) {
2437             style->setCursor(parentStyle->cursor());
2438             style->setCursorList(parentStyle->cursors());
2439             return;
2440         }
2441         style->clearCursorList();
2442         if (isInitial) {
2443             style->setCursor(RenderStyle::initialCursor());
2444             return;
2445         }
2446         if (value->isValueList()) {
2447             CSSValueList* list = static_cast<CSSValueList*>(value);
2448             int len = list->length();
2449             style->setCursor(CURSOR_AUTO);
2450             for (int i = 0; i < len; i++) {
2451                 CSSValue* item = list->item(i);
2452                 if (!item->isPrimitiveValue())
2453                     continue;
2454                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
2455                 int type = primitiveValue->primitiveType();
2456                 if (type == CSSPrimitiveValue::CSS_URI) {
2457 #ifdef SVG_SUPPORT
2458                     if (primitiveValue->getStringValue().find("#") == 0)
2459                         style->addSVGCursor(primitiveValue->getStringValue().substring(1));
2460                     else
2461 #endif
2462                     {
2463                         CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
2464                         style->addCursor(image->image(element->document()->docLoader()), image->hotspot());
2465                     }
2466                 } else if (type == CSSPrimitiveValue::CSS_IDENT) {
2467                     int ident = primitiveValue->getIdent();
2468                     if (ident == CSS_VAL_COPY)
2469                         style->setCursor(CURSOR_COPY);
2470                     else if (ident == CSS_VAL_NONE)
2471                         style->setCursor(CURSOR_NONE);
2472                     else
2473                         style->setCursor((ECursor)(ident - CSS_VAL_AUTO));
2474                 }
2475             }
2476         } else if (primitiveValue) {
2477             int type = primitiveValue->primitiveType();
2478             if (type == CSSPrimitiveValue::CSS_IDENT) {
2479                 int ident = primitiveValue->getIdent();
2480                 if (ident == CSS_VAL_COPY)
2481                     style->setCursor(CURSOR_COPY);
2482                 else if (ident == CSS_VAL_NONE)
2483                     style->setCursor(CURSOR_NONE);
2484                 else
2485                     style->setCursor((ECursor)(ident - CSS_VAL_AUTO));
2486             }
2487         }
2488         break;
2489 // colors || inherit
2490     case CSS_PROP_BACKGROUND_COLOR:
2491     case CSS_PROP_BORDER_TOP_COLOR:
2492     case CSS_PROP_BORDER_RIGHT_COLOR:
2493     case CSS_PROP_BORDER_BOTTOM_COLOR:
2494     case CSS_PROP_BORDER_LEFT_COLOR:
2495     case CSS_PROP_COLOR:
2496     case CSS_PROP_OUTLINE_COLOR:
2497     case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR:
2498     case CSS_PROP__WEBKIT_TEXT_FILL_COLOR: {
2499         Color col;
2500         if (isInherit) {
2501             HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
2502             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
2503             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
2504             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
2505             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
2506             HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
2507             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
2508             HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, textStrokeColor, TextStrokeColor)
2509             HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_TEXT_FILL_COLOR, textFillColor, TextFillColor)
2510             return;
2511         }
2512         if (isInitial) {
2513             // The border/outline colors will just map to the invalid color |col| above.  This will have the
2514             // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2515             // not painting the background since the color won't be valid).
2516             if (id == CSS_PROP_COLOR)
2517                 col = RenderStyle::initialColor();
2518         } else {
2519             if (!primitiveValue)
2520                 return;
2521             col = getColorFromPrimitiveValue(primitiveValue);
2522         }
2523
2524         switch(id) {
2525         case CSS_PROP_BACKGROUND_COLOR:
2526             style->setBackgroundColor(col); break;
2527         case CSS_PROP_BORDER_TOP_COLOR:
2528             style->setBorderTopColor(col); break;
2529         case CSS_PROP_BORDER_RIGHT_COLOR:
2530             style->setBorderRightColor(col); break;
2531         case CSS_PROP_BORDER_BOTTOM_COLOR:
2532             style->setBorderBottomColor(col); break;
2533         case CSS_PROP_BORDER_LEFT_COLOR:
2534             style->setBorderLeftColor(col); break;
2535         case CSS_PROP_COLOR:
2536             style->setColor(col); break;
2537         case CSS_PROP_OUTLINE_COLOR:
2538             style->setOutlineColor(col); break;
2539         case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR:
2540             style->setTextStrokeColor(col);
2541             break;
2542         case CSS_PROP__WEBKIT_TEXT_FILL_COLOR:
2543             style->setTextFillColor(col);
2544             break;
2545         }
2546         
2547         return;
2548     }
2549     break;
2550     
2551 // uri || inherit
2552     case CSS_PROP_BACKGROUND_IMAGE:
2553         HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
2554         break;
2555     case CSS_PROP_LIST_STYLE_IMAGE:
2556     {
2557         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2558         if (!primitiveValue)
2559             return;
2560         style->setListStyleImage(static_cast<CSSImageValue*>(primitiveValue)->image(element->document()->docLoader()));
2561         break;
2562     }
2563
2564 // length
2565     case CSS_PROP_BORDER_TOP_WIDTH:
2566     case CSS_PROP_BORDER_RIGHT_WIDTH:
2567     case CSS_PROP_BORDER_BOTTOM_WIDTH:
2568     case CSS_PROP_BORDER_LEFT_WIDTH:
2569     case CSS_PROP_OUTLINE_WIDTH:
2570     {
2571         if (isInherit) {
2572             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
2573             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
2574             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
2575             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
2576             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
2577             return;
2578         }
2579         else if (isInitial) {
2580             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
2581             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
2582             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
2583             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
2584             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
2585             return;
2586         }
2587
2588         if(!primitiveValue) break;
2589         short width = 3;
2590         switch(primitiveValue->getIdent())
2591         {
2592         case CSS_VAL_THIN:
2593             width = 1;
2594             break;
2595         case CSS_VAL_MEDIUM:
2596             width = 3;
2597             break;
2598         case CSS_VAL_THICK:
2599             width = 5;
2600             break;
2601         case CSS_VAL_INVALID:
2602             width = primitiveValue->computeLengthShort(style);
2603             break;
2604         default:
2605             return;
2606         }
2607
2608         if(width < 0) return;
2609         switch(id)
2610         {
2611         case CSS_PROP_BORDER_TOP_WIDTH:
2612             style->setBorderTopWidth(width);
2613             break;
2614         case CSS_PROP_BORDER_RIGHT_WIDTH:
2615             style->setBorderRightWidth(width);
2616             break;
2617         case CSS_PROP_BORDER_BOTTOM_WIDTH:
2618             style->setBorderBottomWidth(width);
2619             break;
2620         case CSS_PROP_BORDER_LEFT_WIDTH:
2621             style->setBorderLeftWidth(width);
2622             break;
2623         case CSS_PROP_OUTLINE_WIDTH:
2624             style->setOutlineWidth(width);
2625             break;
2626         default:
2627             return;
2628         }
2629         return;
2630     }
2631
2632     case CSS_PROP_LETTER_SPACING:
2633     case CSS_PROP_WORD_SPACING:
2634     {
2635         
2636         if (isInherit) {
2637             HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
2638             HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
2639             return;
2640         }
2641         else if (isInitial) {
2642             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
2643             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
2644             return;
2645         }
2646         
2647         int width = 0;
2648         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){
2649             width = 0;
2650         } else {
2651             if(!primitiveValue) return;
2652             width = primitiveValue->computeLengthInt(style);
2653         }
2654         switch(id)
2655         {
2656         case CSS_PROP_LETTER_SPACING:
2657             style->setLetterSpacing(width);
2658             break;
2659         case CSS_PROP_WORD_SPACING:
2660             style->setWordSpacing(width);
2661             break;
2662             // ### needs the definitions in renderstyle
2663         default: break;
2664         }
2665         return;
2666     }
2667
2668     case CSS_PROP_WORD_WRAP:
2669     {
2670         HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap)
2671
2672         if(!primitiveValue->getIdent()) return;
2673
2674         EWordWrap s;
2675         switch(primitiveValue->getIdent()) {
2676         case CSS_VAL_BREAK_WORD:
2677             s = BREAK_WORD;
2678             break;
2679         case CSS_VAL_NORMAL:
2680         default:
2681             s = WBNORMAL;
2682             break;
2683         }
2684         style->setWordWrap(s);
2685         break;
2686     }
2687
2688     case CSS_PROP__WEBKIT_NBSP_MODE:
2689     {
2690         HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode)
2691
2692         if (!primitiveValue->getIdent()) return;
2693
2694         ENBSPMode m;
2695         switch(primitiveValue->getIdent()) {
2696         case CSS_VAL_SPACE:
2697             m = SPACE;
2698             break;
2699         case CSS_VAL_NORMAL:
2700         default:
2701             m = NBNORMAL;
2702             break;
2703         }
2704         style->setNBSPMode(m);
2705         break;
2706     }
2707
2708     case CSS_PROP__WEBKIT_LINE_BREAK:
2709     {
2710         HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak)
2711
2712         if (!primitiveValue->getIdent()) return;
2713
2714         EKHTMLLineBreak b;
2715         switch(primitiveValue->getIdent()) {
2716         case CSS_VAL_AFTER_WHITE_SPACE:
2717             b = AFTER_WHITE_SPACE;
2718             break;
2719         case CSS_VAL_NORMAL:
2720         default:
2721             b = LBNORMAL;
2722             break;
2723         }
2724         style->setKHTMLLineBreak(b);
2725         break;
2726     }
2727
2728     case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR:
2729     {
2730         HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2731
2732         if (!primitiveValue->getIdent()) return;
2733
2734         EMatchNearestMailBlockquoteColor c;
2735         switch(primitiveValue->getIdent()) {
2736         case CSS_VAL_NORMAL:
2737             c = BCNORMAL;
2738             break;
2739         case CSS_VAL_MATCH:
2740         default:
2741             c = MATCH;
2742             break;
2743         }
2744         style->setMatchNearestMailBlockquoteColor(c);
2745         break;
2746     }
2747
2748     case CSS_PROP_RESIZE:
2749     {
2750         HANDLE_INHERIT_AND_INITIAL(resize, Resize)
2751
2752         if (!primitiveValue->getIdent()) return;
2753
2754         EResize r;
2755         switch(primitiveValue->getIdent()) {
2756         case CSS_VAL_BOTH:
2757             r = RESIZE_BOTH;
2758             break;
2759         case CSS_VAL_HORIZONTAL:
2760             r = RESIZE_HORIZONTAL;
2761             break;
2762         case CSS_VAL_VERTICAL:
2763             r = RESIZE_VERTICAL;
2764             break;
2765         case CSS_VAL_AUTO:
2766             r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
2767             break;
2768         case CSS_VAL_NONE:
2769         default:
2770             r = RESIZE_NONE;
2771             break;
2772         }
2773         style->setResize(r);
2774         break;
2775     }
2776     
2777     // length, percent
2778     case CSS_PROP_MAX_WIDTH:
2779         // +none +inherit
2780         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2781             apply = true;
2782     case CSS_PROP_TOP:
2783     case CSS_PROP_LEFT:
2784     case CSS_PROP_RIGHT:
2785     case CSS_PROP_BOTTOM:
2786     case CSS_PROP_WIDTH:
2787     case CSS_PROP_MIN_WIDTH:
2788     case CSS_PROP_MARGIN_TOP:
2789     case CSS_PROP_MARGIN_RIGHT:
2790     case CSS_PROP_MARGIN_BOTTOM:
2791     case CSS_PROP_MARGIN_LEFT:
2792         // +inherit +auto
2793         if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) {
2794             if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2795                 l = Length(Intrinsic);
2796                 apply = true;
2797             }
2798             else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2799                 l = Length(MinIntrinsic);
2800                 apply = true;
2801             }
2802         }
2803         if (id != CSS_PROP_MAX_WIDTH && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2804             apply = true;
2805     case CSS_PROP_PADDING_TOP:
2806     case CSS_PROP_PADDING_RIGHT:
2807     case CSS_PROP_PADDING_BOTTOM:
2808     case CSS_PROP_PADDING_LEFT:
2809     case CSS_PROP_TEXT_INDENT:
2810         // +inherit
2811     {
2812         if (isInherit) {
2813             HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
2814             HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
2815             HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
2816             HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
2817             HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
2818             HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
2819             HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
2820             HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
2821             HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
2822             HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
2823             HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
2824             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
2825             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
2826             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
2827             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
2828             HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
2829             return;
2830         }
2831         else if (isInitial) {
2832             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
2833             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
2834             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
2835             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
2836             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
2837             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
2838             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
2839             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
2840             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
2841             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
2842             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
2843             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
2844             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
2845             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
2846             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
2847             HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
2848             return;
2849         } 
2850
2851         if (primitiveValue && !apply) {
2852             int type = primitiveValue->primitiveType();
2853             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2854                 // Handle our quirky margin units if we have them.
2855                 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed, 
2856                            primitiveValue->isQuirkValue());
2857             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2858                 l = Length((int)primitiveValue->getFloatValue(), Percent);
2859             else
2860                 return;
2861             if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT ||
2862                 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM)
2863                 // Padding can't be negative
2864                 apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0);
2865             else
2866                 apply = true;
2867         }
2868         if(!apply) return;
2869         switch(id)
2870             {
2871             case CSS_PROP_MAX_WIDTH:
2872                 style->setMaxWidth(l); break;
2873             case CSS_PROP_BOTTOM:
2874                 style->setBottom(l); break;
2875             case CSS_PROP_TOP:
2876                 style->setTop(l); break;
2877             case CSS_PROP_LEFT:
2878                 style->setLeft(l); break;
2879             case CSS_PROP_RIGHT:
2880                 style->setRight(l); break;
2881             case CSS_PROP_WIDTH:
2882                 style->setWidth(l); break;
2883             case CSS_PROP_MIN_WIDTH:
2884                 style->setMinWidth(l); break;
2885             case CSS_PROP_PADDING_TOP:
2886                 style->setPaddingTop(l); break;
2887             case CSS_PROP_PADDING_RIGHT:
2888                 style->setPaddingRight(l); break;
2889             case CSS_PROP_PADDING_BOTTOM:
2890                 style->setPaddingBottom(l); break;
2891             case CSS_PROP_PADDING_LEFT:
2892                 style->setPaddingLeft(l); break;
2893             case CSS_PROP_MARGIN_TOP:
2894                 style->setMarginTop(l); break;
2895             case CSS_PROP_MARGIN_RIGHT:
2896                 style->setMarginRight(l); break;
2897             case CSS_PROP_MARGIN_BOTTOM:
2898                 style->setMarginBottom(l); break;
2899             case CSS_PROP_MARGIN_LEFT:
2900                 style->setMarginLeft(l); break;
2901             case CSS_PROP_TEXT_INDENT:
2902                 style->setTextIndent(l); break;
2903             default: break;
2904             }
2905         return;
2906     }
2907
2908     case CSS_PROP_MAX_HEIGHT:
2909         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
2910             l = Length(undefinedLength, Fixed);
2911             apply = true;
2912         }
2913     case CSS_PROP_HEIGHT:
2914     case CSS_PROP_MIN_HEIGHT:
2915         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2916             l = Length(Intrinsic);
2917             apply = true;
2918         } else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2919             l = Length(MinIntrinsic);
2920             apply = true;
2921         } else if (id != CSS_PROP_MAX_HEIGHT && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2922             apply = true;
2923         if (isInherit) {
2924             HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
2925             HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
2926             HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
2927             return;
2928         }
2929         if (isInitial) {
2930             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
2931             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
2932             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
2933             return;
2934         }
2935
2936         if (primitiveValue && !apply) {
2937             unsigned short type = primitiveValue->primitiveType();
2938             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2939                 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2940             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2941                 l = Length((int)primitiveValue->getFloatValue(), Percent);
2942             else
2943                 return;
2944             apply = true;
2945         }
2946         if (apply)
2947             switch (id) {
2948                 case CSS_PROP_MAX_HEIGHT:
2949                     style->setMaxHeight(l);
2950                     break;
2951                 case CSS_PROP_HEIGHT:
2952                     style->setHeight(l);
2953                     break;
2954                 case CSS_PROP_MIN_HEIGHT:
2955                     style->setMinHeight(l);
2956                     break;
2957             }
2958         break;
2959
2960     case CSS_PROP_VERTICAL_ALIGN:
2961         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2962         if (!primitiveValue) return;
2963         if (primitiveValue->getIdent()) {
2964           EVerticalAlign align;
2965
2966           switch(primitiveValue->getIdent())
2967             {
2968                 case CSS_VAL_TOP:
2969                     align = TOP; break;
2970                 case CSS_VAL_BOTTOM:
2971                     align = BOTTOM; break;
2972                 case CSS_VAL_MIDDLE:
2973                     align = MIDDLE; break;
2974                 case CSS_VAL_BASELINE:
2975                     align = BASELINE; break;
2976                 case CSS_VAL_TEXT_BOTTOM:
2977                     align = TEXT_BOTTOM; break;
2978                 case CSS_VAL_TEXT_TOP:
2979                     align = TEXT_TOP; break;
2980                 case CSS_VAL_SUB:
2981                     align = SUB; break;
2982                 case CSS_VAL_SUPER:
2983                     align = SUPER; break;
2984                 case CSS_VAL__WEBKIT_BASELINE_MIDDLE:
2985                     align = BASELINE_MIDDLE; break;
2986                 default:
2987                     return;
2988             }
2989           style->setVerticalAlign(align);
2990           return;
2991         } else {
2992           int type = primitiveValue->primitiveType();
2993           Length l;
2994           if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2995             l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2996           else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2997             l = Length(int(primitiveValue->getFloatValue()), Percent);
2998
2999           style->setVerticalAlign(LENGTH);
3000           style->setVerticalAlignLength(l);
3001         }
3002         break;
3003
3004     case CSS_PROP_FONT_SIZE:
3005     {
3006         FontDescription fontDescription = style->fontDescription();
3007         fontDescription.setKeywordSize(0);
3008         bool familyIsFixed = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
3009         float oldSize = 0;
3010         float size = 0;
3011         
3012         bool parentIsAbsoluteSize = false;
3013         if (parentNode) {
3014             oldSize = parentStyle->fontDescription().specifiedSize();
3015             parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize();
3016         }
3017
3018         if (isInherit) {
3019             size = oldSize;
3020             if (parentNode)
3021                 fontDescription.setKeywordSize(parentStyle->fontDescription().keywordSize());
3022         } else if (isInitial) {
3023             size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks(), familyIsFixed);
3024             fontDescription.setKeywordSize(CSS_VAL_MEDIUM - CSS_VAL_XX_SMALL + 1);
3025         } else if (primitiveValue->getIdent()) {
3026             // Keywords are being used.
3027             switch (primitiveValue->getIdent()) {
3028                 case CSS_VAL_XX_SMALL:
3029                 case CSS_VAL_X_SMALL:
3030                 case CSS_VAL_SMALL:
3031                 case CSS_VAL_MEDIUM:
3032                 case CSS_VAL_LARGE:
3033                 case CSS_VAL_X_LARGE:
3034                 case CSS_VAL_XX_LARGE:
3035                 case CSS_VAL__WEBKIT_XXX_LARGE:
3036                     size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks(), familyIsFixed);
3037                     fontDescription.setKeywordSize(primitiveValue->getIdent() - CSS_VAL_XX_SMALL + 1);
3038                     break;
3039                 case CSS_VAL_LARGER:
3040                     size = largerFontSize(oldSize, style->htmlHacks());
3041                     break;
3042                 case CSS_VAL_SMALLER:
3043                     size = smallerFontSize(oldSize, style->htmlHacks());
3044                     break;
3045                 default:
3046                     return;
3047             }
3048
3049             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && 
3050                                               (primitiveValue->getIdent() == CSS_VAL_LARGER ||
3051                                                primitiveValue->getIdent() == CSS_VAL_SMALLER));
3052         } else {
3053             int type = primitiveValue->primitiveType();
3054             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
3055                                               (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
3056                                                type != CSSPrimitiveValue::CSS_EMS && 
3057                                                type != CSSPrimitiveValue::CSS_EXS));
3058             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
3059                 size = primitiveValue->computeLengthFloat(parentStyle, false);
3060             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
3061                 size = (primitiveValue->getFloatValue() * oldSize) / 100;
3062             else
3063                 return;
3064         }
3065
3066         if (size < 0)
3067             return;
3068
3069         setFontSize(fontDescription, size);
3070         if (style->setFontDescription(fontDescription))
3071             fontDirty = true;
3072         return;
3073     }
3074         break;
3075     case CSS_PROP_Z_INDEX:
3076     {
3077         HANDLE_INHERIT(zIndex, ZIndex)
3078         else if (isInitial) {
3079             style->setHasAutoZIndex();
3080             return;
3081         }
3082         
3083         if (!primitiveValue)
3084             return;
3085
3086         if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
3087             style->setHasAutoZIndex();
3088             return;
3089         }
3090         
3091         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3092             return; // Error case.
3093         
3094         style->setZIndex((int)primitiveValue->getFloatValue());
3095         
3096         return;
3097     }
3098         
3099     case CSS_PROP_WIDOWS:
3100     {
3101         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
3102         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3103             return;
3104         style->setWidows((int)primitiveValue->getFloatValue());
3105         break;
3106     }
3107         
3108     case CSS_PROP_ORPHANS:
3109     {
3110         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
3111         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3112             return;
3113         style->setOrphans((int)primitiveValue->getFloatValue());
3114         break;
3115     }        
3116
3117 // length, percent, number
3118     case CSS_PROP_LINE_HEIGHT:
3119     {
3120         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
3121         if(!primitiveValue) return;
3122         Length lineHeight;
3123         int type = primitiveValue->primitiveType();
3124         if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
3125             lineHeight = Length(-100, Percent);
3126         else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3127             double multiplier = 1.0;
3128             // Scale for the font zoom factor only for types other than "em" and "ex", since those are
3129             // already based on the font size.
3130             if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->frame()) {
3131                 multiplier = view->frame()->zoomFactor() / 100.0;
3132             }
3133             lineHeight = Length(primitiveValue->computeLengthIntForLength(style, multiplier), Fixed);
3134         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3135             lineHeight = Length((style->fontSize() * int(primitiveValue->getFloatValue())) / 100, Fixed);
3136         else if (type == CSSPrimitiveValue::CSS_NUMBER)
3137             lineHeight = Length(int(primitiveValue->getFloatValue() * 100), Percent);
3138         else
3139             return;
3140         style->setLineHeight(lineHeight);
3141         return;
3142     }
3143
3144 // string
3145     case CSS_PROP_TEXT_ALIGN:
3146     {
3147         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
3148         if (!primitiveValue) return;
3149         if (primitiveValue->getIdent())
3150             style->setTextAlign((ETextAlign) (primitiveValue->getIdent() - CSS_VAL__WEBKIT_AUTO));
3151         return;
3152     }
3153
3154 // rect
3155     case CSS_PROP_CLIP:
3156     {
3157         Length top;
3158         Length right;
3159         Length bottom;
3160         Length left;
3161         bool hasClip = true;
3162         if (isInherit) {
3163             if (parentStyle->hasClip()) {
3164                 top = parentStyle->clipTop();
3165                 right = parentStyle->clipRight();
3166                 bottom = parentStyle->clipBottom();
3167                 left = parentStyle->clipLeft();
3168             }
3169             else {
3170                 hasClip = false;
3171                 top = right = bottom = left = Length();
3172             }
3173         } else if (isInitial) {
3174             hasClip = false;
3175             top = right = bottom = left = Length();
3176         } else if (!primitiveValue) {
3177             break;
3178         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
3179             RectImpl* rect = primitiveValue->getRectValue();
3180             if (!rect)
3181                 break;
3182             top = convertToLength(rect->top(), style);
3183             right = convertToLength(rect->right(), style);
3184             bottom = convertToLength(rect->bottom(), style);
3185             left = convertToLength(rect->left(), style);
3186
3187         } else if (primitiveValue->getIdent() != CSS_VAL_AUTO) {
3188             break;
3189         }
3190         style->setClip(top, right, bottom, left);
3191         style->setHasClip(hasClip);
3192     
3193         // rect, ident
3194         break;
3195     }
3196
3197 // lists
3198     case CSS_PROP_CONTENT:
3199         // list of string, uri, counter, attr, i
3200     {
3201         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
3202         // note is a reminder that eventually "inherit" needs to be supported.
3203
3204         if (isInitial) {
3205             if (style->contentData())
3206                 style->contentData()->clearContent();
3207             return;
3208         }
3209         
3210         if (!value->isValueList()) return;
3211         CSSValueList *list = static_cast<CSSValueList*>(value);
3212         int len = list->length();
3213
3214         for (int i = 0; i < len; i++) {
3215             CSSValue *item = list->item(i);
3216             if (!item->isPrimitiveValue())
3217                 continue;
3218             
3219             CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3220             if (val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
3221                 style->setContent(val->getStringValue().impl(), i != 0);
3222             else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR) {
3223                 // FIXME: Can a namespace be specified for an attr(foo)?
3224                 if (style->styleType() == RenderStyle::NOPSEUDO)
3225                     style->setUnique();
3226                 else
3227                     parentStyle->setUnique();
3228                 QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom);
3229                 style->setContent(element->getAttribute(attr).impl(), i != 0);
3230                 // register the fact that the attribute value affects the style
3231                 m_selectorAttrs.add(attr.localName().impl());
3232             } else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI) {
3233                 CSSImageValue *image = static_cast<CSSImageValue*>(val);
3234                 style->setContent(image->image(element->document()->docLoader()), i != 0);
3235             } else if (val->primitiveType()==CSSPrimitiveValue::CSS_COUNTER) {
3236                 Counter* counterValue = val->getCounterValue();
3237                 CounterData counter(counterValue->identifier(),
3238                     (EListStyleType)counterValue->listStyleNumber(), counterValue->separator());
3239                 style->setContent(new CounterData(counter), i != 0);
3240            }
3241         }
3242         break;
3243     }
3244
3245     case CSS_PROP_COUNTER_INCREMENT:
3246         if (!value->isValueList())
3247             return;
3248         style->setCounterIncrementList(static_cast<CSSValueList*>(value));
3249         break;
3250     case CSS_PROP_COUNTER_RESET:
3251         if (!value->isValueList())
3252             return;
3253         style->setCounterResetList(static_cast<CSSValueList*>(value));
3254         break;
3255     case CSS_PROP_FONT_FAMILY: {
3256         // list of strings and ids
3257         if (isInherit) {
3258             FontDescription parentFontDescription = parentStyle->fontDescription();
3259             FontDescription fontDescription = style->fontDescription();
3260             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
3261             fontDescription.setFamily(parentFontDescription.firstFamily());
3262             if (style->setFontDescription(fontDescription))
3263                 fontDirty = true;
3264             return;
3265         }
3266         else if (isInitial) {
3267             FontDescription initialDesc = FontDescription();
3268             FontDescription fontDescription = style->fontDescription();
3269             // We need to adjust the size to account for the generic family change from monospace
3270             // to non-monospace.
3271             if (fontDescription.keywordSize() && fontDescription.genericFamily() == FontDescription::MonospaceFamily)
3272                 setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, style->htmlHacks(), false));
3273             fontDescription.setGenericFamily(initialDesc.genericFamily());
3274             fontDescription.setFamily(initialDesc.firstFamily());
3275             if (style->setFontDescription(fontDescription))
3276                 fontDirty = true;
3277             return;
3278         }
3279         
3280         if (!value->isValueList()) return;
3281         FontDescription fontDescription = style->fontDescription();
3282         CSSValueList *list = static_cast<CSSValueList*>(value);
3283         int len = list->length();
3284         FontFamily& firstFamily = fontDescription.firstFamily();
3285         FontFamily *currFamily = 0;
3286         
3287         // Before mapping in a new font-family property, we should reset the generic family.
3288         bool oldFamilyIsMonospace = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
3289         fontDescription.setGenericFamily(FontDescription::NoFamily);
3290
3291         for(int i = 0; i < len; i++) {
3292             CSSValue *item = list->item(i);
3293             if(!item->isPrimitiveValue()) continue;
3294             CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3295             AtomicString face;
3296             if(val->primitiveType() == CSSPrimitiveValue::CSS_STRING)
3297                 face = static_cast<FontFamilyValue*>(val)->fontName();
3298             else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3299                 switch (val->getIdent()) {
3300