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