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