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