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