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