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