File indexing completed on 2024-04-21 11:29:32

0001 /**
0002  * This file is part of the CSS implementation for KDE.
0003  *
0004  * Copyright 1999-2003 Lars Knoll (knoll@kde.org)
0005  * Copyright 2003-2004 Apple Computer, Inc.
0006  * Copyright 2004-2010 Allan Sandfeld Jensen (kde@carewolf.com)
0007  * Copyright 2004-2008 Germain Garand (germain@ebooksfrance.org)
0008  * Copyright 2008 Vyacheslav Tokarev (tsjoker@gmail.com)
0009  *           (C) 2005, 2006, 2008 Apple Computer, Inc.
0010  *
0011  * This library is free software; you can redistribute it and/or
0012  * modify it under the terms of the GNU Library General Public
0013  * License as published by the Free Software Foundation; either
0014  * version 2 of the License, or (at your option) any later version.
0015  *
0016  * This library is distributed in the hope that it will be useful,
0017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019  * Library General Public License for more details.
0020  *
0021  * You should have received a copy of the GNU Library General Public License
0022  * along with this library; see the file COPYING.LIB.  If not, write to
0023  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0024  * Boston, MA 02110-1301, USA.
0025  */
0026 
0027 #include "css/cssstyleselector.h"
0028 #include "css/css_stylesheetimpl.h"
0029 #include "css/css_ruleimpl.h"
0030 #include "css/css_valueimpl.h"
0031 #include "css/csshelper.h"
0032 #include "css/css_webfont.h"
0033 #include "rendering/render_object.h"
0034 #include "html/html_documentimpl.h"
0035 #include "html/html_elementimpl.h"
0036 #include "xml/dom_elementimpl.h"
0037 #include "xml/dom_restyler.h"
0038 #include "dom/css_rule.h"
0039 #include "dom/css_value.h"
0040 #include "khtml_global.h"
0041 #include "khtmlpart_p.h"
0042 using namespace khtml;
0043 using namespace DOM;
0044 
0045 #include "css/cssproperties.h"
0046 #include "css/cssvalues.h"
0047 
0048 #include "misc/khtmllayout.h"
0049 #include "khtml_settings.h"
0050 #include "misc/helper.h"
0051 #include "misc/loader.h"
0052 
0053 #include "rendering/font.h"
0054 
0055 #include "khtmlview.h"
0056 #include "khtml_part.h"
0057 
0058 #include <kconfig.h>
0059 #include <QFile>
0060 #include <QString>
0061 #include <QFileInfo>
0062 #include <QUrl>
0063 #include <QFontDatabase>
0064 #include <qstandardpaths.h>
0065 
0066 #include "khtml_debug.h"
0067 #include <assert.h>
0068 #include <stdlib.h>
0069 
0070 // keep in sync with html4.css'
0071 #define KHTML_STYLE_VERSION 1
0072 
0073 #undef PRELATIVE
0074 #undef PABSOLUTE
0075 
0076 // handle value "inherit" on a default inherited property
0077 #define HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \
0078     if (isInherit) \
0079     {\
0080         style->set##Prop(parentStyle->prop());\
0081         return;\
0082     }
0083 
0084 // handle value "inherit" on a default non-inherited property
0085 #define HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \
0086     if (isInherit) \
0087     {\
0088         style->setInheritedNoninherited(true);\
0089         style->set##Prop(parentStyle->prop());\
0090         return;\
0091     }
0092 
0093 #define HANDLE_INITIAL(prop, Prop) \
0094     if (isInitial) \
0095     {\
0096         style->set##Prop(RenderStyle::initial##Prop());\
0097         return;\
0098     }
0099 
0100 #define HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \
0101     HANDLE_INITIAL(prop, Prop) \
0102     else \
0103         HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop)
0104 
0105 #define HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \
0106     HANDLE_INITIAL(prop, Prop) \
0107     else \
0108         HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop)
0109 
0110 // all non-inherited properties
0111 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
0112     HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \
0113     else if (isInitial) \
0114     {\
0115         style->set##Prop(RenderStyle::initial##Value());\
0116         return;\
0117     }
0118 
0119 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
0120     if (isInherit) { \
0121         style->setInheritedNoninherited(true); \
0122         BackgroundLayer* currChild = style->accessBackgroundLayers(); \
0123         BackgroundLayer* prevChild = nullptr; \
0124         const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \
0125         while (currParent && currParent->is##Prop##Set()) { \
0126             if (!currChild) { \
0127                 /* Need to make a new layer.*/ \
0128                 currChild = new BackgroundLayer(); \
0129                 prevChild->setNext(currChild); \
0130             } \
0131             currChild->set##Prop(currParent->prop()); \
0132             prevChild = currChild; \
0133             currChild = prevChild->next(); \
0134             currParent = currParent->next(); \
0135         } \
0136         \
0137         while (currChild) { \
0138             /* Reset any remaining layers to not have the property set. */ \
0139             currChild->clear##Prop(); \
0140             currChild = currChild->next(); \
0141         } \
0142     } else if (isInitial) { \
0143         BackgroundLayer* currChild = style->accessBackgroundLayers(); \
0144         currChild->set##Prop(RenderStyle::initial##Prop()); \
0145         for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
0146             currChild->clear##Prop(); \
0147     }
0148 
0149 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \
0150         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
0151         else { \
0152             if (!value->isPrimitiveValue() && !value->isValueList()) \
0153                 return; \
0154             BackgroundLayer* currChild = style->accessBackgroundLayers(); \
0155             BackgroundLayer* prevChild = nullptr; \
0156             if (value->isPrimitiveValue()) { \
0157                 map##Prop(currChild, value); \
0158                 currChild = currChild->next(); \
0159             } \
0160             else { \
0161                 /* Walk each value and put it into a layer, creating new layers as needed. */ \
0162                 CSSValueListImpl* valueList = static_cast<CSSValueListImpl*>(value); \
0163                 for (unsigned int i = 0; i < valueList->length(); i++) { \
0164                     if (!currChild) { \
0165                         /* Need to make a new layer to hold this value */ \
0166                         currChild = new BackgroundLayer(); \
0167                         prevChild->setNext(currChild); \
0168                     } \
0169                     map##Prop(currChild, valueList->item(i)); \
0170                     prevChild = currChild; \
0171                     currChild = currChild->next(); \
0172                 } \
0173             } \
0174             while (currChild) { \
0175                 /* Reset all remaining layers to not have the property set. */ \
0176                 currChild->clear##Prop(); \
0177                 currChild = currChild->next(); \
0178             } \
0179         } }
0180 
0181 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
0182     if (id == propID) \
0183     {\
0184         style->set##Prop(parentStyle->prop());\
0185         return;\
0186     }
0187 
0188 #define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
0189     if (id == propID) { \
0190         if (parentStyle->prop().isValid()) \
0191             style->set##Prop(parentStyle->prop()); \
0192         else \
0193             style->set##Prop(parentStyle->propAlt()); \
0194         return; \
0195     }
0196 
0197 #define HANDLE_INITIAL_COND(propID, Prop) \
0198     if (id == propID) \
0199     {\
0200         style->set##Prop(RenderStyle::initial##Prop());\
0201         return;\
0202     }
0203 
0204 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
0205     if (id == propID) \
0206     {\
0207         style->set##Prop(RenderStyle::initial##Value());\
0208         return;\
0209     }
0210 
0211 namespace khtml
0212 {
0213 
0214 CSSStyleSelectorList *CSSStyleSelector::s_defaultStyle;
0215 CSSStyleSelectorList *CSSStyleSelector::s_defaultQuirksStyle;
0216 CSSStyleSelectorList *CSSStyleSelector::s_defaultNonCSSHintsStyle;
0217 CSSStyleSelectorList *CSSStyleSelector::s_defaultPrintStyle;
0218 CSSStyleSheetImpl *CSSStyleSelector::s_defaultSheet;
0219 CSSStyleSheetImpl *CSSStyleSelector::s_defaultNonCSSHintsSheet;
0220 RenderStyle *CSSStyleSelector::styleNotYetAvailable;
0221 CSSStyleSheetImpl *CSSStyleSelector::s_quirksSheet;
0222 
0223 enum PseudoState { PseudoUnknown, PseudoNone, PseudoLink, PseudoVisited};
0224 static PseudoState pseudoState;
0225 
0226 CSSStyleSelector::CSSStyleSelector(DocumentImpl *doc, QString userStyleSheet, StyleSheetListImpl *styleSheets,
0227                                    const QUrl &url, bool _strictParsing)
0228 {
0229     KHTMLView *view = doc->view();
0230     KHTMLPart *part = doc->part();
0231 
0232     m_fontSelector = new CSSFontSelector(doc);
0233 
0234     init(part ? part->settings() : nullptr, doc);
0235 
0236     strictParsing = _strictParsing;
0237 
0238     selectors = nullptr;
0239     selectorCache = nullptr;
0240     propertiesBuffer = nullptr;
0241     nextPropertyIndexes = nullptr;
0242     userStyle = nullptr;
0243     userSheet = nullptr;
0244     logicalDpiY = doc->logicalDpiY();
0245 
0246     if (logicalDpiY) { // this may be null, not everyone uses khtmlview (Niko)
0247         computeFontSizes(logicalDpiY, part ? part->fontScaleFactor() : 100);
0248     }
0249 
0250     // build a limited default style suitable to evaluation of media queries
0251     // containing relative constraints, like "screen and (max-width: 10em)"
0252     setupDefaultRootStyle(doc);
0253 
0254     if (view) {
0255         m_medium = new MediaQueryEvaluator(view->mediaType(), view->part(), m_rootDefaultStyle);
0256     } else {
0257         m_medium = new MediaQueryEvaluator("all", nullptr, m_rootDefaultStyle);
0258     }
0259 
0260     if (!userStyleSheet.isEmpty()) {
0261         userSheet = new DOM::CSSStyleSheetImpl(doc);
0262         userSheet->parseString(DOMString(userStyleSheet));
0263 
0264         userStyle = new CSSStyleSelectorList();
0265         userStyle->append(userSheet, m_medium, this);
0266     }
0267 
0268     // add stylesheets from document
0269     authorStyle = nullptr;
0270     implicitStyle = nullptr;
0271 
0272     foreach (StyleSheetImpl *sh, styleSheets->styleSheets) {
0273         if (sh->isCSSStyleSheet()) {
0274             if (static_cast<CSSStyleSheetImpl *>(sh)->implicit()) {
0275                 if (!implicitStyle) {
0276                     implicitStyle = new CSSStyleSelectorList();
0277                 }
0278                 implicitStyle->append(static_cast<CSSStyleSheetImpl *>(sh), m_medium, this);
0279             } else if (sh->isCSSStyleSheet() && !sh->disabled()) {
0280                 if (!authorStyle) {
0281                     authorStyle = new CSSStyleSelectorList();
0282                 }
0283                 authorStyle->append(static_cast<CSSStyleSheetImpl *>(sh), m_medium, this);
0284             }
0285         }
0286     }
0287 
0288     buildLists();
0289 
0290     //qCDebug(KHTML_LOG) << "number of style sheets in document " << authorStyleSheets.count();
0291     //qCDebug(KHTML_LOG) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements";
0292 
0293     QUrl u = url;
0294 
0295     u.setQuery(QString());
0296     u.setFragment(QString());
0297     encodedurl.file = u.url();
0298     int pos = encodedurl.file.lastIndexOf('/');
0299     encodedurl.path = encodedurl.file;
0300     if (pos > 0) {
0301         encodedurl.path.truncate(pos);
0302         encodedurl.path += '/';
0303     }
0304     u.setPath(QString());
0305     encodedurl.host = u.url();
0306 
0307     //qCDebug(KHTML_LOG) << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path;
0308 }
0309 
0310 CSSStyleSelector::CSSStyleSelector(CSSStyleSheetImpl *sheet)
0311 {
0312     m_fontSelector = new CSSFontSelector(sheet->doc());
0313 
0314     init(nullptr, nullptr);
0315 
0316     KHTMLView *view = sheet->doc()->view();
0317 
0318     setupDefaultRootStyle(sheet->doc());
0319 
0320     if (view) {
0321         m_medium = new MediaQueryEvaluator(view->mediaType(), view->part(), m_rootDefaultStyle);
0322     } else {
0323         m_medium = new MediaQueryEvaluator("screen", nullptr, m_rootDefaultStyle);
0324     }
0325 
0326     if (sheet->implicit()) {
0327         implicitStyle = new CSSStyleSelectorList();
0328         implicitStyle->append(sheet, m_medium, this);
0329     } else {
0330         authorStyle = new CSSStyleSelectorList();
0331         authorStyle->append(sheet, m_medium, this);
0332     }
0333 }
0334 
0335 void CSSStyleSelector::init(const KHTMLSettings *_settings, DocumentImpl *doc)
0336 {
0337     element = nullptr;
0338     settings = _settings;
0339     logicalDpiY = 0;
0340     if (!s_defaultStyle) {
0341         loadDefaultStyle(settings, doc);
0342     }
0343 
0344     defaultStyle = s_defaultStyle;
0345     defaultPrintStyle = s_defaultPrintStyle;
0346     defaultQuirksStyle = s_defaultQuirksStyle;
0347     defaultNonCSSHintsStyle = s_defaultNonCSSHintsStyle;
0348     m_rootDefaultStyle = nullptr;
0349     m_medium = nullptr;
0350 }
0351 
0352 CSSStyleSelector::~CSSStyleSelector()
0353 {
0354     clearLists();
0355     delete authorStyle;
0356     delete implicitStyle;
0357     delete userStyle;
0358     delete userSheet;
0359     delete m_rootDefaultStyle;
0360     delete m_medium;
0361     delete m_fontSelector;
0362 }
0363 
0364 void CSSStyleSelector::addSheet(CSSStyleSheetImpl *sheet)
0365 {
0366     KHTMLView *view = sheet->doc()->view();
0367 
0368     setupDefaultRootStyle(sheet->doc());
0369 
0370     delete m_medium; m_medium = nullptr;
0371     delete authorStyle; authorStyle = nullptr;
0372     delete implicitStyle; implicitStyle = nullptr;
0373 
0374     if (view) {
0375         m_medium = new MediaQueryEvaluator(view->mediaType(), view->part(), m_rootDefaultStyle);
0376     } else {
0377         m_medium = new MediaQueryEvaluator("screen", nullptr, m_rootDefaultStyle);
0378     }
0379 
0380     if (sheet->implicit()) {
0381         if (!implicitStyle) {
0382             implicitStyle = new CSSStyleSelectorList();
0383         }
0384         implicitStyle->append(sheet, m_medium, this);
0385     } else {
0386         if (!authorStyle) {
0387             authorStyle = new CSSStyleSelectorList();
0388         }
0389         authorStyle->append(sheet, m_medium, this);
0390     }
0391 }
0392 
0393 void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s, DocumentImpl *doc)
0394 {
0395     if (s_defaultStyle) {
0396         return;
0397     }
0398 
0399     MediaQueryEvaluator screenEval("screen");
0400     MediaQueryEvaluator printEval("print");
0401 
0402     {
0403         QFile f(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kf5/khtml/css/html4.css"));
0404         f.open(QIODevice::ReadOnly);
0405 
0406         QByteArray file(f.size() + 1, 0);
0407         int readbytes = f.read(file.data(), f.size());
0408         f.close();
0409         if (readbytes >= 0) {
0410             file[readbytes] = '\0';
0411         }
0412 
0413         QString style = QLatin1String(file.data());
0414 
0415         QRegExp checkVersion("KHTML_STYLE_VERSION:\\s*(\\d+)");
0416         checkVersion.setMinimal(true);
0417         if (checkVersion.indexIn(style) == -1 || checkVersion.cap(1).toInt() != KHTML_STYLE_VERSION) {
0418             qFatal("!!!!!!! ERROR !!!!!!! - KHTML default stylesheet version mismatch. Aborting. Check your installation. File used was: %s. Expected STYLE_VERSION %d\n",
0419                    QFileInfo(f).absoluteFilePath().toLatin1().data(), KHTML_STYLE_VERSION);
0420         }
0421 
0422         if (s) {
0423             style += s->settingsToCSS();
0424         }
0425         DOMString str(style);
0426 
0427         s_defaultSheet = new DOM::CSSStyleSheetImpl(doc);
0428         s_defaultSheet->parseString(str);
0429 
0430         // Collect only strict-mode rules.
0431         s_defaultStyle = new CSSStyleSelectorList();
0432         s_defaultStyle->append(s_defaultSheet, &screenEval, doc->styleSelector());
0433 
0434         s_defaultPrintStyle = new CSSStyleSelectorList();
0435         s_defaultPrintStyle->append(s_defaultSheet, &printEval, doc->styleSelector());
0436     }
0437     {
0438         QFile f(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kf5/khtml/css/quirks.css"));
0439         f.open(QIODevice::ReadOnly);
0440 
0441         QByteArray file(f.size() + 1, 0);
0442         int readbytes = f.read(file.data(), f.size());
0443         f.close();
0444         if (readbytes >= 0) {
0445             file[readbytes] = '\0';
0446         }
0447 
0448         QString style = QLatin1String(file.data());
0449         DOMString str(style);
0450 
0451         s_quirksSheet = new DOM::CSSStyleSheetImpl(doc);
0452         s_quirksSheet->parseString(str);
0453 
0454         // Collect only quirks-mode rules.
0455         s_defaultQuirksStyle = new CSSStyleSelectorList();
0456         s_defaultQuirksStyle->append(s_quirksSheet, &screenEval, doc->styleSelector());
0457     }
0458     {
0459         QFile f(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kf5/khtml/css/presentational.css"));
0460         f.open(QIODevice::ReadOnly);
0461 
0462         QByteArray file(f.size() + 1, 0);
0463         int readbytes = f.read(file.data(), f.size());
0464         f.close();
0465         if (readbytes >= 0) {
0466             file[readbytes] = '\0';
0467         }
0468 
0469         QString style = QLatin1String(file.data());
0470         DOMString str(style);
0471 
0472         s_defaultNonCSSHintsSheet = new DOM::CSSStyleSheetImpl(doc);
0473         s_defaultNonCSSHintsSheet->parseString(str);
0474 
0475         s_defaultNonCSSHintsStyle = new CSSStyleSelectorList();
0476         s_defaultNonCSSHintsStyle->append(s_defaultNonCSSHintsSheet, &screenEval, doc->styleSelector());
0477     }
0478     //qCDebug(KHTML_LOG) << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements";
0479 }
0480 
0481 void CSSStyleSelector::clear()
0482 {
0483     delete s_defaultStyle;
0484     delete s_defaultQuirksStyle;
0485     delete s_defaultPrintStyle;
0486     delete s_defaultNonCSSHintsStyle;
0487     delete s_defaultSheet;
0488     delete s_defaultNonCSSHintsSheet;
0489     delete styleNotYetAvailable;
0490     s_defaultStyle = nullptr;
0491     s_defaultQuirksStyle = nullptr;
0492     s_defaultPrintStyle = nullptr;
0493     s_defaultNonCSSHintsStyle = nullptr;
0494     s_defaultSheet = nullptr;
0495     s_defaultNonCSSHintsSheet = nullptr;
0496     styleNotYetAvailable = nullptr;
0497 }
0498 
0499 void CSSStyleSelector::reparseConfiguration()
0500 {
0501     // nice leak, but best we can do right now. hopefully it is only rare.
0502     s_defaultStyle = nullptr;
0503     s_defaultQuirksStyle = nullptr;
0504     s_defaultPrintStyle = nullptr;
0505     s_defaultNonCSSHintsStyle = nullptr;
0506     s_defaultSheet = nullptr;
0507 }
0508 
0509 #define MAXFONTSIZES 8
0510 
0511 void CSSStyleSelector::computeFontSizes(int logicalDpiY,  int zoomFactor)
0512 {
0513     computeFontSizesFor(logicalDpiY, zoomFactor, m_fontSizes, false);
0514     computeFontSizesFor(logicalDpiY, zoomFactor, m_fixedFontSizes, true);
0515 }
0516 
0517 void CSSStyleSelector::computeFontSizesFor(int logicalDpiY, int zoomFactor, QVector<int> &fontSizes, bool isFixed)
0518 {
0519 #ifdef APPLE_CHANGES
0520     // We don't want to scale the settings by the dpi.
0521     const float toPix = 1.0;
0522 #else
0523     Q_UNUSED(isFixed);
0524 
0525     const float toPix = qMax(logicalDpiY, 96) / 72.0f;
0526 #endif // ######### fix isFixed code again.
0527 
0528     fontSizes.resize(MAXFONTSIZES);
0529     float scale = 1.0;
0530     static const float fontFactors[] =      {3.0f / 5.0f, 3.0f / 4.0f, 8.0f / 9.0f, 1.0f, 6.0f / 5.0f, 3.0f / 2.0f, 2.0f, 3.0f};
0531     static const float smallFontFactors[] = {3.0f / 4.0f, 5.0f / 6.0f, 8.0f / 9.0f, 1.0f, 6.0f / 5.0f, 3.0f / 2.0f, 2.0f, 3.0f};
0532     float mediumFontSize, factor;
0533     if (!khtml::printpainter) {
0534         scale *= zoomFactor / 100.0;
0535 #ifdef APPLE_CHANGES
0536         if (isFixed) {
0537             mediumFontSize = settings->mediumFixedFontSize() * toPix;
0538         } else
0539 #endif
0540             mediumFontSize = settings->mediumFontSize() * toPix;
0541         m_minFontSize = settings->minFontSize() * toPix;
0542     } else {
0543         // ### depending on something / configurable ?
0544         mediumFontSize = 12;
0545         m_minFontSize = 6;
0546     }
0547     const float *factors = scale * mediumFontSize >= 12.5 ? fontFactors : smallFontFactors;
0548     for (int i = 0; i < MAXFONTSIZES; i++) {
0549         factor = scale * factors[i];
0550         fontSizes[i] = qMax(qRound(mediumFontSize * factor), m_minFontSize);
0551         //qCDebug(KHTML_LOG) << "index:" << i << "factor:" << factors[i] << "font pix size:" << fontSizes[i];
0552     }
0553 }
0554 
0555 #undef MAXFONTSIZES
0556 
0557 RenderStyle *CSSStyleSelector::locateSimilarStyle()
0558 {
0559     ElementImpl *s = nullptr, *t = nullptr, *c = nullptr;
0560     if (!element) {
0561         return nullptr;
0562     }
0563     // Check previous siblings.
0564     unsigned count = 0;
0565     NodeImpl *n = element;
0566     do {
0567         for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
0568         if (!n) {
0569             break;
0570         }
0571         ElementImpl *e = static_cast<ElementImpl *>(n);
0572         if (++count > 10) {
0573             break;
0574         }
0575         if (!s) {
0576             s = e;    // sibling match
0577         }
0578         if (e->id() != element->id()) {
0579             continue;
0580         }
0581         if (!t) {
0582             t = e;    // tag match
0583         }
0584         if (element->hasClass()) {
0585             if (!e->hasClass()) {
0586                 continue;
0587             }
0588             const DOMString &class1 = element->getAttribute(ATTR_CLASS);
0589             const DOMString &class2 = e->getAttribute(ATTR_CLASS);
0590             if (class1 != class2) {
0591                 continue;
0592             }
0593         }
0594         if (!c) {
0595             c = e;    // class match
0596         }
0597         break;
0598     } while (true);
0599 
0600     // if possible return sibling that matches tag and class
0601     if (c && c->renderer() && c->renderer()->style()) {
0602         return c->renderer()->style();
0603     }
0604     // second best: return sibling that matches tag
0605     if (t && t->renderer() && t->renderer()->style()) {
0606         return t->renderer()->style();
0607     }
0608     // third best: return sibling element
0609     if (s && s->renderer() && s->renderer()->style()) {
0610         return s->renderer()->style();
0611     }
0612     // last attempt: return parent element
0613     NodeImpl *p = element->parentNode();
0614     if (p && p->renderer()) {
0615         return p->renderer()->style();
0616     }
0617 
0618     return nullptr;
0619 }
0620 
0621 static inline void bubbleSort(CSSOrderedProperty **b, CSSOrderedProperty **e)
0622 {
0623     while (b < e) {
0624         bool swapped = false;
0625         CSSOrderedProperty **y = e + 1;
0626         CSSOrderedProperty **x = e;
0627         CSSOrderedProperty **swappedPos = nullptr;
0628         do {
0629             if (!((**(--x)) < (**(--y)))) {
0630                 swapped = true;
0631                 swappedPos = x;
0632                 CSSOrderedProperty *tmp = *y;
0633                 *y = *x;
0634                 *x = tmp;
0635             }
0636         } while (x != b);
0637         if (!swapped) {
0638             break;
0639         }
0640         b = swappedPos + 1;
0641     }
0642 }
0643 
0644 RenderStyle *CSSStyleSelector::styleForElement(ElementImpl *e, RenderStyle *fallbackParentStyle)
0645 {
0646     if (!e->document()->haveStylesheetsLoaded() || !e->document()->view()) {
0647         if (!styleNotYetAvailable) {
0648             styleNotYetAvailable = new RenderStyle();
0649             styleNotYetAvailable->setDisplay(NONE);
0650             styleNotYetAvailable->ref();
0651         }
0652         return styleNotYetAvailable;
0653     }
0654 
0655     // set some variables we will need
0656     pseudoState = PseudoUnknown;
0657 
0658     element = e;
0659     parentNode = e->parentNode();
0660     parentStyle = (parentNode && parentNode->renderer()) ?
0661                   parentNode->renderer()->style() : fallbackParentStyle;
0662     view = element->document()->view();
0663     part = view->part();
0664     settings = part->settings();
0665     logicalDpiY = element->document()->logicalDpiY();
0666 
0667     // reset dynamic DOM dependencies
0668     e->document()->dynamicDomRestyler().resetDependencies(e);
0669 
0670     style = new RenderStyle();
0671     if (parentStyle) {
0672         style->inheritFrom(parentStyle);
0673     } else {
0674         parentStyle = style;
0675     }
0676 
0677     const RenderObject *docElementRenderer = e->document()->documentElement()->renderer();
0678     m_rootStyle = docElementRenderer ? docElementRenderer->style() : m_rootDefaultStyle;
0679 
0680     // try to sort out most style rules as early as possible.
0681     quint16 cssTagId = localNamePart(element->id());
0682     int smatch = 0;
0683     int schecked = 0;
0684 
0685     // do aggressive selection of selectors to check
0686     // instead of going over whole constructed list,
0687     // skip selectors that won't match for sure (e.g. with different id or class)
0688     QVarLengthArray<int> selectorsForCheck;
0689     // add unknown selectors to always be checked
0690     for (unsigned int i = otherSelector; i < selectors_size; i = nextSimilarSelector[i]) {
0691         selectorsForCheck.append(i);
0692     }
0693     // check if we got class attribute on element: add selectors with it to the list
0694     if (e->hasClass()) {
0695         const ClassNames &classNames = element->classNames();
0696         for (unsigned int i = 0; i < classNames.size(); ++i) {
0697             WTF::HashMap<quintptr, int>::iterator it = classSelector.find((quintptr)classNames[i].impl());
0698             if (it != classSelector.end())
0699                 for (unsigned int j = it->second; j < selectors_size; j = nextSimilarSelector[j]) {
0700                     selectorsForCheck.append(j);
0701                 }
0702         }
0703     }
0704     // check if we got id attribute on element: add selectors with it to the list
0705     DOMStringImpl *idValue = element->getAttributeImplById(ATTR_ID);
0706     if (idValue && idValue->length()) {
0707         bool caseSensitive = (e->document()->htmlMode() == DocumentImpl::XHtml) || strictParsing;
0708         AtomicString elementId = caseSensitive ? idValue : idValue->lower();
0709         WTF::HashMap<quintptr, int>::iterator it = idSelector.find((quintptr)elementId.impl());
0710         if (it != idSelector.end())
0711             for (unsigned int j = it->second; j < selectors_size; j = nextSimilarSelector[j]) {
0712                 selectorsForCheck.append(j);
0713             }
0714     }
0715     // add all selectors with given local tag
0716     WTF::HashMap<unsigned, int>::iterator it = tagSelector.find(cssTagId);
0717     if (it != tagSelector.end())
0718         for (unsigned int j = it->second; j < selectors_size; j = nextSimilarSelector[j]) {
0719             selectorsForCheck.append(j);
0720         }
0721 
0722     // build per-element cache summaries.
0723     prepareToMatchElement(element, true);
0724 
0725     propsToApply.clear();
0726     pseudoProps.clear();
0727     // now go over selectors that we prepared for check
0728     // selectors yet in random order, so we store only matched selector indexes to sort after
0729     unsigned amountOfMatchedSelectors = 0;
0730     for (int k = 0; k < selectorsForCheck.size(); ++k) {
0731         unsigned i = selectorsForCheck[k];
0732         quint16 tag = selectors[i]->tagLocalName.id();
0733         if (cssTagId == tag || tag == anyLocalName) {
0734             ++schecked;
0735             checkSelector(i, e);
0736             if (selectorCache[i].state == Applies || selectorCache[i].state == AppliesPseudo) {
0737                 selectorsForCheck[amountOfMatchedSelectors++] = i;
0738             }
0739         } else {
0740             selectorCache[i].state = Invalid;
0741         }
0742     }
0743 
0744     // sort only matched selectors and then collect properties
0745     std::sort(selectorsForCheck.data(), selectorsForCheck.data() + amountOfMatchedSelectors);
0746     for (unsigned k = 0; k < amountOfMatchedSelectors; ++k) {
0747         unsigned i = selectorsForCheck[k];
0748         if (selectorCache[i].state == Applies) {
0749             ++smatch;
0750             for (unsigned p = selectorCache[i].firstPropertyIndex; p < properties_size; p = nextPropertyIndexes[p]) {
0751                 propsToApply.append(propertiesBuffer + p);
0752             }
0753         } else if (selectorCache[i].state == AppliesPseudo) {
0754             for (unsigned p = selectorCache[i].firstPropertyIndex; p < properties_size; p = nextPropertyIndexes[p]) {
0755                 pseudoProps.append(propertiesBuffer + p);
0756                 propertiesBuffer[p].pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId;
0757             }
0758         }
0759     }
0760     // clear selectorsForCheck, it shouldn't be used after
0761     selectorsForCheck.clear();
0762 
0763     // Inline style declarations, after all others.
0764     // Non-css hints from presentational attributes will also be collected here
0765     // receiving the proper priority so has to cascade from before author rules (cf.CSS 2.1-6.4.4).
0766     addInlineDeclarations(e);
0767 
0768 //     qDebug( "styleForElement( %s )", e->tagName().string().toLatin1().constData() );
0769 //     qDebug( "%d selectors, %d checked,  %d match,  %d properties ( of %d )",
0770 //      selectors_size, schecked, smatch, numPropsToApply, properties_size );
0771 
0772     if (propsToApply.size()) {
0773         bubbleSort(propsToApply.data(), propsToApply.data() + propsToApply.size() - 1);
0774     }
0775     if (pseudoProps.size()) {
0776         bubbleSort(pseudoProps.data(), pseudoProps.data() + pseudoProps.size() - 1);
0777     }
0778 
0779     // we can't apply style rules without a view() and a part. This
0780     // tends to happen on delayed destruction of widget Renderobjects
0781     if (part) {
0782         fontDirty = false;
0783 
0784         if (propsToApply.size()) {
0785             for (unsigned int i = 0; i < propsToApply.size(); ++i) {
0786                 if (fontDirty && propsToApply[i]->priority >= (1 << 30)) {
0787                     // we are past the font properties, time to update to the
0788                     // correct font
0789 #ifdef APPLE_CHANGES
0790                     checkForGenericFamilyChange(style, parentStyle);
0791 #endif
0792                     style->htmlFont().update(logicalDpiY);
0793                     fontDirty = false;
0794                 }
0795                 DOM::CSSProperty *prop = propsToApply[i]->prop;
0796 //      if (prop->m_id == CSS_PROP__KONQ_USER_INPUT) qCDebug(KHTML_LOG) << "El: "<<e->nodeName().string() << " user-input: "<<((CSSPrimitiveValueImpl *)prop->value())->getIdent();
0797 //      if (prop->m_id == CSS_PROP_TEXT_TRANSFORM) qCDebug(KHTML_LOG) << "El: "<<e->nodeName().string();
0798                 applyRule(prop->m_id, prop->value());
0799             }
0800             if (fontDirty) {
0801 #ifdef APPLE_CHANGES
0802                 checkForGenericFamilyChange(style, parentStyle);
0803 #endif
0804                 style->htmlFont().update(logicalDpiY);
0805             }
0806         }
0807 
0808         // Clean up our style object's display and text decorations (among other fixups).
0809         adjustRenderStyle(style, e);
0810 
0811         if (pseudoProps.size()) {
0812             fontDirty = false;
0813             //qDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() );
0814             for (unsigned int i = 0; i < pseudoProps.size(); ++i) {
0815                 if (fontDirty && pseudoProps[i]->priority >= (1 << 30)) {
0816                     // we are past the font properties, time to update to the
0817                     // correct font
0818                     //We have to do this for all pseudo styles
0819                     RenderStyle *pseudoStyle = style->pseudoStyle;
0820                     while (pseudoStyle) {
0821                         pseudoStyle->htmlFont().update(logicalDpiY);
0822                         pseudoStyle = pseudoStyle->pseudoStyle;
0823                     }
0824                     fontDirty = false;
0825                 }
0826 
0827                 RenderStyle *pseudoStyle;
0828                 pseudoStyle = style->getPseudoStyle(pseudoProps[i]->pseudoId);
0829                 if (!pseudoStyle) {
0830                     pseudoStyle = style->addPseudoStyle(pseudoProps[i]->pseudoId);
0831                     if (pseudoStyle) {
0832                         pseudoStyle->inheritFrom(style);
0833                     }
0834                 }
0835 
0836                 RenderStyle *oldStyle = style;
0837                 RenderStyle *oldParentStyle = parentStyle;
0838                 parentStyle = style;
0839                 style = pseudoStyle;
0840                 if (pseudoStyle) {
0841                     DOM::CSSProperty *prop = pseudoProps[i]->prop;
0842                     applyRule(prop->m_id, prop->value());
0843                 }
0844                 style = oldStyle;
0845                 parentStyle = oldParentStyle;
0846             }
0847 
0848             if (fontDirty) {
0849                 RenderStyle *pseudoStyle = style->pseudoStyle;
0850                 while (pseudoStyle) {
0851                     pseudoStyle->htmlFont().update(logicalDpiY);
0852                     pseudoStyle = pseudoStyle->pseudoStyle;
0853                 }
0854             }
0855         }
0856     }
0857 
0858     // Now adjust all our pseudo-styles.
0859     RenderStyle *pseudoStyle = style->pseudoStyle;
0860     while (pseudoStyle) {
0861         adjustRenderStyle(pseudoStyle, nullptr);
0862         pseudoStyle = pseudoStyle->pseudoStyle;
0863     }
0864 
0865     // Try and share or partially share the style with our siblings
0866     RenderStyle *commonStyle = locateSimilarStyle();
0867     if (commonStyle) {
0868         style->compactWith(commonStyle);
0869     }
0870 
0871     // Now return the style.
0872     return style;
0873 }
0874 
0875 void CSSStyleSelector::prepareToMatchElement(DOM::ElementImpl *e, bool withDeps)
0876 {
0877     rememberDependencies = withDeps;
0878     element              = e;
0879 
0880     // build caches for element so it could be used in heuristic for descendant selectors
0881     // go up the tree and cache possible tags, classes and ids
0882     tagCache.clear();
0883     idCache.clear();
0884     classCache.clear();
0885     ElementImpl *current = element;
0886     while (true) {
0887         NodeImpl *parent = current->parentNode();
0888         if (!parent || !parent->isElementNode()) {
0889             break;
0890         }
0891         current = static_cast<ElementImpl *>(parent);
0892 
0893         if (current->hasClass()) {
0894             const ClassNames &classNames = current->classNames();
0895             for (unsigned i = 0; i < classNames.size(); ++i) {
0896                 classCache.add((quintptr)classNames[i].impl());
0897             }
0898         }
0899 
0900         DOMStringImpl *idValue = current->getAttributeImplById(ATTR_ID);
0901         if (idValue && idValue->length()) {
0902             bool caseSensitive = (current->document()->htmlMode() == DocumentImpl::XHtml) || strictParsing;
0903             AtomicString currentId = caseSensitive ? idValue : idValue->lower();
0904             // though currentId is local and could be deleted from AtomicStringImpl cache right away
0905             // don't care about that, cause selector values are stable and only they will be checked later
0906             idCache.add((quintptr)currentId.impl());
0907         }
0908 
0909         tagCache.add(localNamePart(current->id()));
0910     }
0911 }
0912 
0913 void CSSStyleSelector::adjustRenderStyle(RenderStyle *style, DOM::ElementImpl *e)
0914 {
0915     // Cache our original display.
0916     style->setOriginalDisplay(style->display());
0917 
0918     if (style->display() != NONE) {
0919         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
0920         // property.
0921         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
0922         // these tags to retain their display types.
0923         if (!strictParsing && e) {
0924             if (e->id() == ID_TD) {
0925                 style->setDisplay(TABLE_CELL);
0926                 style->setFloating(FNONE);
0927             } else if (e->id() == ID_TABLE) {
0928                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
0929             }
0930         }
0931 
0932         // Table headers with a text-align of auto will change the text-align to center.
0933         if (e && e->id() == ID_TH && style->textAlign() == TAAUTO) {
0934             style->setTextAlign(CENTER);
0935         }
0936 
0937         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
0938         // position or float an inline, compact, or run-in.  Cache the original display, since it
0939         // may be needed for positioned elements that have to compute their static normal flow
0940         // positions.  We also force inline-level roots to be block-level.
0941         if (style->display() != BLOCK && style->display() != TABLE /*&& style->display() != BOX*/ &&
0942                 (style->position() == PABSOLUTE || style->position() == PFIXED || style->floating() != FNONE ||
0943                  (e && e->document()->documentElement() == e))) {
0944             if (style->display() == INLINE_TABLE) {
0945                 style->setDisplay(TABLE);
0946             }
0947 //             else if (style->display() == INLINE_BOX)
0948 //                 style->setDisplay(BOX);
0949             else if (style->display() == LIST_ITEM) {
0950                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
0951                 // but only in quirks mode.
0952                 if (!strictParsing && style->floating() != FNONE) {
0953                     style->setDisplay(BLOCK);
0954                 }
0955             } else {
0956                 style->setDisplay(BLOCK);
0957             }
0958         } else if (e && e->id() == ID_BUTTON && style->isOriginalDisplayInlineType()) {
0959             // <button>s are supposed to be replaced elements; but we don't handle
0960             // them as such (as they are rendered as CSS contexts, not natives
0961             // with intrinsic sizes), so we must be careful not to make them fully
0962             // inline, as that will display stuff like width:; so mutate inline-like
0963             // display types into inline-block
0964             style->setDisplay(INLINE_BLOCK);
0965         }
0966 
0967         // After performing the display mutation, check our position.  We do not honor position:relative on
0968         // table rows and some other table displays. This is undefined behaviour in CSS2.1 (cf. 9.3.1)
0969         if (style->position() == PRELATIVE) {
0970             switch (style->display()) {
0971             case TABLE_ROW_GROUP:
0972             case TABLE_HEADER_GROUP:
0973             case TABLE_FOOTER_GROUP:
0974             case TABLE_ROW:
0975                 style->setPosition(PSTATIC);
0976             default:
0977                 break;
0978             }
0979         }
0980     }
0981 
0982     // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
0983     // fix a crash where a site tries to position these objects.
0984     if (e) {
0985         // ignore display: none for <frame>
0986         if (e->id() == ID_FRAME) {
0987             style->setPosition(PSTATIC);
0988             style->setDisplay(BLOCK);
0989         } else if (e->id() == ID_FRAMESET) {
0990             style->setPosition(PSTATIC);
0991         }
0992     }
0993 
0994     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
0995     // tables, inline blocks, inline tables, or run-ins.
0996     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
0997             || style->display() == INLINE_BLOCK /*|| style->display() == INLINE_BOX*/) {
0998         style->setTextDecorationsInEffect(style->textDecoration());
0999     } else {
1000         style->addToTextDecorationsInEffect(style->textDecoration());
1001     }
1002 
1003     // If either overflow value is not visible, change to auto.
1004     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE) {
1005         style->setOverflowY(OMARQUEE);
1006     } else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE) {
1007         style->setOverflowX(OMARQUEE);
1008     } else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) {
1009         style->setOverflowX(OAUTO);
1010     } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) {
1011         style->setOverflowY(OAUTO);
1012     }
1013 
1014     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1015     // FIXME: Eventually table sections will support auto and scroll.
1016     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1017             style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1018         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) {
1019             style->setOverflowX(OVISIBLE);
1020         }
1021         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) {
1022             style->setOverflowY(OVISIBLE);
1023         }
1024 
1025         // do comparable resets as Mozilla's nsStyleContext::ApplyStyleFixups
1026         // except they decided to do it only for center and right, for whatever strange reason. cf.#193093
1027         if (style->display() == TABLE && (style->textAlign() == KHTML_LEFT ||
1028                                           style->textAlign() == KHTML_RIGHT ||
1029                                           style->textAlign() == KHTML_CENTER)) {
1030             style->setTextAlign(TAAUTO);
1031         }
1032 
1033     }
1034 
1035     // Cull out any useless layers and also repeat patterns into additional layers.
1036     style->adjustBackgroundLayers();
1037 }
1038 
1039 void CSSStyleSelector::addInlineDeclarations(DOM::ElementImpl *e)
1040 {
1041     CSSStyleDeclarationImpl *inlineDecls = e->inlineStyleDecls();
1042     CSSStyleDeclarationImpl *nonCSSDecls = e->nonCSSStyleDecls();
1043     if (!inlineDecls && !nonCSSDecls) {
1044         return;
1045     }
1046 
1047     QList<CSSProperty *> *values = inlineDecls ? inlineDecls->values() : nullptr;
1048     QList<CSSProperty *> *nonCSSValues = nonCSSDecls ? nonCSSDecls->values() : nullptr;
1049     if (!values && !nonCSSValues) {
1050         return;
1051     }
1052 
1053     int firstLen = values ? values->count() : 0;
1054     int secondLen = nonCSSValues ? nonCSSValues->count() : 0;
1055     int totalLen = firstLen + secondLen;
1056 
1057     if (inlineProps.size() < totalLen) {
1058         inlineProps.resize(totalLen + 1);
1059     }
1060     propsToApply.reserveCapacity(propsToApply.size() + totalLen);
1061 
1062     bool inNonCSSDecls = false;
1063     CSSOrderedProperty *array = (CSSOrderedProperty *)inlineProps.data();
1064     for (int i = 0; i < totalLen; i++) {
1065         if (i == firstLen) {
1066             values = nonCSSValues;
1067             inNonCSSDecls = true;
1068         }
1069 
1070         CSSProperty *prop = values->at(i >= firstLen ? i - firstLen : i);
1071         Source source = Inline;
1072 
1073         if (prop->m_important) {
1074             source = InlineImportant;
1075         }
1076         if (inNonCSSDecls) {
1077             source = NonCSSHint;
1078         }
1079 
1080         bool first;
1081         // give special priority to font-xxx, color properties
1082         switch (prop->m_id) {
1083         case CSS_PROP_FONT_STYLE:
1084         case CSS_PROP_FONT_SIZE:
1085         case CSS_PROP_FONT_WEIGHT:
1086         case CSS_PROP_FONT_FAMILY:
1087         case CSS_PROP_FONT_VARIANT:
1088         case CSS_PROP_FONT:
1089         case CSS_PROP_COLOR:
1090         case CSS_PROP_DIRECTION:
1091         case CSS_PROP_DISPLAY:
1092             // these have to be applied first, because other properties use the computed
1093             // values of these properties.
1094             first = true;
1095             break;
1096         default:
1097             first = false;
1098             break;
1099         }
1100 
1101         array->prop = prop;
1102         array->pseudoId = RenderStyle::NOPSEUDO;
1103         array->selector = 0;
1104         array->position = i;
1105         array->priority = (!first << 30) | (source << 24);
1106         propsToApply.append(array++);
1107     }
1108 }
1109 
1110 // modified version of the one in kurl.cpp
1111 static void cleanpath(QString &path)
1112 {
1113     int pos;
1114     while ((pos = path.indexOf(QLatin1String("/../"))) != -1) {
1115         int prev = 0;
1116         if (pos > 0) {
1117             prev = path.lastIndexOf(QLatin1Char('/'), pos - 1);
1118         }
1119         // don't remove the host, i.e. http://foo.org/../foo.html
1120         if (prev < 0 || (prev > 3 && path.midRef(prev - 2, 3) == QLatin1String("://"))) {
1121             path.remove(pos, 3);
1122         } else
1123             // matching directory found ?
1124         {
1125             path.remove(prev, pos - prev + 3);
1126         }
1127     }
1128     pos = 0;
1129 
1130     // Don't remove "//" from an anchor identifier. -rjw
1131     // Set refPos to -2 to mean "I haven't looked for the anchor yet".
1132     // We don't want to waste a function call on the search for the anchor
1133     // in the vast majority of cases where there is no "//" in the path.
1134     int refPos = -2;
1135     while ((pos = path.indexOf(QLatin1String("//"), pos)) != -1) {
1136         if (refPos == -2) {
1137             refPos = path.indexOf(QLatin1Char('#'), 0);
1138         }
1139         if (refPos > 0 && pos >= refPos) {
1140             break;
1141         }
1142 
1143         if (pos == 0 || path[pos - 1] != QLatin1Char(':')) {
1144             path.remove(pos, 1);
1145         } else {
1146             pos += 2;
1147         }
1148     }
1149     while ((pos = path.indexOf(QLatin1String("/./"))) != -1) {
1150         path.remove(pos, 2);
1151     }
1152     //qCDebug(KHTML_LOG) << "checkPseudoState " << path;
1153 }
1154 
1155 static PseudoState checkPseudoState(const CSSStyleSelector::Encodedurl &encodedurl, DOM::ElementImpl *e)
1156 {
1157     if (e->id() != ID_A) {
1158         return PseudoNone;
1159     }
1160     DOMString attr = e->getAttribute(ATTR_HREF);
1161     if (attr.isNull()) {
1162         return PseudoNone;
1163     }
1164     QString url = QString::fromRawData(attr.unicode(), attr.length());
1165     if (!url.contains(QLatin1String("://"))) {
1166         if (url[0] == QLatin1Char('/')) {
1167             url = encodedurl.host + url;
1168         } else if (url[0] == QLatin1Char('#')) {
1169             url = encodedurl.file + url;
1170         } else {
1171             url = encodedurl.path + url;
1172         }
1173         cleanpath(url);
1174     }
1175     //completeURL( attr.string() );
1176     bool contains = KHTMLGlobal::vLinks()->contains(url);
1177     if (!contains && url.count(QLatin1Char('/')) == 2) {
1178         contains = KHTMLGlobal::vLinks()->contains(url + QLatin1Char('/'));
1179     }
1180     return contains ? PseudoVisited : PseudoLink;
1181 }
1182 
1183 // a helper function for parsing nth-arguments
1184 static bool matchNth(int count, const QString &nth)
1185 {
1186     if (nth.isEmpty()) {
1187         return false;
1188     }
1189     int a = 0;
1190     int b = 0;
1191     bool ok = true;
1192     if (nth == "odd") {
1193         a = 2;
1194         b = 1;
1195     } else if (nth == "even") {
1196         a = 2;
1197         b = 0;
1198     } else {
1199         int n = nth.indexOf('n'), l = nth.length();
1200         if (n != -1) {
1201             int i = 0, j, sgn = 0;
1202             // skip trailing spaces
1203             while (i < n && nth[i].isSpace()) {
1204                 ++i;
1205             }
1206 
1207             // check sign
1208             if (nth[i] == '-') {
1209                 sgn = -1;
1210                 ++i;
1211             } else if (nth[i] == '+') {
1212                 sgn = 1;
1213                 ++i;
1214             }
1215 
1216             // skip spaces between '-'/'+' and digits
1217             while (i < n && nth[i].isSpace()) {
1218                 ++i;
1219             }
1220 
1221             // find the number before 'n'
1222             for (j = i; j < n && nth[j].isDigit(); ++j) {}
1223 
1224             // do we have number or it's assumed to be 1
1225             a = (i < j) ? nth.mid(i, j - i).toInt(&ok) : 1;
1226             if (!ok) {
1227                 return false;
1228             }
1229             if (sgn == -1) {
1230                 a = -a;
1231             }
1232 
1233             // should have nothing between a and n except spaces
1234             for (; j < n; ++j) if (!nth[j].isSpace()) {
1235                     return false;
1236                 }
1237 
1238             // skip spaces
1239             for (i = n + 1; i < l && nth[i].isSpace(); ++i) {}
1240 
1241             // parse b
1242             if (i < l) {
1243                 // must have sign
1244                 if (nth[i] == '-') {
1245                     sgn = -1;
1246                     ++i;
1247                 } else if (nth[i] == '+') {
1248                     sgn = 1;
1249                     ++i;
1250                 } else {
1251                     return false;
1252                 }
1253 
1254                 // skip spaces
1255                 while (i < l && nth[i].isSpace()) {
1256                     ++i;
1257                 }
1258 
1259                 // find digits
1260                 for (j = i; j < l && nth[j].isDigit(); ++j) {}
1261 
1262                 // must have digits
1263                 if (j == i) {
1264                     return false;
1265                 }
1266 
1267                 b = sgn * nth.mid(i, j - i).toInt(&ok);
1268                 if (!ok) {
1269                     return false;
1270                 }
1271 
1272                 // should be nothing except spaces in the end
1273                 for (; j < l; ++j) if (!nth[j].isSpace()) {
1274                         return false;
1275                     }
1276             }
1277         } else {
1278             b = nth.toInt(&ok);
1279             if (!ok) {
1280                 return false;
1281             }
1282         }
1283     }
1284     if (a == 0) {
1285         return b != 0 && count == b;
1286     }
1287     if (a > 0) {
1288         return (count < b) ? false : ((count - b) % a == 0);
1289     }
1290     // a < 0
1291     return (count > b) ? false : ((b - count) % (-a) == 0);
1292 }
1293 
1294 // Recursively work the combinator to compute static attribute dependency, similar to
1295 //structure of checkSubSelectors
1296 static void precomputeAttributeDependenciesAux(DOM::DocumentImpl *doc, DOM::CSSSelector *sel, bool isAncestor, bool isSubject)
1297 {
1298     if (sel->attrLocalName.id()) {
1299         uint selAttr = makeId(sel->attrNamespace.id(), sel->attrLocalName.id());
1300         // Sets up global dependencies of attributes
1301         if (isSubject) {
1302             doc->dynamicDomRestyler().addDependency(selAttr, PersonalDependency);
1303         } else if (isAncestor) {
1304             doc->dynamicDomRestyler().addDependency(selAttr, AncestorDependency);
1305         } else {
1306             doc->dynamicDomRestyler().addDependency(selAttr, PredecessorDependency);
1307         }
1308     }
1309     if (sel->match == CSSSelector::PseudoClass) {
1310         switch (sel->pseudoType()) {
1311         case CSSSelector::PseudoNot:
1312             precomputeAttributeDependenciesAux(doc, sel->simpleSelector, isAncestor, true);
1313             break;
1314         default:
1315             break;
1316         }
1317     }
1318     CSSSelector::Relation relation = KDE_CAST_BF_ENUM(CSSSelector::Relation, sel->relation);
1319     sel = sel->tagHistory;
1320     if (!sel) {
1321         return;
1322     }
1323 
1324     switch (relation) {
1325     case CSSSelector::Descendant:
1326     case CSSSelector::Child:
1327         precomputeAttributeDependenciesAux(doc, sel, true, false);
1328         break;
1329     case CSSSelector::IndirectAdjacent:
1330     case CSSSelector::DirectAdjacent:
1331         precomputeAttributeDependenciesAux(doc, sel, false, false);
1332         break;
1333     case CSSSelector::SubSelector:
1334         precomputeAttributeDependenciesAux(doc, sel, isAncestor, isSubject);
1335         break;
1336     }
1337 }
1338 
1339 void CSSStyleSelector::precomputeAttributeDependencies(DOM::DocumentImpl *doc, DOM::CSSSelector *sel)
1340 {
1341     precomputeAttributeDependenciesAux(doc, sel, false, true);
1342 }
1343 
1344 // Recursive check of selectors and combinators
1345 // It can return 3 different values:
1346 // * SelectorMatches - the selector is match for the node e
1347 // * SelectorFailsLocal - the selector fails for the node e
1348 // * SelectorFails - the selector fails for e and any sibling or ancestor of e
1349 CSSStyleSelector::SelectorMatch CSSStyleSelector::checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)
1350 {
1351     // The simple selector has to match
1352     if (!checkSimpleSelector(sel, e, isAncestor, isSubSelector)) {
1353         return SelectorFailsLocal;
1354     }
1355 
1356     // The rest of the selectors has to match
1357     CSSSelector::Relation relation = KDE_CAST_BF_ENUM(CSSSelector::Relation, sel->relation);
1358 
1359     // Prepare next sel
1360     sel = sel->tagHistory;
1361     if (!sel) {
1362         return SelectorMatches;
1363     }
1364 
1365     switch (relation) {
1366     case CSSSelector::Descendant: {
1367         // if ancestor of original element we may want to check prepared caches first
1368         // whether given selector could possibly have a match
1369         // if no we return SelectorFails result right away and avoid going up the tree
1370         if (isAncestor) {
1371             int id = sel->tagLocalName.id();
1372             if (id != anyLocalName && !tagCache.contains(id)) {
1373                 return SelectorFails;
1374             }
1375             if (sel->match == CSSSelector::Class && !classCache.contains((quintptr)sel->value.impl())) {
1376                 return SelectorFails;
1377             }
1378             if (sel->match == CSSSelector::Id && !idCache.contains((quintptr)sel->value.impl())) {
1379                 return SelectorFails;
1380             }
1381         }
1382 
1383         while (true) {
1384             DOM::NodeImpl *n = e->parentNode();
1385             if (!n || !n->isElementNode()) {
1386                 return SelectorFails;
1387             }
1388             e = static_cast<ElementImpl *>(n);
1389             SelectorMatch match = checkSelector(sel, e, true);
1390             if (match != SelectorFailsLocal) {
1391                 return match;
1392             }
1393         }
1394         break;
1395     }
1396     case CSSSelector::Child: {
1397         DOM::NodeImpl *n = e->parentNode();
1398         if (!strictParsing)
1399             while (n && n->implicitNode()) {
1400                 n = n->parentNode();
1401             }
1402         if (!n || !n->isElementNode()) {
1403             return SelectorFails;
1404         }
1405         e = static_cast<ElementImpl *>(n);
1406         return checkSelector(sel, e, true);
1407     }
1408     case CSSSelector::IndirectAdjacent: {
1409         // Sibling selectors always generate structural dependencies
1410         // because newly inserted element might fullfill them.
1411         if (e->parentNode() && e->parentNode()->isElementNode()) {
1412             addDependency(StructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1413         }
1414         while (true) {
1415             DOM::NodeImpl *n = e->previousSibling();
1416             while (n && !n->isElementNode()) {
1417                 n = n->previousSibling();
1418             }
1419             if (!n) {
1420                 return SelectorFailsLocal;
1421             }
1422             e = static_cast<ElementImpl *>(n);
1423             SelectorMatch match = checkSelector(sel, e, false);
1424             if (match != SelectorFailsLocal) {
1425                 return match;
1426             }
1427         };
1428         break;
1429     }
1430     case CSSSelector::DirectAdjacent: {
1431         if (e->parentNode() && e->parentNode()->isElementNode()) {
1432             addDependency(StructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1433         }
1434         DOM::NodeImpl *n = e->previousSibling();
1435         while (n && !n->isElementNode()) {
1436             n = n->previousSibling();
1437         }
1438         if (!n) {
1439             return SelectorFailsLocal;
1440         }
1441         e = static_cast<ElementImpl *>(n);
1442         return checkSelector(sel, e, false);
1443     }
1444     case CSSSelector::SubSelector:
1445         return checkSelector(sel, e, isAncestor, true);
1446     }
1447     assert(false); // never reached
1448     return SelectorFails;
1449 }
1450 
1451 void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl *e)
1452 {
1453     assert(e == element); // yes, actually
1454 
1455     dynamicPseudo = RenderStyle::NOPSEUDO;
1456 
1457     selectorCache[ selIndex ].state = Invalid;
1458     CSSSelector *sel = selectors[ selIndex ];
1459 
1460     // Check the selector
1461     SelectorMatch match = checkSelector(sel, e, true);
1462     if (match != SelectorMatches) {
1463         return;
1464     }
1465 
1466     if (dynamicPseudo != RenderStyle::NOPSEUDO) {
1467         selectorCache[selIndex].state = AppliesPseudo;
1468         selectors[ selIndex ]->pseudoId = dynamicPseudo;
1469     } else {
1470         selectorCache[ selIndex ].state = Applies;
1471     }
1472     //qDebug( "selector %d applies", selIndex );
1473     //selectors[ selIndex ]->print();
1474     return;
1475 }
1476 
1477 bool CSSStyleSelector::isMatchedByAnySelector(DOM::ElementImpl *e, const QList<DOM::CSSSelector *> &sels)
1478 {
1479     bool inited = false;
1480 
1481     quint16 elementTagId = localNamePart(e->id());
1482 
1483     // ### this may introduce extraneous restyling dependencies
1484     for (int i = 0; i < sels.size(); ++i) {
1485         DOM::CSSSelector *sel = sels[i];
1486         quint16 tag = sel->tagLocalName.id();
1487         if (elementTagId == tag || tag == anyLocalName) {
1488             if (!inited) {
1489                 prepareToMatchElement(e, false);
1490                 inited = true;
1491             }
1492 
1493             dynamicPseudo = RenderStyle::NOPSEUDO;
1494             SelectorMatch match = checkSelector(sel, e, true);
1495 
1496             if (match == SelectorMatches && dynamicPseudo == RenderStyle::NOPSEUDO) {
1497                 return true;
1498             }
1499         }
1500     }
1501 
1502     return false;
1503 }
1504 
1505 void CSSStyleSelector::addDependency(int dependencyType, ElementImpl *dependency)
1506 {
1507     if (!rememberDependencies) {
1508         return;
1509     }
1510     element->document()->dynamicDomRestyler().addDependency(element, dependency, (StructuralDependencyType)dependencyType);
1511 }
1512 
1513 bool CSSStyleSelector::checkSimpleSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)
1514 {
1515     uint selTag = makeId(sel->tagNamespace.id(), sel->tagLocalName.id());
1516     if (selTag != anyQName) {
1517         int eltID = e->id();
1518         quint16 localName = localNamePart(eltID);
1519         quint16 ns = namespacePart(eltID);
1520         quint16 selLocalName = localNamePart(selTag);
1521         quint16 selNS = namespacePart(selTag);
1522 
1523         // match on local
1524         if (selLocalName != anyLocalName && localName != selLocalName) {
1525             return false;
1526         }
1527         // match on namespace
1528         if (selNS != anyNamespace && ns != selNS) {
1529             return false;
1530         }
1531     }
1532 
1533     uint selAttr = makeId(sel->attrNamespace.id(), sel->attrLocalName.id());
1534     if (selAttr) {
1535         // "class" is special attribute which is pre-parsed for fast look-ups
1536         // avoid ElementImpl::getAttributeImpl here, as we don't need it
1537         if (sel->match == CSSSelector::Class) {
1538             return e->hasClass() && e->classNames().contains(sel->value);
1539         }
1540 
1541         DOMStringImpl *value = e->getAttributeImplById(selAttr);
1542         if (!value) {
1543             return false;    // attribute is not set
1544         }
1545 
1546         // attributes are always case-sensitive in XHTML
1547         // attributes are sometimes case-sensitive in HTML
1548         bool caseSensitive = (e->document()->htmlMode() == DocumentImpl::XHtml) || caseSensitiveAttr(selAttr);
1549 
1550         switch (sel->match) {
1551         case CSSSelector::Set:
1552             // True if we make it this far
1553             break;
1554         case CSSSelector::Id:
1555             // treat id selectors as case-sensitive in HTML strict
1556             // for compatibility reasons
1557             caseSensitive = (e->document()->htmlMode() == DocumentImpl::XHtml) || strictParsing;
1558         // no break
1559         case CSSSelector::Exact:
1560             return caseSensitive ?
1561                    !strcmp(sel->value.impl(), value) :
1562                    !strcasecmp(sel->value.impl(), value);
1563             break;
1564         case CSSSelector::List: {
1565             int sel_len = sel->value.length();
1566             int val_len = value->length();
1567             // Be smart compare on length first
1568             if ((!sel_len && !val_len) || sel_len > val_len) {
1569                 return false;
1570             }
1571             // Selector string may not contain spaces
1572             if ((selAttr != ATTR_CLASS || e->hasClass()) && sel->value.string().find(' ') != -1) {
1573                 return false;
1574             }
1575             if (sel_len == val_len)
1576                 return caseSensitive ?
1577                        !strcmp(sel->value.impl(), value) :
1578                        !strcasecmp(sel->value.impl(), value);
1579             // else the value is longer and can be a list
1580 
1581             QChar *sel_uc = sel->value.string().unicode();
1582             QChar *val_uc = value->unicode();
1583 
1584             QString sel_str = QString::fromRawData(sel_uc, sel_len);
1585             QString val_str = QString::fromRawData(val_uc, val_len);
1586 
1587             int pos = 0;
1588             for (;;) {
1589                 pos = val_str.indexOf(sel_str, pos, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
1590                 if (pos == -1) {
1591                     return false;
1592                 }
1593                 if (pos == 0 || val_uc[pos - 1].isSpace()) {
1594                     int endpos = pos + sel_len;
1595                     if (endpos >= val_len || val_uc[endpos].isSpace()) {
1596                         break;    // We have a match.
1597                     }
1598                 }
1599                 ++pos;
1600             }
1601             break;
1602         }
1603         case CSSSelector::Contain: {
1604             //qCDebug(KHTML_LOG) << "checking for contains match";
1605             QString val_str = QString::fromRawData(value->unicode(), value->length());
1606             QString sel_str = QString::fromRawData(sel->value.string().unicode(), sel->value.length());
1607             return val_str.contains(sel_str, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive) && !sel_str.isEmpty();
1608         }
1609         case CSSSelector::Begin: {
1610             //qCDebug(KHTML_LOG) << "checking for beginswith match";
1611             DOMStringImpl *selValue = sel->value.impl();
1612             return selValue && selValue->length() && value->startsWith(selValue, caseSensitive ? DOM::CaseSensitive : DOM::CaseInsensitive);
1613         }
1614         case CSSSelector::End: {
1615             //qCDebug(KHTML_LOG) << "checking for endswith match";
1616             DOMStringImpl *selValue = sel->value.impl();
1617             return selValue && selValue->length() && value->endsWith(selValue, caseSensitive ? DOM::CaseSensitive : DOM::CaseInsensitive);
1618         }
1619         case CSSSelector::Hyphen: {
1620             //qCDebug(KHTML_LOG) << "checking for hyphen match";
1621             DOMStringImpl *selValue = sel->value.impl();
1622             if (value->length() < selValue->length()) {
1623                 return false;
1624             }
1625             // Check if value begins with selStr:
1626             if (!value->startsWith(selValue, caseSensitive ? DOM::CaseSensitive : DOM::CaseInsensitive)) {
1627                 return false;
1628             }
1629             // It does. Check for exact match or following '-':
1630             return value->length() == selValue->length() || (*value)[selValue->length()].unicode() == '-';
1631         }
1632         case CSSSelector::PseudoClass:
1633         case CSSSelector::PseudoElement:
1634         case CSSSelector::None:
1635             break;
1636         }
1637     }
1638 
1639     if (sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement) {
1640         switch (sel->pseudoType()) {
1641         // Pseudo classes:
1642         case CSSSelector::PseudoEmpty: {
1643             addDependency(BackwardsStructuralDependency, e);
1644             // If e is not closed yet we don't know the number of children
1645             if (!e->closed()) {
1646                 return false;
1647             }
1648             NodeImpl *t = e->firstChild();
1649 
1650             // check for empty text nodes and comments
1651             while (t && (t->nodeType() == Node::COMMENT_NODE ||
1652                          (t->isTextNode() && static_cast<TextImpl *>(t)->length() == 0))) {
1653                 t = t->nextSibling();
1654             }
1655 
1656             return !t;
1657             break;
1658         }
1659         case CSSSelector::PseudoFirstChild: {
1660             // first-child matches the first child that is an element!
1661             if (e->parentNode() && e->parentNode()->isElementNode()) {
1662                 // Handle dynamic DOM changes
1663                 addDependency(StructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1664                 DOM::NodeImpl *n = e->previousSibling();
1665                 while (n && !n->isElementNode()) {
1666                     n = n->previousSibling();
1667                 }
1668                 if (!n) {
1669                     return true;
1670                 }
1671             }
1672             break;
1673         }
1674         case CSSSelector::PseudoLastChild: {
1675             // last-child matches the last child that is an element!
1676             if (e->parentNode() && e->parentNode()->isElementNode()) {
1677                 // Handle unfinished parsing and dynamic DOM changes
1678                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1679                 if (!e->parentNode()->closed()) {
1680 //                     qCDebug(KHTML_LOG) << e->nodeName().string() << "::last-child: Parent unclosed";
1681                     return false;
1682                 }
1683                 DOM::NodeImpl *n = e->nextSibling();
1684                 while (n && !n->isElementNode()) {
1685                     n = n->nextSibling();
1686                 }
1687                 if (!n) {
1688                     return true;
1689                 }
1690             }
1691             break;
1692         }
1693         case CSSSelector::PseudoOnlyChild: {
1694             // If both first-child and last-child apply, then only-child applies.
1695             if (e->parentNode() && e->parentNode()->isElementNode()) {
1696                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1697                 if (!e->parentNode()->closed()) {
1698                     return false;
1699                 }
1700                 DOM::NodeImpl *n = e->previousSibling();
1701                 while (n && !n->isElementNode()) {
1702                     n = n->previousSibling();
1703                 }
1704                 if (!n) {
1705                     n = e->nextSibling();
1706                     while (n && !n->isElementNode()) {
1707                         n = n->nextSibling();
1708                     }
1709                     if (!n) {
1710                         return true;
1711                     }
1712                 }
1713             }
1714             break;
1715         }
1716         case CSSSelector::PseudoNthChild: {
1717             // nth-child matches every (a*n+b)th element!
1718             if (e->parentNode() && e->parentNode()->isElementNode()) {
1719                 addDependency(StructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1720                 int count = 1;
1721                 DOM::NodeImpl *n = e->previousSibling();
1722                 while (n) {
1723                     if (n->isElementNode()) {
1724                         count++;
1725                     }
1726                     n = n->previousSibling();
1727                 }
1728 //                 qCDebug(KHTML_LOG) << "NthChild " << count << "=" << sel->string_arg;
1729                 if (matchNth(count, sel->string_arg.string())) {
1730                     return true;
1731                 }
1732             }
1733             break;
1734         }
1735         case CSSSelector::PseudoNthLastChild: {
1736             if (e->parentNode() && e->parentNode()->isElementNode()) {
1737                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1738                 if (!e->parentNode()->closed()) {
1739                     return false;
1740                 }
1741                 int count = 1;
1742                 DOM::NodeImpl *n = e->nextSibling();
1743                 while (n) {
1744                     if (n->isElementNode()) {
1745                         count++;
1746                     }
1747                     n = n->nextSibling();
1748                 }
1749 //                qCDebug(KHTML_LOG) << "NthLastChild " << count << "=" << sel->string_arg;
1750                 if (matchNth(count, sel->string_arg.string())) {
1751                     return true;
1752                 }
1753             }
1754             break;
1755         }
1756         case CSSSelector::PseudoFirstOfType: {
1757             // first-of-type matches the first element of its type!
1758             if (e->parentNode() && e->parentNode()->isElementNode()) {
1759                 addDependency(StructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1760                 const DOMString &type = e->tagName();
1761                 DOM::NodeImpl *n = e->previousSibling();
1762                 while (n) {
1763                     if (n->isElementNode())
1764                         if (static_cast<ElementImpl *>(n)->tagName() == type) {
1765                             break;
1766                         }
1767                     n = n->previousSibling();
1768                 }
1769                 if (!n) {
1770                     return true;
1771                 }
1772             }
1773             break;
1774         }
1775         case CSSSelector::PseudoLastOfType: {
1776             // last-child matches the last child that is an element!
1777             if (e->parentNode() && e->parentNode()->isElementNode()) {
1778                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1779                 if (!e->parentNode()->closed()) {
1780                     return false;
1781                 }
1782                 const DOMString &type = e->tagName();
1783                 DOM::NodeImpl *n = e->nextSibling();
1784                 while (n) {
1785                     if (n->isElementNode())
1786                         if (static_cast<ElementImpl *>(n)->tagName() == type) {
1787                             break;
1788                         }
1789                     n = n->nextSibling();
1790                 }
1791                 if (!n) {
1792                     return true;
1793                 }
1794             }
1795             break;
1796         }
1797         case CSSSelector::PseudoOnlyOfType: {
1798             // If both first-of-type and last-of-type apply, then only-of-type applies.
1799             if (e->parentNode() && e->parentNode()->isElementNode()) {
1800                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1801                 if (!e->parentNode()->closed()) {
1802                     return false;
1803                 }
1804                 const DOMString &type = e->tagName();
1805                 DOM::NodeImpl *n = e->previousSibling();
1806                 while (n && !(n->isElementNode() && static_cast<ElementImpl *>(n)->tagName() == type)) {
1807                     n = n->previousSibling();
1808                 }
1809                 if (!n) {
1810                     n = e->nextSibling();
1811                     while (n && !(n->isElementNode() && static_cast<ElementImpl *>(n)->tagName() == type)) {
1812                         n = n->nextSibling();
1813                     }
1814                     if (!n) {
1815                         return true;
1816                     }
1817                 }
1818             }
1819             break;
1820         }
1821         case CSSSelector::PseudoNthOfType: {
1822             // nth-of-type matches every (a*n+b)th element of this type!
1823             if (e->parentNode() && e->parentNode()->isElementNode()) {
1824                 addDependency(StructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1825                 int count = 1;
1826                 const DOMString &type = e->tagName();
1827                 DOM::NodeImpl *n = e->previousSibling();
1828                 while (n) {
1829                     if (n->isElementNode() && static_cast<ElementImpl *>(n)->tagName() == type) {
1830                         count++;
1831                     }
1832                     n = n->previousSibling();
1833                 }
1834 //                qCDebug(KHTML_LOG) << "NthOfType " << count << "=" << sel->string_arg;
1835                 if (matchNth(count, sel->string_arg.string())) {
1836                     return true;
1837                 }
1838             }
1839             break;
1840         }
1841         case CSSSelector::PseudoNthLastOfType: {
1842             if (e->parentNode() && e->parentNode()->isElementNode()) {
1843                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl *>(e->parentNode()));
1844                 if (!e->parentNode()->closed()) {
1845                     return false;
1846                 }
1847                 int count = 1;
1848                 const DOMString &type = e->tagName();
1849                 DOM::NodeImpl *n = e->nextSibling();
1850                 while (n) {
1851                     if (n->isElementNode() && static_cast<ElementImpl *>(n)->tagName() == type) {
1852                         count++;
1853                     }
1854                     n = n->nextSibling();
1855                 }
1856 //                qCDebug(KHTML_LOG) << "NthLastOfType " << count << "=" << sel->string_arg;
1857                 if (matchNth(count, sel->string_arg.string())) {
1858                     return true;
1859                 }
1860             }
1861             break;
1862         }
1863         case CSSSelector::PseudoTarget:
1864             if (e == e->document()->getCSSTarget()) {
1865                 return true;
1866             }
1867             break;
1868         case CSSSelector::PseudoRoot:
1869             if (e == e->document()->documentElement()) {
1870                 return true;
1871             }
1872             break;
1873         case CSSSelector::PseudoLink:
1874             if (e == element) {
1875                 // cache pseudoState
1876                 if (pseudoState == PseudoUnknown) {
1877                     pseudoState = checkPseudoState(encodedurl, e);
1878                 }
1879                 if (pseudoState == PseudoLink) {
1880                     return true;
1881                 }
1882             } else {
1883                 return checkPseudoState(encodedurl, e) == PseudoLink;
1884             }
1885             break;
1886         case CSSSelector::PseudoVisited:
1887             if (e == element) {
1888                 // cache pseudoState
1889                 if (pseudoState == PseudoUnknown) {
1890                     pseudoState = checkPseudoState(encodedurl, e);
1891                 }
1892                 if (pseudoState == PseudoVisited) {
1893                     return true;
1894                 }
1895             } else {
1896                 return checkPseudoState(encodedurl, e) == PseudoVisited;
1897             }
1898             break;
1899         case CSSSelector::PseudoHover: {
1900             // If we're in quirks mode, then *:hover should only match focusable elements.
1901             if (strictParsing || (selTag != anyQName) || isSubSelector || e->isFocusable()) {
1902                 addDependency(HoverDependency, e);
1903 
1904                 if (e->hovered()) {
1905                     return true;
1906                 }
1907             }
1908             break;
1909         }
1910         case CSSSelector::PseudoActive:
1911             // If we're in quirks mode, then *:active should only match focusable elements
1912             if (strictParsing || (selTag != anyQName) || isSubSelector || e->isFocusable()) {
1913                 addDependency(ActiveDependency, e);
1914 
1915                 if (e->active()) {
1916                     return true;
1917                 }
1918             }
1919             break;
1920         case CSSSelector::PseudoFocus:
1921             if (e != element && e->isFocusable()) {
1922                 // *:focus is a default style, no need to track it.
1923                 addDependency(OtherStateDependency, e);
1924             }
1925             if (e->focused()) {
1926                 return true;
1927             }
1928             break;
1929         case CSSSelector::PseudoLang: {
1930             // Set dynamic attribute dependency
1931             if (e == element) {
1932                 e->document()->dynamicDomRestyler().addDependency(ATTR_LANG, PersonalDependency);
1933                 e->document()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
1934             } else if (isAncestor) {
1935                 e->document()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
1936             } else {
1937                 e->document()->dynamicDomRestyler().addDependency(ATTR_LANG, PredecessorDependency);
1938             }
1939             // ### check xml:lang attribute in XML and XHTML documents
1940             DOMStringImpl *value = e->getAttributeImplById(ATTR_LANG);
1941             // The LANG attribute is inherited like a property
1942             NodeImpl *n = e->parent();
1943             while (n && !(value && value->length())) {
1944                 if (n->isElementNode()) {
1945                     value = static_cast<ElementImpl *>(n)->getAttributeImplById(ATTR_LANG);
1946                 } else if (n->isDocumentNode()) {
1947                     value = static_cast<DocumentImpl *>(n)->contentLanguage().implementation();
1948                 }
1949                 n = n->parent();
1950             }
1951             if (!(value && value->length())) {
1952                 return false;
1953             }
1954 
1955             DOMStringImpl *langValue = sel->string_arg.implementation();
1956             if (value->length() < langValue->length()) {
1957                 return false;
1958             }
1959             if (!value->startsWith(langValue, DOM::CaseInsensitive)) {
1960                 return false;
1961             }
1962             if (value->length() != langValue->length() && (*value)[langValue->length()].unicode() != '-') {
1963                 return false;
1964             }
1965             return true;
1966         }
1967         case CSSSelector::PseudoNot: {
1968             // check the simple selector
1969             for (CSSSelector *subSel = sel->simpleSelector; subSel;
1970                     subSel = subSel->tagHistory) {
1971                 // :not cannot nest.  I don't really know why this is a restriction in CSS3,
1972                 // but it is, so let's honor it.
1973                 if (subSel->simpleSelector) {
1974                     break;
1975                 }
1976                 if (!checkSimpleSelector(subSel, e, isAncestor, true)) {
1977                     return true;
1978                 }
1979             }
1980             break;
1981         }
1982         case CSSSelector::PseudoEnabled: {
1983             if (e->isGenericFormElement()) {
1984                 addDependency(OtherStateDependency, e);
1985                 HTMLGenericFormElementImpl *form;
1986                 form = static_cast<HTMLGenericFormElementImpl *>(e);
1987                 return !form->disabled() && !form->isHiddenInput();
1988             }
1989             break;
1990         }
1991         case CSSSelector::PseudoDisabled: {
1992             if (e->isGenericFormElement()) {
1993                 addDependency(OtherStateDependency, e);
1994                 HTMLGenericFormElementImpl *form;
1995                 form = static_cast<HTMLGenericFormElementImpl *>(e);
1996                 return form->disabled() && !form->isHiddenInput();
1997             }
1998             break;
1999         }
2000         case CSSSelector::PseudoContains: {
2001             if (e->isHTMLElement()) {
2002                 addDependency(BackwardsStructuralDependency, e);
2003                 if (!e->closed()) {
2004                     return false;
2005                 }
2006                 HTMLElementImpl *elem;
2007                 elem = static_cast<HTMLElementImpl *>(e);
2008                 DOMString s = elem->innerText();
2009                 QString selStr = sel->string_arg.string();
2010 //                qCDebug(KHTML_LOG) << ":contains(\"" << selStr << "\")" << " on \"" << s << "\"";
2011                 return s.string().contains(selStr);
2012             }
2013             break;
2014         }
2015         case CSSSelector::PseudoDefault: {
2016             if (e->isGenericFormElement()) {
2017                 return static_cast<HTMLGenericFormElementImpl *>(e)->isDefault();
2018             }
2019             break;
2020         }
2021         case CSSSelector::PseudoReadWrite:
2022             if (e->isGenericFormElement()) {
2023                 HTMLGenericFormElementImpl *fe = static_cast<HTMLGenericFormElementImpl *>(e);
2024                 // no need for dependency tracking - readonly attr change always triggers a recalc
2025                 return fe->isEditable() && !fe->readOnly();
2026             } else {
2027                 // ### contentEditable should either not be accessible from CSS, or should not trigger selection
2028                 //     by this pseudo class. See with CSS WG.
2029                 return e->isContentEditable();
2030             }
2031             break;
2032         case CSSSelector::PseudoReadOnly:
2033             if (e->isGenericFormElement()) {
2034                 HTMLGenericFormElementImpl *fe = static_cast<HTMLGenericFormElementImpl *>(e);
2035                 // no need for dependency tracking - readonly attr change always triggers a recalc
2036                 return !fe->isEditable() || fe->readOnly();
2037             } else {
2038                 // ### contentEditable should either not be accessible from CSS, or should not trigger selection
2039                 //     by this pseudo class. See with CSS WG.
2040                 return !e->isContentEditable();
2041             }
2042             break;
2043         case CSSSelector::PseudoChecked: {
2044             if (e->isHTMLElement() && e->id() == ID_INPUT) {
2045                 HTMLInputElementImpl *ie = static_cast<HTMLInputElementImpl *>(e);
2046                 addDependency(OtherStateDependency, e);
2047                 return (ie->checked() &&
2048                         (ie->inputType() == HTMLInputElementImpl::RADIO || ie->inputType() == HTMLInputElementImpl::CHECKBOX));
2049             }
2050             return false;
2051         }
2052         case CSSSelector::PseudoIndeterminate: {
2053 #if 0
2054             if (e->isHTMLElement() && e->id() == ID_INPUT) {
2055                 return (static_cast<HTMLInputElementImpl *>(e)->indeterminate() &&
2056                         !static_cast<HTMLInputElementImpl *>(e)->checked());
2057             }
2058             return false;
2059 #endif
2060         }
2061         case CSSSelector::PseudoOther:
2062             break;
2063 
2064         // Pseudo-elements:
2065         case CSSSelector::PseudoFirstLine:
2066         case CSSSelector::PseudoFirstLetter:
2067         case CSSSelector::PseudoSelection:
2068         case CSSSelector::PseudoBefore:
2069         case CSSSelector::PseudoAfter:
2070         case CSSSelector::PseudoMarker:
2071         case CSSSelector::PseudoReplaced:
2072             // Pseudo-elements can only apply to subject
2073             if (e == element) {
2074                 // Pseudo-elements has to be the last sub-selector on subject
2075                 if (sel->tagHistory && sel->relation == CSSSelector::SubSelector) {
2076                     return false;
2077                 }
2078 
2079                 assert(dynamicPseudo == RenderStyle::NOPSEUDO);
2080 
2081                 switch (sel->pseudoType()) {
2082                 case CSSSelector::PseudoFirstLine:
2083                     dynamicPseudo = RenderStyle::FIRST_LINE;
2084                     break;
2085                 case CSSSelector::PseudoFirstLetter:
2086                     dynamicPseudo = RenderStyle::FIRST_LETTER;
2087                     break;
2088                 case CSSSelector::PseudoSelection:
2089                     dynamicPseudo = RenderStyle::SELECTION;
2090                     break;
2091                 case CSSSelector::PseudoBefore:
2092                     dynamicPseudo = RenderStyle::BEFORE;
2093                     break;
2094                 case CSSSelector::PseudoAfter:
2095                     dynamicPseudo = RenderStyle::AFTER;
2096                     break;
2097                 case CSSSelector::PseudoMarker:
2098                     dynamicPseudo = RenderStyle::MARKER;
2099                     break;
2100                 case CSSSelector::PseudoReplaced:
2101                     dynamicPseudo = RenderStyle::REPLACED;
2102                     break;
2103                 default:
2104                     assert(false);
2105                 }
2106                 return true;
2107             }
2108             break;
2109         case CSSSelector::PseudoNotParsed:
2110             assert(false);
2111             break;
2112         }
2113         return false;
2114     }
2115     // ### add the rest of the checks...
2116     return true;
2117 }
2118 
2119 void CSSStyleSelector::clearLists()
2120 {
2121     delete[] selectors;
2122     if (selectorCache) {
2123         delete[] selectorCache;
2124         delete[] nextSimilarSelector;
2125     }
2126     if (propertiesBuffer) {
2127         delete[] propertiesBuffer;
2128         delete[] nextPropertyIndexes;
2129     }
2130     selectors = nullptr;
2131     propertiesBuffer = nullptr;
2132     selectorCache = nullptr;
2133     nextPropertyIndexes = nullptr;
2134 
2135     classSelector.clear();
2136     idSelector.clear();
2137     tagSelector.clear();
2138 }
2139 
2140 void CSSStyleSelector::setupDefaultRootStyle(DOM::DocumentImpl *d)
2141 {
2142     assert(m_fontSizes.size());
2143 
2144     // We only care about setting up a default font
2145     // that the media queries module can use early for
2146     // computing its font-relative units (e.g.em/ex)
2147     if (d) {
2148         // setup some variables needed by applyRule
2149         logicalDpiY = d->logicalDpiY();
2150         if (d->view()) {
2151             view = d->view();
2152         }
2153         if (view) {
2154             part = view->part();
2155         }
2156         if (part) {
2157             settings = part->settings();
2158         }
2159     }
2160     parentNode = nullptr;
2161     delete m_rootDefaultStyle;
2162     m_rootDefaultStyle = style = new RenderStyle();
2163     CSSInitialValueImpl i(true);
2164     applyRule(CSS_PROP_FONT_SIZE, &i);
2165     style->htmlFont().update(logicalDpiY);
2166     fontDirty = false;
2167 }
2168 
2169 void CSSStyleSelector::buildLists()
2170 {
2171     clearLists();
2172     // collect all selectors and Properties in lists. Then transfer them to the array for faster lookup.
2173 
2174     QList<CSSSelector *> selectorList;
2175     CSSOrderedPropertyList propertyList;
2176     WTF::HashMap<CSSSelector *, int> selectorsCache;
2177 
2178     if (defaultPrintStyle && m_medium->mediaTypeMatchSpecific("print"))
2179         defaultPrintStyle->collect(&selectorsCache, &selectorList, &propertyList, Default,
2180                                    Default);
2181     else if (defaultStyle) defaultStyle->collect(&selectorsCache, &selectorList, &propertyList,
2182                 Default, Default);
2183 
2184     if (!strictParsing && defaultQuirksStyle) {
2185         defaultQuirksStyle->collect(&selectorsCache, &selectorList, &propertyList, Default, Default);
2186     }
2187 
2188     if (userStyle) {
2189         userStyle->collect(&selectorsCache, &selectorList, &propertyList, User, UserImportant);
2190     }
2191 
2192     if (defaultNonCSSHintsStyle) {
2193         defaultNonCSSHintsStyle->collect(&selectorsCache, &selectorList, &propertyList, NonCSSHint, NonCSSHint);
2194     }
2195 
2196     // Implicit styles are gathered from hidden, dynamically generated, implicit stylesheets.
2197     // They have the same priority as presentational attributes.
2198     if (implicitStyle) {
2199         implicitStyle->collect(&selectorsCache, &selectorList, &propertyList, NonCSSHint, NonCSSHint);
2200     }
2201 
2202     if (authorStyle) {
2203         authorStyle->collect(&selectorsCache, &selectorList, &propertyList, Author, AuthorImportant);
2204     }
2205 
2206     selectors_size = selectorList.count();
2207     selectors = new CSSSelector *[selectors_size];
2208     CSSSelector **sel = selectors;
2209     for (QListIterator<CSSSelector *> sit(selectorList); sit.hasNext(); ++sel) {
2210         *sel = sit.next();
2211     }
2212 
2213     selectorCache = new SelectorCache[selectors_size];
2214     for (unsigned int i = 0; i < selectors_size; i++) {
2215         selectorCache[i].state = Unknown;
2216         selectorCache[i].firstPropertyIndex = propertyList.size();
2217     }
2218 
2219     // do some pre-compution to make styleForElement faster:
2220     // 1. class selectors: put in hash by selector value
2221     // 2. the same goes for id selectors
2222     // 3. put tag selectors in hash by id
2223     // 4. other selectors (shouldn't be much) goes to plain list
2224     nextSimilarSelector = new unsigned[selectors_size];
2225     otherSelector = selectors_size;
2226     for (unsigned int i = 0; i < selectors_size; ++i) {
2227         nextSimilarSelector[i] = selectors_size;
2228     }
2229     for (int i = selectors_size - 1; i >= 0; --i) {
2230         if (selectors[i]->match == CSSSelector::Class) {
2231             pair<WTF::HashMap<quintptr, int>::iterator, bool> it = classSelector.add((quintptr)selectors[i]->value.impl(), i);
2232             if (!it.second) {
2233                 nextSimilarSelector[i] = it.first->second;
2234                 it.first->second = i;
2235             }
2236         } else if (selectors[i]->match == CSSSelector::Id) {
2237             pair<WTF::HashMap<quintptr, int>::iterator, bool> it = idSelector.add((quintptr)selectors[i]->value.impl(), i);
2238             if (!it.second) {
2239                 nextSimilarSelector[i] = it.first->second;
2240                 it.first->second = i;
2241             }
2242         } else if (selectors[i]->tagLocalName.id() && selectors[i]->tagLocalName.id() != anyLocalName) {
2243             pair<WTF::HashMap<unsigned, int>::iterator, bool> it = tagSelector.add(selectors[i]->tagLocalName.id(), i);
2244             if (!it.second) {
2245                 nextSimilarSelector[i] = it.first->second;
2246                 it.first->second = i;
2247             }
2248         } else {
2249             nextSimilarSelector[i] = otherSelector;
2250             otherSelector = i;
2251         }
2252     }
2253 
2254     // presort properties. Should make the sort() calls in styleForElement faster.
2255     std::sort(propertyList.begin(), propertyList.end());
2256     properties_size = propertyList.count();
2257     propertiesBuffer = new CSSOrderedProperty[properties_size];
2258     for (int i = 0; i < propertyList.size(); ++i) {
2259         propertiesBuffer[i] = propertyList[i];
2260     }
2261 
2262     // properties for one selector are not necessarily adjacent at this point
2263     // prepare sublists with same selector
2264     // create for every property next property index with same selector
2265     nextPropertyIndexes = new unsigned[properties_size];
2266     for (int i = properties_size - 1; i >= 0; --i) {
2267         unsigned selector = propertiesBuffer[i].selector;
2268         nextPropertyIndexes[i] = selectorCache[selector].firstPropertyIndex;
2269         selectorCache[selector].firstPropertyIndex = i;
2270     }
2271 }
2272 
2273 // ----------------------------------------------------------------------
2274 
2275 CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index)
2276 {
2277     rule = r;
2278     if (rule) {
2279         r->ref();
2280     }
2281     index = _index;
2282     selector = s;
2283 }
2284 
2285 CSSOrderedRule::~CSSOrderedRule()
2286 {
2287     if (rule) {
2288         rule->deref();
2289     }
2290 }
2291 
2292 // -----------------------------------------------------------------
2293 
2294 CSSStyleSelectorList::CSSStyleSelectorList()
2295     : QList<CSSOrderedRule *>()
2296 {
2297 }
2298 CSSStyleSelectorList::~CSSStyleSelectorList()
2299 {
2300     qDeleteAll(*this);
2301     clear();
2302 }
2303 
2304 void CSSStyleSelectorList::append(CSSStyleSheetImpl *sheet,
2305                                   MediaQueryEvaluator *medium, CSSStyleSelector *styleSelector)
2306 {
2307     if (!sheet || !sheet->isCSSStyleSheet()) {
2308         return;
2309     }
2310 
2311     // No media implies "all", but if a medialist exists it must
2312     // contain our current medium
2313     if (sheet->media() && !medium->eval(sheet->media(), styleSelector)) {
2314         return;    // style sheet not applicable for this medium
2315     }
2316 
2317     int len = sheet->length();
2318     for (int i = 0; i < len; i++) {
2319         StyleBaseImpl *item = sheet->item(i);
2320         if (item->isStyleRule()) {
2321             CSSStyleRuleImpl *r = static_cast<CSSStyleRuleImpl *>(item);
2322             QList<CSSSelector *> *s = r->selector();
2323             for (int j = 0; j < s->count(); j++) {
2324                 CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count());
2325                 QList<CSSOrderedRule *>::append(rule);
2326                 //qCDebug(KHTML_LOG) << "appending StyleRule!";
2327             }
2328         } else if (item->isImportRule()) {
2329             CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
2330 
2331             //qCDebug(KHTML_LOG) << "@import: Media: "
2332             //                << import->media()->mediaText().string();
2333 
2334             if (!import->media() || medium->eval(import->media(), styleSelector)) {
2335                 CSSStyleSheetImpl *importedSheet = import->styleSheet();
2336                 append(importedSheet, medium, styleSelector);
2337             }
2338         } else if (item->isMediaRule()) {
2339             CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl *>(item);
2340             CSSRuleListImpl *rules = r->cssRules();
2341 
2342             //qCDebug(KHTML_LOG) << "@media: Media: "
2343             //                << r->media()->mediaText().string();
2344 
2345             if ((!r->media() || medium->eval(r->media(), styleSelector)) && rules) {
2346                 // Traverse child elements of the @import rule. Since
2347                 // many elements are not allowed as child we do not use
2348                 // a recursive call to append() here
2349                 for (unsigned j = 0; j < rules->length(); j++) {
2350                     //qCDebug(KHTML_LOG) << "*** Rule #" << j;
2351 
2352                     CSSRuleImpl *childItem = rules->item(j);
2353                     if (childItem->isStyleRule()) {
2354                         // It is a StyleRule, so append it to our list
2355                         CSSStyleRuleImpl *styleRule =
2356                             static_cast<CSSStyleRuleImpl *>(childItem);
2357 
2358                         QList<CSSSelector *> *s = styleRule->selector();
2359                         for (int j = 0; j < s->count(); j++) {
2360                             CSSOrderedRule *orderedRule = new CSSOrderedRule(
2361                                 styleRule, s->at(j), count());
2362                             QList<CSSOrderedRule *>::append(orderedRule);
2363                         }
2364                     } else if (childItem->isFontFaceRule() && styleSelector) {
2365                         const CSSFontFaceRuleImpl *fontFaceRule = static_cast<CSSFontFaceRuleImpl *>(childItem);
2366                         styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2367                     } else {
2368                         //qCDebug(KHTML_LOG) << "Ignoring child rule of "
2369                         //    "ImportRule: rule is not a StyleRule!";
2370                     }
2371                 }   // for rules
2372             }   // if rules
2373             else {
2374                 //qCDebug(KHTML_LOG) << "CSSMediaRule not rendered: "
2375                 //                << "rule empty or wrong medium!";
2376             }
2377         } else if (item->isFontFaceRule() && styleSelector) {
2378             const CSSFontFaceRuleImpl *fontFaceRule = static_cast<CSSFontFaceRuleImpl *>(item);
2379             styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2380         }
2381         // ### include other rules
2382     }
2383 }
2384 
2385 void CSSStyleSelectorList::collect(WTF::HashMap<CSSSelector *, int> *selectorsCache, QList<CSSSelector *> *selectorList,
2386                                    CSSOrderedPropertyList *propList, Source regular, Source important)
2387 {
2388     CSSOrderedRule *r;
2389     QListIterator<CSSOrderedRule *> tIt(*this);
2390 
2391     propList->reserve(propList->size() + selectorList->size());
2392     while (tIt.hasNext()) {
2393         r = tIt.next();
2394         int selectorNum = selectorsCache->size();
2395         pair<WTF::HashMap<CSSSelector *, int>::iterator, bool> cacheIterator = selectorsCache->add(r->selector, selectorNum);
2396         if (cacheIterator.second) {
2397             selectorList->append(r->selector);
2398         }
2399         selectorNum = cacheIterator.first->second;
2400         propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important);
2401     }
2402 }
2403 
2404 // -------------------------------------------------------------------------
2405 
2406 void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
2407                                     Source regular, Source important)
2408 {
2409     QList<CSSProperty *> *values = decl->values();
2410     if (!values) {
2411         return;
2412     }
2413     int len = values->count();
2414     for (int i = 0; i < len; i++) {
2415         CSSProperty *prop = values->at(i);
2416         Source source = regular;
2417 
2418         if (prop->m_important) {
2419             source = important;
2420         }
2421 
2422         bool first = false;
2423         // give special priority to font-xxx, color properties
2424         switch (prop->m_id) {
2425         case CSS_PROP_FONT_STYLE:
2426         case CSS_PROP_FONT_SIZE:
2427         case CSS_PROP_FONT_WEIGHT:
2428         case CSS_PROP_FONT_FAMILY:
2429         case CSS_PROP_FONT_VARIANT:
2430         case CSS_PROP_FONT:
2431         case CSS_PROP_COLOR:
2432         case CSS_PROP_DIRECTION:
2433         case CSS_PROP_DISPLAY:
2434             // these have to be applied first, because other properties use the computed
2435             // values of these porperties.
2436             first = true;
2437             break;
2438         default:
2439             break;
2440         }
2441 
2442         QVector<CSSOrderedProperty>::append(CSSOrderedProperty(prop, selector, first, source, specificity, count()));
2443     }
2444 }
2445 
2446 // -------------------------------------------------------------------------------------
2447 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2448 
2449 static Length convertToLength(CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, RenderStyle *rootStyle, int logicalDpiY, bool *ok = nullptr)
2450 {
2451     Length l;
2452     if (!primitiveValue) {
2453         if (ok) {
2454             *ok = false;
2455         }
2456     } else {
2457         int type = primitiveValue->primitiveType();
2458         if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
2459             l = Length(primitiveValue->computeLength(style, rootStyle, logicalDpiY), Fixed);
2460         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
2461             l = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2462         } else if (type == CSSPrimitiveValue::CSS_NUMBER) {
2463             l = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER) * 100.0, Percent);
2464         } else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE) {
2465             l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
2466         } else if (ok) {
2467             *ok = false;
2468         }
2469     }
2470     return l;
2471 }
2472 
2473 static inline int nextFontSize(const QVector<int> &a, int v, bool smaller)
2474 {
2475     // return the nearest bigger/smaller value in scale a, when v is in range.
2476     // otherwise increase/decrease value using a 1.2 fixed ratio
2477     int m, l = 0, r = a.count() - 1;
2478     while (l <= r) {
2479         m = (l + r) / 2;
2480         if (a[m] == v)
2481             return smaller ? (m ? a[m - 1] : (v * 5) / 6) :
2482                    (m + 1 < int(a.count()) ? a[m + 1] : (v * 6) / 5);
2483         else if (v < a[m]) {
2484             r = m - 1;
2485         } else {
2486             l = m + 1;
2487         }
2488     }
2489     if (!l) {
2490         return smaller ? (v * 5) / 6 : qMin((v * 6) / 5, a[0]);
2491     }
2492     if (l == int(a.count())) {
2493         return smaller ? qMax((v * 5) / 6, a[r]) : (v * 6) / 5;
2494     }
2495 
2496     return smaller ? a[r] : a[l];
2497 }
2498 
2499 // If we're explicitly inheriting an initial border-color, its computed value is based
2500 // on the parents' computed value of color, not ours.
2501 static QColor inheritedBorderColor(RenderStyle *parentStyle, const QColor &value)
2502 {
2503     if (value.isValid()) {
2504         return value;
2505     } else {
2506         return parentStyle->color();
2507     }
2508 }
2509 
2510 void CSSStyleSelector::applyRule(int id, DOM::CSSValueImpl *value)
2511 {
2512 //     qCDebug(KHTML_LOG) << "applying property " << getPropertyName(id);
2513 
2514     CSSPrimitiveValueImpl *primitiveValue = nullptr;
2515     if (value->isPrimitiveValue()) {
2516         primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
2517     }
2518 
2519     Length l;
2520     bool apply = false;
2521 
2522     bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
2523     bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) ||
2524                      (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
2525 
2526     // These properties are used to set the correct margins/padding on RTL lists.
2527     if (id == CSS_PROP__KHTML_MARGIN_START) {
2528         id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
2529     } else if (id == CSS_PROP__KHTML_PADDING_START) {
2530         id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
2531     }
2532 
2533     // What follows is a list that maps the CSS properties into their corresponding front-end
2534     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
2535     // are only hit when mapping "inherit" or "initial" into front-end values.
2536     switch (id) {
2537 // ident only properties
2538     case CSS_PROP_BACKGROUND_ATTACHMENT:
2539         HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
2540         break;
2541     case CSS_PROP_BACKGROUND_CLIP:
2542         HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
2543         break;
2544     case CSS_PROP_BACKGROUND_ORIGIN:
2545         HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
2546         break;
2547     case CSS_PROP_BACKGROUND_REPEAT:
2548         HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
2549         break;
2550     case CSS_PROP_BACKGROUND_SIZE:
2551         HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
2552         break;
2553     case CSS_PROP_BORDER_COLLAPSE:
2554         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(borderCollapse, BorderCollapse)
2555         if (!primitiveValue) {
2556             break;
2557         }
2558         switch (primitiveValue->getIdent()) {
2559         case CSS_VAL_COLLAPSE:
2560             style->setBorderCollapse(true);
2561             break;
2562         case CSS_VAL_SEPARATE:
2563             style->setBorderCollapse(false);
2564             break;
2565         default:
2566             return;
2567         }
2568         break;
2569 
2570     case CSS_PROP_BORDER_TOP_STYLE:
2571         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
2572         if (!primitiveValue) {
2573             return;
2574         }
2575         style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
2576         break;
2577     case CSS_PROP_BORDER_RIGHT_STYLE:
2578         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
2579         if (!primitiveValue) {
2580             return;
2581         }
2582         style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
2583         break;
2584     case CSS_PROP_BORDER_BOTTOM_STYLE:
2585         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
2586         if (!primitiveValue) {
2587             return;
2588         }
2589         style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
2590         break;
2591     case CSS_PROP_BORDER_LEFT_STYLE:
2592         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
2593         if (!primitiveValue) {
2594             return;
2595         }
2596         style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
2597         break;
2598     case CSS_PROP_OUTLINE_STYLE:
2599         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
2600         if (!primitiveValue) {
2601             return;
2602         }
2603         style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
2604         break;
2605     case CSS_PROP_CAPTION_SIDE: {
2606         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(captionSide, CaptionSide)
2607 
2608         if (!primitiveValue) {
2609             break;
2610         }
2611         ECaptionSide c = RenderStyle::initialCaptionSide();
2612         switch (primitiveValue->getIdent()) {
2613         case CSS_VAL_LEFT:
2614             c = CAPLEFT; break;
2615         case CSS_VAL_RIGHT:
2616             c = CAPRIGHT; break;
2617         case CSS_VAL_TOP:
2618             c = CAPTOP; break;
2619         case CSS_VAL_BOTTOM:
2620             c = CAPBOTTOM; break;
2621         default:
2622             return;
2623         }
2624         style->setCaptionSide(c);
2625         return;
2626     }
2627     case CSS_PROP_CLEAR: {
2628         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(clear, Clear)
2629         if (!primitiveValue) {
2630             break;
2631         }
2632         EClear c = CNONE;
2633         switch (primitiveValue->getIdent()) {
2634         case CSS_VAL_LEFT:
2635             c = CLEFT; break;
2636         case CSS_VAL_RIGHT:
2637             c = CRIGHT; break;
2638         case CSS_VAL_BOTH:
2639             c = CBOTH; break;
2640         case CSS_VAL_NONE:
2641             c = CNONE; break;
2642         default:
2643             return;
2644         }
2645         style->setClear(c);
2646         return;
2647     }
2648     case CSS_PROP_DIRECTION: {
2649         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(direction, Direction)
2650         if (!primitiveValue) {
2651             break;
2652         }
2653         style->setDirection((EDirection)(primitiveValue->getIdent() - CSS_VAL_LTR));
2654         return;
2655     }
2656     case CSS_PROP_DISPLAY: {
2657         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(display, Display)
2658         if (!primitiveValue) {
2659             break;
2660         }
2661         int id = primitiveValue->getIdent();
2662         style->setDisplay(id == CSS_VAL_NONE ? NONE : EDisplay(id - CSS_VAL_INLINE));
2663         break;
2664     }
2665 
2666     case CSS_PROP_EMPTY_CELLS: {
2667         HANDLE_INHERIT_ON_INHERITED_PROPERTY(emptyCells, EmptyCells);
2668         if (!primitiveValue) {
2669             break;
2670         }
2671         int id = primitiveValue->getIdent();
2672         if (id == CSS_VAL_SHOW) {
2673             style->setEmptyCells(SHOW);
2674         } else if (id == CSS_VAL_HIDE) {
2675             style->setEmptyCells(HIDE);
2676         }
2677         break;
2678     }
2679     case CSS_PROP_FLOAT: {
2680         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(floating, Floating)
2681         if (!primitiveValue) {
2682             return;
2683         }
2684         EFloat f;
2685         switch (primitiveValue->getIdent()) {
2686         case CSS_VAL__KHTML_LEFT:
2687             f = FLEFT_ALIGN; break;
2688         case CSS_VAL_LEFT:
2689             f = FLEFT; break;
2690         case CSS_VAL__KHTML_RIGHT:
2691             f = FRIGHT_ALIGN; break;
2692         case CSS_VAL_RIGHT:
2693             f = FRIGHT; break;
2694         case CSS_VAL_NONE:
2695         case CSS_VAL_CENTER:  //Non standart CSS-Value
2696             f = FNONE; break;
2697         default:
2698             return;
2699         }
2700         if (f != FNONE && style->display() == LIST_ITEM) {
2701             style->setDisplay(BLOCK);
2702         }
2703 
2704         style->setFloating(f);
2705         break;
2706     }
2707 
2708     case CSS_PROP_FONT_STYLE: {
2709         FontDef fontDef = style->htmlFont().fontDef;
2710         if (isInherit) {
2711             fontDef.italic = parentStyle->htmlFont().fontDef.italic;
2712         } else if (isInitial) {
2713             fontDef.italic = false;
2714         } else {
2715             if (!primitiveValue) {
2716                 return;
2717             }
2718             switch (primitiveValue->getIdent()) {
2719             case CSS_VAL_OBLIQUE:
2720             // ### oblique is the same as italic for the moment...
2721             case CSS_VAL_ITALIC:
2722                 fontDef.italic = true;
2723                 break;
2724             case CSS_VAL_NORMAL:
2725                 fontDef.italic = false;
2726                 break;
2727             default:
2728                 return;
2729             }
2730         }
2731         fontDirty |= style->setFontDef(fontDef);
2732         break;
2733     }
2734 
2735     case CSS_PROP_FONT_VARIANT: {
2736         FontDef fontDef = style->htmlFont().fontDef;
2737         if (isInherit) {
2738             fontDef.smallCaps = parentStyle->htmlFont().fontDef.smallCaps;
2739         } else if (isInitial) {
2740             fontDef.smallCaps = false;
2741         } else {
2742             if (!primitiveValue) {
2743                 return;
2744             }
2745             int id = primitiveValue->getIdent();
2746             if (id == CSS_VAL_NORMAL) {
2747                 fontDef.smallCaps = false;
2748             } else if (id == CSS_VAL_SMALL_CAPS) {
2749                 fontDef.smallCaps = true;
2750             } else {
2751                 return;
2752             }
2753         }
2754         fontDirty |= style->setFontDef(fontDef);
2755         break;
2756     }
2757 
2758     case CSS_PROP_FONT_WEIGHT: {
2759         FontDef fontDef = style->htmlFont().fontDef;
2760         if (isInherit) {
2761             fontDef.weight = parentStyle->htmlFont().fontDef.weight;
2762         } else if (isInitial) {
2763             fontDef.weight = QFont::Normal;
2764         } else if (primitiveValue) {
2765             // Map CSS weights into available QFont::Weight
2766             switch (primitiveValue->getIdent()) {
2767             case CSS_VAL_100:
2768             case CSS_VAL_200:
2769             case CSS_VAL_300:
2770                 fontDef.weight = QFont::Light; // 25
2771                 break;
2772             case CSS_VAL_NORMAL:
2773             case CSS_VAL_400:
2774             case CSS_VAL_500:
2775                 fontDef.weight = QFont::Normal; // 50
2776                 break;
2777             case CSS_VAL_600:
2778                 fontDef.weight = QFont::DemiBold; // 63
2779                 break;
2780             case CSS_VAL_BOLD:
2781             case CSS_VAL_700:
2782                 fontDef.weight = QFont::Bold; // 75
2783                 break;
2784             case CSS_VAL_800:
2785             case CSS_VAL_900:
2786                 fontDef.weight = QFont::Black; // 87
2787                 break;
2788             case CSS_VAL_BOLDER: {
2789                 // FIXME: Should return the next heaviest weight available for current family
2790                 const unsigned int inheritedWeight = parentStyle->htmlFont().fontDef.weight;
2791                 if (inheritedWeight < QFont::Normal) {
2792                     fontDef.weight = QFont::Normal;
2793                 } else if (inheritedWeight < QFont::DemiBold) {
2794                     fontDef.weight = QFont::DemiBold;
2795                 } else if (inheritedWeight < QFont::Bold) {
2796                     fontDef.weight = QFont::Bold;
2797                 } else {
2798                     fontDef.weight = QFont::Black;
2799                 }
2800             }
2801                 break;
2802             case CSS_VAL_LIGHTER: {
2803                 // FIXME: Should return the next lightest weight available for current family
2804                 const unsigned int inheritedWeight = parentStyle->htmlFont().fontDef.weight;
2805                 if (inheritedWeight > QFont::Bold) {
2806                     fontDef.weight = QFont::Bold;
2807                 } else if (inheritedWeight > QFont::DemiBold) {
2808                     fontDef.weight = QFont::DemiBold;
2809                 } else if (inheritedWeight > QFont::Normal) {
2810                     fontDef.weight = QFont::Normal;
2811                 } else {
2812                     fontDef.weight = QFont::Light;
2813                 }
2814             }
2815                 break;
2816             default:
2817                 return;
2818             }
2819         } else {
2820             return;
2821         }
2822         fontDirty |= style->setFontDef( fontDef );
2823         break;
2824     }
2825 
2826     case CSS_PROP_LIST_STYLE_POSITION: {
2827         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(listStylePosition, ListStylePosition)
2828         if (!primitiveValue) {
2829             return;
2830         }
2831         if (primitiveValue->getIdent()) {
2832             style->setListStylePosition((EListStylePosition)(primitiveValue->getIdent() - CSS_VAL_OUTSIDE));
2833         }
2834         return;
2835     }
2836 
2837     case CSS_PROP_LIST_STYLE_TYPE: {
2838         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(listStyleType, ListStyleType)
2839         if (!primitiveValue) {
2840             return;
2841         }
2842         if (primitiveValue->getIdent()) {
2843             EListStyleType t;
2844             int id = primitiveValue->getIdent();
2845             if (id == CSS_VAL_NONE) {  // important!!
2846                 t = LNONE;
2847             } else {
2848                 t = EListStyleType(id - CSS_VAL_DISC);
2849             }
2850             style->setListStyleType(t);
2851         }
2852         return;
2853     }
2854 
2855     case CSS_PROP_OVERFLOW: {
2856         if (isInherit) {
2857             style->setOverflowX(parentStyle->overflowX());
2858             style->setOverflowY(parentStyle->overflowY());
2859             style->setInheritedNoninherited(true);
2860             return;
2861         }
2862 
2863         if (isInitial) {
2864             style->setOverflowX(RenderStyle::initialOverflowX());
2865             style->setOverflowY(RenderStyle::initialOverflowY());
2866             return;
2867         }
2868 
2869         if (!primitiveValue) {
2870             return;
2871         }
2872         EOverflow o;
2873         switch (primitiveValue->getIdent()) {
2874         case CSS_VAL_VISIBLE:
2875             o = OVISIBLE; break;
2876         case CSS_VAL_HIDDEN:
2877             o = OHIDDEN; break;
2878         case CSS_VAL_SCROLL:
2879             o = OSCROLL; break;
2880         case CSS_VAL_AUTO:
2881             o = OAUTO; break;
2882         case CSS_VAL_MARQUEE:
2883             o = OMARQUEE; break;
2884         default:
2885             return;
2886         }
2887         style->setOverflowX(o);
2888         style->setOverflowY(o);
2889         return;
2890     }
2891     case CSS_PROP_OVERFLOW_X: {
2892         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(overflowX, OverflowX)
2893         if (!primitiveValue) {
2894             return;
2895         }
2896         EOverflow o;
2897         switch (primitiveValue->getIdent()) {
2898         case CSS_VAL_VISIBLE:
2899             o = OVISIBLE; break;
2900         case CSS_VAL_HIDDEN:
2901             o = OHIDDEN; break;
2902         case CSS_VAL_SCROLL:
2903             o = OSCROLL; break;
2904         case CSS_VAL_AUTO:
2905             o = OAUTO; break;
2906         default:
2907             return;
2908         }
2909         style->setOverflowX(o);
2910         return;
2911     }
2912     case CSS_PROP_OVERFLOW_Y: {
2913         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(overflowY, OverflowY)
2914         if (!primitiveValue) {
2915             return;
2916         }
2917         EOverflow o;
2918         switch (primitiveValue->getIdent()) {
2919         case CSS_VAL_VISIBLE:
2920             o = OVISIBLE; break;
2921         case CSS_VAL_HIDDEN:
2922             o = OHIDDEN; break;
2923         case CSS_VAL_SCROLL:
2924             o = OSCROLL; break;
2925         case CSS_VAL_AUTO:
2926             o = OAUTO; break;
2927         default:
2928             return;
2929         }
2930         style->setOverflowY(o);
2931         return;
2932     }
2933     case CSS_PROP_PAGE_BREAK_BEFORE: {
2934         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2935         if (!primitiveValue) {
2936             return;
2937         }
2938         switch (primitiveValue->getIdent()) {
2939         case CSS_VAL_AUTO:
2940             style->setPageBreakBefore(PBAUTO);
2941             break;
2942         case CSS_VAL_LEFT:
2943         case CSS_VAL_RIGHT:
2944         // CSS2.1: "Conforming user agents may map left/right to always."
2945         case CSS_VAL_ALWAYS:
2946             style->setPageBreakBefore(PBALWAYS);
2947             break;
2948         case CSS_VAL_AVOID:
2949             style->setPageBreakBefore(PBAVOID);
2950             break;
2951         }
2952         break;
2953     }
2954 
2955     case CSS_PROP_PAGE_BREAK_AFTER: {
2956         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2957         if (!primitiveValue) {
2958             return;
2959         }
2960         switch (primitiveValue->getIdent()) {
2961         case CSS_VAL_AUTO:
2962             style->setPageBreakAfter(PBAUTO);
2963             break;
2964         case CSS_VAL_LEFT:
2965         case CSS_VAL_RIGHT:
2966         // CSS2.1: "Conforming user agents may map left/right to always."
2967         case CSS_VAL_ALWAYS:
2968             style->setPageBreakAfter(PBALWAYS);
2969             break;
2970         case CSS_VAL_AVOID:
2971             style->setPageBreakAfter(PBAVOID);
2972             break;
2973         }
2974         break;
2975     }
2976 
2977     case CSS_PROP_PAGE_BREAK_INSIDE: {
2978         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(pageBreakInside, PageBreakInside)
2979         if (!primitiveValue) {
2980             return;
2981         }
2982         if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
2983             style->setPageBreakInside(true);
2984         } else if (primitiveValue->getIdent() == CSS_VAL_AVOID) {
2985             style->setPageBreakInside(false);
2986         }
2987         return;
2988     }
2989 //    case CSS_PROP_PAUSE_AFTER:
2990 //    case CSS_PROP_PAUSE_BEFORE:
2991     break;
2992 
2993     case CSS_PROP_POSITION: {
2994         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(position, Position)
2995         if (!primitiveValue) {
2996             return;
2997         }
2998         EPosition p;
2999         switch (primitiveValue->getIdent()) {
3000         case CSS_VAL_STATIC:
3001             p = PSTATIC; break;
3002         case CSS_VAL_RELATIVE:
3003             p = PRELATIVE; break;
3004         case CSS_VAL_ABSOLUTE:
3005             p = PABSOLUTE; break;
3006         case CSS_VAL_FIXED:
3007             p = PFIXED; break;
3008         default:
3009             return;
3010         }
3011         style->setPosition(p);
3012         return;
3013     }
3014 
3015     case CSS_PROP_TABLE_LAYOUT: {
3016         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(tableLayout, TableLayout)
3017 
3018         if (!primitiveValue) {
3019             return;
3020         }
3021 
3022         ETableLayout l = RenderStyle::initialTableLayout();
3023         switch (primitiveValue->getIdent()) {
3024         case CSS_VAL_FIXED:
3025             l = TFIXED;
3026         // fall through
3027         case CSS_VAL_AUTO:
3028             style->setTableLayout(l);
3029         default:
3030             break;
3031         }
3032         break;
3033     }
3034 
3035     case CSS_PROP_UNICODE_BIDI: {
3036         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(unicodeBidi, UnicodeBidi)
3037         if (!primitiveValue) {
3038             break;
3039         }
3040         switch (primitiveValue->getIdent()) {
3041         case CSS_VAL_NORMAL:
3042             style->setUnicodeBidi(UBNormal);
3043             break;
3044         case CSS_VAL_EMBED:
3045             style->setUnicodeBidi(Embed);
3046             break;
3047         case CSS_VAL_BIDI_OVERRIDE:
3048             style->setUnicodeBidi(Override);
3049             break;
3050         default:
3051             return;
3052         }
3053         break;
3054     }
3055     case CSS_PROP_TEXT_TRANSFORM: {
3056         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(textTransform, TextTransform)
3057 
3058         if (!primitiveValue) {
3059             break;
3060         }
3061         if (!primitiveValue->getIdent()) {
3062             return;
3063         }
3064 
3065         ETextTransform tt;
3066         switch (primitiveValue->getIdent()) {
3067         case CSS_VAL_CAPITALIZE:  tt = CAPITALIZE;  break;
3068         case CSS_VAL_UPPERCASE:   tt = UPPERCASE;   break;
3069         case CSS_VAL_LOWERCASE:   tt = LOWERCASE;   break;
3070         case CSS_VAL_NONE:
3071         default:                  tt = TTNONE;      break;
3072         }
3073         style->setTextTransform(tt);
3074         break;
3075     }
3076 
3077     case CSS_PROP_VISIBILITY: {
3078         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(visibility, Visibility)
3079 
3080         if (!primitiveValue) {
3081             break;
3082         }
3083         switch (primitiveValue->getIdent()) {
3084         case CSS_VAL_HIDDEN:
3085             style->setVisibility(HIDDEN);
3086             break;
3087         case CSS_VAL_VISIBLE:
3088             style->setVisibility(VISIBLE);
3089             break;
3090         case CSS_VAL_COLLAPSE:
3091             style->setVisibility(COLLAPSE);
3092         default:
3093             break;
3094         }
3095         break;
3096     }
3097     case CSS_PROP_WHITE_SPACE:
3098         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(whiteSpace, WhiteSpace)
3099 
3100         if (!primitiveValue) {
3101             break;
3102         }
3103         if (!primitiveValue->getIdent()) {
3104             return;
3105         }
3106 
3107         EWhiteSpace s;
3108         switch (primitiveValue->getIdent()) {
3109         case CSS_VAL__KHTML_NOWRAP:
3110             s = KHTML_NOWRAP;
3111             break;
3112         case CSS_VAL_NOWRAP:
3113             s = NOWRAP;
3114             break;
3115         case CSS_VAL_PRE:
3116             s = PRE;
3117             break;
3118         case CSS_VAL_PRE_WRAP:
3119             s = PRE_WRAP;
3120             break;
3121         case CSS_VAL_PRE_LINE:
3122             s = PRE_LINE;
3123             break;
3124         case CSS_VAL_NORMAL:
3125         default:
3126             s = NORMAL;
3127             break;
3128         }
3129         style->setWhiteSpace(s);
3130         break;
3131 
3132     case CSS_PROP_BACKGROUND_POSITION:
3133         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
3134         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
3135         break;
3136     case CSS_PROP_BACKGROUND_POSITION_X: {
3137         HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
3138         break;
3139     }
3140     case CSS_PROP_BACKGROUND_POSITION_Y: {
3141         HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
3142         break;
3143     }
3144     case CSS_PROP_BORDER_SPACING: {
3145         if (value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) {
3146             return;
3147         }
3148         style->setBorderHorizontalSpacing(parentStyle->borderHorizontalSpacing());
3149         style->setBorderVerticalSpacing(parentStyle->borderVerticalSpacing());
3150         break;
3151     }
3152     case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: {
3153         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(borderHorizontalSpacing, BorderHorizontalSpacing)
3154         if (!primitiveValue) {
3155             break;
3156         }
3157         short spacing =  primitiveValue->computeLength(style, m_rootStyle, logicalDpiY);
3158         style->setBorderHorizontalSpacing(spacing);
3159         break;
3160     }
3161     case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: {
3162         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(borderVerticalSpacing, BorderVerticalSpacing)
3163         if (!primitiveValue) {
3164             break;
3165         }
3166         short spacing =  primitiveValue->computeLength(style, m_rootStyle, logicalDpiY);
3167         style->setBorderVerticalSpacing(spacing);
3168         break;
3169     }
3170 
3171     case CSS_PROP_BORDER_TOP_RIGHT_RADIUS:
3172     case CSS_PROP_BORDER_TOP_LEFT_RADIUS:
3173     case CSS_PROP_BORDER_BOTTOM_RIGHT_RADIUS:
3174     case CSS_PROP_BORDER_BOTTOM_LEFT_RADIUS: {
3175         if (isInherit) {
3176             style->setInheritedNoninherited(true);
3177             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_RIGHT_RADIUS, borderTopRightRadius, BorderTopRightRadius)
3178             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_LEFT_RADIUS, borderTopLeftRadius, BorderTopLeftRadius)
3179             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_RIGHT_RADIUS, borderBottomRightRadius, BorderBottomRightRadius)
3180             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_LEFT_RADIUS, borderBottomLeftRadius, BorderBottomLeftRadius)
3181             return;
3182         }
3183         if (isInitial) {
3184             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_RIGHT_RADIUS, BorderTopRightRadius, BorderRadius)
3185             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_LEFT_RADIUS, BorderTopLeftRadius, BorderRadius)
3186             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_RIGHT_RADIUS, BorderBottomRightRadius, BorderRadius)
3187             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_LEFT_RADIUS, BorderBottomLeftRadius, BorderRadius)
3188             return;
3189         }
3190 
3191         if (!primitiveValue) {
3192             return;
3193         }
3194 
3195         PairImpl *p = primitiveValue->getPairValue();
3196         if (!p) {
3197             return;
3198         }
3199 
3200         BorderRadii bradii;
3201         bradii.horizontal = convertToLength((p->first()), style, m_rootStyle, logicalDpiY);
3202         bradii.vertical = convertToLength((p->second()), style, m_rootStyle, logicalDpiY);
3203 
3204         switch(id) {
3205             case CSS_PROP_BORDER_TOP_RIGHT_RADIUS:
3206                 style->setBorderTopRightRadius(bradii);
3207                 break;
3208             case CSS_PROP_BORDER_TOP_LEFT_RADIUS:
3209                 style->setBorderTopLeftRadius(bradii);
3210                 break;
3211             case CSS_PROP_BORDER_BOTTOM_RIGHT_RADIUS:
3212                 style->setBorderBottomRightRadius(bradii);
3213                 break;
3214             case CSS_PROP_BORDER_BOTTOM_LEFT_RADIUS:
3215                 style->setBorderBottomLeftRadius(bradii);
3216                 break;
3217             default:
3218                 break;
3219             }
3220         return;
3221     }
3222     break;
3223 
3224     case CSS_PROP_CURSOR:
3225         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(cursor, Cursor)
3226         if (!primitiveValue) {
3227             break;
3228         }
3229         ECursor cursor;
3230         switch (primitiveValue->getIdent()) {
3231         case CSS_VAL_NONE:
3232             cursor = CURSOR_NONE;
3233             break;
3234         default:
3235             cursor = (ECursor)(primitiveValue->getIdent() - CSS_VAL_AUTO);
3236         }
3237         style->setCursor(cursor);
3238         break;
3239 // colors || inherit
3240     case CSS_PROP_COLOR:
3241         // If the 'currentColor' keyword is set on the 'color' property itself,
3242         // it is treated as 'color:inherit' at parse time
3243         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_CURRENTCOLOR) {
3244             isInherit = true;
3245         }
3246     case CSS_PROP_BACKGROUND_COLOR:
3247     case CSS_PROP_BORDER_TOP_COLOR:
3248     case CSS_PROP_BORDER_RIGHT_COLOR:
3249     case CSS_PROP_BORDER_BOTTOM_COLOR:
3250     case CSS_PROP_BORDER_LEFT_COLOR:
3251     case CSS_PROP_OUTLINE_COLOR:
3252     // this property is an extension used to get HTML4 <font> right.
3253     case CSS_PROP_SCROLLBAR_BASE_COLOR:
3254     case CSS_PROP_SCROLLBAR_FACE_COLOR:
3255     case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
3256     case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
3257     case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
3258     case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
3259     case CSS_PROP_SCROLLBAR_TRACK_COLOR:
3260     case CSS_PROP_SCROLLBAR_ARROW_COLOR: {
3261         QColor col;
3262         if (isInherit) {
3263             if (id != CSS_PROP_COLOR) {
3264                 style->setInheritedNoninherited(true);
3265             }
3266             HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
3267             HANDLE_INHERIT_COND_WITH_BACKUP(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, color, BorderTopColor)
3268             HANDLE_INHERIT_COND_WITH_BACKUP(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, color, BorderBottomColor)
3269             HANDLE_INHERIT_COND_WITH_BACKUP(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, color, BorderRightColor)
3270             HANDLE_INHERIT_COND_WITH_BACKUP(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, color, BorderLeftColor)
3271             HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
3272             HANDLE_INHERIT_COND_WITH_BACKUP(CSS_PROP_OUTLINE_COLOR, outlineColor, color, OutlineColor)
3273             return;
3274         } else if (isInitial) {
3275             // The border/outline colors will just map to the invalid color |col| above.  This will have the
3276             // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
3277             // not painting the background since the color won't be valid).
3278             if (id == CSS_PROP_COLOR) {
3279                 col = RenderStyle::initialColor();
3280             }
3281         } else {
3282             if (!primitiveValue) {
3283                 return;
3284             }
3285             int ident = primitiveValue->getIdent();
3286             if (ident) {
3287                 if (ident == CSS_VAL__KHTML_TEXT) {
3288                     col = element->document()->textColor();
3289                 } else if (ident == CSS_VAL_CURRENTCOLOR) {
3290                     col = style->color();
3291                 } else {
3292                     col = colorForCSSValue(ident);
3293                 }
3294             } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) {
3295                 col.setRgba(primitiveValue->getRGBColorValue());
3296             } else {
3297                 return;
3298             }
3299         }
3300         //qCDebug(KHTML_LOG) << "applying color " << col.isValid();
3301         switch (id) {
3302         case CSS_PROP_BACKGROUND_COLOR:
3303             style->setBackgroundColor(col); break;
3304         case CSS_PROP_BORDER_TOP_COLOR:
3305             style->setBorderTopColor(col); break;
3306         case CSS_PROP_BORDER_RIGHT_COLOR:
3307             style->setBorderRightColor(col); break;
3308         case CSS_PROP_BORDER_BOTTOM_COLOR:
3309             style->setBorderBottomColor(col); break;
3310         case CSS_PROP_BORDER_LEFT_COLOR:
3311             style->setBorderLeftColor(col); break;
3312         case CSS_PROP_COLOR:
3313             style->setColor(col); break;
3314         case CSS_PROP_OUTLINE_COLOR:
3315             style->setOutlineColor(col); break;
3316 #ifndef APPLE_CHANGES
3317         case CSS_PROP_SCROLLBAR_FACE_COLOR:
3318             style->setPaletteColor(QPalette::Active, QPalette::Button, col);
3319             style->setPaletteColor(QPalette::Inactive, QPalette::Button, col);
3320             break;
3321         case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
3322             style->setPaletteColor(QPalette::Active, QPalette::Shadow, col);
3323             style->setPaletteColor(QPalette::Inactive, QPalette::Shadow, col);
3324             break;
3325         case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
3326             style->setPaletteColor(QPalette::Active, QPalette::Light, col);
3327             style->setPaletteColor(QPalette::Inactive, QPalette::Light, col);
3328             break;
3329         case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
3330             break;
3331         case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
3332             style->setPaletteColor(QPalette::Active, QPalette::Dark, col);
3333             style->setPaletteColor(QPalette::Inactive, QPalette::Dark, col);
3334             break;
3335         case CSS_PROP_SCROLLBAR_TRACK_COLOR:
3336             style->setPaletteColor(QPalette::Active, QPalette::Mid, col);
3337             style->setPaletteColor(QPalette::Inactive, QPalette::Mid, col);
3338             style->setPaletteColor(QPalette::Active, QPalette::Window, col);
3339             style->setPaletteColor(QPalette::Inactive, QPalette::Window, col);
3340         // fall through
3341         case CSS_PROP_SCROLLBAR_BASE_COLOR:
3342             style->setPaletteColor(QPalette::Active, QPalette::Base, col);
3343             style->setPaletteColor(QPalette::Inactive, QPalette::Base, col);
3344             break;
3345         case CSS_PROP_SCROLLBAR_ARROW_COLOR:
3346             style->setPaletteColor(QPalette::Active, QPalette::ButtonText, col);
3347             style->setPaletteColor(QPalette::Inactive, QPalette::ButtonText, col);
3348             break;
3349 #endif
3350         default:
3351             return;
3352         }
3353         return;
3354     }
3355     break;
3356 // uri || inherit
3357     case CSS_PROP_BACKGROUND_IMAGE:
3358         HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
3359         break;
3360     case CSS_PROP_LIST_STYLE_IMAGE: {
3361         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(listStyleImage, ListStyleImage)
3362         if (!primitiveValue) {
3363             return;
3364         }
3365         style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)->requestCssImage(element->document()));
3366         break;
3367     }
3368 
3369 // length
3370     case CSS_PROP_BORDER_TOP_WIDTH:
3371     case CSS_PROP_BORDER_RIGHT_WIDTH:
3372     case CSS_PROP_BORDER_BOTTOM_WIDTH:
3373     case CSS_PROP_BORDER_LEFT_WIDTH:
3374     case CSS_PROP_OUTLINE_WIDTH: {
3375         if (isInherit) {
3376             style->setInheritedNoninherited(true);
3377             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
3378             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
3379             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
3380             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
3381             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
3382             return;
3383         } else if (isInitial) {
3384             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
3385             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
3386             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
3387             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
3388             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
3389             return;
3390         }
3391 
3392         if (!primitiveValue) {
3393             break;
3394         }
3395         short width = 3;
3396         switch (primitiveValue->getIdent()) {
3397         case CSS_VAL_THIN:
3398             width = 1;
3399             break;
3400         case CSS_VAL_MEDIUM:
3401             width = 3;
3402             break;
3403         case CSS_VAL_THICK:
3404             width = 5;
3405             break;
3406         case CSS_VAL_INVALID: {
3407             double widthd = primitiveValue->computeLengthFloat(style, m_rootStyle, logicalDpiY);
3408             width = CSSPrimitiveValueImpl::snapValue(widthd);
3409             // somewhat resemble Mozilla's granularity
3410             // this makes border-width: 0.5pt borders visible
3411             if (width == 0 && widthd >= 0.025) {
3412                 width++;
3413             }
3414             break;
3415         }
3416         default:
3417             return;
3418         }
3419 
3420         if (width < 0) {
3421             return;
3422         }
3423         switch (id) {
3424         case CSS_PROP_BORDER_TOP_WIDTH:
3425             style->setBorderTopWidth(width);
3426             break;
3427         case CSS_PROP_BORDER_RIGHT_WIDTH:
3428             style->setBorderRightWidth(width);
3429             break;
3430         case CSS_PROP_BORDER_BOTTOM_WIDTH:
3431             style->setBorderBottomWidth(width);
3432             break;
3433         case CSS_PROP_BORDER_LEFT_WIDTH:
3434             style->setBorderLeftWidth(width);
3435             break;
3436         case CSS_PROP_OUTLINE_WIDTH:
3437             style->setOutlineWidth(width);
3438             break;
3439         default:
3440             return;
3441         }
3442         return;
3443     }
3444 
3445     case CSS_PROP_LETTER_SPACING:
3446     case CSS_PROP_WORD_SPACING: {
3447         if (isInherit) {
3448             HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
3449             HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
3450             return;
3451         } else if (isInitial) {
3452             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
3453             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
3454             return;
3455         }
3456         if (!primitiveValue) {
3457             return;
3458         }
3459 
3460         int width = 0;
3461         if (primitiveValue->getIdent() != CSS_VAL_NORMAL) {
3462             width = primitiveValue->computeLength(style, m_rootStyle, logicalDpiY);
3463         }
3464 
3465         switch (id) {
3466         case CSS_PROP_LETTER_SPACING:
3467             style->setLetterSpacing(width);
3468             break;
3469         case CSS_PROP_WORD_SPACING:
3470             style->setWordSpacing(width);
3471             break;
3472         // ### needs the definitions in renderstyle
3473         default: break;
3474         }
3475         return;
3476     }
3477 
3478     // length, percent
3479     case CSS_PROP_MAX_WIDTH:
3480         // +none +inherit
3481         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3482             apply = true;
3483             l = Length(UNDEFINED, Fixed);
3484         }
3485     case CSS_PROP_TOP:
3486     case CSS_PROP_LEFT:
3487     case CSS_PROP_RIGHT:
3488     case CSS_PROP_BOTTOM:
3489     case CSS_PROP_WIDTH:
3490     case CSS_PROP_MIN_WIDTH:
3491     case CSS_PROP_MARGIN_TOP:
3492     case CSS_PROP_MARGIN_RIGHT:
3493     case CSS_PROP_MARGIN_BOTTOM:
3494     case CSS_PROP_MARGIN_LEFT:
3495         // +inherit +auto
3496         if (id != CSS_PROP_MAX_WIDTH && primitiveValue &&
3497                 primitiveValue->getIdent() == CSS_VAL_AUTO) {
3498             //qCDebug(KHTML_LOG) << "found value=auto";
3499             apply = true;
3500         }
3501     case CSS_PROP_PADDING_TOP:
3502     case CSS_PROP_PADDING_RIGHT:
3503     case CSS_PROP_PADDING_BOTTOM:
3504     case CSS_PROP_PADDING_LEFT:
3505     case CSS_PROP_TEXT_INDENT:
3506         // +inherit
3507     {
3508         if (isInherit) {
3509             if (id != CSS_PROP_TEXT_INDENT) {
3510                 style->setInheritedNoninherited(true);
3511             }
3512             HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
3513             HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
3514             HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
3515             HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
3516             HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
3517             HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
3518             HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
3519             HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
3520             HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
3521             HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
3522             HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
3523             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
3524             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
3525             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
3526             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
3527             HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
3528             return;
3529         } else if (isInitial) {
3530             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
3531             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
3532             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
3533             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
3534             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
3535             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
3536             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
3537             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
3538             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
3539             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
3540             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
3541             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
3542             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
3543             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
3544             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
3545             HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
3546             return;
3547         }
3548 
3549         if (primitiveValue && !apply) {
3550             int type = primitiveValue->primitiveType();
3551             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
3552                 // Handle our quirky margin units if we have them.
3553                 l = Length(primitiveValue->computeLength(style, m_rootStyle, logicalDpiY), Fixed, primitiveValue->isQuirkValue());
3554             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
3555                 l = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
3556             } else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE) {
3557                 l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
3558             } else {
3559                 return;
3560             }
3561             apply = true;
3562         }
3563         if (!apply) {
3564             return;
3565         }
3566         switch (id) {
3567         case CSS_PROP_MAX_WIDTH:
3568             style->setMaxWidth(l); break;
3569         case CSS_PROP_BOTTOM:
3570             style->setBottom(l); break;
3571         case CSS_PROP_TOP:
3572             style->setTop(l); break;
3573         case CSS_PROP_LEFT:
3574             style->setLeft(l); break;
3575         case CSS_PROP_RIGHT:
3576             style->setRight(l); break;
3577         case CSS_PROP_WIDTH:
3578             style->setWidth(l); break;
3579         case CSS_PROP_MIN_WIDTH:
3580             style->setMinWidth(l); break;
3581         case CSS_PROP_PADDING_TOP:
3582             style->setPaddingTop(l); break;
3583         case CSS_PROP_PADDING_RIGHT:
3584             style->setPaddingRight(l); break;
3585         case CSS_PROP_PADDING_BOTTOM:
3586             style->setPaddingBottom(l); break;
3587         case CSS_PROP_PADDING_LEFT:
3588             style->setPaddingLeft(l); break;
3589         case CSS_PROP_MARGIN_TOP:
3590             style->setMarginTop(l); break;
3591         case CSS_PROP_MARGIN_RIGHT:
3592             style->setMarginRight(l); break;
3593         case CSS_PROP_MARGIN_BOTTOM:
3594             style->setMarginBottom(l); break;
3595         case CSS_PROP_MARGIN_LEFT:
3596             style->setMarginLeft(l); break;
3597         case CSS_PROP_TEXT_INDENT:
3598             style->setTextIndent(l); break;
3599         default: break;
3600         }
3601         return;
3602     }
3603 
3604     case CSS_PROP_MAX_HEIGHT:
3605         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3606             apply = true;
3607             l = Length(UNDEFINED, Fixed);
3608         }
3609     case CSS_PROP_HEIGHT:
3610     case CSS_PROP_MIN_HEIGHT:
3611         if (id != CSS_PROP_MAX_HEIGHT && primitiveValue &&
3612                 primitiveValue->getIdent() == CSS_VAL_AUTO) {
3613             apply = true;
3614         }
3615         if (isInherit) {
3616             style->setInheritedNoninherited(true);
3617             HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
3618             HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
3619             HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
3620             return;
3621         } else if (isInitial) {
3622             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
3623             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
3624             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
3625             return;
3626         }
3627 
3628         if (primitiveValue && !apply) {
3629             int type = primitiveValue->primitiveType();
3630             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3631                 l = Length(primitiveValue->computeLength(style, m_rootStyle, logicalDpiY), Fixed);
3632             } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
3633                 l = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
3634             } else {
3635                 return;
3636             }
3637             apply = true;
3638         }
3639         if (!apply) {
3640             return;
3641         }
3642         switch (id) {
3643         case CSS_PROP_MAX_HEIGHT:
3644             style->setMaxHeight(l); break;
3645         case CSS_PROP_HEIGHT:
3646             style->setHeight(l); break;
3647         case CSS_PROP_MIN_HEIGHT:
3648             style->setMinHeight(l); break;
3649         default:
3650             return;
3651         }
3652         return;
3653 
3654         break;
3655 
3656     case CSS_PROP_VERTICAL_ALIGN:
3657         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(verticalAlign, VerticalAlign)
3658         if (!primitiveValue) {
3659             return;
3660         }
3661         if (primitiveValue->getIdent()) {
3662             khtml::EVerticalAlign align;
3663 
3664             switch (primitiveValue->getIdent()) {
3665             case CSS_VAL_TOP:
3666                 align = TOP; break;
3667             case CSS_VAL_BOTTOM:
3668                 align = BOTTOM; break;
3669             case CSS_VAL_MIDDLE:
3670                 align = MIDDLE; break;
3671             case CSS_VAL_BASELINE:
3672                 align = BASELINE; break;
3673             case CSS_VAL_TEXT_BOTTOM:
3674                 align = TEXT_BOTTOM; break;
3675             case CSS_VAL_TEXT_TOP:
3676                 align = TEXT_TOP; break;
3677             case CSS_VAL_SUB:
3678                 align = SUB; break;
3679             case CSS_VAL_SUPER:
3680                 align = SUPER; break;
3681             case CSS_VAL__KHTML_BASELINE_MIDDLE:
3682                 align = BASELINE_MIDDLE; break;
3683             default:
3684                 return;
3685             }
3686             style->setVerticalAlign(align);
3687             return;
3688         } else {
3689             int type = primitiveValue->primitiveType();
3690             Length l;
3691             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3692                 l = Length(primitiveValue->computeLength(style, m_rootStyle, logicalDpiY), Fixed);
3693             } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
3694                 l = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
3695             }
3696 
3697             style->setVerticalAlign(LENGTH);
3698             style->setVerticalAlignLength(l);
3699         }
3700         break;
3701 
3702     case CSS_PROP_FONT_SIZE: {
3703         FontDef fontDef = style->htmlFont().fontDef;
3704         int size = 0;
3705 
3706         const bool isRootElement = element && (element->document()->documentElement() == element);
3707 
3708         if (isInherit) {
3709             size = parentStyle->font().pixelSize();
3710         } else if (isInitial) {
3711             size = m_fontSizes[3];
3712         } else if (primitiveValue->getIdent()) {
3713             // keywords are being used.  Pick the correct default
3714             // based off the font family.
3715 #ifdef APPLE_CHANGES
3716             const QVector<int> &fontSizes = (fontDef.genericFamily == FontDef::eMonospace) ?
3717                                             m_fixedFontSizes : m_fontSizes;
3718 #else
3719             const QVector<int> &fontSizes = m_fontSizes;
3720 #endif
3721             int oldSize;
3722             if (parentNode) {
3723                 oldSize = parentStyle->font().pixelSize();
3724             } else {
3725                 oldSize = m_fontSizes[3];
3726             }
3727             switch (primitiveValue->getIdent()) {
3728             case CSS_VAL_XX_SMALL: size = fontSizes[0]; break;
3729             case CSS_VAL_X_SMALL:  size = fontSizes[1]; break;
3730             case CSS_VAL_SMALL:    size = fontSizes[2]; break;
3731             case CSS_VAL_MEDIUM:   size = fontSizes[3]; break;
3732             case CSS_VAL_LARGE:    size = fontSizes[4]; break;
3733             case CSS_VAL_X_LARGE:  size = fontSizes[5]; break;
3734             case CSS_VAL_XX_LARGE: size = fontSizes[6]; break;
3735             case CSS_VAL__KHTML_XXX_LARGE: size = fontSizes[7]; break;
3736             case CSS_VAL_LARGER:
3737                 size = nextFontSize(fontSizes, oldSize, false);
3738                 break;
3739             case CSS_VAL_SMALLER:
3740                 size = nextFontSize(fontSizes, oldSize, true);
3741                 break;
3742             default:
3743                 return;
3744             }
3745 
3746         } else {
3747             const int type = primitiveValue->primitiveType();
3748             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3749                 // Scale for the font zoom factor only for types other than "em", "ex", "ch", "rem",
3750                 // since those are already based on the font size.
3751                 if (!khtml::printpainter && !(type >= CSSPrimitiveValue::CSS_EMS && type <= CSSPrimitiveValue::CSS_REMS) && view && view->part()) {
3752                     size = qRound(primitiveValue->computeLengthFloat(parentStyle, m_rootStyle, logicalDpiY) * view->part()->fontScaleFactor() / 100.0);
3753                 } else {
3754                     size = qRound(primitiveValue->computeLengthFloat(parentStyle, isRootElement ? m_rootDefaultStyle : m_rootStyle, logicalDpiY));
3755                 }
3756             } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3757                 size = qRound(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) * parentStyle->font().pixelSize() / 100.0);
3758             else {
3759                 return;
3760             }
3761 
3762             // we never want to get smaller than the minimum font size to keep fonts readable
3763             // do not however maximize zero as that is commonly used for fancy layouting purposes
3764             if (size) {
3765                 size = qMax(size, m_minFontSize);
3766             }
3767         }
3768 
3769         //qCDebug(KHTML_LOG) << "computed raw font size: " << size;
3770 
3771         fontDef.size = size;
3772         fontDirty |= style->setFontDef(fontDef);
3773 
3774         if (isRootElement) {
3775             // We changed font size of root element, update now our root style reference
3776             // so that root css properties based on 'rem' unit are correctly computed
3777             // TESTCASE: html { font-size: 30px; width: 10rem; border: solid; }
3778             m_rootStyle = style;
3779         }
3780 
3781         return;
3782     }
3783 
3784     case CSS_PROP_Z_INDEX: {
3785         if (isInherit) {
3786             style->setInheritedNoninherited(true);
3787             if (parentStyle->hasAutoZIndex()) {
3788                 style->setHasAutoZIndex();
3789             } else {
3790                 style->setZIndex(parentStyle->zIndex());
3791             }
3792             return;
3793         }
3794 
3795         if (isInitial) {
3796             style->setHasAutoZIndex();
3797             return;
3798         }
3799 
3800         if (!primitiveValue) {
3801             return;
3802         }
3803 
3804         if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
3805             style->setHasAutoZIndex();
3806             return;
3807         }
3808 
3809         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) {
3810             return;    // Error case.
3811         }
3812 
3813         style->setZIndex((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
3814         return;
3815     }
3816 
3817     case CSS_PROP_WIDOWS: {
3818         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(widows, Widows)
3819         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) {
3820             return;
3821         }
3822         style->setWidows((short)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
3823         break;
3824     }
3825 
3826     case CSS_PROP_ORPHANS: {
3827         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(orphans, Orphans)
3828         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) {
3829             return;
3830         }
3831         style->setOrphans((short)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
3832         break;
3833     }
3834 
3835 // length, percent, number
3836     case CSS_PROP_LINE_HEIGHT: {
3837         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(lineHeight, LineHeight)
3838         if (!primitiveValue) {
3839             return;
3840         }
3841         Length lineHeight;
3842         const int type = primitiveValue->primitiveType();
3843         if (primitiveValue->getIdent() == CSS_VAL_NORMAL) {
3844             lineHeight = Length(-100.0, Percent);
3845         } else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3846             // Scale for the font zoom factor only for types other than "em", "ex", "ch", "rem",
3847             // since those are already based on the font size.
3848             if (!khtml::printpainter && !(type >= CSSPrimitiveValue::CSS_EMS && type <= CSSPrimitiveValue::CSS_REMS) && view && view->part()) {
3849                 lineHeight = Length(primitiveValue->computeLength(style, m_rootStyle, logicalDpiY) * view->part()->fontScaleFactor() / 100, Fixed);
3850             } else {
3851                 lineHeight = Length(primitiveValue->computeLength(style, m_rootStyle, logicalDpiY), Fixed);
3852             }
3853         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
3854             lineHeight = Length((style->font().pixelSize() * int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE))) / 100, Fixed);
3855         } else if (type == CSSPrimitiveValue::CSS_NUMBER) {
3856             lineHeight = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER) * 100.0, Percent);
3857         } else {
3858             return;
3859         }
3860         style->setLineHeight(lineHeight);
3861         return;
3862     }
3863 
3864 // string
3865     case CSS_PROP_TEXT_ALIGN: {
3866         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(textAlign, TextAlign)
3867         if (!primitiveValue) {
3868             return;
3869         }
3870         if (primitiveValue->getIdent()) {
3871             style->setTextAlign((ETextAlign)(primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO));
3872         }
3873         return;
3874     }
3875 
3876 // rect
3877     case CSS_PROP_CLIP: {
3878         Length top = Length();
3879         Length right = Length();
3880         Length bottom = Length();
3881         Length left = Length();
3882 
3883         bool hasClip = false;
3884 
3885         if (isInherit && parentStyle->hasClip()) {
3886             hasClip = true;
3887             top = parentStyle->clipTop();
3888             right = parentStyle->clipRight();
3889             bottom = parentStyle->clipBottom();
3890             left = parentStyle->clipLeft();
3891         } else if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
3892             RectImpl *rect = primitiveValue->getRectValue();
3893             if (rect) {
3894                 hasClip = true;
3895                 // As a convention, we pass in auto as Length(Auto). See RenderBox::clipRect
3896                 top    = rect->top()->getIdent()    == CSS_VAL_AUTO ? Length(Auto)
3897                          : convertToLength(rect->top(), style, m_rootStyle, logicalDpiY);
3898 
3899                 right  = rect->right()->getIdent()  == CSS_VAL_AUTO ? Length(Auto)
3900                          : convertToLength(rect->right(), style, m_rootStyle, logicalDpiY);
3901 
3902                 bottom = rect->bottom()->getIdent() == CSS_VAL_AUTO ? Length(Auto)
3903                          : convertToLength(rect->bottom(), style, m_rootStyle, logicalDpiY);
3904 
3905                 left   = rect->left()->getIdent()   == CSS_VAL_AUTO ? Length(Auto)
3906                          : convertToLength(rect->left(), style, m_rootStyle, logicalDpiY);
3907             }
3908         }
3909 
3910         style->setClip(top, right, bottom, left);
3911         style->setHasClip(hasClip);
3912 
3913         // rect, ident
3914         break;
3915     }
3916 
3917 // lists
3918     case CSS_PROP_CONTENT:
3919         // list of string, uri, counter, attr, i
3920     {
3921         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
3922         // note is a reminder that eventually "inherit" needs to be supported.
3923 
3924         // not allowed on non-generated pseudo-elements:
3925         if (style->styleType() == RenderStyle::FIRST_LETTER ||
3926                 style->styleType() == RenderStyle::FIRST_LINE ||
3927                 style->styleType() == RenderStyle::SELECTION) {
3928             break;
3929         }
3930 
3931         if (isInitial) {
3932             style->setContentNormal();
3933             return;
3934         }
3935 
3936         if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3937             // normal | none
3938             if (primitiveValue->getIdent() == CSS_VAL_NORMAL) {
3939                 style->setContentNormal();
3940             } else if (primitiveValue->getIdent() == CSS_VAL_NONE) {
3941                 style->setContentNone();
3942             } else {
3943                 assert(false);
3944             }
3945             return;
3946         }
3947 
3948         if (!value->isValueList()) {
3949             return;
3950         }
3951         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3952         int len = list->length();
3953 
3954         style->setContentNormal(); // clear the content
3955 
3956         for (int i = 0; i < len; i++) {
3957             CSSValueImpl *item = list->item(i);
3958             if (!item->isPrimitiveValue()) {
3959                 continue;
3960             }
3961             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
3962             if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
3963                 style->addContent(val->getStringValue());
3964             } else if (val->primitiveType() == CSSPrimitiveValue::CSS_ATTR) {
3965                 // TODO: setup dynamic attribute dependencies
3966                 LocalName attrName;
3967                 if (element->htmlCompat()) {
3968                     attrName = LocalName::fromString(DOMString(val->getStringValue()).lower());
3969                 } else {
3970                     attrName = LocalName::fromString(val->getStringValue());
3971                 }
3972                 if (attrName.id()) {
3973                     style->addContent(element->getAttribute(makeId(emptyNamespace, attrName.id())).implementation());
3974                 } else {
3975                     // qCDebug(KHTML_LOG) << "Attribute \"" << val->getStringValue() << "\" not found";
3976                 }
3977             } else if (val->primitiveType() == CSSPrimitiveValue::CSS_URI) {
3978                 CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val);
3979                 style->addContent(image->requestCssImage(element->document()));
3980             } else if (val->primitiveType() == CSSPrimitiveValue::CSS_COUNTER) {
3981                 style->addContent(val->getCounterValue());
3982             } else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3983                 EQuoteContent quote;
3984                 switch (val->getIdent()) {
3985                 case CSS_VAL_OPEN_QUOTE:
3986                     quote = OPEN_QUOTE;
3987                     break;
3988                 case CSS_VAL_NO_OPEN_QUOTE:
3989                     quote = NO_OPEN_QUOTE;
3990                     break;
3991                 case CSS_VAL_CLOSE_QUOTE:
3992                     quote = CLOSE_QUOTE;
3993                     break;
3994                 case CSS_VAL_NO_CLOSE_QUOTE:
3995                     quote = NO_CLOSE_QUOTE;
3996                     break;
3997                 default:
3998                     assert(false);
3999                     quote = NO_QUOTE;
4000                 }
4001                 style->addContent(quote);
4002             } else {
4003                 // qCDebug(KHTML_LOG) << "Unrecognized CSS content";
4004             }
4005         }
4006         break;
4007     }
4008 
4009     case CSS_PROP_COUNTER_INCREMENT: {
4010         if (!value->isValueList()) {
4011             return;
4012         }
4013 
4014         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
4015         style->setCounterIncrement(list);
4016         break;
4017     }
4018     case CSS_PROP_COUNTER_RESET: {
4019         if (!value->isValueList()) {
4020             return;
4021         }
4022 
4023         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
4024         style->setCounterReset(list);
4025         break;
4026     }
4027     case CSS_PROP_FONT_FAMILY:
4028         // list of strings and ids
4029     {
4030         if (isInherit) {
4031             FontDef parentFontDef = parentStyle->htmlFont().fontDef;
4032             FontDef fontDef = style->htmlFont().fontDef;
4033             fontDef.family = parentFontDef.family;
4034             if (style->setFontDef(fontDef)) {
4035                 fontDirty = true;
4036             }
4037             return;
4038         } else if (isInitial) {
4039             FontDef fontDef = style->htmlFont().fontDef;
4040             FontDef initialDef = FontDef();
4041 #ifdef APPLE_CHANGES
4042             fontDef.family = initialDef.firstFamily();
4043 #else
4044             fontDef.family = initialDef.family;
4045 #endif
4046             if (style->setFontDef(fontDef)) {
4047                 fontDirty = true;
4048             }
4049             return;
4050         }
4051         if (!value->isValueList()) {
4052             return;
4053         }
4054         FontDef fontDef = style->htmlFont().fontDef;
4055         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
4056         int len = list->length();
4057         bool hasFamilyName = false;
4058         for (int i = 0; i < len; i++) {
4059             CSSValueImpl *item = list->item(i);
4060             if (!item->isPrimitiveValue()) {
4061                 continue;
4062             }
4063             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
4064             QString face;
4065             if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
4066                 face = static_cast<FontFamilyValueImpl *>(val)->fontName();
4067                 m_fontSelector->requestFamilyName(DOMString(face));
4068             } else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
4069                 switch (val->getIdent()) {
4070                 case CSS_VAL_SERIF:
4071                     face = settings->serifFontName();
4072                     break;
4073                 case CSS_VAL_SANS_SERIF:
4074                     face = settings->sansSerifFontName();
4075                     break;
4076                 case CSS_VAL_CURSIVE:
4077                     face = settings->cursiveFontName();
4078                     break;
4079                 case CSS_VAL_FANTASY:
4080                     face = settings->fantasyFontName();
4081                     break;
4082                 case CSS_VAL_MONOSPACE:
4083                     face = settings->fixedFontName();
4084                     break;
4085                 default:
4086                     return;
4087                 }
4088             } else {
4089                 return;
4090             }
4091             if (!face.isEmpty()) {
4092                 if (!hasFamilyName) {
4093                     fontDef.family = face;
4094                     hasFamilyName = true;
4095                 } else {
4096                     fontDef.family += ",";
4097                     fontDef.family += face;
4098                 }
4099             }
4100         }
4101         if (hasFamilyName) {
4102             fontDirty |= style->setFontDef(fontDef);
4103         }
4104         break;
4105     }
4106     case CSS_PROP_QUOTES:
4107         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(quotes, Quotes)
4108         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
4109             // set a set of empty quotes
4110             QuotesValueImpl *quotes = new QuotesValueImpl();
4111             style->setQuotes(quotes);
4112         } else {
4113             QuotesValueImpl *quotes = static_cast<QuotesValueImpl *>(value);
4114             style->setQuotes(quotes);
4115         }
4116         break;
4117     case CSS_PROP_SIZE:
4118         // ### look up
4119         break;
4120     case CSS_PROP_TEXT_DECORATION: {
4121         // list of ident
4122         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(textDecoration, TextDecoration)
4123         int t = RenderStyle::initialTextDecoration();
4124         if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
4125             // do nothing
4126         } else {
4127             if (!value->isValueList()) {
4128                 return;
4129             }
4130             CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
4131             int len = list->length();
4132             for (int i = 0; i < len; i++) {
4133                 CSSValueImpl *item = list->item(i);
4134                 if (!item->isPrimitiveValue()) {
4135                     continue;
4136                 }
4137                 primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item);
4138                 switch (primitiveValue->getIdent()) {
4139                 case CSS_VAL_NONE:
4140                     t = TDNONE; break;
4141                 case CSS_VAL_UNDERLINE:
4142                     t |= UNDERLINE; break;
4143                 case CSS_VAL_OVERLINE:
4144                     t |= OVERLINE; break;
4145                 case CSS_VAL_LINE_THROUGH:
4146                     t |= LINE_THROUGH; break;
4147                 case CSS_VAL_BLINK:
4148                     t |= BLINK; break;
4149                 default:
4150                     return;
4151                 }
4152             }
4153         }
4154         style->setTextDecoration(t);
4155         break;
4156     }
4157     case CSS_PROP__KHTML_FLOW_MODE:
4158         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(flowAroundFloats, FlowAroundFloats)
4159         if (!primitiveValue) {
4160             return;
4161         }
4162         if (primitiveValue->getIdent()) {
4163             style->setFlowAroundFloats(primitiveValue->getIdent() == CSS_VAL__KHTML_AROUND_FLOATS);
4164             return;
4165         }
4166         break;
4167     case CSS_PROP__KHTML_USER_INPUT: {
4168         if (value->cssValueType() == CSSValue::CSS_INHERIT) {
4169             if (!parentNode) {
4170                 return;
4171             }
4172             style->setUserInput(parentStyle->userInput());
4173 //      qCDebug(KHTML_LOG) << "UI erm";
4174             return;
4175         }
4176         if (!primitiveValue) {
4177             return;
4178         }
4179         int id = primitiveValue->getIdent();
4180         if (id == CSS_VAL_NONE) {
4181             style->setUserInput(UI_NONE);
4182         } else {
4183             style->setUserInput(EUserInput(id - CSS_VAL_ENABLED));
4184         }
4185 //  qCDebug(KHTML_LOG) << "userInput: " << style->userEdit();
4186         return;
4187     }
4188 
4189 // shorthand properties
4190     case CSS_PROP_BACKGROUND:
4191         if (isInitial) {
4192             style->setBackgroundColor(QColor());
4193             return;
4194         } else if (isInherit) {
4195             style->setInheritedNoninherited(true);
4196             style->inheritBackgroundLayers(*parentStyle->backgroundLayers());
4197             style->setBackgroundColor(parentStyle->backgroundColor());
4198         }
4199         break;
4200     case CSS_PROP_BORDER:
4201     case CSS_PROP_BORDER_STYLE:
4202     case CSS_PROP_BORDER_WIDTH:
4203     case CSS_PROP_BORDER_COLOR:
4204         if (isInherit) {
4205             style->setInheritedNoninherited(true);
4206         }
4207         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR) {
4208             if (isInherit) {
4209                 style->setBorderTopColor(inheritedBorderColor(parentStyle, parentStyle->borderTopColor()));
4210                 style->setBorderBottomColor(inheritedBorderColor(parentStyle, parentStyle->borderBottomColor()));
4211                 style->setBorderLeftColor(inheritedBorderColor(parentStyle, parentStyle->borderLeftColor()));
4212                 style->setBorderRightColor(inheritedBorderColor(parentStyle, parentStyle->borderRightColor()));
4213             } else if (isInitial) {
4214                 style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead.
4215                 style->setBorderBottomColor(QColor());
4216                 style->setBorderLeftColor(QColor());
4217                 style->setBorderRightColor(QColor());
4218             }
4219         }
4220         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE) {
4221             if (isInherit) {
4222                 style->setBorderTopStyle(parentStyle->borderTopStyle());
4223                 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
4224                 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
4225                 style->setBorderRightStyle(parentStyle->borderRightStyle());
4226             } else if (isInitial) {
4227                 style->setBorderTopStyle(RenderStyle::initialBorderStyle());
4228                 style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
4229                 style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
4230                 style->setBorderRightStyle(RenderStyle::initialBorderStyle());
4231             }
4232         }
4233         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH) {
4234             if (isInherit) {
4235                 style->setBorderTopWidth(parentStyle->borderTopWidth());
4236                 style->setBorderBottomWidth(parentStyle->borderBottomWidth());
4237                 style->setBorderLeftWidth(parentStyle->borderLeftWidth());
4238                 style->setBorderRightWidth(parentStyle->borderRightWidth());
4239             } else if (isInitial) {
4240                 style->setBorderTopWidth(RenderStyle::initialBorderWidth());
4241                 style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
4242                 style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
4243                 style->setBorderRightWidth(RenderStyle::initialBorderWidth());
4244             }
4245         }
4246         return;
4247     case CSS_PROP_BORDER_RADIUS:
4248         if (isInherit) {
4249             style->setInheritedNoninherited(true);
4250             style->setBorderTopLeftRadius(parentStyle->borderTopLeftRadius());
4251             style->setBorderTopRightRadius(parentStyle->borderTopRightRadius());
4252             style->setBorderBottomRightRadius(parentStyle->borderBottomRightRadius());
4253             style->setBorderBottomLeftRadius(parentStyle->borderBottomLeftRadius());
4254         } else if (isInitial) {
4255             style->setBorderTopLeftRadius(RenderStyle::initialBorderRadius());
4256             style->setBorderTopRightRadius(RenderStyle::initialBorderRadius());
4257             style->setBorderBottomRightRadius(RenderStyle::initialBorderRadius());
4258             style->setBorderBottomLeftRadius(RenderStyle::initialBorderRadius());
4259         }
4260         return;
4261     case CSS_PROP_BORDER_TOP:
4262         if (isInherit) {
4263             style->setInheritedNoninherited(true);
4264             style->setBorderTopColor(inheritedBorderColor(parentStyle, parentStyle->borderTopColor()));
4265             style->setBorderTopStyle(parentStyle->borderTopStyle());
4266             style->setBorderTopWidth(parentStyle->borderTopWidth());
4267         } else if (isInitial) {
4268             style->resetBorderTop();
4269         }
4270         return;
4271     case CSS_PROP_BORDER_RIGHT:
4272         if (isInherit) {
4273             style->setInheritedNoninherited(true);
4274             style->setBorderRightColor(inheritedBorderColor(parentStyle, parentStyle->borderRightColor()));
4275             style->setBorderRightStyle(parentStyle->borderRightStyle());
4276             style->setBorderRightWidth(parentStyle->borderRightWidth());
4277         } else if (isInitial) {
4278             style->resetBorderRight();
4279         }
4280         return;
4281     case CSS_PROP_BORDER_BOTTOM:
4282         if (isInherit) {
4283             style->setInheritedNoninherited(true);
4284             style->setBorderBottomColor(inheritedBorderColor(parentStyle, parentStyle->borderBottomColor()));
4285             style->setBorderBottomStyle(parentStyle->borderBottomStyle());
4286             style->setBorderBottomWidth(parentStyle->borderBottomWidth());
4287         } else if (isInitial) {
4288             style->resetBorderBottom();
4289         }
4290         return;
4291     case CSS_PROP_BORDER_LEFT:
4292         if (isInherit) {
4293             style->setInheritedNoninherited(true);
4294             style->setBorderLeftColor(inheritedBorderColor(parentStyle, parentStyle->borderLeftColor()));
4295             style->setBorderLeftStyle(parentStyle->borderLeftStyle());
4296             style->setBorderLeftWidth(parentStyle->borderLeftWidth());
4297         } else if (isInitial) {
4298             style->resetBorderLeft();
4299         }
4300         return;
4301     case CSS_PROP_MARGIN:
4302         if (isInherit) {
4303             style->setInheritedNoninherited(true);
4304             style->setMarginTop(parentStyle->marginTop());
4305             style->setMarginBottom(parentStyle->marginBottom());
4306             style->setMarginLeft(parentStyle->marginLeft());
4307             style->setMarginRight(parentStyle->marginRight());
4308         } else if (isInitial) {
4309             style->resetMargin();
4310         }
4311         return;
4312     case CSS_PROP_PADDING:
4313         if (isInherit) {
4314             style->setInheritedNoninherited(true);
4315             style->setPaddingTop(parentStyle->paddingTop());
4316             style->setPaddingBottom(parentStyle->paddingBottom());
4317             style->setPaddingLeft(parentStyle->paddingLeft());
4318             style->setPaddingRight(parentStyle->paddingRight());
4319         } else if (isInitial) {
4320             style->resetPadding();
4321         }
4322         return;
4323     case CSS_PROP_FONT:
4324         if (isInherit) {
4325             FontDef fontDef = parentStyle->htmlFont().fontDef;
4326             style->setLineHeight(parentStyle->lineHeight());
4327             fontDirty |= style->setFontDef(fontDef);
4328         } else if (isInitial) {
4329             FontDef fontDef;
4330             fontDef.size = m_fontSizes[3];
4331             style->setLineHeight(RenderStyle::initialLineHeight());
4332             fontDirty |= style->setFontDef(fontDef);
4333         } else if (primitiveValue) {
4334             // Handle system fonts. We extract out properties from a QFont
4335             // into the RenderStyle.
4336             QFont f;
4337             switch (primitiveValue->getIdent()) {
4338             case CSS_VAL_ICON:
4339                 f = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
4340                 break;
4341 
4342             case CSS_VAL_MENU:
4343                 f = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
4344                 break;
4345 
4346             case CSS_VAL_SMALL_CAPTION:
4347                 f = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);
4348                 break;
4349 
4350             case CSS_VAL_CAPTION:
4351             case CSS_VAL_MESSAGE_BOX:
4352             case CSS_VAL_STATUS_BAR:
4353                 f = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
4354                 break;
4355             default:
4356                 return;
4357             }
4358 
4359             FontDef fontDef = style->htmlFont().fontDef;
4360             fontDef.family    = f.family();
4361             fontDef.italic    = f.italic();
4362             fontDef.smallCaps = (f.capitalization() == QFont::SmallCaps);
4363             fontDef.weight    = f.weight();
4364             fontDirty |= style->setFontDef(fontDef);
4365 
4366             // Use applyRule to apply height, so it can convert
4367             // point sizes, and cap pixel sizes appropriately.
4368             if (f.pixelSize() != -1) {
4369                 CSSPrimitiveValueImpl size(f.pixelSize(), CSSPrimitiveValue::CSS_PX);
4370                 applyRule(CSS_PROP_FONT_SIZE, &size);
4371             } else {
4372                 CSSPrimitiveValueImpl size(f.pointSize(), CSSPrimitiveValue::CSS_PT);
4373                 applyRule(CSS_PROP_FONT_SIZE, &size);
4374             }
4375 
4376             // line-height just gets default.
4377             style->setLineHeight(RenderStyle::initialLineHeight());
4378         }
4379         return;
4380 
4381     case CSS_PROP_LIST_STYLE:
4382         if (isInherit) {
4383             style->setListStyleType(parentStyle->listStyleType());
4384             style->setListStyleImage(parentStyle->listStyleImage());
4385             style->setListStylePosition(parentStyle->listStylePosition());
4386         } else if (isInitial) {
4387             style->setListStyleType(RenderStyle::initialListStyleType());
4388             style->setListStyleImage(RenderStyle::initialListStyleImage());
4389             style->setListStylePosition(RenderStyle::initialListStylePosition());
4390         }
4391         break;
4392     case CSS_PROP_OUTLINE:
4393         if (isInherit) {
4394             style->setInheritedNoninherited(true);
4395             style->setOutlineWidth(parentStyle->outlineWidth());
4396             style->setOutlineColor(parentStyle->outlineColor());
4397             style->setOutlineStyle(parentStyle->outlineStyle());
4398         } else if (isInitial) {
4399             style->resetOutline();
4400         }
4401         break;
4402     /* CSS3 properties */
4403     case CSS_PROP_BOX_SIZING:
4404         HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(boxSizing, BoxSizing)
4405         if (!primitiveValue) {
4406             return;
4407         }
4408         if (primitiveValue->getIdent() == CSS_VAL_CONTENT_BOX) {
4409             style->setBoxSizing(CONTENT_BOX);
4410         } else if (primitiveValue->getIdent() == CSS_VAL_BORDER_BOX) {
4411             style->setBoxSizing(BORDER_BOX);
4412         }
4413         break;
4414     case CSS_PROP_OUTLINE_OFFSET: {
4415         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(outlineOffset, OutlineOffset)
4416 
4417         int offset = primitiveValue->computeLength(style, m_rootStyle, logicalDpiY);
4418         if (offset < 0) {
4419             return;
4420         }
4421 
4422         style->setOutlineOffset(offset);
4423         break;
4424     }
4425     case CSS_PROP_TEXT_SHADOW: {
4426         if (isInherit) {
4427             style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : nullptr);
4428             return;
4429         } else if (isInitial) {
4430             style->setTextShadow(nullptr);
4431             return;
4432         }
4433 
4434         if (primitiveValue) { // none
4435             style->setTextShadow(nullptr);
4436             return;
4437         }
4438 
4439         if (!value->isValueList()) {
4440             return;
4441         }
4442         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
4443         int len = list->length();
4444         for (int i = 0; i < len; i++) {
4445             ShadowValueImpl *item = static_cast<ShadowValueImpl *>(list->item(i));
4446 
4447             int x = item->x->computeLength(style, m_rootStyle, logicalDpiY);
4448             int y = item->y->computeLength(style, m_rootStyle, logicalDpiY);
4449             int blur = item->blur ? item->blur->computeLength(style, m_rootStyle, logicalDpiY) : 0;
4450             QColor col = khtml::transparentColor;
4451             if (item->color) {
4452                 int ident = item->color->getIdent();
4453                 if (ident) {
4454                     col = colorForCSSValue(ident);
4455                 } else if (item->color->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) {
4456                     col.setRgba(item->color->getRGBColorValue());
4457                 }
4458             }
4459             ShadowData *shadowData = new ShadowData(x, y, blur, col);
4460             style->setTextShadow(shadowData, i != 0);
4461         }
4462 
4463         break;
4464     }
4465     case CSS_PROP_OPACITY:
4466         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(opacity, Opacity)
4467         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) {
4468             return;    // Error case.
4469         }
4470 
4471         // Clamp opacity to the range 0-1
4472         style->setOpacity(qMin(1.0f, qMax(0.0f, (float)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))));
4473         break;
4474     case CSS_PROP__KHTML_MARQUEE:
4475         if (value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) {
4476             return;
4477         }
4478         style->setMarqueeDirection(parentStyle->marqueeDirection());
4479         style->setMarqueeIncrement(parentStyle->marqueeIncrement());
4480         style->setMarqueeSpeed(parentStyle->marqueeSpeed());
4481         style->setMarqueeLoopCount(parentStyle->marqueeLoopCount());
4482         style->setMarqueeBehavior(parentStyle->marqueeBehavior());
4483         break;
4484     case CSS_PROP__KHTML_MARQUEE_REPETITION: {
4485         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeLoopCount, MarqueeLoopCount)
4486         if (!primitiveValue) {
4487             return;
4488         }
4489         if (primitiveValue->getIdent() == CSS_VAL_INFINITE) {
4490             style->setMarqueeLoopCount(-1);    // -1 means repeat forever.
4491         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
4492             style->setMarqueeLoopCount((int)(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
4493         }
4494         break;
4495     }
4496     case CSS_PROP__KHTML_MARQUEE_SPEED: {
4497         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeSpeed, MarqueeSpeed)
4498         if (!primitiveValue) {
4499             return;
4500         }
4501         if (primitiveValue->getIdent()) {
4502             switch (primitiveValue->getIdent()) {
4503             case CSS_VAL_SLOW:
4504                 style->setMarqueeSpeed(500); // 500 msec.
4505                 break;
4506             case CSS_VAL_NORMAL:
4507                 style->setMarqueeSpeed(85); // 85msec. The WinIE default.
4508                 break;
4509             case CSS_VAL_FAST:
4510                 style->setMarqueeSpeed(10); // 10msec. Super fast.
4511                 break;
4512             }
4513         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) {
4514             style->setMarqueeSpeed(int(1000 * primitiveValue->floatValue(CSSPrimitiveValue::CSS_S)));
4515         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) {
4516             style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_MS)));
4517         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { // For scrollamount support.
4518             style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
4519         }
4520         break;
4521     }
4522     case CSS_PROP__KHTML_MARQUEE_INCREMENT: {
4523         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeIncrement, MarqueeIncrement)
4524         if (!primitiveValue) {
4525             return;
4526         }
4527         if (primitiveValue->getIdent()) {
4528             switch (primitiveValue->getIdent()) {
4529             case CSS_VAL_SMALL:
4530                 style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
4531                 break;
4532             case CSS_VAL_NORMAL:
4533                 style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
4534                 break;
4535             case CSS_VAL_LARGE:
4536                 style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
4537                 break;
4538             }
4539         } else {
4540             bool ok = true;
4541             Length l = convertToLength(primitiveValue, style, m_rootStyle, logicalDpiY, &ok);
4542             if (ok) {
4543                 style->setMarqueeIncrement(l);
4544             }
4545         }
4546         break;
4547     }
4548     case CSS_PROP__KHTML_MARQUEE_STYLE: {
4549         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeBehavior, MarqueeBehavior)
4550         if (!primitiveValue || !primitiveValue->getIdent()) {
4551             return;
4552         }
4553         switch (primitiveValue->getIdent()) {
4554         case CSS_VAL_NONE:
4555             style->setMarqueeBehavior(MNONE);
4556             break;
4557         case CSS_VAL_SCROLL:
4558             style->setMarqueeBehavior(MSCROLL);
4559             break;
4560         case CSS_VAL_SLIDE:
4561             style->setMarqueeBehavior(MSLIDE);
4562             break;
4563         case CSS_VAL_ALTERNATE:
4564             style->setMarqueeBehavior(MALTERNATE);
4565             break;
4566         case CSS_VAL_UNFURL:
4567             style->setMarqueeBehavior(MUNFURL);
4568             break;
4569         }
4570         break;
4571     }
4572     case CSS_PROP__KHTML_MARQUEE_DIRECTION: {
4573         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeDirection, MarqueeDirection)
4574         if (!primitiveValue || !primitiveValue->getIdent()) {
4575             return;
4576         }
4577         switch (primitiveValue->getIdent()) {
4578         case CSS_VAL_FORWARDS:
4579             style->setMarqueeDirection(MFORWARD);
4580             break;
4581         case CSS_VAL_BACKWARDS:
4582             style->setMarqueeDirection(MBACKWARD);
4583             break;
4584         case CSS_VAL_AUTO:
4585             style->setMarqueeDirection(MAUTO);
4586             break;
4587         case CSS_VAL_AHEAD:
4588         case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP.
4589             style->setMarqueeDirection(MUP);
4590             break;
4591         case CSS_VAL_REVERSE:
4592         case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text.
4593             style->setMarqueeDirection(MDOWN);
4594             break;
4595         case CSS_VAL_LEFT:
4596             style->setMarqueeDirection(MLEFT);
4597             break;
4598         case CSS_VAL_RIGHT:
4599             style->setMarqueeDirection(MRIGHT);
4600             break;
4601         }
4602         break;
4603     }
4604     case CSS_PROP_TEXT_OVERFLOW: {
4605         // This property is supported by WinIE, and so we leave off the "-khtml-" in order to
4606         // work with WinIE-specific pages that use the property.
4607         HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(textOverflow, TextOverflow)
4608         if (!primitiveValue || !primitiveValue->getIdent()) {
4609             return;
4610         }
4611         style->setTextOverflow(primitiveValue->getIdent() == CSS_VAL_ELLIPSIS);
4612         break;
4613     }
4614     case CSS_PROP_WORD_WRAP: {
4615         HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(wordWrap, WordWrap)
4616         if (!primitiveValue) {
4617             return;
4618         }
4619         style->setWordWrap(primitiveValue->getIdent() == CSS_VAL_NORMAL ? WWNORMAL : WWBREAKWORD);
4620         break;
4621     }
4622     default:
4623         applySVGRule(id, value);
4624         return;
4625     }
4626 }
4627 
4628 void CSSStyleSelector::mapBackgroundAttachment(BackgroundLayer *layer, DOM::CSSValueImpl *value)
4629 {
4630     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4631         layer->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment());
4632         return;
4633     }
4634 
4635     if (!value->isPrimitiveValue()) {
4636         return;
4637     }
4638     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4639     switch (primitiveValue->getIdent()) {
4640     case CSS_VAL_SCROLL:
4641         layer->setBackgroundAttachment(BGASCROLL);
4642         break;
4643     case CSS_VAL_FIXED:
4644         layer->setBackgroundAttachment(BGAFIXED);
4645         break;
4646     case CSS_VAL_LOCAL:
4647         layer->setBackgroundAttachment(BGALOCAL);
4648         break;
4649     default:
4650         return;
4651     }
4652 }
4653 
4654 void CSSStyleSelector::mapBackgroundClip(BackgroundLayer *layer, CSSValueImpl *value)
4655 {
4656     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4657         layer->setBackgroundClip(RenderStyle::initialBackgroundClip());
4658         return;
4659     }
4660 
4661     if (!value->isPrimitiveValue()) {
4662         return;
4663     }
4664     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4665     switch (primitiveValue->getIdent()) {
4666     case CSS_VAL_BORDER_BOX:
4667         layer->setBackgroundClip(BGBORDER);
4668         break;
4669     case CSS_VAL_PADDING_BOX:
4670         layer->setBackgroundClip(BGPADDING);
4671         break;
4672     default: // CSS_VAL_CONTENT_BOX
4673         layer->setBackgroundClip(BGCONTENT);
4674         break;
4675     }
4676 }
4677 
4678 void CSSStyleSelector::mapBackgroundOrigin(BackgroundLayer *layer, CSSValueImpl *value)
4679 {
4680     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4681         layer->setBackgroundOrigin(RenderStyle::initialBackgroundOrigin());
4682         return;
4683     }
4684 
4685     if (!value->isPrimitiveValue()) {
4686         return;
4687     }
4688     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4689     switch (primitiveValue->getIdent()) {
4690     case CSS_VAL_BORDER_BOX:
4691         layer->setBackgroundOrigin(BGBORDER);
4692         break;
4693     case CSS_VAL_PADDING_BOX:
4694         layer->setBackgroundOrigin(BGPADDING);
4695         break;
4696     default: // CSS_VAL_CONTENT_BOX
4697         layer->setBackgroundOrigin(BGCONTENT);
4698         break;
4699     }
4700 }
4701 
4702 void CSSStyleSelector::mapBackgroundImage(BackgroundLayer *layer, DOM::CSSValueImpl *value)
4703 {
4704     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4705         layer->setBackgroundImage(RenderStyle::initialBackgroundImage());
4706         return;
4707     }
4708 
4709     if (!value->isPrimitiveValue()) {
4710         return;
4711     }
4712     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4713     layer->setBackgroundImage(static_cast<CSSImageValueImpl *>(primitiveValue)->requestCssImage(element->document()));
4714 }
4715 
4716 void CSSStyleSelector::mapBackgroundRepeat(BackgroundLayer *layer, DOM::CSSValueImpl *value)
4717 {
4718     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4719         layer->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat());
4720         return;
4721     }
4722 
4723     if (!value->isPrimitiveValue()) {
4724         return;
4725     }
4726     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4727     switch (primitiveValue->getIdent()) {
4728     case CSS_VAL_REPEAT:
4729         layer->setBackgroundRepeat(REPEAT);
4730         break;
4731     case CSS_VAL_REPEAT_X:
4732         layer->setBackgroundRepeat(REPEAT_X);
4733         break;
4734     case CSS_VAL_REPEAT_Y:
4735         layer->setBackgroundRepeat(REPEAT_Y);
4736         break;
4737     case CSS_VAL_NO_REPEAT:
4738         layer->setBackgroundRepeat(NO_REPEAT);
4739         break;
4740     default:
4741         return;
4742     }
4743 }
4744 
4745 void CSSStyleSelector::mapBackgroundSize(BackgroundLayer *layer, CSSValueImpl *value)
4746 {
4747     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4748         layer->setBackgroundSize(RenderStyle::initialBackgroundSize());
4749         return;
4750     }
4751 
4752     if (!value->isPrimitiveValue()) {
4753         return;
4754     }
4755 
4756     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4757     const int id = primitiveValue->getIdent();
4758     if (id == CSS_VAL_CONTAIN) {
4759         layer->setBackgroundSize(BGSize(BGSCONTAIN));
4760         return;
4761     }
4762     if (id == CSS_VAL_COVER) {
4763         layer->setBackgroundSize(BGSize(BGSCOVER));
4764         return;
4765     }
4766 
4767     PairImpl *pair = primitiveValue->getPairValue();
4768     if (!pair) {
4769         return;
4770     }
4771 
4772     CSSPrimitiveValueImpl *first = static_cast<CSSPrimitiveValueImpl *>(pair->first());
4773     CSSPrimitiveValueImpl *second = static_cast<CSSPrimitiveValueImpl *>(pair->second());
4774 
4775     if (!first || !second) {
4776         return;
4777     }
4778 
4779     Length firstLength, secondLength;
4780 
4781     if (first->getIdent() == CSS_VAL_AUTO) {
4782         firstLength = Length(Auto);
4783     } else {
4784         const int type = first->primitiveType();
4785         if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
4786             firstLength = Length(first->computeLength(style, m_rootStyle, logicalDpiY), Fixed);
4787         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
4788             firstLength = Length(first->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
4789         } else {
4790             return;
4791         }
4792     }
4793 
4794     if (second->getIdent() == CSS_VAL_AUTO) {
4795         secondLength = Length(Auto);
4796     } else {
4797         const int type = second->primitiveType();
4798         if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
4799             secondLength = Length(second->computeLength(style, m_rootStyle, logicalDpiY), Fixed);
4800         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
4801             secondLength = Length(second->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
4802         } else {
4803             return;
4804         }
4805     }
4806 
4807     layer->setBackgroundSize(BGSize(firstLength, secondLength));
4808 }
4809 
4810 void CSSStyleSelector::mapBackgroundXPosition(BackgroundLayer *layer, DOM::CSSValueImpl *value)
4811 {
4812     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4813         layer->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
4814         return;
4815     }
4816 
4817     if (!value->isPrimitiveValue()) {
4818         return;
4819     }
4820     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4821     Length l;
4822     int type = primitiveValue->primitiveType();
4823     if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
4824         l = Length(primitiveValue->computeLength(style, m_rootStyle, logicalDpiY), Fixed);
4825     } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
4826         l = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
4827     } else {
4828         return;
4829     }
4830     layer->setBackgroundXPosition(l);
4831 }
4832 
4833 void CSSStyleSelector::mapBackgroundYPosition(BackgroundLayer *layer, DOM::CSSValueImpl *value)
4834 {
4835     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4836         layer->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
4837         return;
4838     }
4839 
4840     if (!value->isPrimitiveValue()) {
4841         return;
4842     }
4843     CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
4844     Length l;
4845     int type = primitiveValue->primitiveType();
4846     if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
4847         l = Length(primitiveValue->computeLength(style, m_rootStyle, logicalDpiY), Fixed);
4848     } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
4849         l = Length(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
4850     } else {
4851         return;
4852     }
4853     layer->setBackgroundYPosition(l);
4854 }
4855 
4856 #ifdef APPLE_CHANGES
4857 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle *aStyle, RenderStyle *aParentStyle)
4858 {
4859     const FontDef &childFont = aStyle->htmlFont().fontDef;
4860 
4861     if (childFont.sizeSpecified || !aParentStyle) {
4862         return;
4863     }
4864 
4865     const FontDef &parentFont = aParentStyle->htmlFont().fontDef;
4866 
4867     if (childFont.genericFamily == parentFont.genericFamily) {
4868         return;
4869     }
4870 
4871     // For now, lump all families but monospace together.
4872     if (childFont.genericFamily != FontDef::eMonospace &&
4873             parentFont.genericFamily != FontDef::eMonospace) {
4874         return;
4875     }
4876 
4877     // We know the parent is monospace or the child is monospace, and that font
4878     // size was unspecified.  We want to alter our font size to use the correct
4879     // "medium" font for our family.
4880     float size = 0;
4881     int minFontSize = settings->minFontSize();
4882     size = (childFont.genericFamily == FontDef::eMonospace) ? m_fixedFontSizes[3] : m_fontSizes[3];
4883     int isize = (int)size;
4884     if (isize < minFontSize) {
4885         isize = minFontSize;
4886     }
4887 
4888     FontDef newFontDef(childFont);
4889     newFontDef.size = isize;
4890     aStyle->setFontDef(newFontDef);
4891 }
4892 #endif
4893 
4894 // #### FIXME!! this is ugly and isn't even properly updated or destroyed.
4895 
4896 void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp *expr, bool result)
4897 {
4898     m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result));
4899 }
4900 
4901 bool CSSStyleSelector::affectedByViewportChange() const
4902 {
4903     const int s = m_viewportDependentMediaQueryResults.size();
4904     for (int i = 0; i < s; i++) {
4905         if (m_medium->eval(&m_viewportDependentMediaQueryResults.at(i)->m_expression) != m_viewportDependentMediaQueryResults.at(i)->m_result) {
4906             return true;
4907         }
4908     }
4909     return false;
4910 }
4911 
4912 } // namespace khtml
4913