Fix for 3800316, test 37 for tables is failing on the layout tests. Make sure we...
[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 (localName < ID_LAST_TAG && e->isHTMLElement())
1052             ns = xhtmlNamespace; // FIXME: Really want to move away from this complicated hackery and just
1053                                  // switch tags and attr names over to AtomicStrings.
1054         
1055         if ((selLocalName != anyLocalName && localName != selLocalName) ||
1056             (selNS != anyNamespace && ns != selNS))
1057             return false;
1058     }
1059
1060     if (sel->attr) {
1061         if (sel->match == CSSSelector::Class) {
1062             if (!e->hasClass())
1063                 return false;
1064             for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
1065                 if (c->string() == sel->value)
1066                     return true;
1067             return false;
1068         }
1069         else if (sel->match == CSSSelector::Id)
1070             return e->hasID() && e->getIDAttribute() == sel->value;
1071         else if (style && (e != element || !htmlElement || !htmlElement->isMappedAttribute(sel->attr)))
1072             style->setAffectedByAttributeSelectors();
1073
1074         const AtomicString& value = e->getAttribute(sel->attr);
1075         if (value.isNull()) return false; // attribute is not set
1076
1077         switch(sel->match) {
1078         case CSSSelector::Exact:
1079             if ((isXMLDoc && sel->value != value) ||
1080                 (!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
1081                 return false;
1082             break;
1083         case CSSSelector::List:
1084         {
1085             int spacePos = value.find(' ', 0);
1086             if (spacePos == -1) {
1087                 // There is no list, just a single item.  We can avoid
1088                 // allocing QStrings and just treat this as an exact
1089                 // match check.
1090                 if ((isXMLDoc && sel->value != value) ||
1091                     (!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
1092                     return false;
1093                 break;
1094             }
1095
1096             // The selector's value can't contain a space, or it's totally bogus.
1097             spacePos = sel->value.find(' ');
1098             if (spacePos != -1)
1099                 return false;
1100
1101             QString str = value.string();
1102             QString selStr = sel->value.string();
1103             int startSearchAt = 0;
1104             while (true) {
1105                 int foundPos = str.find(selStr, startSearchAt, isXMLDoc);
1106                 if (foundPos == -1) return false;
1107                 if (foundPos == 0 || str[foundPos-1] == ' ') {
1108                     uint endStr = foundPos + selStr.length();
1109                     if (endStr == str.length() || str[endStr] == ' ')
1110                         break; // We found a match.
1111                 }
1112                 
1113                 // No match.  Keep looking.
1114                 startSearchAt = foundPos + 1;
1115             }
1116
1117             break;
1118         }
1119         case CSSSelector::Contain:
1120         {
1121             //kdDebug( 6080 ) << "checking for contains match" << endl;
1122             QString str = value.string();
1123             QString selStr = sel->value.string();
1124             int pos = str.find(selStr, 0, isXMLDoc);
1125             if(pos == -1) return false;
1126             break;
1127         }
1128         case CSSSelector::Begin:
1129         {
1130             //kdDebug( 6080 ) << "checking for beginswith match" << endl;
1131             QString str = value.string();
1132             QString selStr = sel->value.string();
1133             int pos = str.find(selStr, 0, isXMLDoc);
1134             if(pos != 0) return false;
1135             break;
1136         }
1137         case CSSSelector::End:
1138         {
1139             //kdDebug( 6080 ) << "checking for endswith match" << endl;
1140             QString str = value.string();
1141             QString selStr = sel->value.string();
1142             if (isXMLDoc && !str.endsWith(selStr)) return false;
1143             if (!isXMLDoc) {
1144                 int pos = str.length() - selStr.length();
1145                 if (pos < 0 || pos != str.find(selStr, pos, false) )
1146                     return false;
1147             }
1148             break;
1149         }
1150         case CSSSelector::Hyphen:
1151         {
1152             //kdDebug( 6080 ) << "checking for hyphen match" << endl;
1153             QString str = value.string();
1154             QString selStr = sel->value.string();
1155             if(str.length() < selStr.length()) return false;
1156             // Check if str begins with selStr:
1157             if(str.find(selStr, 0, isXMLDoc) != 0) return false;
1158             // It does. Check for exact match or following '-':
1159             if(str.length() != selStr.length()
1160                 && str[selStr.length()] != '-') return false;
1161             break;
1162         }
1163         default:
1164             break;
1165         }
1166     }
1167     if(sel->match == CSSSelector::Pseudo)
1168     {
1169         // Pseudo elements. We need to check first child here. No dynamic pseudo
1170         // elements for the moment
1171 //      kdDebug() << "CSSOrderedRule::pseudo " << value << endl;
1172         switch (sel->pseudoType()) {
1173             case CSSSelector::PseudoEmpty:
1174                 if (!e->firstChild())
1175                     return true;
1176                 break;
1177             case CSSSelector::PseudoFirstChild: {
1178                 // first-child matches the first child that is an element!
1179                 if (e->parentNode()) {
1180                     DOM::NodeImpl* n = e->previousSibling();
1181                     while ( n && !n->isElementNode() )
1182                         n = n->previousSibling();
1183                     if ( !n )
1184                         return true;
1185                 }
1186                 break;
1187             }
1188             case CSSSelector::PseudoLastChild: {
1189                 // last-child matches the last child that is an element!
1190                 if (e->parentNode()) {
1191                     DOM::NodeImpl* n = e->nextSibling();
1192                     while ( n && !n->isElementNode() )
1193                         n = n->nextSibling();
1194                     if ( !n )
1195                         return true;
1196                 }
1197                 break;
1198             }
1199             case CSSSelector::PseudoOnlyChild: {
1200                 // If both first-child and last-child apply, then only-child applies.
1201                 if (e->parentNode()) {
1202                     DOM::NodeImpl* n = e->previousSibling();
1203                     while ( n && !n->isElementNode() )
1204                         n = n->previousSibling();
1205                     if ( !n ) {
1206                         n = e->nextSibling();
1207                         while ( n && !n->isElementNode() )
1208                             n = n->nextSibling();
1209                         if ( !n )
1210                             return true;
1211                     }
1212                 }
1213                 break;
1214             }
1215             case CSSSelector::PseudoFirstLine:
1216                 if ( subject ) {
1217                     dynamicPseudo=RenderStyle::FIRST_LINE;
1218                     return true;
1219                 }
1220                 break;
1221             case CSSSelector::PseudoFirstLetter:
1222                 if ( subject ) {
1223                     dynamicPseudo=RenderStyle::FIRST_LETTER;
1224                     return true;
1225                 }
1226                 break;
1227             case CSSSelector::PseudoTarget:
1228                 if (e == e->getDocument()->getCSSTarget())
1229                     return true;
1230                 break;
1231             case CSSSelector::PseudoAnyLink:
1232                 if (pseudoState == PseudoUnknown)
1233                     checkPseudoState(e, false);
1234                 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
1235                     return true;
1236                 break;
1237             case CSSSelector::PseudoLink:
1238                 if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
1239                     checkPseudoState( e );
1240                 if ( pseudoState == PseudoLink )
1241                     return true;
1242                 break;
1243             case CSSSelector::PseudoVisited:
1244                 if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
1245                     checkPseudoState( e );
1246                 if ( pseudoState == PseudoVisited )
1247                     return true;
1248                 break;
1249             case CSSSelector::PseudoHover: {
1250                 // If we're in quirks mode, then hover should never match anchors with no
1251                 // href.  This is important for sites like wsj.com.
1252                 if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
1253                     if (element == e && style)
1254                         style->setAffectedByHoverRules(true);
1255                     if (e->renderer()) {
1256                         if (element != e)
1257                             e->renderer()->style()->setAffectedByHoverRules(true);
1258                         if (e->renderer()->mouseInside())
1259                             return true;
1260                     }
1261                 }
1262                 break;
1263             }
1264             case CSSSelector::PseudoDrag: {
1265                 if (element == e && style)
1266                     style->setAffectedByDragRules(true);
1267                 if (e->renderer()) {
1268                     if (element != e)
1269                         e->renderer()->style()->setAffectedByDragRules(true);
1270                     if (e->renderer()->isDragging())
1271                         return true;
1272                 }
1273                 break;
1274             }
1275             case CSSSelector::PseudoFocus:
1276                 if (e && e->focused()) {
1277                     return true;
1278                 }
1279                 break;
1280             case CSSSelector::PseudoActive:
1281                 // If we're in quirks mode, then :active should never match anchors with no
1282                 // href. 
1283                 if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
1284                     if (element == e && style)
1285                         style->setAffectedByActiveRules(true);
1286                     else if (e->renderer())
1287                         e->renderer()->style()->setAffectedByActiveRules(true);
1288                     if (e->active())
1289                         return true;
1290                 }
1291                 break;
1292             case CSSSelector::PseudoRoot:
1293                 if (e == e->getDocument()->documentElement())
1294                     return true;
1295                 break;
1296             case CSSSelector::PseudoNot: {
1297                 // check the simple selector
1298                 for (CSSSelector* subSel = sel->simpleSelector; subSel;
1299                      subSel = subSel->tagHistory) {
1300                     // :not cannot nest.  I don't really know why this is a restriction in CSS3,
1301                     // but it is, so let's honor it.
1302                     if (subSel->simpleSelector)
1303                         break;
1304                     if (!checkOneSelector(subSel, e))
1305                         return true;
1306                 }
1307                 break;
1308             }
1309             case CSSSelector::PseudoSelection:
1310                 dynamicPseudo = RenderStyle::SELECTION;
1311                 return true;
1312             case CSSSelector::PseudoBefore:
1313                 dynamicPseudo = RenderStyle::BEFORE;
1314                 return true;
1315             case CSSSelector::PseudoAfter:
1316                 dynamicPseudo = RenderStyle::AFTER;
1317                 return true;
1318                 
1319             case CSSSelector::PseudoNotParsed:
1320                 assert(false);
1321                 break;
1322             case CSSSelector::PseudoLang:
1323                 /* not supported for now */
1324             case CSSSelector::PseudoOther:
1325                 break;
1326         }
1327         return false;
1328     }
1329     // ### add the rest of the checks...
1330     return true;
1331 }
1332
1333 // -----------------------------------------------------------------
1334
1335 CSSRuleSet::CSSRuleSet()
1336 {
1337     m_idRules.setAutoDelete(true);
1338     m_classRules.setAutoDelete(true);
1339     m_tagRules.setAutoDelete(true);
1340     m_universalRules = 0;
1341     m_ruleCount = 0;
1342 }
1343
1344 void CSSRuleSet::addToRuleSet(void* hash, QPtrDict<CSSRuleDataList>& dict,
1345                               CSSStyleRuleImpl* rule, CSSSelector* sel)
1346 {
1347     if (!hash) return;
1348     CSSRuleDataList* rules = dict.find(hash);
1349     if (!rules) {
1350         rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1351         dict.insert(hash, rules);
1352     }
1353     else
1354         rules->append(m_ruleCount++, rule, sel);
1355 }
1356
1357 void CSSRuleSet::addRule(CSSStyleRuleImpl* rule, CSSSelector* sel)
1358 {
1359     if (sel->match == CSSSelector::Id) {
1360         addToRuleSet(sel->value.implementation(), m_idRules, rule, sel);
1361         return;
1362     }
1363     if (sel->match == CSSSelector::Class) {
1364         addToRuleSet(sel->value.implementation(), m_classRules, rule, sel);
1365         return;
1366     }
1367      
1368     Q_UINT16 localName = localNamePart(sel->tag);
1369     if (localName != anyLocalName) {
1370         addToRuleSet((void*)(int)localName, m_tagRules, rule, sel);
1371         return;
1372     }
1373     
1374     // Just put it in the universal rule set.
1375     if (!m_universalRules)
1376         m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1377     else
1378         m_universalRules->append(m_ruleCount++, rule, sel);
1379 }
1380
1381 void CSSRuleSet::addRulesFromSheet(CSSStyleSheetImpl *sheet, const DOMString &medium)
1382 {
1383     if (!sheet || !sheet->isCSSStyleSheet()) return;
1384
1385     // No media implies "all", but if a media list exists it must
1386     // contain our current medium
1387     if (sheet->media() && !sheet->media()->contains(medium))
1388         return; // the style sheet doesn't apply
1389
1390     int len = sheet->length();
1391
1392     for (int i = 0; i < len; i++) {
1393         StyleBaseImpl *item = sheet->item(i);
1394         if (item->isStyleRule()) {
1395             CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(item);
1396             for (CSSSelector* s = rule->selector(); s; s = s->next())
1397                 addRule(rule, s);
1398         }
1399         else if(item->isImportRule()) {
1400             CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
1401
1402             //kdDebug( 6080 ) << "@import: Media: "
1403             //                << import->media()->mediaText().string() << endl;
1404
1405             if (!import->media() || import->media()->contains(medium))
1406                 addRulesFromSheet(import->styleSheet(), medium);
1407         }
1408         else if(item->isMediaRule()) {
1409             CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl*>(item);
1410             CSSRuleListImpl *rules = r->cssRules();
1411
1412             //DOMString mediaText = media->mediaText();
1413             //kdDebug( 6080 ) << "@media: Media: "
1414             //                << r->media()->mediaText().string() << endl;
1415
1416             if ((!r->media() || r->media()->contains(medium)) && rules) {
1417                 // Traverse child elements of the @media rule.
1418                 for (unsigned j = 0; j < rules->length(); j++) {
1419                     //kdDebug( 6080 ) << "*** Rule #" << j << endl;
1420
1421                     CSSRuleImpl *childItem = rules->item(j);
1422                     if (childItem->isStyleRule()) {
1423                         // It is a StyleRule, so append it to our list
1424                         CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(childItem);
1425                         for (CSSSelector* s = rule->selector(); s; s = s->next())
1426                             addRule(rule, s);
1427                         
1428                     }
1429                     else
1430                     {
1431                         //kdDebug( 6080 ) << "Ignoring child rule of "
1432                         //    "ImportRule: rule is not a StyleRule!" << endl;
1433                     }
1434                 }   // for rules
1435             }   // if rules
1436             else
1437             {
1438                 //kdDebug( 6080 ) << "CSSMediaRule not rendered: "
1439                 //                << "rule empty or wrong medium!" << endl;
1440             }
1441         }
1442         // ### include other rules
1443     }
1444 }
1445
1446 // -------------------------------------------------------------------------------------
1447 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1448
1449 static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, QPaintDeviceMetrics *paintDeviceMetrics, bool *ok = 0 )
1450 {
1451     Length l;
1452     if ( !primitiveValue ) {
1453         if ( ok )
1454             *ok = false;
1455     } else {
1456         int type = primitiveValue->primitiveType();
1457         if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
1458             l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
1459         else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
1460             l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent);
1461         else if(type == CSSPrimitiveValue::CSS_NUMBER)
1462             l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
1463         else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
1464             l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
1465         else if ( ok )
1466             *ok = false;
1467     }
1468     return l;
1469 }
1470
1471
1472 // color mapping code
1473 struct colorMap {
1474     int css_value;
1475     QRgb color;
1476 };
1477
1478 static const colorMap cmap[] = {
1479     { CSS_VAL_AQUA, 0xFF00FFFF },
1480     { CSS_VAL_BLACK, 0xFF000000 },
1481     { CSS_VAL_BLUE, 0xFF0000FF },
1482     { CSS_VAL_FUCHSIA, 0xFFFF00FF },
1483     { CSS_VAL_GRAY, 0xFF808080 },
1484     { CSS_VAL_GREEN, 0xFF008000  },
1485     { CSS_VAL_LIME, 0xFF00FF00 },
1486     { CSS_VAL_MAROON, 0xFF800000 },
1487     { CSS_VAL_NAVY, 0xFF000080 },
1488     { CSS_VAL_OLIVE, 0xFF808000  },
1489     { CSS_VAL_ORANGE, 0xFFFFA500 },
1490     { CSS_VAL_PURPLE, 0xFF800080 },
1491     { CSS_VAL_RED, 0xFFFF0000 },
1492     { CSS_VAL_SILVER, 0xFFC0C0C0 },
1493     { CSS_VAL_TEAL, 0xFF008080  },
1494     { CSS_VAL_WHITE, 0xFFFFFFFF },
1495     { CSS_VAL_YELLOW, 0xFFFFFF00 },
1496 #if !APPLE_CHANGES
1497     { CSS_VAL_INVERT, invertedColor },
1498 #endif
1499     { CSS_VAL_TRANSPARENT, transparentColor },
1500     { CSS_VAL_GREY, 0xFF808080 },
1501 #if APPLE_CHANGES
1502     { CSS_VAL_ACTIVEBORDER, 0xFFE0E0E0 },
1503     { CSS_VAL_ACTIVECAPTION, 0xFF000000 },
1504     { CSS_VAL_APPWORKSPACE, 0xFF000000 },
1505     { CSS_VAL_BUTTONFACE, 0xFFC0C0C0 },
1506     { CSS_VAL_BUTTONHIGHLIGHT, 0xFFE0E0E0 },
1507     { CSS_VAL_BUTTONSHADOW, 0xFFFFFFFF },
1508     { CSS_VAL_BUTTONTEXT, 0xFF000000 },
1509     { CSS_VAL_CAPTIONTEXT, 0xFF000000 },
1510     { CSS_VAL_GRAYTEXT, 0xFF000000 },
1511     { CSS_VAL_HIGHLIGHT, 0xFFFFFFFF },
1512     { CSS_VAL_HIGHLIGHTTEXT, 0xFFFFFFFF },
1513     { CSS_VAL_INACTIVEBORDER, 0xFFFFFFFF },
1514     { CSS_VAL_INACTIVECAPTION, 0xFFFFFFFF },
1515     { CSS_VAL_INACTIVECAPTIONTEXT, 0xFF000000 },
1516     { CSS_VAL_INFOBACKGROUND, 0xFF000000 },
1517     { CSS_VAL_INFOTEXT, 0xFF000000 },
1518     { CSS_VAL_MENU, 0xFFFFFFFF },
1519     { CSS_VAL_MENUTEXT, 0xFFFFFFFF },
1520     { CSS_VAL_SCROLLBAR, 0xFFFFFFFF },
1521     { CSS_VAL_TEXT, 0xFF000000 },
1522     { CSS_VAL_THREEDDARKSHADOW, 0xFF404040 },
1523     { CSS_VAL_THREEDFACE, 0xFFC0C0C0 },
1524     { CSS_VAL_THREEDHIGHLIGHT, 0xFFE0E0E0 },
1525     { CSS_VAL_THREEDLIGHTSHADOW, 0xFFC0C0C0 },
1526     { CSS_VAL_THREEDSHADOW, 0xFFFFFFFF },
1527     { CSS_VAL_WINDOW, 0xFFFFFFFF },
1528     { CSS_VAL_WINDOWFRAME, 0xFFFFFFFF },
1529     { CSS_VAL_WINDOWTEXT, 0xFF000000 },
1530 #endif
1531     { 0, 0 }
1532 };
1533
1534 #if !APPLE_CHANGES
1535
1536 struct uiColors {
1537     int css_value;
1538     const char * configGroup;
1539     const char * configEntry;
1540 QPalette::ColorGroup group;
1541 QColorGroup::ColorRole role;
1542 };
1543
1544 const char * const wmgroup = "WM";
1545 const char * const generalgroup = "General";
1546
1547 /* Mapping system settings to CSS 2
1548 * Tried hard to get an appropriate mapping - schlpbch
1549 */
1550 static const uiColors uimap[] = {
1551     // Active window border.
1552     { CSS_VAL_ACTIVEBORDER, wmgroup, "background", QPalette::Active, QColorGroup::Light },
1553     // Active window caption.
1554     { CSS_VAL_ACTIVECAPTION, wmgroup, "background", QPalette::Active, QColorGroup::Text },
1555     // Text in caption, size box, and scrollbar arrow box.
1556     { CSS_VAL_CAPTIONTEXT, wmgroup, "activeForeground", QPalette::Active, QColorGroup::Text },
1557     // Face color for three-dimensional display elements.
1558     { CSS_VAL_BUTTONFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
1559     // Dark shadow for three-dimensional display elements (for edges facing away from the light source).
1560     { CSS_VAL_BUTTONHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
1561     // Shadow color for three-dimensional display elements.
1562     { CSS_VAL_BUTTONSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
1563     // Text on push buttons.
1564     { CSS_VAL_BUTTONTEXT, wmgroup, "buttonForeground", QPalette::Inactive, QColorGroup::ButtonText },
1565     // Dark shadow for three-dimensional display elements.
1566     { CSS_VAL_THREEDDARKSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Dark },
1567     // Face color for three-dimensional display elements.
1568     { CSS_VAL_THREEDFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
1569     // Highlight color for three-dimensional display elements.
1570     { CSS_VAL_THREEDHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
1571     // Light color for three-dimensional display elements (for edges facing the light source).
1572     { CSS_VAL_THREEDLIGHTSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Midlight },
1573     // Dark shadow for three-dimensional display elements.
1574     { CSS_VAL_THREEDSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
1575
1576     // Inactive window border.
1577     { CSS_VAL_INACTIVEBORDER, wmgroup, "background", QPalette::Disabled, QColorGroup::Background },
1578     // Inactive window caption.
1579     { CSS_VAL_INACTIVECAPTION, wmgroup, "inactiveBackground", QPalette::Disabled, QColorGroup::Background },
1580     // Color of text in an inactive caption.
1581     { CSS_VAL_INACTIVECAPTIONTEXT, wmgroup, "inactiveForeground", QPalette::Disabled, QColorGroup::Text },
1582     { CSS_VAL_GRAYTEXT, wmgroup, 0, QPalette::Disabled, QColorGroup::Text },
1583
1584     // Menu background
1585     { CSS_VAL_MENU, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
1586     // Text in menus
1587     { CSS_VAL_MENUTEXT, generalgroup, "foreground", QPalette::Inactive, QColorGroup::Background },
1588
1589     // Text of item(s) selected in a control.
1590     { CSS_VAL_HIGHLIGHT, generalgroup, "selectBackground", QPalette::Inactive, QColorGroup::Background },
1591
1592     // Text of item(s) selected in a control.
1593     { CSS_VAL_HIGHLIGHTTEXT, generalgroup, "selectForeground", QPalette::Inactive, QColorGroup::Background },
1594
1595     // Background color of multiple document interface.
1596     { CSS_VAL_APPWORKSPACE, generalgroup, "background", QPalette::Inactive, QColorGroup::Text },
1597
1598     // Scroll bar gray area.
1599     { CSS_VAL_SCROLLBAR, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
1600
1601     // Window background.
1602     { CSS_VAL_WINDOW, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
1603     // Window frame.
1604     { CSS_VAL_WINDOWFRAME, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
1605     // WindowText
1606     { CSS_VAL_WINDOWTEXT, generalgroup, "windowForeground", QPalette::Inactive, QColorGroup::Text },
1607     { CSS_VAL_TEXT, generalgroup, 0, QPalette::Inactive, QColorGroup::Text },
1608     { 0, 0, 0, QPalette::NColorGroups, QColorGroup::NColorRoles }
1609 };
1610
1611 #endif // !APPLE_CHANGES
1612
1613 static QColor colorForCSSValue( int css_value )
1614 {
1615     // try the regular ones first
1616     const colorMap *col = cmap;
1617     while ( col->css_value && col->css_value != css_value )
1618         ++col;
1619     if ( col->css_value )
1620         return col->color;
1621
1622 #if APPLE_CHANGES
1623     return QColor();
1624 #else
1625     const uiColors *uicol = uimap;
1626     while ( uicol->css_value && uicol->css_value != css_value )
1627         ++uicol;
1628     if ( !uicol->css_value ) {
1629         if ( css_value == CSS_VAL_INFOBACKGROUND )
1630             return QToolTip::palette().inactive().background();
1631         else if ( css_value == CSS_VAL_INFOTEXT )
1632             return QToolTip::palette().inactive().foreground();
1633         else if ( css_value == CSS_VAL_BACKGROUND ) {
1634             KConfig bckgrConfig("kdesktoprc", true, false); // No multi-screen support
1635             bckgrConfig.setGroup("Desktop0");
1636             // Desktop background.
1637             return bckgrConfig.readColorEntry("Color1", &qApp->palette().disabled().background());
1638         }
1639         return khtml::invalidColor;
1640     }
1641     
1642     const QPalette &pal = qApp->palette();
1643     QColor c = pal.color( uicol->group, uicol->role );
1644     if ( uicol->configEntry ) {
1645         KConfig *globalConfig = KGlobal::config();
1646         globalConfig->setGroup( uicol->configGroup );
1647         c = globalConfig->readColorEntry( uicol->configEntry, &c );
1648     }
1649     
1650     return c;
1651 #endif
1652 }
1653
1654 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
1655                                          int startIndex, int endIndex)
1656 {
1657     if (startIndex == -1) return;
1658     for (int i = startIndex; i <= endIndex; i++) {
1659         CSSStyleDeclarationImpl* decl = m_matchedDecls[i];
1660         QPtrList<CSSProperty>* props = decl->values();
1661         if (props) {
1662             QPtrListIterator<CSSProperty> propertyIt(*props);
1663             CSSProperty* current;
1664             for (propertyIt.toFirst(); (current = propertyIt.current()); ++propertyIt) {
1665                 // give special priority to font-xxx, color properties
1666                 if (isImportant == current->isImportant()) {
1667                     bool first;
1668                     switch(current->id())
1669                     {
1670                         case CSS_PROP_BACKGROUND:
1671                         case CSS_PROP_BACKGROUND_IMAGE:
1672                         case CSS_PROP_COLOR:
1673                         case CSS_PROP_DISPLAY:
1674                         case CSS_PROP_FONT:
1675                         case CSS_PROP_FONT_SIZE:
1676                         case CSS_PROP_FONT_STYLE:
1677                         case CSS_PROP_FONT_FAMILY:
1678                         case CSS_PROP_FONT_WEIGHT:
1679 #if APPLE_CHANGES
1680                         case CSS_PROP__APPLE_TEXT_SIZE_ADJUST:
1681 #endif
1682                             // these have to be applied first, because other properties use the computed
1683                             // values of these porperties.
1684                             first = true;
1685                             break;
1686                         default:
1687                             first = false;
1688                             break;
1689                     }
1690                     
1691                     if (first == applyFirst)
1692                         applyProperty(current->id(), current->value());
1693                 }
1694             }
1695         }
1696     }
1697 }
1698
1699 void CSSStyleSelector::applyProperty( int id, DOM::CSSValueImpl *value )
1700 {
1701     //kdDebug( 6080 ) << "applying property " << prop->m_id << endl;
1702
1703     CSSPrimitiveValueImpl *primitiveValue = 0;
1704     if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
1705
1706     Length l;
1707     bool apply = false;
1708
1709     bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
1710     bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) ||
1711                      (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
1712
1713     // What follows is a list that maps the CSS properties into their corresponding front-end
1714     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
1715     // are only hit when mapping "inherit" or "initial" into front-end values.
1716     switch(id)
1717     {
1718 // ident only properties
1719     case CSS_PROP_BACKGROUND_ATTACHMENT:
1720         HANDLE_INHERIT_AND_INITIAL(backgroundAttachment, BackgroundAttachment)
1721         if(!primitiveValue) break;
1722         switch (primitiveValue->getIdent()) {
1723         case CSS_VAL_FIXED:
1724             style->setBackgroundAttachment(false);
1725             break;
1726         case CSS_VAL_SCROLL:
1727             style->setBackgroundAttachment(true);
1728             break;
1729         default:
1730             return;
1731         }
1732     case CSS_PROP_BACKGROUND_REPEAT:
1733     {
1734         HANDLE_INHERIT_AND_INITIAL(backgroundRepeat, BackgroundRepeat)
1735         if(!primitiveValue) return;
1736         switch(primitiveValue->getIdent())
1737         {
1738         case CSS_VAL_REPEAT:
1739             style->setBackgroundRepeat( REPEAT );
1740             break;
1741         case CSS_VAL_REPEAT_X:
1742             style->setBackgroundRepeat( REPEAT_X );
1743             break;
1744         case CSS_VAL_REPEAT_Y:
1745             style->setBackgroundRepeat( REPEAT_Y );
1746             break;
1747         case CSS_VAL_NO_REPEAT:
1748             style->setBackgroundRepeat( NO_REPEAT );
1749             break;
1750         default:
1751             return;
1752         }
1753     }
1754     case CSS_PROP_BORDER_COLLAPSE:
1755         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
1756         if(!primitiveValue) break;
1757         switch(primitiveValue->getIdent())
1758         {
1759         case CSS_VAL_COLLAPSE:
1760             style->setBorderCollapse(true);
1761             break;
1762         case CSS_VAL_SEPARATE:
1763             style->setBorderCollapse(false);
1764             break;
1765         default:
1766             return;
1767         }
1768         break;
1769         
1770     case CSS_PROP_BORDER_TOP_STYLE:
1771         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
1772         if (!primitiveValue) return;
1773         style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1774         break;
1775     case CSS_PROP_BORDER_RIGHT_STYLE:
1776         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
1777         if (!primitiveValue) return;
1778         style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1779         break;
1780     case CSS_PROP_BORDER_BOTTOM_STYLE:
1781         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
1782         if (!primitiveValue) return;
1783         style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1784         break;
1785     case CSS_PROP_BORDER_LEFT_STYLE:
1786         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
1787         if (!primitiveValue) return;
1788         style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1789         break;
1790     case CSS_PROP_OUTLINE_STYLE:
1791         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
1792         if (!primitiveValue) return;
1793         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
1794             style->setOutlineStyle(DOTTED, true);
1795         else
1796             style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1797         break;
1798     case CSS_PROP_CAPTION_SIDE:
1799     {
1800         HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
1801         if(!primitiveValue) break;
1802         ECaptionSide c = RenderStyle::initialCaptionSide();
1803         switch(primitiveValue->getIdent())
1804         {
1805         case CSS_VAL_LEFT:
1806             c = CAPLEFT; break;
1807         case CSS_VAL_RIGHT:
1808             c = CAPRIGHT; break;
1809         case CSS_VAL_TOP:
1810             c = CAPTOP; break;
1811         case CSS_VAL_BOTTOM:
1812             c = CAPBOTTOM; break;
1813         default:
1814             return;
1815         }
1816         style->setCaptionSide(c);
1817         return;
1818     }
1819     case CSS_PROP_CLEAR:
1820     {
1821         HANDLE_INHERIT_AND_INITIAL(clear, Clear)
1822         if(!primitiveValue) break;
1823         EClear c;
1824         switch(primitiveValue->getIdent())
1825         {
1826         case CSS_VAL_NONE:
1827             c = CNONE; break;
1828         case CSS_VAL_LEFT:
1829             c = CLEFT; break;
1830         case CSS_VAL_RIGHT:
1831             c = CRIGHT; break;
1832         case CSS_VAL_BOTH:
1833             c = CBOTH; break;
1834         default:
1835             return;
1836         }
1837         style->setClear(c);
1838         return;
1839     }
1840     case CSS_PROP_DIRECTION:
1841     {
1842         HANDLE_INHERIT_AND_INITIAL(direction, Direction)
1843         if(!primitiveValue) break;
1844         style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) );
1845         return;
1846     }
1847     case CSS_PROP_DISPLAY:
1848     {
1849         HANDLE_INHERIT_AND_INITIAL(display, Display)
1850         if(!primitiveValue) break;
1851         int id = primitiveValue->getIdent();
1852         EDisplay d;
1853         if (id == CSS_VAL_NONE)
1854             d = NONE;
1855         else
1856             d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE);
1857
1858         style->setDisplay(d);
1859         //kdDebug( 6080 ) << "setting display to " << d << endl;
1860
1861         break;
1862     }
1863
1864     case CSS_PROP_EMPTY_CELLS:
1865     {
1866         HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
1867         if (!primitiveValue) break;
1868         int id = primitiveValue->getIdent();
1869         if (id == CSS_VAL_SHOW)
1870             style->setEmptyCells(SHOW);
1871         else if (id == CSS_VAL_HIDE)
1872             style->setEmptyCells(HIDE);
1873         break;
1874     }
1875     case CSS_PROP_FLOAT:
1876     {
1877         HANDLE_INHERIT_AND_INITIAL(floating, Floating)
1878         if(!primitiveValue) return;
1879         EFloat f;
1880         switch(primitiveValue->getIdent())
1881         {
1882         case CSS_VAL_LEFT:
1883             f = FLEFT; break;
1884         case CSS_VAL_RIGHT:
1885             f = FRIGHT; break;
1886         case CSS_VAL_NONE:
1887         case CSS_VAL_CENTER:  //Non standart CSS-Value
1888             f = FNONE; break;
1889         default:
1890             return;
1891         }
1892         
1893         style->setFloating(f);
1894         break;
1895     }
1896
1897         break;
1898     case CSS_PROP_FONT_STRETCH:
1899         break; /* Not supported. */
1900
1901     case CSS_PROP_FONT_STYLE:
1902     {
1903         FontDef fontDef = style->htmlFont().fontDef;
1904         if (isInherit)
1905             fontDef.italic = parentStyle->htmlFont().fontDef.italic;
1906         else if (isInitial)
1907             fontDef.italic = false;
1908         else {
1909             if(!primitiveValue) return;
1910             switch(primitiveValue->getIdent()) {
1911                 case CSS_VAL_OBLIQUE:
1912                 // ### oblique is the same as italic for the moment...
1913                 case CSS_VAL_ITALIC:
1914                     fontDef.italic = true;
1915                     break;
1916                 case CSS_VAL_NORMAL:
1917                     fontDef.italic = false;
1918                     break;
1919                 default:
1920                     return;
1921             }
1922         }
1923         if (style->setFontDef( fontDef ))
1924         fontDirty = true;
1925         break;
1926     }
1927
1928
1929     case CSS_PROP_FONT_VARIANT:
1930     {
1931         FontDef fontDef = style->htmlFont().fontDef;
1932         if (isInherit) 
1933             fontDef.smallCaps = parentStyle->htmlFont().fontDef.smallCaps;
1934         else if (isInitial)
1935             fontDef.smallCaps = false;
1936         else {
1937             if(!primitiveValue) return;
1938             int id = primitiveValue->getIdent();
1939             if ( id == CSS_VAL_NORMAL )
1940                 fontDef.smallCaps = false;
1941             else if ( id == CSS_VAL_SMALL_CAPS )
1942                 fontDef.smallCaps = true;
1943             else
1944                 return;
1945         }
1946         if (style->setFontDef( fontDef ))
1947             fontDirty = true;
1948         break;        
1949     }
1950
1951     case CSS_PROP_FONT_WEIGHT:
1952     {
1953         FontDef fontDef = style->htmlFont().fontDef;
1954         if (isInherit)
1955             fontDef.weight = parentStyle->htmlFont().fontDef.weight;
1956         else if (isInitial)
1957             fontDef.weight = QFont::Normal;
1958         else {
1959             if(!primitiveValue) return;
1960             if(primitiveValue->getIdent())
1961             {
1962                 switch(primitiveValue->getIdent()) {
1963                     // ### we just support normal and bold fonts at the moment...
1964                     // setWeight can actually accept values between 0 and 99...
1965                     case CSS_VAL_BOLD:
1966                     case CSS_VAL_BOLDER:
1967                     case CSS_VAL_600:
1968                     case CSS_VAL_700:
1969                     case CSS_VAL_800:
1970                     case CSS_VAL_900:
1971                         fontDef.weight = QFont::Bold;
1972                         break;
1973                     case CSS_VAL_NORMAL:
1974                     case CSS_VAL_LIGHTER:
1975                     case CSS_VAL_100:
1976                     case CSS_VAL_200:
1977                     case CSS_VAL_300:
1978                     case CSS_VAL_400:
1979                     case CSS_VAL_500:
1980                         fontDef.weight = QFont::Normal;
1981                         break;
1982                     default:
1983                         return;
1984                 }
1985             }
1986             else
1987             {
1988                 // ### fix parsing of 100-900 values in parser, apply them here
1989             }
1990         }
1991         if (style->setFontDef( fontDef ))
1992             fontDirty = true;
1993         break;
1994     }
1995         
1996     case CSS_PROP_LIST_STYLE_POSITION:
1997     {
1998         HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
1999         if (!primitiveValue) return;
2000         if (primitiveValue->getIdent())
2001             style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) );
2002         return;
2003     }
2004
2005     case CSS_PROP_LIST_STYLE_TYPE:
2006     {
2007         HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2008         if (!primitiveValue) return;
2009         if (primitiveValue->getIdent())
2010         {
2011             EListStyleType t;
2012             int id = primitiveValue->getIdent();
2013             if ( id == CSS_VAL_NONE) { // important!!
2014               t = LNONE;
2015             } else {
2016               t = EListStyleType(id - CSS_VAL_DISC);
2017             }
2018             style->setListStyleType(t);
2019         }
2020         return;
2021     }
2022
2023     case CSS_PROP_OVERFLOW:
2024     {
2025         HANDLE_INHERIT_AND_INITIAL(overflow, Overflow)
2026         if (!primitiveValue) return;
2027         EOverflow o;
2028         switch(primitiveValue->getIdent())
2029         {
2030         case CSS_VAL_VISIBLE:
2031             o = OVISIBLE; break;
2032         case CSS_VAL_HIDDEN:
2033             o = OHIDDEN; break;
2034         case CSS_VAL_SCROLL:
2035             o = OSCROLL; break;
2036         case CSS_VAL_AUTO:
2037             o = OAUTO; break;
2038         case CSS_VAL_MARQUEE:
2039             o = OMARQUEE; break;
2040         case CSS_VAL_OVERLAY:
2041             o = OOVERLAY; break;
2042         default:
2043             return;
2044         }
2045         style->setOverflow(o);
2046         return;
2047     }
2048
2049     case CSS_PROP_PAGE_BREAK_BEFORE:
2050     {
2051         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2052         if (!primitiveValue) return;
2053         switch (primitiveValue->getIdent()) {
2054             case CSS_VAL_AUTO:
2055                 style->setPageBreakBefore(PBAUTO);
2056                 break;
2057             case CSS_VAL_LEFT:
2058             case CSS_VAL_RIGHT:
2059             case CSS_VAL_ALWAYS:
2060                 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2061                 break;
2062             case CSS_VAL_AVOID:
2063                 style->setPageBreakBefore(PBAVOID);
2064                 break;
2065         }
2066         break;
2067     }
2068
2069     case CSS_PROP_PAGE_BREAK_AFTER:
2070     {
2071         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2072         if (!primitiveValue) return;
2073         switch (primitiveValue->getIdent()) {
2074             case CSS_VAL_AUTO:
2075                 style->setPageBreakAfter(PBAUTO);
2076                 break;
2077             case CSS_VAL_LEFT:
2078             case CSS_VAL_RIGHT:
2079             case CSS_VAL_ALWAYS:
2080                 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2081                 break;
2082             case CSS_VAL_AVOID:
2083                 style->setPageBreakAfter(PBAVOID);
2084                 break;
2085         }
2086         break;
2087     }
2088
2089     case CSS_PROP_PAGE_BREAK_INSIDE: {
2090         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2091         if (!primitiveValue) return;
2092         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
2093             style->setPageBreakInside(PBAUTO);
2094         else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
2095             style->setPageBreakInside(PBAVOID);
2096         return;
2097     }
2098         
2099     case CSS_PROP_PAGE:
2100         break; /* FIXME: Not even sure what this is...  -dwh */
2101
2102     case CSS_PROP_POSITION:
2103     {
2104         HANDLE_INHERIT_AND_INITIAL(position, Position)
2105         if(!primitiveValue) return;
2106         EPosition p;
2107         switch(primitiveValue->getIdent())
2108         {
2109         case CSS_VAL_STATIC:
2110             p = STATIC; break;
2111         case CSS_VAL_RELATIVE:
2112             p = RELATIVE; break;
2113         case CSS_VAL_ABSOLUTE:
2114             p = ABSOLUTE; break;
2115         case CSS_VAL_FIXED:
2116             {
2117                 if ( view )
2118                     view->useSlowRepaints();
2119                 p = FIXED;
2120                 break;
2121             }
2122         default:
2123             return;
2124         }
2125         style->setPosition(p);
2126         return;
2127     }
2128
2129     case CSS_PROP_TABLE_LAYOUT: {
2130         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2131
2132         if ( !primitiveValue->getIdent() )
2133             return;
2134
2135         ETableLayout l = RenderStyle::initialTableLayout();
2136         switch( primitiveValue->getIdent() ) {
2137             case CSS_VAL_FIXED:
2138                 l = TFIXED;
2139                 // fall through
2140             case CSS_VAL_AUTO:
2141                 style->setTableLayout( l );
2142             default:
2143                 break;
2144         }
2145         break;
2146     }
2147         
2148     case CSS_PROP_UNICODE_BIDI: {
2149         HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2150         switch (primitiveValue->getIdent()) {
2151             case CSS_VAL_NORMAL:
2152                 style->setUnicodeBidi(UBNormal); 
2153                 break;
2154             case CSS_VAL_EMBED:
2155                 style->setUnicodeBidi(Embed); 
2156                 break;
2157             case CSS_VAL_BIDI_OVERRIDE:
2158                 style->setUnicodeBidi(Override);
2159                 break;
2160             default:
2161                 return;
2162         }
2163         break;
2164     }
2165     case CSS_PROP_TEXT_TRANSFORM: {
2166         HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2167         
2168         if(!primitiveValue->getIdent()) return;
2169
2170         ETextTransform tt;
2171         switch(primitiveValue->getIdent()) {
2172         case CSS_VAL_CAPITALIZE:  tt = CAPITALIZE;  break;
2173         case CSS_VAL_UPPERCASE:   tt = UPPERCASE;   break;
2174         case CSS_VAL_LOWERCASE:   tt = LOWERCASE;   break;
2175         case CSS_VAL_NONE:
2176         default:                  tt = TTNONE;      break;
2177         }
2178         style->setTextTransform(tt);
2179         break;
2180         }
2181
2182     case CSS_PROP_VISIBILITY:
2183     {
2184         HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2185
2186         switch( primitiveValue->getIdent() ) {
2187         case CSS_VAL_HIDDEN:
2188             style->setVisibility( HIDDEN );
2189             break;
2190         case CSS_VAL_VISIBLE:
2191             style->setVisibility( VISIBLE );
2192             break;
2193         case CSS_VAL_COLLAPSE:
2194             style->setVisibility( COLLAPSE );
2195         default:
2196             break;
2197         }
2198         break;
2199     }
2200     case CSS_PROP_WHITE_SPACE:
2201         HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2202
2203         if(!primitiveValue->getIdent()) return;
2204
2205         EWhiteSpace s;
2206         switch(primitiveValue->getIdent()) {
2207         case CSS_VAL__KHTML_NOWRAP:
2208             s = KHTML_NOWRAP;
2209             break;
2210         case CSS_VAL_NOWRAP:
2211             s = NOWRAP;
2212             break;
2213         case CSS_VAL_PRE:
2214             s = PRE;
2215             break;
2216         case CSS_VAL_NORMAL:
2217         default:
2218             s = NORMAL;
2219             break;
2220         }
2221         style->setWhiteSpace(s);
2222         break;
2223
2224     case CSS_PROP_BACKGROUND_POSITION:
2225         if (isInherit) {
2226             style->setBackgroundXPosition(parentStyle->backgroundXPosition());
2227             style->setBackgroundYPosition(parentStyle->backgroundYPosition());
2228         }
2229         else if (isInitial) {
2230             style->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
2231             style->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
2232         }
2233         break;
2234     case CSS_PROP_BACKGROUND_POSITION_X: {
2235         HANDLE_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition)
2236         if(!primitiveValue) break;
2237         Length l;
2238         int type = primitiveValue->primitiveType();
2239         if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2240         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
2241         else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2242         l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2243         else
2244         return;
2245         style->setBackgroundXPosition(l);
2246         break;
2247     }
2248     case CSS_PROP_BACKGROUND_POSITION_Y: {
2249         HANDLE_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition)
2250         if(!primitiveValue) break;
2251         Length l;
2252         int type = primitiveValue->primitiveType();
2253         if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2254         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
2255         else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2256         l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2257         else
2258         return;
2259         style->setBackgroundYPosition(l);
2260         break;
2261     }
2262     case CSS_PROP_BORDER_SPACING: {
2263         if (isInherit) {
2264             style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing());
2265             style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing());
2266         }
2267         else if (isInitial) {
2268             style->setHorizontalBorderSpacing(0);
2269             style->setVerticalBorderSpacing(0);
2270         }
2271         break;
2272     }
2273     case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: {
2274         HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2275         if (!primitiveValue) break;
2276         short spacing =  primitiveValue->computeLength(style, paintDeviceMetrics);
2277         style->setHorizontalBorderSpacing(spacing);
2278         break;
2279     }
2280     case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: {
2281         HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2282         if (!primitiveValue) break;
2283         short spacing =  primitiveValue->computeLength(style, paintDeviceMetrics);
2284         style->setVerticalBorderSpacing(spacing);
2285         break;
2286     }
2287     case CSS_PROP_CURSOR:
2288         HANDLE_INHERIT_AND_INITIAL(cursor, Cursor)
2289         if (primitiveValue)
2290             style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) );
2291         break;        
2292 // colors || inherit
2293     case CSS_PROP_BACKGROUND_COLOR:
2294     case CSS_PROP_BORDER_TOP_COLOR:
2295     case CSS_PROP_BORDER_RIGHT_COLOR:
2296     case CSS_PROP_BORDER_BOTTOM_COLOR:
2297     case CSS_PROP_BORDER_LEFT_COLOR:
2298     case CSS_PROP_COLOR:
2299     case CSS_PROP_OUTLINE_COLOR:
2300         // this property is an extension used to get HTML4 <font> right.
2301 #if !APPLE_CHANGES
2302     case CSS_PROP_SCROLLBAR_FACE_COLOR:
2303     case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
2304     case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
2305     case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
2306     case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
2307     case CSS_PROP_SCROLLBAR_TRACK_COLOR:
2308     case CSS_PROP_SCROLLBAR_ARROW_COLOR:
2309 #endif
2310     {
2311         QColor col;
2312         if (isInherit) {
2313             HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
2314             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
2315             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
2316             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
2317             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
2318             HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
2319             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
2320             return;
2321         }
2322         else if (isInitial) {
2323             // The border/outline colors will just map to the invalid color |col| above.  This will have the
2324             // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2325             // not painting the background since the color won't be valid).
2326             if (id == CSS_PROP_COLOR)
2327                 col = RenderStyle::initialColor();
2328         }
2329         else {
2330             if(!primitiveValue)
2331                 return;
2332             col = getColorFromPrimitiveValue(primitiveValue);
2333         }
2334
2335         //kdDebug( 6080 ) << "applying color " << col.isValid() << endl;
2336         switch(id)
2337         {
2338         case CSS_PROP_BACKGROUND_COLOR:
2339             style->setBackgroundColor(col); break;
2340         case CSS_PROP_BORDER_TOP_COLOR:
2341             style->setBorderTopColor(col); break;
2342         case CSS_PROP_BORDER_RIGHT_COLOR:
2343             style->setBorderRightColor(col); break;
2344         case CSS_PROP_BORDER_BOTTOM_COLOR:
2345             style->setBorderBottomColor(col); break;
2346         case CSS_PROP_BORDER_LEFT_COLOR:
2347             style->setBorderLeftColor(col); break;
2348         case CSS_PROP_COLOR:
2349             style->setColor(col); break;
2350         case CSS_PROP_OUTLINE_COLOR:
2351             style->setOutlineColor(col); break;
2352 #if !APPLE_CHANGES
2353         case CSS_PROP_SCROLLBAR_FACE_COLOR:
2354             style->setPaletteColor(QPalette::Active, QColorGroup::Button, col);
2355             style->setPaletteColor(QPalette::Inactive, QColorGroup::Button, col);
2356             break;
2357         case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
2358             style->setPaletteColor(QPalette::Active, QColorGroup::Shadow, col);
2359             style->setPaletteColor(QPalette::Inactive, QColorGroup::Shadow, col);
2360             break;
2361         case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
2362             style->setPaletteColor(QPalette::Active, QColorGroup::Light, col);
2363             style->setPaletteColor(QPalette::Inactive, QColorGroup::Light, col);
2364             break;
2365         case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
2366             break;
2367         case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
2368             style->setPaletteColor(QPalette::Active, QColorGroup::Dark, col);
2369             style->setPaletteColor(QPalette::Inactive, QColorGroup::Dark, col);
2370             break;
2371         case CSS_PROP_SCROLLBAR_TRACK_COLOR:
2372             style->setPaletteColor(QPalette::Active, QColorGroup::Base, col);
2373             style->setPaletteColor(QPalette::Inactive, QColorGroup::Base, col);
2374             style->setPaletteColor(QPalette::Active, QColorGroup::Mid, col);
2375             style->setPaletteColor(QPalette::Inactive, QColorGroup::Mid, col);
2376             style->setPaletteColor(QPalette::Active, QColorGroup::Background, col);
2377             style->setPaletteColor(QPalette::Inactive, QColorGroup::Background, col);
2378             break;
2379         case CSS_PROP_SCROLLBAR_ARROW_COLOR:
2380             style->setPaletteColor(QPalette::Active, QColorGroup::ButtonText, col);
2381             style->setPaletteColor(QPalette::Inactive, QColorGroup::ButtonText, col);
2382             break;
2383 #endif
2384         default:
2385             return;
2386         }
2387         return;
2388     }
2389     break;
2390 // uri || inherit
2391     case CSS_PROP_BACKGROUND_IMAGE:
2392     {
2393         HANDLE_INHERIT_AND_INITIAL(backgroundImage, BackgroundImage)
2394         if (!primitiveValue) return;
2395         style->setBackgroundImage(static_cast<CSSImageValueImpl *>(primitiveValue)
2396                                   ->image(element->getDocument()->docLoader()));
2397         //kdDebug( 6080 ) << "setting image in style to " << image->image() << endl;
2398         break;
2399     }
2400     case CSS_PROP_LIST_STYLE_IMAGE:
2401     {
2402         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2403         if (!primitiveValue) return;
2404         style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)
2405                                  ->image(element->getDocument()->docLoader()));
2406         //kdDebug( 6080 ) << "setting image in list to " << image->image() << endl;
2407         break;
2408     }
2409
2410 // length
2411     case CSS_PROP_BORDER_TOP_WIDTH:
2412     case CSS_PROP_BORDER_RIGHT_WIDTH:
2413     case CSS_PROP_BORDER_BOTTOM_WIDTH:
2414     case CSS_PROP_BORDER_LEFT_WIDTH:
2415     case CSS_PROP_OUTLINE_WIDTH:
2416     {
2417         if (isInherit) {
2418             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
2419             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
2420             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
2421             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
2422             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
2423             return;
2424         }
2425         else if (isInitial) {
2426             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
2427             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
2428             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
2429             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
2430             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
2431             return;
2432         }
2433
2434         if(!primitiveValue) break;
2435         short width = 3;
2436         switch(primitiveValue->getIdent())
2437         {
2438         case CSS_VAL_THIN:
2439             width = 1;
2440             break;
2441         case CSS_VAL_MEDIUM:
2442             width = 3;
2443             break;
2444         case CSS_VAL_THICK:
2445             width = 5;
2446             break;
2447         case CSS_VAL_INVALID:
2448             width = primitiveValue->computeLength(style, paintDeviceMetrics);
2449             break;
2450         default:
2451             return;
2452         }
2453
2454         if(width < 0) return;
2455         switch(id)
2456         {
2457         case CSS_PROP_BORDER_TOP_WIDTH:
2458             style->setBorderTopWidth(width);
2459             break;
2460         case CSS_PROP_BORDER_RIGHT_WIDTH:
2461             style->setBorderRightWidth(width);
2462             break;
2463         case CSS_PROP_BORDER_BOTTOM_WIDTH:
2464             style->setBorderBottomWidth(width);
2465             break;
2466         case CSS_PROP_BORDER_LEFT_WIDTH:
2467             style->setBorderLeftWidth(width);
2468             break;
2469         case CSS_PROP_OUTLINE_WIDTH:
2470             style->setOutlineWidth(width);
2471             break;
2472         default:
2473             return;
2474         }
2475         return;
2476     }
2477
2478     case CSS_PROP_LETTER_SPACING:
2479     case CSS_PROP_WORD_SPACING:
2480     {
2481         
2482         if (isInherit) {
2483             HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
2484             HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
2485             return;
2486         }
2487         else if (isInitial) {
2488             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
2489             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
2490             return;
2491         }
2492         
2493         int width = 0;
2494         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){
2495             width = 0;
2496         } else {
2497             if(!primitiveValue) return;
2498             width = primitiveValue->computeLength(style, paintDeviceMetrics);
2499         }
2500         switch(id)
2501         {
2502         case CSS_PROP_LETTER_SPACING:
2503             style->setLetterSpacing(width);
2504             break;
2505         case CSS_PROP_WORD_SPACING:
2506             style->setWordSpacing(width);
2507             break;
2508             // ### needs the definitions in renderstyle
2509         default: break;
2510         }
2511         return;
2512     }
2513
2514         // length, percent
2515     case CSS_PROP_MAX_WIDTH:
2516         // +none +inherit
2517         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2518             apply = true;
2519     case CSS_PROP_TOP:
2520     case CSS_PROP_LEFT:
2521     case CSS_PROP_RIGHT:
2522     case CSS_PROP_BOTTOM:
2523     case CSS_PROP_WIDTH:
2524     case CSS_PROP_MIN_WIDTH:
2525     case CSS_PROP_MARGIN_TOP:
2526     case CSS_PROP_MARGIN_RIGHT:
2527     case CSS_PROP_MARGIN_BOTTOM:
2528     case CSS_PROP_MARGIN_LEFT:
2529         // +inherit +auto
2530         if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) {
2531             if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2532                 l = Length(Intrinsic);
2533                 apply = true;
2534             }
2535             else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2536                 l = Length(MinIntrinsic);
2537                 apply = true;
2538             }
2539         }
2540         if (id != CSS_PROP_MAX_WIDTH && primitiveValue &&
2541            primitiveValue->getIdent() == CSS_VAL_AUTO)
2542         {
2543             //kdDebug( 6080 ) << "found value=auto" << endl;
2544             apply = true;
2545         }
2546     case CSS_PROP_PADDING_TOP:
2547     case CSS_PROP_PADDING_RIGHT:
2548     case CSS_PROP_PADDING_BOTTOM:
2549     case CSS_PROP_PADDING_LEFT:
2550     case CSS_PROP_TEXT_INDENT:
2551         // +inherit
2552     {
2553         if (isInherit) {
2554             HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
2555             HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
2556             HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
2557             HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
2558             HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
2559             HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
2560             HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
2561             HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
2562             HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
2563             HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
2564             HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
2565             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
2566             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
2567             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
2568             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
2569             HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
2570             return;
2571         }
2572         else if (isInitial) {
2573             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
2574             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
2575             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
2576             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
2577             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
2578             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
2579             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
2580             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
2581             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
2582             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
2583             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
2584             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
2585             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
2586             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
2587             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
2588             HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
2589             return;
2590         } 
2591
2592         if (primitiveValue && !apply) {
2593             int type = primitiveValue->primitiveType();
2594             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2595                 // Handle our quirky margin units if we have them.
2596                 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed, 
2597                            primitiveValue->isQuirkValue());
2598             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2599                 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2600             else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
2601                 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
2602             else
2603                 return;
2604             if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT ||
2605                 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM)
2606                 // Padding can't be negative
2607                 apply = !((l.isFixed() || l.isPercent()) && l.width(100) < 0);
2608             else
2609                 apply = true;
2610         }
2611         if(!apply) return;
2612         switch(id)
2613             {
2614             case CSS_PROP_MAX_WIDTH:
2615                 style->setMaxWidth(l); break;
2616             case CSS_PROP_BOTTOM:
2617                 style->setBottom(l); break;
2618             case CSS_PROP_TOP:
2619                 style->setTop(l); break;
2620             case CSS_PROP_LEFT:
2621                 style->setLeft(l); break;
2622             case CSS_PROP_RIGHT:
2623                 style->setRight(l); break;
2624             case CSS_PROP_WIDTH:
2625                 style->setWidth(l); break;
2626             case CSS_PROP_MIN_WIDTH:
2627                 style->setMinWidth(l); break;
2628             case CSS_PROP_PADDING_TOP:
2629                 style->setPaddingTop(l); break;
2630             case CSS_PROP_PADDING_RIGHT:
2631                 style->setPaddingRight(l); break;
2632             case CSS_PROP_PADDING_BOTTOM:
2633                 style->setPaddingBottom(l); break;
2634             case CSS_PROP_PADDING_LEFT:
2635                 style->setPaddingLeft(l); break;
2636             case CSS_PROP_MARGIN_TOP:
2637                 style->setMarginTop(l); break;
2638             case CSS_PROP_MARGIN_RIGHT:
2639                 style->setMarginRight(l); break;
2640             case CSS_PROP_MARGIN_BOTTOM:
2641                 style->setMarginBottom(l); break;
2642             case CSS_PROP_MARGIN_LEFT:
2643                 style->setMarginLeft(l); break;
2644             case CSS_PROP_TEXT_INDENT:
2645                 style->setTextIndent(l); break;
2646             default: break;
2647             }
2648         return;
2649     }
2650
2651     case CSS_PROP_MAX_HEIGHT:
2652         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2653             apply = true;
2654     case CSS_PROP_HEIGHT:
2655     case CSS_PROP_MIN_HEIGHT:
2656         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2657             l = Length(Intrinsic);
2658             apply = true;
2659         }
2660         else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2661             l = Length(MinIntrinsic);
2662             apply = true;
2663         }
2664         if(id != CSS_PROP_MAX_HEIGHT && primitiveValue &&
2665            primitiveValue->getIdent() == CSS_VAL_AUTO)
2666             apply = true;
2667         if (isInherit) {
2668             HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
2669             HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
2670             HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
2671             return;
2672         }
2673         else if (isInitial) {
2674             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
2675             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
2676             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
2677             return;
2678         }
2679
2680         if (primitiveValue && !apply)
2681         {
2682             int type = primitiveValue->primitiveType();
2683             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2684                 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
2685             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2686             {
2687                 // ### compute from parents height!!!
2688                 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2689             }
2690             else
2691                 return;
2692             apply = true;
2693         }
2694         if(!apply) return;
2695         switch(id)
2696         {
2697         case CSS_PROP_MAX_HEIGHT:
2698             style->setMaxHeight(l); break;
2699         case CSS_PROP_HEIGHT:
2700             style->setHeight(l); break;
2701         case CSS_PROP_MIN_HEIGHT:
2702             style->setMinHeight(l); break;
2703         default:
2704             return;
2705         }
2706         return;
2707
2708         break;
2709
2710     case CSS_PROP_VERTICAL_ALIGN:
2711         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2712         if (!primitiveValue) return;
2713         if (primitiveValue->getIdent()) {
2714           khtml::EVerticalAlign align;
2715
2716           switch(primitiveValue->getIdent())
2717             {
2718                 case CSS_VAL_TOP:
2719                     align = TOP; break;
2720                 case CSS_VAL_BOTTOM:
2721                     align = BOTTOM; break;
2722                 case CSS_VAL_MIDDLE:
2723                     align = MIDDLE; break;
2724                 case CSS_VAL_BASELINE:
2725                     align = BASELINE; break;
2726                 case CSS_VAL_TEXT_BOTTOM:
2727                     align = TEXT_BOTTOM; break;
2728                 case CSS_VAL_TEXT_TOP:
2729                     align = TEXT_TOP; break;
2730                 case CSS_VAL_SUB:
2731                     align = SUB; break;
2732                 case CSS_VAL_SUPER:
2733                     align = SUPER; break;
2734                 case CSS_VAL__KHTML_BASELINE_MIDDLE:
2735                     align = BASELINE_MIDDLE; break;
2736                 default:
2737                     return;
2738             }
2739           style->setVerticalAlign(align);
2740           return;
2741         } else {
2742           int type = primitiveValue->primitiveType();
2743           Length l;
2744           if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2745             l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
2746           else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2747             l = Length( int( primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent );
2748
2749           style->setVerticalAlign( LENGTH );
2750           style->setVerticalAlignLength( l );
2751         }
2752         break;
2753
2754     case CSS_PROP_FONT_SIZE:
2755     {
2756         FontDef fontDef = style->htmlFont().fontDef;
2757         float oldSize = 0;
2758         float size = 0;
2759         
2760         bool parentIsAbsoluteSize = false;
2761         if (parentNode) {
2762             oldSize = parentStyle->htmlFont().fontDef.specifiedSize;
2763             parentIsAbsoluteSize = parentStyle->htmlFont().fontDef.isAbsoluteSize;
2764         }
2765
2766         if (isInherit)
2767             size = oldSize;
2768         else if (isInitial)
2769             size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks());
2770         else if (primitiveValue->getIdent()) {
2771             // Keywords are being used.
2772             switch (primitiveValue->getIdent()) {
2773             case CSS_VAL_XX_SMALL:
2774             case CSS_VAL_X_SMALL:
2775             case CSS_VAL_SMALL:
2776             case CSS_VAL_MEDIUM:
2777             case CSS_VAL_LARGE:
2778             case CSS_VAL_X_LARGE:
2779             case CSS_VAL_XX_LARGE:
2780             case CSS_VAL__KHTML_XXX_LARGE:
2781                 size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks());
2782                 break;
2783             case CSS_VAL_LARGER:
2784                 size = largerFontSize(oldSize, style->htmlHacks());
2785                 break;
2786             case CSS_VAL_SMALLER:
2787                 size = smallerFontSize(oldSize, style->htmlHacks());
2788                 break;
2789             default:
2790                 return;
2791             }
2792
2793             fontDef.isAbsoluteSize = parentIsAbsoluteSize && 
2794                                     (primitiveValue->getIdent() == CSS_VAL_LARGER ||
2795                                      primitiveValue->getIdent() == CSS_VAL_SMALLER);
2796         } else {
2797             int type = primitiveValue->primitiveType();
2798             fontDef.isAbsoluteSize = parentIsAbsoluteSize ||
2799                                           (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
2800                                            type != CSSPrimitiveValue::CSS_EMS && 
2801                                            type != CSSPrimitiveValue::CSS_EXS);
2802             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2803                 size = primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics, false);
2804             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2805                 size = (primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)
2806                         * oldSize) / 100;
2807             else
2808                 return;
2809         }
2810
2811         if (size <= 0) return;
2812
2813         //kdDebug( 6080 ) << "computed raw font size: " << size << endl;
2814
2815         setFontSize(fontDef, size);
2816         if (style->setFontDef( fontDef ))
2817             fontDirty = true;
2818         return;
2819     }
2820         break;
2821     case CSS_PROP_Z_INDEX:
2822     {
2823         HANDLE_INHERIT(zIndex, ZIndex)
2824         else if (isInitial) {
2825             style->setHasAutoZIndex();
2826             return;
2827         }
2828         
2829         if (!primitiveValue)
2830             return;
2831
2832         if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
2833             style->setHasAutoZIndex();
2834             return;
2835         }
2836         
2837         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2838             return; // Error case.
2839         
2840         style->setZIndex((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2841         
2842         return;
2843     }
2844         
2845     case CSS_PROP_WIDOWS:
2846     {
2847         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
2848         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2849             return;
2850         style->setWidows((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2851         break;
2852     }
2853         
2854     case CSS_PROP_ORPHANS:
2855     {
2856         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
2857         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2858             return;
2859         style->setOrphans((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2860         break;
2861     }        
2862
2863 // length, percent, number
2864     case CSS_PROP_LINE_HEIGHT:
2865     {
2866         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
2867         if(!primitiveValue) return;
2868         Length lineHeight;
2869         int type = primitiveValue->primitiveType();
2870         if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
2871             lineHeight = Length( -100, Percent );
2872         else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
2873             double multiplier = 1.0;
2874             // Scale for the font zoom factor only for types other than "em" and "ex", since those are
2875             // already based on the font size.
2876             if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->part()) {
2877                 multiplier = view->part()->zoomFactor() / 100.0;
2878             }
2879             lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics, multiplier), Fixed);
2880         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2881             lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed );
2882         else if (type == CSSPrimitiveValue::CSS_NUMBER)
2883             lineHeight = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
2884         else
2885             return;
2886         style->setLineHeight(lineHeight);
2887         return;
2888     }
2889
2890 // string
2891     case CSS_PROP_TEXT_ALIGN:
2892     {
2893         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
2894         if (!primitiveValue) return;
2895         if (primitiveValue->getIdent())
2896             style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) );
2897         return;
2898     }
2899
2900 // rect
2901     case CSS_PROP_CLIP:
2902     {
2903         Length top;
2904         Length right;
2905         Length bottom;
2906         Length left;
2907         bool hasClip = true;
2908         if (isInherit) {
2909             if (parentStyle->hasClip()) {
2910                 top = parentStyle->clipTop();
2911                 right = parentStyle->clipRight();
2912                 bottom = parentStyle->clipBottom();
2913                 left = parentStyle->clipLeft();
2914             }
2915             else {
2916                 hasClip = false;
2917                 top = right = bottom = left = Length();
2918             }
2919         } else if (isInitial) {
2920             hasClip = false;
2921             top = right = bottom = left = Length();
2922         } else if ( !primitiveValue ) {
2923             break;
2924         } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT ) {
2925             RectImpl *rect = primitiveValue->getRectValue();
2926             if ( !rect )
2927                 break;
2928             top = convertToLength( rect->top(), style, paintDeviceMetrics );
2929             right = convertToLength( rect->right(), style, paintDeviceMetrics );
2930             bottom = convertToLength( rect->bottom(), style, paintDeviceMetrics );
2931             left = convertToLength( rect->left(), style, paintDeviceMetrics );
2932
2933         } else if ( primitiveValue->getIdent() != CSS_VAL_AUTO ) {
2934             break;
2935         }
2936 //      qDebug("setting clip top to %d", top.value );
2937 //      qDebug("setting clip right to %d", right.value );
2938 //      qDebug("setting clip bottom to %d", bottom.value );
2939 //      qDebug("setting clip left to %d", left.value );
2940         style->setClip(top, right, bottom, left);
2941         style->setHasClip(hasClip);
2942     
2943         // rect, ident
2944         break;
2945     }
2946
2947 // lists
2948     case CSS_PROP_CONTENT:
2949         // list of string, uri, counter, attr, i
2950     {
2951         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
2952         // note is a reminder that eventually "inherit" needs to be supported.
2953         if (!(style->styleType()==RenderStyle::BEFORE ||
2954                 style->styleType()==RenderStyle::AFTER))
2955             break;
2956
2957         if (isInitial) {
2958             if (style->contentData())
2959                 style->contentData()->clearContent();
2960             return;
2961         }
2962         
2963         if(!value->isValueList()) return;
2964         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
2965         int len = list->length();
2966
2967         for(int i = 0; i < len; i++) {
2968             CSSValueImpl *item = list->item(i);
2969             if(!item->isPrimitiveValue()) continue;
2970             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
2971             if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
2972             {
2973                 style->setContent(val->getStringValue(), i != 0);
2974             }
2975             else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR)
2976             {
2977                 // FIXME: Should work with generic XML attributes also, and not
2978                 // just the hardcoded HTML set.  Can a namespace be specified for
2979                 // an attr(foo)?
2980                 int attrID = element->getDocument()->attrId(0, val->getStringValue(), false);
2981                 if (attrID)
2982                     style->setContent(element->getAttribute(attrID).implementation(), i != 0);
2983             }
2984             else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI)
2985             {
2986                 CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val);
2987                 style->setContent(image->image(element->getDocument()->docLoader()), i != 0);
2988             }
2989
2990         }
2991         break;
2992     }
2993
2994     case CSS_PROP_COUNTER_INCREMENT:
2995         // list of CSS2CounterIncrement
2996     case CSS_PROP_COUNTER_RESET:
2997         // list of CSS2CounterReset
2998         break;
2999     case CSS_PROP_FONT_FAMILY:
3000         // list of strings and ids
3001     {
3002         if (isInherit) {
3003             FontDef parentFontDef = parentStyle->htmlFont().fontDef;
3004             FontDef fontDef = style->htmlFont().fontDef;
3005             fontDef.genericFamily = parentFontDef.genericFamily;
3006             fontDef.family = parentFontDef.family;
3007             if (style->setFontDef(fontDef))
3008                 fontDirty = true;
3009             return;
3010         }
3011         else if (isInitial) {
3012             FontDef fontDef = style->htmlFont().fontDef;
3013             FontDef initialDef = FontDef();
3014             fontDef.genericFamily = initialDef.genericFamily;
3015             fontDef.family = initialDef.firstFamily();
3016             if (style->setFontDef(fontDef))
3017                 fontDirty = true;
3018             return;
3019         }
3020         
3021         if (!value->isValueList()) return;
3022         FontDef fontDef = style->htmlFont().fontDef;
3023         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3024         int len = list->length();
3025         KWQFontFamily &firstFamily = fontDef.firstFamily();
3026         KWQFontFamily *currFamily = 0;
3027         
3028         for(int i = 0; i < len; i++) {
3029             CSSValueImpl *item = list->item(i);
3030             if(!item->isPrimitiveValue()) continue;
3031             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
3032             QString face;
3033             if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING )
3034                 face = static_cast<FontFamilyValueImpl *>(val)->fontName();
3035             else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3036                 switch (val->getIdent()) {
3037                     case CSS_VAL__KHTML_BODY:
3038                         face = settings->stdFontName();
3039                         break;
3040                     case CSS_VAL_SERIF:
3041                         face = settings->serifFontName();
3042                         fontDef.setGenericFamily(FontDef::eSerif);
3043                         break;
3044                     case CSS_VAL_SANS_SERIF:
3045                         face = settings->sansSerifFontName();
3046                         fontDef.setGenericFamily(FontDef::eSansSerif);
3047                         break;
3048                     case CSS_VAL_CURSIVE:
3049                         face = settings->cursiveFontName();
3050                         fontDef.setGenericFamily(FontDef::eCursive);
3051                         break;
3052                     case CSS_VAL_FANTASY:
3053                         face = settings->fantasyFontName();
3054                         fontDef.setGenericFamily(FontDef::eFantasy);
3055                         break;
3056                     case CSS_VAL_MONOSPACE:
3057                         face = settings->fixedFontName();
3058                         fontDef.setGenericFamily(FontDef::eMonospace);
3059                         break;
3060                 }
3061             }
3062     
3063             if ( !face.isEmpty() ) {
3064                 if (!currFamily) {
3065                     // Filling in the first family.
3066                     firstFamily.setFamily(face);
3067                     currFamily = &firstFamily;
3068                 }
3069                 else {
3070                     KWQFontFamily *newFamily = new KWQFontFamily;
3071                     newFamily->setFamily(face);
3072                     currFamily->appendFamily(newFamily);
3073                     currFamily = newFamily;
3074                 }
3075                 
3076                 if (style->setFontDef( fontDef )) {
3077                     fontDirty = true;
3078                 }
3079             }
3080         }
3081       break;
3082     }
3083     case CSS_PROP_QUOTES:
3084         // list of strings or i
3085     case CSS_PROP_SIZE:
3086         // ### look up
3087       break;
3088     case CSS_PROP_TEXT_DECORATION: {
3089         // list of ident
3090         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3091         int t = RenderStyle::initialTextDecoration();
3092         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3093             // do nothing
3094         } else {
3095             if(!value->isValueList()) return;
3096             CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3097             int len = list->length();
3098             for(int i = 0; i < len; i++)
3099             {
3100                 CSSValueImpl *item = list->item(i);
3101                 if(!item->isPrimitiveValue()) continue;
3102                 primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item);
3103                 switch(primitiveValue->getIdent())
3104                 {
3105                     case CSS_VAL_NONE:
3106                         t = TDNONE; break;
3107                     case CSS_VAL_UNDERLINE:
3108                         t |= UNDERLINE; break;
3109                     case CSS_VAL_OVERLINE:
3110                         t |= OVERLINE; break;
3111                     case CSS_VAL_LINE_THROUGH:
3112                         t |= LINE_THROUGH; break;
3113                     case CSS_VAL_BLINK:
3114                         t |= BLINK; break;
3115                     default:
3116                         return;
3117                 }
3118             }
3119         }
3120
3121         style->setTextDecoration(t);
3122         break;
3123     }
3124
3125 // shorthand properties
3126     case CSS_PROP_BACKGROUND:
3127         if (isInherit) {
3128             style->setBackgroundColor(parentStyle->backgroundColor());
3129             style->setBackgroundImage(parentStyle->backgroundImage());
3130             style->setBackgroundRepeat(parentStyle->backgroundRepeat());
3131             style->setBackgroundAttachment(parentStyle->backgroundAttachment());
3132             style->setBackgroundXPosition(parentStyle->backgroundXPosition());
3133             style->setBackgroundYPosition(parentStyle->backgroundYPosition());
3134         }
3135         else if (isInitial) {
3136             style->setBackgroundColor(QColor());
3137             style->setBackgroundImage(RenderStyle::initialBackgroundImage());
3138             style->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat());
3139             style->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment());
3140             style->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
3141             style->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
3142         }
3143         break;
3144     case CSS_PROP_BORDER:
3145     case CSS_PROP_BORDER_STYLE:
3146     case CSS_PROP_BORDER_WIDTH:
3147     case CSS_PROP_BORDER_COLOR:
3148         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
3149         {
3150             if (isInherit) {
3151                 style->setBorderTopColor(parentStyle->borderTopColor());
3152                 style->setBorderBottomColor(parentStyle->borderBottomColor());
3153                 style->setBorderLeftColor(parentStyle->borderLeftColor());
3154                 style->setBorderRightColor(parentStyle->borderRightColor());
3155             }
3156             else if (isInitial) {
3157                 style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead.
3158                 style->setBorderBottomColor(QColor());
3159                 style->setBorderLeftColor(QColor());
3160                 style->setBorderRightColor(QColor());
3161             }
3162         }
3163         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
3164         {
3165             if (isInherit) {
3166                 style->setBorderTopStyle(parentStyle->borderTopStyle());
3167                 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
3168                 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
3169                 style->setBorderRightStyle(parentStyle->borderRightStyle());
3170             }
3171             else if (isInitial) {
3172                 style->setBorderTopStyle(RenderStyle::initialBorderStyle());
3173                 style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
3174                 style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
3175                 style->setBorderRightStyle(RenderStyle::initialBorderStyle());
3176             }
3177         }
3178         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH)
3179         {
3180             if (isInherit) {
3181                 style->setBorderTopWidth(parentStyle->borderTopWidth());
3182                 style->setBorderBottomWidth(parentStyle->borderBottomWidth());
3183                 style->setBorderLeftWidth(parentStyle->borderLeftWidth());
3184                 style->setBorderRightWidth(parentStyle->borderRightWidth());
3185             }
3186             else if (isInitial) {
3187                 style->setBorderTopWidth(RenderStyle::initialBorderWidth());
3188                 style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
3189                 style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
3190                 style->setBorderRightWidth(RenderStyle::initialBorderWidth());
3191             }
3192         }
3193         return;
3194     case CSS_PROP_BORDER_TOP:
3195         if (isInherit) {
3196             style->setBorderTopColor(parentStyle->borderTopColor());
3197             style->setBorderTopStyle(parentStyle->borderTopStyle());
3198             style->setBorderTopWidth(parentStyle->borderTopWidth());
3199         }
3200         else if (isInitial)
3201             style->resetBorderTop();
3202         return;
3203     case CSS_PROP_BORDER_RIGHT:
3204         if (isInherit) {
3205             style->setBorderRightColor(parentStyle->borderRightColor());
3206             style->setBorderRightStyle(parentStyle->borderRightStyle());
3207             style->setBorderRightWidth(parentStyle->borderRightWidth());
3208         }
3209         else if (isInitial)
3210             style->resetBorderRight();
3211         return;
3212     case CSS_PROP_BORDER_BOTTOM:
3213         if (isInherit) {
3214             style->setBorderBottomColor(parentStyle->borderBottomColor());
3215             style->setBorderBottomStyle(parentStyle->borderBottomStyle());
3216             style->setBorderBottomWidth(parentStyle->borderBottomWidth());
3217         }
3218         else if (isInitial)
3219             style->resetBorderBottom();
3220         return;
3221     case CSS_PROP_BORDER_LEFT:
3222         if (isInherit) {
3223             style->setBorderLeftColor(parentStyle->borderLeftColor());