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