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