cssstyleselector.cpp

00001 
00026 #include "css/cssstyleselector.h"
00027 #include "rendering/render_style.h"
00028 #include "css/css_stylesheetimpl.h"
00029 #include "css/css_ruleimpl.h"
00030 #include "css/css_valueimpl.h"
00031 #include "css/csshelper.h"
00032 #include "rendering/render_object.h"
00033 #include "html/html_documentimpl.h"
00034 #include "html/html_elementimpl.h"
00035 #include "xml/dom_elementimpl.h"
00036 #include "xml/dom_restyler.h"
00037 #include "dom/css_rule.h"
00038 #include "dom/css_value.h"
00039 #include "khtml_factory.h"
00040 #include "khtmlpart_p.h"
00041 using namespace khtml;
00042 using namespace DOM;
00043 
00044 #include "css/cssproperties.h"
00045 #include "css/cssvalues.h"
00046 
00047 #include "misc/khtmllayout.h"
00048 #include "khtml_settings.h"
00049 #include "misc/htmlhashes.h"
00050 #include "misc/helper.h"
00051 #include "misc/loader.h"
00052 
00053 #include "rendering/font.h"
00054 
00055 #include "khtmlview.h"
00056 #include "khtml_part.h"
00057 
00058 #include <kstandarddirs.h>
00059 #include <kcharsets.h>
00060 #include <kglobal.h>
00061 #include <kconfig.h>
00062 #include <qfile.h>
00063 #include <qvaluelist.h>
00064 #include <qstring.h>
00065 #include <qtooltip.h>
00066 #include <kdebug.h>
00067 #include <kurl.h>
00068 #include <assert.h>
00069 #include <qpaintdevicemetrics.h>
00070 #include <stdlib.h>
00071 
00072 #define HANDLE_INHERIT(prop, Prop) \
00073 if (isInherit) \
00074 {\
00075     style->set##Prop(parentStyle->prop());\
00076     return;\
00077 }
00078 
00079 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
00080 HANDLE_INHERIT(prop, Prop) \
00081 else if (isInitial) \
00082 {\
00083     style->set##Prop(RenderStyle::initial##Prop());\
00084     return;\
00085 }
00086 
00087 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
00088 HANDLE_INHERIT(prop, Prop) \
00089 else if (isInitial) \
00090 {\
00091     style->set##Prop(RenderStyle::initial##Value());\
00092     return;\
00093 }
00094 
00095 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
00096 if (isInherit) { \
00097     BackgroundLayer* currChild = style->accessBackgroundLayers(); \
00098     BackgroundLayer* prevChild = 0; \
00099     const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \
00100     while (currParent && currParent->is##Prop##Set()) { \
00101         if (!currChild) { \
00102             /* Need to make a new layer.*/ \
00103             currChild = new BackgroundLayer(); \
00104             prevChild->setNext(currChild); \
00105         } \
00106         currChild->set##Prop(currParent->prop()); \
00107         prevChild = currChild; \
00108         currChild = prevChild->next(); \
00109         currParent = currParent->next(); \
00110     } \
00111     \
00112     while (currChild) { \
00113         /* Reset any remaining layers to not have the property set. */ \
00114         currChild->clear##Prop(); \
00115         currChild = currChild->next(); \
00116     } \
00117     return; \
00118 } \
00119 if (isInitial) { \
00120     BackgroundLayer* currChild = style->accessBackgroundLayers(); \
00121     currChild->set##Prop(RenderStyle::initial##Prop()); \
00122     for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
00123         currChild->clear##Prop(); \
00124     return; \
00125 }
00126 
00127 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \
00128 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
00129 if (!value->isPrimitiveValue() && !value->isValueList()) \
00130     return; \
00131 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
00132 BackgroundLayer* prevChild = 0; \
00133 if (value->isPrimitiveValue()) { \
00134     map##Prop(currChild, value); \
00135     currChild = currChild->next(); \
00136 } \
00137 else { \
00138     /* Walk each value and put it into a layer, creating new layers as needed. */ \
00139     CSSValueListImpl* valueList = static_cast<CSSValueListImpl*>(value); \
00140     for (unsigned int i = 0; i < valueList->length(); i++) { \
00141         if (!currChild) { \
00142             /* Need to make a new layer to hold this value */ \
00143             currChild = new BackgroundLayer(); \
00144             prevChild->setNext(currChild); \
00145         } \
00146         map##Prop(currChild, valueList->item(i)); \
00147         prevChild = currChild; \
00148         currChild = currChild->next(); \
00149     } \
00150 } \
00151 while (currChild) { \
00152     /* Reset all remaining layers to not have the property set. */ \
00153     currChild->clear##Prop(); \
00154     currChild = currChild->next(); \
00155 } }
00156 
00157 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
00158 if (id == propID) \
00159 {\
00160     style->set##Prop(parentStyle->prop());\
00161     return;\
00162 }
00163 
00164 #define HANDLE_INITIAL_COND(propID, Prop) \
00165 if (id == propID) \
00166 {\
00167     style->set##Prop(RenderStyle::initial##Prop());\
00168     return;\
00169 }
00170 
00171 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
00172 if (id == propID) \
00173 {\
00174     style->set##Prop(RenderStyle::initial##Value());\
00175     return;\
00176 }
00177 
00178 namespace khtml {
00179 
00180 CSSStyleSelectorList *CSSStyleSelector::s_defaultStyle;
00181 CSSStyleSelectorList *CSSStyleSelector::s_defaultQuirksStyle;
00182 CSSStyleSelectorList *CSSStyleSelector::s_defaultPrintStyle;
00183 CSSStyleSheetImpl *CSSStyleSelector::s_defaultSheet;
00184 RenderStyle* CSSStyleSelector::styleNotYetAvailable;
00185 CSSStyleSheetImpl *CSSStyleSelector::s_quirksSheet;
00186 
00187 enum PseudoState { PseudoUnknown, PseudoNone, PseudoLink, PseudoVisited};
00188 static PseudoState pseudoState;
00189 
00190 
00191 CSSStyleSelector::CSSStyleSelector( DocumentImpl* doc, QString userStyleSheet, StyleSheetListImpl *styleSheets,
00192                                     const KURL &url, bool _strictParsing )
00193 {
00194     KHTMLView* view = doc->view();
00195 
00196     init(view ? view->part()->settings() : 0, doc);
00197 
00198     strictParsing = _strictParsing;
00199     m_medium = view ? view->mediaType() : QString("all");
00200 
00201     selectors = 0;
00202     selectorCache = 0;
00203     properties = 0;
00204     userStyle = 0;
00205     userSheet = 0;
00206     paintDeviceMetrics = doc->paintDeviceMetrics();
00207 
00208     if(paintDeviceMetrics) // this may be null, not everyone uses khtmlview (Niko)
00209         computeFontSizes(paintDeviceMetrics, view ? view->part()->zoomFactor() : 100);
00210 
00211     if ( !userStyleSheet.isEmpty() ) {
00212         userSheet = new DOM::CSSStyleSheetImpl(doc);
00213         userSheet->parseString( DOMString( userStyleSheet ) );
00214 
00215         userStyle = new CSSStyleSelectorList();
00216         userStyle->append( userSheet, m_medium );
00217     }
00218 
00219     // add stylesheets from document
00220     authorStyle = new CSSStyleSelectorList();
00221 
00222 
00223     QPtrListIterator<StyleSheetImpl> it( styleSheets->styleSheets );
00224     for ( ; it.current(); ++it ) {
00225         if ( it.current()->isCSSStyleSheet() && !it.current()->disabled()) {
00226             authorStyle->append( static_cast<CSSStyleSheetImpl*>( it.current() ), m_medium );
00227         }
00228     }
00229 
00230     buildLists();
00231 
00232     //kdDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count() << endl;
00233     //kdDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements"<< endl;
00234 
00235     KURL u = url;
00236 
00237     u.setQuery( QString::null );
00238     u.setRef( QString::null );
00239     encodedurl.file = u.url();
00240     int pos = encodedurl.file.findRev('/');
00241     encodedurl.path = encodedurl.file;
00242     if ( pos > 0 ) {
00243     encodedurl.path.truncate( pos );
00244     encodedurl.path += '/';
00245     }
00246     u.setPath( QString::null );
00247     encodedurl.host = u.url();
00248 
00249     //kdDebug() << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path << endl;
00250 }
00251 
00252 CSSStyleSelector::CSSStyleSelector( CSSStyleSheetImpl *sheet )
00253 {
00254     init(0L, 0L);
00255 
00256     KHTMLView *view = sheet->doc()->view();
00257     m_medium = view ? view->mediaType() : "screen";
00258 
00259     authorStyle = new CSSStyleSelectorList();
00260     authorStyle->append( sheet, m_medium );
00261 }
00262 
00263 void CSSStyleSelector::init(const KHTMLSettings* _settings, DocumentImpl* doc)
00264 {
00265     element = 0;
00266     settings = _settings;
00267     paintDeviceMetrics = 0;
00268     propsToApply = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *));
00269     pseudoProps = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *));
00270     propsToApplySize = 128;
00271     pseudoPropsSize = 128;
00272     if(!s_defaultStyle) loadDefaultStyle(settings, doc);
00273 
00274     defaultStyle = s_defaultStyle;
00275     defaultPrintStyle = s_defaultPrintStyle;
00276     defaultQuirksStyle = s_defaultQuirksStyle;
00277 }
00278 
00279 CSSStyleSelector::~CSSStyleSelector()
00280 {
00281     clearLists();
00282     delete authorStyle;
00283     delete userStyle;
00284     delete userSheet;
00285     free(propsToApply);
00286     free(pseudoProps);
00287 }
00288 
00289 void CSSStyleSelector::addSheet( CSSStyleSheetImpl *sheet )
00290 {
00291     KHTMLView *view = sheet->doc()->view();
00292     m_medium = view ? view->mediaType() : "screen";
00293     authorStyle->append( sheet, m_medium );
00294 }
00295 
00296 void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s, DocumentImpl *doc)
00297 {
00298     if(s_defaultStyle) return;
00299 
00300     {
00301     QFile f(locate( "data", "khtml/css/html4.css" ) );
00302     f.open(IO_ReadOnly);
00303 
00304     QCString file( f.size()+1 );
00305     int readbytes = f.readBlock( file.data(), f.size() );
00306     f.close();
00307     if ( readbytes >= 0 )
00308         file[readbytes] = '\0';
00309 
00310     QString style = QString::fromLatin1( file.data() );
00311     if(s)
00312         style += s->settingsToCSS();
00313     DOMString str(style);
00314 
00315     s_defaultSheet = new DOM::CSSStyleSheetImpl(doc);
00316     s_defaultSheet->parseString( str );
00317 
00318     // Collect only strict-mode rules.
00319     s_defaultStyle = new CSSStyleSelectorList();
00320     s_defaultStyle->append( s_defaultSheet, "screen" );
00321 
00322     s_defaultPrintStyle = new CSSStyleSelectorList();
00323     s_defaultPrintStyle->append( s_defaultSheet, "print" );
00324     }
00325     {
00326     QFile f(locate( "data", "khtml/css/quirks.css" ) );
00327     f.open(IO_ReadOnly);
00328 
00329     QCString file( f.size()+1 );
00330     int readbytes = f.readBlock( file.data(), f.size() );
00331     f.close();
00332     if ( readbytes >= 0 )
00333         file[readbytes] = '\0';
00334 
00335     QString style = QString::fromLatin1( file.data() );
00336     DOMString str(style);
00337 
00338     s_quirksSheet = new DOM::CSSStyleSheetImpl(doc);
00339     s_quirksSheet->parseString( str );
00340 
00341     // Collect only quirks-mode rules.
00342     s_defaultQuirksStyle = new CSSStyleSelectorList();
00343     s_defaultQuirksStyle->append( s_quirksSheet, "screen" );
00344     }
00345 
00346     //kdDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements"<< endl;
00347 }
00348 
00349 void CSSStyleSelector::clear()
00350 {
00351     delete s_defaultStyle;
00352     delete s_defaultQuirksStyle;
00353     delete s_defaultPrintStyle;
00354     delete s_defaultSheet;
00355     delete styleNotYetAvailable;
00356     s_defaultStyle = 0;
00357     s_defaultQuirksStyle = 0;
00358     s_defaultPrintStyle = 0;
00359     s_defaultSheet = 0;
00360     styleNotYetAvailable = 0;
00361 }
00362 
00363 void CSSStyleSelector::reparseConfiguration()
00364 {
00365     // nice leak, but best we can do right now. hopefully its only rare.
00366     s_defaultStyle = 0;
00367     s_defaultQuirksStyle = 0;
00368     s_defaultPrintStyle = 0;
00369     s_defaultSheet = 0;
00370 }
00371 
00372 #define MAXFONTSIZES 8
00373 
00374 void CSSStyleSelector::computeFontSizes(QPaintDeviceMetrics* paintDeviceMetrics,  int zoomFactor)
00375 {
00376     computeFontSizesFor(paintDeviceMetrics, zoomFactor, m_fontSizes, false);
00377     computeFontSizesFor(paintDeviceMetrics, zoomFactor, m_fixedFontSizes, true);
00378 }
00379 
00380 void CSSStyleSelector::computeFontSizesFor(QPaintDeviceMetrics* paintDeviceMetrics, int zoomFactor, QValueVector<int>& fontSizes, bool isFixed)
00381 {
00382 #ifdef APPLE_CHANGES
00383     // We don't want to scale the settings by the dpi.
00384     const float toPix = 1;
00385 #else
00386     Q_UNUSED( isFixed );
00387 
00388     // ### get rid of float / double
00389     float toPix = paintDeviceMetrics->logicalDpiY()/72.;
00390     if (toPix  < 96./72.) toPix = 96./72.;
00391 #endif // ######### fix isFixed code again.
00392 
00393     fontSizes.resize( MAXFONTSIZES );
00394     float scale = 1.0;
00395     static const float fontFactors[] =      {3./5., 3./4., 8./9., 1., 6./5., 3./2., 2., 3.};
00396     static const float smallFontFactors[] = {3./4., 5./6., 8./9., 1., 6./5., 3./2., 2., 3.};
00397     float mediumFontSize, minFontSize, factor;
00398     if (!khtml::printpainter) {
00399         scale *= zoomFactor / 100.0;
00400 #ifdef APPLE_CHANGES
00401     if (isFixed)
00402         mediumFontSize = settings->mediumFixedFontSize() * toPix;
00403     else
00404 #endif
00405         mediumFontSize = settings->mediumFontSize() * toPix;
00406         minFontSize = settings->minFontSize() * toPix;
00407     }
00408     else {
00409         // ## depending on something / configurable ?
00410         mediumFontSize = 12;
00411         minFontSize = 6;
00412     }
00413     const float* factors = scale*mediumFontSize >= 12.5 ? fontFactors : smallFontFactors;
00414     for ( int i = 0; i < MAXFONTSIZES; i++ ) {
00415         factor = scale*factors[i];
00416         fontSizes[i] = int(KMAX( mediumFontSize*factor +.5f, minFontSize));
00417         //kdDebug( 6080 ) << "index: " << i << " factor: " << factors[i] << " font pix size: " << int(KMAX( mediumFontSize*factor +.5f, minFontSize)) << endl;
00418     }
00419 }
00420 
00421 #undef MAXFONTSIZES
00422 
00423 static inline void bubbleSort( CSSOrderedProperty **b, CSSOrderedProperty **e )
00424 {
00425     while( b < e ) {
00426     bool swapped = false;
00427         CSSOrderedProperty **y = e+1;
00428     CSSOrderedProperty **x = e;
00429         CSSOrderedProperty **swappedPos = 0;
00430     do {
00431         if ( !((**(--x)) < (**(--y))) ) {
00432         swapped = true;
00433                 swappedPos = x;
00434                 CSSOrderedProperty *tmp = *y;
00435                 *y = *x;
00436                 *x = tmp;
00437         }
00438     } while( x != b );
00439     if ( !swapped ) break;
00440         b = swappedPos + 1;
00441     }
00442 }
00443 
00444 RenderStyle *CSSStyleSelector::styleForElement(ElementImpl *e)
00445 {
00446     if (!e->getDocument()->haveStylesheetsLoaded() || !e->getDocument()->view()) {
00447         if (!styleNotYetAvailable) {
00448             styleNotYetAvailable = new RenderStyle();
00449             styleNotYetAvailable->setDisplay(NONE);
00450             styleNotYetAvailable->ref();
00451         }
00452         return styleNotYetAvailable;
00453     }
00454 
00455     // set some variables we will need
00456     pseudoState = PseudoUnknown;
00457 
00458     element = e;
00459     parentNode = e->parentNode();
00460     parentStyle = ( parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0;
00461     view = element->getDocument()->view();
00462     part = view->part();
00463     settings = part->settings();
00464     paintDeviceMetrics = element->getDocument()->paintDeviceMetrics();
00465 
00466     // reset dynamic DOM dependencies
00467     e->getDocument()->dynamicDomRestyler().resetDependencies(e);
00468 
00469     style = new RenderStyle();
00470     if( parentStyle )
00471         style->inheritFrom( parentStyle );
00472     else
00473     parentStyle = style;
00474 
00475     unsigned int numPropsToApply = 0;
00476     unsigned int numPseudoProps = 0;
00477 
00478     // try to sort out most style rules as early as possible.
00479     Q_UINT16 cssTagId = localNamePart(element->id());
00480     int smatch = 0;
00481     int schecked = 0;
00482 
00483     for ( unsigned int i = 0; i < selectors_size; i++ ) {
00484     Q_UINT16 tag = localNamePart(selectors[i]->tag);
00485     if ( cssTagId == tag || tag == anyLocalName ) {
00486         ++schecked;
00487 
00488         checkSelector( i, e );
00489 
00490         if ( selectorCache[i].state == Applies ) {
00491         ++smatch;
00492 
00493 //      qDebug("adding property" );
00494         for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
00495             for ( unsigned int j = 0; j < (unsigned int )selectorCache[i].props[p+1]; ++j ) {
00496                         if (numPropsToApply >= propsToApplySize ) {
00497                             propsToApplySize *= 2;
00498                 propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) );
00499             }
00500             propsToApply[numPropsToApply++] = properties[selectorCache[i].props[p]+j];
00501             }
00502         } else if ( selectorCache[i].state == AppliesPseudo ) {
00503         for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
00504             for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j ) {
00505                         if (numPseudoProps >= pseudoPropsSize ) {
00506                             pseudoPropsSize *= 2;
00507                 pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, pseudoPropsSize*sizeof( CSSOrderedProperty * ) );
00508             }
00509             pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j];
00510             properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId;
00511             }
00512         }
00513     }
00514     else
00515         selectorCache[i].state = Invalid;
00516 
00517     }
00518 
00519     // inline style declarations, after all others. non css hints
00520     // count as author rules, and come before all other style sheets, see hack in append()
00521     numPropsToApply = addInlineDeclarations( e, e->m_styleDecls, numPropsToApply );
00522 
00523 //     qDebug( "styleForElement( %s )", e->tagName().string().latin1() );
00524 //     qDebug( "%d selectors, %d checked,  %d match,  %d properties ( of %d )",
00525 //      selectors_size, schecked, smatch, numPropsToApply, properties_size );
00526 
00527     bubbleSort( propsToApply, propsToApply+numPropsToApply-1 );
00528     bubbleSort( pseudoProps, pseudoProps+numPseudoProps-1 );
00529 
00530     // we can't apply style rules without a view() and a part. This
00531     // tends to happen on delayed destruction of widget Renderobjects
00532     if ( part ) {
00533         fontDirty = false;
00534 
00535         if (numPropsToApply ) {
00536             CSSStyleSelector::style = style;
00537             for (unsigned int i = 0; i < numPropsToApply; ++i) {
00538         if ( fontDirty && propsToApply[i]->priority >= (1 << 30) ) {
00539             // we are past the font properties, time to update to the
00540             // correct font
00541 #ifdef APPLE_CHANGES
00542             checkForGenericFamilyChange(style, parentStyle);
00543 #endif
00544             CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
00545             fontDirty = false;
00546         }
00547         DOM::CSSProperty *prop = propsToApply[i]->prop;
00548 //      if (prop->m_id == CSS_PROP__KONQ_USER_INPUT) kdDebug(6080) << "El: "<<e->nodeName().string() << " user-input: "<<((CSSPrimitiveValueImpl *)prop->value())->getIdent() << endl;
00549 //      if (prop->m_id == CSS_PROP_TEXT_TRANSFORM) kdDebug(6080) << "El: "<<e->nodeName().string() << endl;
00550                 applyRule( prop->m_id, prop->value() );
00551         }
00552         if ( fontDirty ) {
00553 #ifdef APPLE_CHANGES
00554             checkForGenericFamilyChange(style, parentStyle);
00555 #endif
00556         CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
00557             }
00558         }
00559 
00560         // Clean up our style object's display and text decorations (among other fixups).
00561         adjustRenderStyle(style, e);
00562 
00563         if ( numPseudoProps ) {
00564         fontDirty = false;
00565             //qDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() );
00566             for (unsigned int i = 0; i < numPseudoProps; ++i) {
00567         if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) {
00568             // we are past the font properties, time to update to the
00569             // correct font
00570             //We have to do this for all pseudo styles
00571             RenderStyle *pseudoStyle = style->pseudoStyle;
00572             while ( pseudoStyle ) {
00573             pseudoStyle->htmlFont().update( paintDeviceMetrics );
00574             pseudoStyle = pseudoStyle->pseudoStyle;
00575             }
00576             fontDirty = false;
00577         }
00578 
00579                 RenderStyle *pseudoStyle;
00580                 pseudoStyle = style->getPseudoStyle(pseudoProps[i]->pseudoId);
00581                 if (!pseudoStyle)
00582                 {
00583                     pseudoStyle = style->addPseudoStyle(pseudoProps[i]->pseudoId);
00584                     if (pseudoStyle)
00585                         pseudoStyle->inheritFrom( style );
00586                 }
00587 
00588                 RenderStyle* oldStyle = style;
00589                 RenderStyle* oldParentStyle = parentStyle;
00590                 parentStyle = style;
00591         style = pseudoStyle;
00592                 if ( pseudoStyle ) {
00593             DOM::CSSProperty *prop = pseudoProps[i]->prop;
00594             applyRule( prop->m_id, prop->value() );
00595         }
00596                 style = oldStyle;
00597                 parentStyle = oldParentStyle;
00598             }
00599 
00600         if ( fontDirty ) {
00601         RenderStyle *pseudoStyle = style->pseudoStyle;
00602         while ( pseudoStyle ) {
00603             pseudoStyle->htmlFont().update( paintDeviceMetrics );
00604             pseudoStyle = pseudoStyle->pseudoStyle;
00605         }
00606         }
00607         }
00608     }
00609 
00610     // Now adjust all our pseudo-styles.
00611     RenderStyle *pseudoStyle = style->pseudoStyle;
00612     while (pseudoStyle) {
00613         adjustRenderStyle(pseudoStyle, 0);
00614         pseudoStyle = pseudoStyle->pseudoStyle;
00615     }
00616 
00617     // Now return the style.
00618     return style;
00619 }
00620 
00621 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e)
00622 {
00623      // Cache our original display.
00624      style->setOriginalDisplay(style->display());
00625 
00626     if (style->display() != NONE) {
00627         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
00628         // property.
00629         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
00630         // these tags to retain their display types.
00631         if (!strictParsing && e) {
00632             if (e->id() == ID_TD) {
00633                 style->setDisplay(TABLE_CELL);
00634                 style->setFloating(FNONE);
00635             }
00636 //             else if (e->id() == ID_TABLE)
00637 //                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
00638         }
00639 
00640         // Table headers with a text-align of auto will change the text-align to center.
00641         if (e && e->id() == ID_TH && style->textAlign() == TAAUTO)
00642             style->setTextAlign(CENTER);
00643 
00644         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
00645         // position or float an inline, compact, or run-in.  Cache the original display, since it
00646         // may be needed for positioned elements that have to compute their static normal flow
00647         // positions.  We also force inline-level roots to be block-level.
00648         if (style->display() != BLOCK && style->display() != TABLE /*&& style->display() != BOX*/ &&
00649             (style->position() == ABSOLUTE || style->position() == FIXED || style->floating() != FNONE ||
00650              (e && e->getDocument()->documentElement() == e))) {
00651              if (style->display() == INLINE_TABLE)
00652                  style->setDisplay(TABLE);
00653 //             else if (style->display() == INLINE_BOX)
00654 //                 style->setDisplay(BOX);
00655             else if (style->display() == LIST_ITEM) {
00656                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
00657                 // but only in quirks mode.
00658                 if (!strictParsing && style->floating() != FNONE)
00659                     style->setDisplay(BLOCK);
00660             }
00661             else
00662                 style->setDisplay(BLOCK);
00663         }
00664 
00665         // After performing the display mutation, check our position.  We do not honor position:relative on
00666         // table rows and some other table displays. This is undefined behaviour in CSS2.1 (cf. 9.3.1)
00667         if (style->position() == RELATIVE) {
00668             switch (style->display()) {
00669               case TABLE_ROW_GROUP:
00670               case TABLE_HEADER_GROUP:
00671               case TABLE_FOOTER_GROUP:
00672               case TABLE_ROW:
00673                 style->setPosition(STATIC);
00674               default:
00675                 break;
00676             }
00677         }
00678     }
00679 
00680     // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
00681     // fix a crash where a site tries to position these objects.
00682     if ( e ) {
00683         // ignore display: none for <frame>
00684         if ( e->id() == ID_FRAME ) {
00685             style->setPosition( STATIC );
00686             style->setDisplay( BLOCK );
00687         }
00688         else if ( e->id() == ID_FRAMESET ) {
00689             style->setPosition( STATIC );
00690         }
00691     }
00692 
00693     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
00694     // tables, inline blocks, inline tables, or run-ins.
00695     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
00696         || style->display() == INLINE_BLOCK /*|| style->display() == INLINE_BOX*/)
00697         style->setTextDecorationsInEffect(style->textDecoration());
00698     else
00699         style->addToTextDecorationsInEffect(style->textDecoration());
00700 
00701     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
00702     // FIXME: Eventually table sections will support auto and scroll.
00703     if (style->overflow() != OVISIBLE && style->overflow() != OHIDDEN && 
00704         (style->display() == TABLE || style->display() == INLINE_TABLE ||
00705          style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW))
00706         style->setOverflow(OVISIBLE);
00707 
00708     // Cull out any useless layers and also repeat patterns into additional layers.
00709     style->adjustBackgroundLayers();
00710 
00711     // Only use slow repaints if we actually have a background image.
00712     // FIXME: We only need to invalidate the fixed regions when scrolling.  It's total overkill to
00713     // prevent the entire view from blitting on a scroll.
00714     if (style->hasFixedBackgroundImage() && view)
00715         view->useSlowRepaints();
00716 }
00717 
00718 unsigned int CSSStyleSelector::addInlineDeclarations(DOM::ElementImpl* e,
00719                                                      DOM::CSSStyleDeclarationImpl *decl,
00720                                                      unsigned int numProps)
00721 {
00722     CSSStyleDeclarationImpl* addDecls = 0;
00723 #ifdef APPLE_CHANGES
00724     if (e->id() == ID_TD || e->id() == ID_TH)     // For now only TableCellElement implements the
00725         addDecls = e->getAdditionalStyleDecls();  // virtual function for shared cell rules.
00726 #else
00727     Q_UNUSED( e );
00728 #endif
00729 
00730     if (!decl && !addDecls)
00731         return numProps;
00732 
00733     QPtrList<CSSProperty>* values = decl ? decl->values() : 0;
00734     QPtrList<CSSProperty>* addValues = addDecls ? addDecls->values() : 0;
00735     if (!values && !addValues)
00736         return numProps;
00737 
00738     int firstLen = values ? values->count() : 0;
00739     int secondLen = addValues ? addValues->count() : 0;
00740     int totalLen = firstLen + secondLen;
00741 
00742     if (inlineProps.size() < (uint)totalLen)
00743         inlineProps.resize(totalLen + 1);
00744 
00745     if (numProps + totalLen >= propsToApplySize ) {
00746         propsToApplySize += propsToApplySize;
00747         propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) );
00748     }
00749 
00750     CSSOrderedProperty *array = (CSSOrderedProperty *)inlineProps.data();
00751     for(int i = 0; i < totalLen; i++)
00752     {
00753         if (i == firstLen)
00754             values = addValues;
00755 
00756         CSSProperty *prop = values->at(i >= firstLen ? i - firstLen : i);
00757     Source source = Inline;
00758 
00759         if( prop->m_important ) source = InlineImportant;
00760     if( prop->nonCSSHint ) source = NonCSSHint;
00761 
00762     bool first;
00763         // give special priority to font-xxx, color properties
00764         switch(prop->m_id)
00765         {
00766         case CSS_PROP_FONT_STYLE:
00767     case CSS_PROP_FONT_SIZE:
00768     case CSS_PROP_FONT_WEIGHT:
00769         case CSS_PROP_FONT_FAMILY:
00770         case CSS_PROP_FONT_VARIANT:
00771         case CSS_PROP_FONT:
00772         case CSS_PROP_COLOR:
00773         case CSS_PROP_DIRECTION:
00774         case CSS_PROP_DISPLAY:
00775             // these have to be applied first, because other properties use the computed
00776             // values of these properties.
00777         first = true;
00778             break;
00779         default:
00780             first = false;
00781             break;
00782         }
00783 
00784     array->prop = prop;
00785     array->pseudoId = RenderStyle::NOPSEUDO;
00786     array->selector = 0;
00787     array->position = i;
00788     array->priority = (!first << 30) | (source << 24);
00789     propsToApply[numProps++] = array++;
00790     }
00791     return numProps;
00792 }
00793 
00794 // modified version of the one in kurl.cpp
00795 static void cleanpath(QString &path)
00796 {
00797     int pos;
00798     while ( (pos = path.find( "/../" )) != -1 ) {
00799         int prev = 0;
00800         if ( pos > 0 )
00801             prev = path.findRev( "/", pos -1 );
00802         // don't remove the host, i.e. http://foo.org/../foo.html
00803         if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2))
00804             path.remove( pos, 3);
00805         else
00806             // matching directory found ?
00807             path.remove( prev, pos- prev + 3 );
00808     }
00809     pos = 0;
00810 
00811     // Don't remove "//" from an anchor identifier. -rjw
00812     // Set refPos to -2 to mean "I haven't looked for the anchor yet".
00813     // We don't want to waste a function call on the search for the anchor
00814     // in the vast majority of cases where there is no "//" in the path.
00815     int refPos = -2;
00816     while ( (pos = path.find( "//", pos )) != -1) {
00817         if (refPos == -2)
00818             refPos = path.find("#", 0);
00819         if (refPos > 0 && pos >= refPos)
00820             break;
00821 
00822         if ( pos == 0 || path[pos-1] != ':' )
00823             path.remove( pos, 1 );
00824         else
00825             pos += 2;
00826     }
00827     while ( (pos = path.find( "/./" )) != -1)
00828         path.remove( pos, 2 );
00829     //kdDebug() << "checkPseudoState " << path << endl;
00830 }
00831 
00832 static PseudoState checkPseudoState( const CSSStyleSelector::Encodedurl& encodedurl, DOM::ElementImpl *e )
00833 {
00834     if( e->id() != ID_A ) {
00835         return PseudoNone;
00836     }
00837     DOMString attr = e->getAttribute(ATTR_HREF);
00838     if( attr.isNull() ) {
00839         return PseudoNone;
00840     }
00841     QConstString cu(attr.unicode(), attr.length());
00842     QString u = cu.string();
00843     if ( !u.contains("://") ) {
00844         if ( u[0] == '/' )
00845             u = encodedurl.host + u;
00846         else if ( u[0] == '#' )
00847             u = encodedurl.file + u;
00848         else
00849             u = encodedurl.path + u;
00850         cleanpath( u );
00851     }
00852     //completeURL( attr.string() );
00853     bool contains = KHTMLFactory::vLinks()->contains( u );
00854     if ( !contains && u.contains('/')==2 )
00855       contains = KHTMLFactory::vLinks()->contains( u+'/' );
00856     return contains ? PseudoVisited : PseudoLink;
00857 }
00858 
00859 // a helper function for parsing nth-arguments
00860 static bool matchNth(int count, const QString& nth)
00861 {
00862     if (nth.isEmpty()) return false;
00863     int a = 0;
00864     int b = 0;
00865     if (nth == "odd") {
00866         a = 2;
00867         b = 1;
00868     }
00869     else if (nth == "even") {
00870         a = 2;
00871         b = 0;
00872     }
00873     else {
00874         int n = nth.find('n');
00875         if (n != -1) {
00876             if (nth[0] == '-')
00877                 if (n==1)
00878                     a = -1;
00879                 else
00880                     a = nth.mid(1,n-1).toInt();
00881             else
00882                 if (n==0)
00883                     a = 1;
00884                 else
00885                     a = nth.left(n).toInt();
00886 
00887             int p = nth.find('+');
00888             if (p != -1)
00889                 b = nth.mid(p+1).toInt();
00890             else {
00891                 p = nth.find('-');
00892                 b = -nth.mid(p+1).toInt();
00893             }
00894         }
00895         else {
00896             b = nth.toInt();
00897         }
00898     }
00899     if (a == 0)
00900         return count == b;
00901     else if (a > 0)
00902         if (count < b)
00903             return false;
00904         else
00905             return (count - b) % a == 0;
00906     else if (a < 0) {
00907         if (count > b)
00908             return false;
00909         else
00910             return (b - count) % (-a) == 0;
00911     }
00912     return false;
00913 }
00914 
00915 
00916 // Recursively work the combinator to compute static attribute dependency, similar to
00917 //structure of checkSubSelectors
00918 static void precomputeAttributeDependenciesAux(DOM::DocumentImpl* doc, DOM::CSSSelector* sel, bool isAncestor, bool isSubject)
00919 {
00920     if(sel->attr)
00921     {
00922         // Sets up global dependencies of attributes
00923         if (isSubject)
00924             doc->dynamicDomRestyler().addDependency(sel->attr, PersonalDependency);
00925         else if (isAncestor)
00926             doc->dynamicDomRestyler().addDependency(sel->attr, AncestorDependency);
00927         else
00928             doc->dynamicDomRestyler().addDependency(sel->attr, PredecessorDependency);
00929     }
00930     if(sel->match == CSSSelector::PseudoClass)
00931     {
00932     switch (sel->pseudoType()) {
00933             case CSSSelector::PseudoNot:
00934                 precomputeAttributeDependenciesAux(doc, sel->simpleSelector, isAncestor, true);
00935                 break;
00936             default:
00937                 break;
00938         }
00939     }
00940     CSSSelector::Relation relation = sel->relation;
00941     sel = sel->tagHistory;
00942     if (!sel) return;
00943 
00944     switch(relation)
00945     {
00946     case CSSSelector::Descendant:
00947     case CSSSelector::Child:
00948         precomputeAttributeDependenciesAux(doc, sel, true, false);
00949         break;
00950     case CSSSelector::IndirectAdjacent:
00951     case CSSSelector::DirectAdjacent:
00952         precomputeAttributeDependenciesAux(doc, sel, false, false);
00953         break;
00954     case CSSSelector::SubSelector:
00955         precomputeAttributeDependenciesAux(doc, sel, isAncestor, isSubject);
00956         break;
00957     }
00958 }
00959 
00960 void CSSStyleSelector::precomputeAttributeDependencies(DOM::DocumentImpl* doc, DOM::CSSSelector* sel)
00961 {
00962     precomputeAttributeDependenciesAux(doc, sel, false, true);
00963 }
00964 
00965 // Recursive check of combinators to support nondeterministic matching
00966 DOM::NodeImpl* CSSStyleSelector::checkSubSelectors(DOM::CSSSelector *sel, DOM::NodeImpl * n, bool isAncestor)
00967 {
00968     if(!n->isElementNode()) return 0;
00969 
00970     CSSSelector::Relation relation = sel->relation;
00971     sel = sel->tagHistory;
00972     if (!sel) return n;
00973 
00974     switch(relation)
00975     {
00976     case CSSSelector::Descendant:
00977     {
00978         ElementImpl *elem = 0;
00979         while(true)
00980         {
00981             n = n->parentNode();
00982             if(!n || !n->isElementNode()) return 0;
00983             elem = static_cast<ElementImpl *>(n);
00984             // Found one matching element
00985             if(checkOneSelector(sel, elem, true)) {
00986                 // Check the rest of the combinators
00987                 if (checkSubSelectors(sel, n, true)) {
00988                     return n;
00989                 }
00990             }
00991         }
00992         return 0;
00993     }
00994     case CSSSelector::Child:
00995     {
00996         n = n->parentNode();
00997         if (!strictParsing)
00998             while (n && n->implicitNode()) n = n->parentNode();
00999         if(!n || !n->isElementNode()) return 0;
01000         ElementImpl *elem = static_cast<ElementImpl *>(n);
01001         if(!checkOneSelector(sel, elem, true)) return 0;
01002         break;
01003     }
01004     case CSSSelector::IndirectAdjacent:
01005     {
01006         // Sibling selectors always generate structural dependencies
01007         // because new inserted element might fullfill them.
01008         if (n->parentNode()->isElementNode())
01009             element->getDocument()->dynamicDomRestyler().addDependency(element,
01010                         static_cast<ElementImpl*>(n->parentNode()),
01011                         StructuralDependency);
01012         ElementImpl *elem = 0;
01013         while(true)
01014         {
01015             n = n->previousSibling();
01016             while( n && !n->isElementNode() )
01017                 n = n->previousSibling();
01018             if( !n ) return 0;
01019             elem = static_cast<ElementImpl *>(n);
01020             if (checkOneSelector(sel, elem, false)) {
01021                 // Check the rest of the combinators
01022                 if (checkSubSelectors(sel, n, false)) {
01023                     return n;
01024                 }
01025             }
01026         };
01027         return 0;
01028     }
01029     case CSSSelector::DirectAdjacent:
01030     {
01031         if (n->parentNode()->isElementNode())
01032             element->getDocument()->dynamicDomRestyler().addDependency(element,
01033                         static_cast<ElementImpl*>(n->parentNode()),
01034                         StructuralDependency);
01035         n = n->previousSibling();
01036         while( n && !n->isElementNode() )
01037             n = n->previousSibling();
01038         if( !n ) return 0;
01039         ElementImpl *elem = static_cast<ElementImpl *>(n);
01040         if(!checkOneSelector(sel, elem, false)) return 0;
01041         break;
01042     }
01043     case CSSSelector::SubSelector:
01044     {
01045         //kdDebug() << "CSSOrderedRule::checkSelector" << endl;
01046         ElementImpl *elem = static_cast<ElementImpl *>(n);
01047 
01048         if(!checkOneSelector(sel, elem, isAncestor, true)) return 0;
01049         //kdDebug() << "CSSOrderedRule::checkSelector: passed" << endl;
01050         break;
01051     }
01052     }
01053     return checkSubSelectors(sel, n, isAncestor);
01054 }
01055 
01056 void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl * e)
01057 {
01058     assert(e == element); // yes, actually
01059 
01060     dynamicPseudo = RenderStyle::NOPSEUDO;
01061 
01062     selectorCache[ selIndex ].state = Invalid;
01063     CSSSelector *sel = selectors[ selIndex ];
01064 
01065     // first selector has to match
01066     if(!checkOneSelector(sel, e,  true)) return;
01067 
01068     // check the subselectors
01069     if(!checkSubSelectors(sel, e, true)) return;
01070 
01071     if ( dynamicPseudo != RenderStyle::NOPSEUDO ) {
01072     selectorCache[selIndex].state = AppliesPseudo;
01073     selectors[ selIndex ]->pseudoId = dynamicPseudo;
01074     } else
01075     selectorCache[ selIndex ].state = Applies;
01076     //qDebug( "selector %d applies", selIndex );
01077     //selectors[ selIndex ]->print();
01078     return;
01079 }
01080 
01081 bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)
01082 {
01083     if(!e)
01084         return false;
01085 
01086     if (sel->tag != anyQName) {
01087         int eltID = e->id();
01088         Q_UINT16 localName = localNamePart(eltID);
01089         Q_UINT16 ns = namespacePart(eltID);
01090         Q_UINT16 selLocalName = localNamePart(sel->tag);
01091         Q_UINT16 selNS = namespacePart(sel->tag);
01092 
01093         if (localName <= ID_LAST_TAG && ns == defaultNamespace) {
01094             assert(e->isHTMLElement());
01095             ns = xhtmlNamespace;
01096         }
01097 
01098         // match on local
01099         if (selLocalName != anyLocalName && localName != selLocalName) return false;
01100         // match on namespace
01101         if (selNS != anyNamespace && ns != selNS) return false;
01102     }
01103 
01104     DOM::DocumentImpl* doc = e->getDocument();
01105 
01106     if(sel->attr)
01107     {
01108         DOMStringImpl* value = e->getAttributeImpl(sel->attr);
01109         if(!value) return false; // attribute is not set
01110 
01111         switch(sel->match)
01112         {
01113         case CSSSelector::Exact:
01114             /* attribute values are case insensitive in all HTML modes,
01115                even in the strict ones */
01116             if ( doc->htmlMode() != DocumentImpl::XHtml ) {
01117                 if ( strcasecmp(sel->value, value) )
01118                     return false;
01119             } else {
01120                 if ( strcmp(sel->value, value) )
01121                     return false;
01122             }
01123             break;
01124         case CSSSelector::Id:
01125         if( (strictParsing && strcmp(sel->value, value) ) ||
01126                 (!strictParsing && strcasecmp(sel->value, value)))
01127                 return false;
01128             break;
01129         case CSSSelector::Set:
01130             break;
01131         case CSSSelector::Class:
01132             // no break
01133         case CSSSelector::List:
01134         {
01135             int sel_len = sel->value.length();
01136             int val_len = value->length();
01137             // Be smart compare on length first
01138             if (sel_len > val_len) return false;
01139             // Selector string may not contain spaces
01140             if (sel->value.find(' ') != -1) return false;
01141             if (sel_len == val_len)
01142                 return (strictParsing && !strcmp(sel->value, value)) ||
01143                (!strictParsing && !strcasecmp(sel->value, value));
01144             // else the value is longer and can be a list
01145             if ( sel->match == CSSSelector::Class && !e->hasClassList() ) return false;
01146 
01147             QChar* sel_uc = sel->value.unicode();
01148             QChar* val_uc = value->unicode();
01149 
01150             QConstString sel_str(sel_uc, sel_len);
01151             QConstString val_str(val_uc, val_len);
01152 
01153             int pos = 0;
01154             for ( ;; ) {
01155                 pos = val_str.string().find(sel_str.string(), pos, strictParsing);
01156                 if ( pos == -1 ) return false;
01157                 if ( pos == 0 || val_uc[pos-1].isSpace() ) {
01158                     int endpos = pos + sel_len;
01159                     if ( endpos >= val_len || val_uc[endpos].isSpace() )
01160                         break; // We have a match.
01161                 }
01162                 ++pos;
01163             }
01164             break;
01165         }
01166         case CSSSelector::Contain:
01167         {
01168             //kdDebug( 6080 ) << "checking for contains match" << endl;
01169             QConstString val_str(value->unicode(), value->length());
01170             QConstString sel_str(sel->value.unicode(), sel->value.length());
01171             return val_str.string().contains(sel_str.string());
01172         }
01173         case CSSSelector::Begin:
01174         {
01175             //kdDebug( 6080 ) << "checking for beginswith match" << endl;
01176             QConstString val_str(value->unicode(), value->length());
01177             QConstString sel_str(sel->value.unicode(), sel->value.length());
01178             return val_str.string().startsWith(sel_str.string());
01179         }
01180         case CSSSelector::End:
01181         {
01182             //kdDebug( 6080 ) << "checking for endswith match" << endl;
01183             QConstString val_str(value->unicode(), value->length());
01184             QConstString sel_str(sel->value.unicode(), sel->value.length());
01185             return val_str.string().endsWith(sel_str.string());
01186         }
01187         case CSSSelector::Hyphen:
01188         {
01189             //kdDebug( 6080 ) << "checking for hyphen match" << endl;
01190             QConstString val_str(value->unicode(), value->length());
01191             QConstString sel_str(sel->value.unicode(), sel->value.length());
01192             const QString& str = val_str.string();
01193             const QString& selStr = sel_str.string();
01194             if(str.length() < selStr.length()) return false;
01195             // Check if str begins with selStr:
01196             if(str.find(selStr, 0, strictParsing) != 0) return false;
01197             // It does. Check for exact match or following '-':
01198             if(str.length() != selStr.length()
01199                 && str[selStr.length()] != '-') return false;
01200             break;
01201         }
01202         case CSSSelector::PseudoClass:
01203         case CSSSelector::PseudoElement:
01204         case CSSSelector::None:
01205             break;
01206         }
01207     }
01208 
01209     if(sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement)
01210     {
01211     switch (sel->pseudoType()) {
01212         // Pseudo classes:
01213     case CSSSelector::PseudoEmpty:
01214             doc->dynamicDomRestyler().addDependency(element, e, BackwardsStructuralDependency);
01215             // If e is not closed yet we don't know the number of children
01216             if (!e->closed()) {
01217                 return false;
01218             }
01219             if (!e->firstChild())
01220                 return true;
01221             else {
01222                 // check for empty text nodes
01223                 NodeImpl *t = e->firstChild();
01224 
01225                 while (t && t->isTextNode() && static_cast<TextImpl*>(t)->length() == 0) t = t->nextSibling();
01226 
01227                 if (t == 0)
01228                     return true;
01229                 else
01230                     return false;
01231             }
01232             break;
01233     case CSSSelector::PseudoFirstChild: {
01234         // first-child matches the first child that is an element!
01235             if (e->parentNode() && e->parentNode()->isElementNode()) {
01236                 // Handle dynamic DOM changes
01237                 doc->dynamicDomRestyler().addDependency(element,
01238                             static_cast<ElementImpl*>(e->parentNode()),
01239                             StructuralDependency);
01240                 DOM::NodeImpl* n = e->previousSibling();
01241                 while ( n && !n->isElementNode() )
01242                     n = n->previousSibling();
01243                 if ( !n )
01244                     return true;
01245             }
01246             break;
01247         }
01248         case CSSSelector::PseudoLastChild: {
01249             // last-child matches the last child that is an element!
01250             if (e->parentNode() && e->parentNode()->isElementNode()) {
01251                 // Handle unfinished parsing and dynamic DOM changes
01252                 doc->dynamicDomRestyler().addDependency(element,
01253                             static_cast<ElementImpl*>(e->parentNode()),
01254                             BackwardsStructuralDependency);
01255                 if (!e->parentNode()->closed()) {
01256 //                     kdDebug(6080) << e->nodeName().string() << "::last-child: Parent unclosed" << endl;
01257                     return false;
01258                 }
01259                 DOM::NodeImpl* n = e->nextSibling();
01260                 while ( n && !n->isElementNode() )
01261                     n = n->nextSibling();
01262                 if ( !n )
01263                     return true;
01264             }
01265             break;
01266         }
01267         case CSSSelector::PseudoOnlyChild: {
01268             // If both first-child and last-child apply, then only-child applies.
01269             if (e->parentNode() && e->parentNode()->isElementNode()) {
01270                 doc->dynamicDomRestyler().addDependency(element,
01271                             static_cast<ElementImpl*>(e->parentNode()),
01272                             BackwardsStructuralDependency);
01273                 if (!e->parentNode()->closed()) {
01274                     return false;
01275                 }
01276                 DOM::NodeImpl* n = e->previousSibling();
01277                 while ( n && !n->isElementNode() )
01278                     n = n->previousSibling();
01279                 if ( !n ) {
01280                     n = e->nextSibling();
01281                     while ( n && !n->isElementNode() )
01282                         n = n->nextSibling();
01283                     if ( !n )
01284                         return true;
01285                 }
01286             }
01287             break;
01288         }
01289         case CSSSelector::PseudoNthChild: {
01290         // nth-child matches every (a*n+b)th element!
01291             if (e->parentNode() && e->parentNode()->isElementNode()) {
01292                 doc->dynamicDomRestyler().addDependency(element,
01293                             static_cast<ElementImpl*>(e->parentNode()),
01294                             StructuralDependency);
01295                 int count = 1;
01296                 DOM::NodeImpl* n = e->previousSibling();
01297                 while ( n ) {
01298                     if (n->isElementNode()) count++;
01299                     n = n->previousSibling();
01300                 }
01301 //                 kdDebug(6080) << "NthChild " << count << "=" << sel->string_arg << endl;
01302                 if (matchNth(count,sel->string_arg.string()))
01303                     return true;
01304             }
01305             break;
01306         }
01307         case CSSSelector::PseudoNthLastChild: {
01308             if (e->parentNode() && e->parentNode()->isElementNode()) {
01309                 doc->dynamicDomRestyler().addDependency(element,
01310                             static_cast<ElementImpl*>(e->parentNode()),
01311                             BackwardsStructuralDependency);
01312                 if (!e->parentNode()->closed()) {
01313                     return false;
01314                 }
01315                 int count = 1;
01316                 DOM::NodeImpl* n = e->nextSibling();
01317                 while ( n ) {
01318                     if (n->isElementNode()) count++;
01319                     n = n->nextSibling();
01320                 }
01321 //                kdDebug(6080) << "NthLastChild " << count << "=" << sel->string_arg << endl;
01322                 if (matchNth(count,sel->string_arg.string()))
01323                     return true;
01324             }
01325             break;
01326         }
01327     case CSSSelector::PseudoFirstOfType: {
01328         // first-of-type matches the first element of its type!
01329             if (e->parentNode() && e->parentNode()->isElementNode()) {
01330                 doc->dynamicDomRestyler().addDependency(element,
01331                             static_cast<ElementImpl*>(e->parentNode()),
01332                             StructuralDependency);
01333                 const DOMString& type = e->tagName();
01334                 DOM::NodeImpl* n = e->previousSibling();
01335                 while ( n ) {
01336                     if (n->isElementNode())
01337                         if (static_cast<ElementImpl*>(n)->tagName() == type) break;
01338                     n = n->previousSibling();
01339                 }
01340                 if ( !n )
01341                     return true;
01342             }
01343             break;
01344         }
01345         case CSSSelector::PseudoLastOfType: {
01346             // last-child matches the last child that is an element!
01347             if (e->parentNode() && e->parentNode()->isElementNode()) {
01348                 doc->dynamicDomRestyler().addDependency(element,
01349                             static_cast<ElementImpl*>(e->parentNode()),
01350                             BackwardsStructuralDependency);
01351                 if (!e->parentNode()->closed()) {
01352                     return false;
01353                 }
01354                 const DOMString& type = e->tagName();
01355                 DOM::NodeImpl* n = e->nextSibling();
01356                 while ( n ) {
01357                     if (n->isElementNode())
01358                         if (static_cast<ElementImpl*>(n)->tagName() == type) break;
01359                     n = n->nextSibling();
01360                 }
01361                 if ( !n )
01362                     return true;
01363             }
01364             break;
01365         }
01366         case CSSSelector::PseudoOnlyOfType: {
01367             // If both first-of-type and last-of-type apply, then only-of-type applies.
01368             if (e->parentNode() && e->parentNode()->isElementNode()) {
01369                 doc->dynamicDomRestyler().addDependency(element,
01370                             static_cast<ElementImpl*>(e->parentNode()),
01371                             BackwardsStructuralDependency);
01372                 if (!e->parentNode()->closed()) {
01373                     return false;
01374                 }
01375                 const DOMString& type = e->tagName();
01376                 DOM::NodeImpl* n = e->previousSibling();
01377                 while ( n && !(n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type))
01378                     n = n->previousSibling();
01379                 if ( !n ) {
01380                     n = e->nextSibling();
01381                     while ( n && !(n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type))
01382                         n = n->nextSibling();
01383                     if ( !n )
01384                         return true;
01385             }
01386             }
01387         break;
01388         }
01389         case CSSSelector::PseudoNthOfType: {
01390         // nth-of-type matches every (a*n+b)th element of this type!
01391             if (e->parentNode() && e->parentNode()->isElementNode()) {
01392                 doc->dynamicDomRestyler().addDependency(element,
01393                             static_cast<ElementImpl*>(e->parentNode()),
01394                             StructuralDependency);
01395                 int count = 1;
01396                 const DOMString& type = e->tagName();
01397                 DOM::NodeImpl* n = e->previousSibling();
01398                 while ( n ) {
01399                     if (n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type) count++;
01400                     n = n->previousSibling();
01401                 }
01402 //                kdDebug(6080) << "NthOfType " << count << "=" << sel->string_arg << endl;
01403                 if (matchNth(count,sel->string_arg.string()))
01404                     return true;
01405             }
01406             break;
01407         }
01408         case CSSSelector::PseudoNthLastOfType: {
01409             if (e->parentNode() && e->parentNode()->isElementNode()) {
01410                 doc->dynamicDomRestyler().addDependency(element,
01411                             static_cast<ElementImpl*>(e->parentNode()),
01412                             BackwardsStructuralDependency);
01413                 if (!e->parentNode()->closed()) {
01414                     return false;
01415                 }
01416                 int count = 1;
01417                 const DOMString& type = e->tagName();
01418                 DOM::NodeImpl* n = e->nextSibling();
01419                 while ( n ) {
01420                     if (n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type) count++;
01421                     n = n->nextSibling();
01422                 }
01423 //                kdDebug(6080) << "NthLastOfType " << count << "=" << sel->string_arg << endl;
01424                 if (matchNth(count,sel->string_arg.string()))
01425                     return true;
01426             }
01427             break;
01428         }
01429         case CSSSelector::PseudoTarget:
01430             if (e == doc->getCSSTarget())
01431                 return true;
01432             break;
01433         case CSSSelector::PseudoRoot:
01434             if (e == doc->documentElement())
01435                 return true;
01436             break;
01437     case CSSSelector::PseudoLink:
01438         if (e == element) {
01439            // cache pseudoState
01440            if ( pseudoState == PseudoUnknown )
01441                     pseudoState = checkPseudoState( encodedurl, e );
01442                if ( pseudoState == PseudoLink )
01443                     return true;
01444             } else
01445                 return checkPseudoState( encodedurl, e ) == PseudoLink;
01446         break;
01447     case CSSSelector::PseudoVisited:
01448         if (e == element) {
01449                 // cache pseudoState
01450                 if ( pseudoState == PseudoUnknown )
01451                     pseudoState = checkPseudoState( encodedurl, e );
01452                 if ( pseudoState == PseudoVisited )
01453                     return true;
01454             } else
01455                 return checkPseudoState( encodedurl, e ) == PseudoVisited;
01456         break;
01457         case CSSSelector::PseudoHover: {
01458         // If we're in quirks mode, then *:active should only match focusable elements, and never
01459         // unfocusable anchors.
01460         if (strictParsing || ((sel->tag != anyQName || isSubSelector) && e->id() != ID_A) || e->isFocusable()) {
01461                 doc->dynamicDomRestyler().addDependency(element, e, HoverDependency);
01462 
01463                 if (e->hovered())
01464                     return true;
01465             }
01466             break;
01467         }
01468     case CSSSelector::PseudoActive:
01469         // If we're in quirks mode, then *:active should only match focusable elements
01470         if (strictParsing || ((sel->tag != anyQName || isSubSelector) && e->id() != ID_A) || e->isFocusable()) {
01471                 doc->dynamicDomRestyler().addDependency(element, e, ActiveDependency);
01472 
01473         if (e->active())
01474             return true;
01475         }
01476         break;
01477     case CSSSelector::PseudoFocus:
01478         if (e != element && e->isFocusable()) {
01479                 // *:focus is a default style, no need to track it.
01480                 doc->dynamicDomRestyler().addDependency(element, e, OtherStateDependency);
01481             }
01482             if (e->focused()) return true;
01483             break;
01484         case CSSSelector::PseudoLang: {
01485             // Set dynamic attribute dependency
01486             if (e == element) {
01487                 doc->dynamicDomRestyler().addDependency(ATTR_LANG, PersonalDependency);
01488                 doc->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
01489             }
01490             else if (isAncestor)
01491                 doc->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
01492             else
01493                 doc->dynamicDomRestyler().addDependency(ATTR_LANG, PredecessorDependency);
01494             // ### check xml:lang attribute in XML and XHTML documents
01495             DOMString value = e->getAttribute(ATTR_LANG);
01496             // The LANG attribute is inherited like a property
01497             NodeImpl *n = e->parent();;
01498             while (n && value.isEmpty()) {
01499                 if (n->isElementNode()) {
01500                     value = static_cast<ElementImpl*>(n)->getAttribute(ATTR_LANG);
01501                 } else
01502                 if (n->isDocumentNode()) {
01503                     value = static_cast<DocumentImpl*>(n)->contentLanguage();
01504                 }
01505                 n = n->parent();
01506             }
01507             if (value.isEmpty()) return false;
01508 
01509             QString langAttr = value.string();
01510             QString langSel = sel->string_arg.string();
01511 
01512             if(langAttr.length() < langSel.length()) return false;
01513 
01514             langAttr = langAttr.lower();
01515             langSel = langSel.lower();
01516 //             kdDebug(6080) << ":lang " << langAttr << "=" << langSel << "?" << endl;
01517             return (langAttr == langSel || langAttr.startsWith(langSel+"-"));
01518         }
01519         case CSSSelector::PseudoNot: {
01520             // check the simple selector
01521             for (CSSSelector* subSel = sel->simpleSelector; subSel;
01522                  subSel = subSel->tagHistory) {
01523                 // :not cannot nest.  I don't really know why this is a restriction in CSS3,
01524                 // but it is, so let's honor it.
01525                 if (subSel->simpleSelector)
01526                     break;
01527                 if (!checkOneSelector(subSel, e, isAncestor))
01528                     return true;
01529             }
01530             break;
01531         }
01532         case CSSSelector::PseudoEnabled: {
01533             if (e->isGenericFormElement()) {
01534                 doc->dynamicDomRestyler().addDependency(element, e, OtherStateDependency);
01535                 HTMLGenericFormElementImpl *form;
01536                 form = static_cast<HTMLGenericFormElementImpl*>(e);
01537                 return !form->disabled();
01538             }
01539             break;
01540         }
01541         case CSSSelector::PseudoDisabled: {
01542             if (e->isGenericFormElement()) {
01543                 doc->dynamicDomRestyler().addDependency(element, e, OtherStateDependency);
01544                 HTMLGenericFormElementImpl *form;
01545                 form = static_cast<HTMLGenericFormElementImpl*>(e);
01546                 return form->disabled();
01547             }
01548             break;
01549         }
01550         case CSSSelector::PseudoContains: {
01551             if (e->isHTMLElement()) {
01552                 doc->dynamicDomRestyler().addDependency(element, e, BackwardsStructuralDependency);
01553                 if (!e->closed()) {
01554                    return false;
01555                 }
01556                 HTMLElementImpl *elem;
01557                 elem = static_cast<HTMLElementImpl*>(e);
01558                 DOMString s = elem->innerText();
01559                 QString selStr = sel->string_arg.string();
01560 //                kdDebug(6080) << ":contains(\"" << selStr << "\")" << " on \"" << s << "\"" << endl;
01561                 return s.string().contains(selStr);
01562             }
01563             break;
01564         }
01565     case CSSSelector::PseudoChecked: {
01566            if (e->isHTMLElement() && e->id() == ID_INPUT) {
01567                doc->dynamicDomRestyler().addDependency(element, e, OtherStateDependency);
01568                return (static_cast<HTMLInputElementImpl*>(e)->checked());
01569            }
01570            return false;
01571         }
01572     case CSSSelector::PseudoIndeterminate: {
01573 #if 0
01574            if (e->isHTMLElement() && e->id() == ID_INPUT) {
01575                return (static_cast<HTMLInputElementImpl*>(e)->indeterminate() &&
01576                       !static_cast<HTMLInputElementImpl*>(e)->checked());
01577            }
01578            return false;
01579 #endif
01580         }
01581     case CSSSelector::PseudoOther:
01582         break;
01583 
01584     // Pseudo-elements:
01585     case CSSSelector::PseudoFirstLine:
01586     case CSSSelector::PseudoFirstLetter:
01587     case CSSSelector::PseudoSelection:
01588     case CSSSelector::PseudoBefore:
01589     case CSSSelector::PseudoAfter:
01590     case CSSSelector::PseudoMarker:
01591     case CSSSelector::PseudoReplaced:
01592         // Pseudo-elements can only apply to subject
01593         if ( e == element ) {
01594                 // Pseudo-elements has to be the last sub-selector on subject
01595                 if (sel->tagHistory && sel->relation == CSSSelector::SubSelector) return false;
01596 
01597                 assert(dynamicPseudo == RenderStyle::NOPSEUDO);
01598 
01599                 switch (sel->pseudoType()) {
01600                 case CSSSelector::PseudoFirstLine:
01601                     dynamicPseudo = RenderStyle::FIRST_LINE;
01602                     break;
01603                 case CSSSelector::PseudoFirstLetter:
01604                     dynamicPseudo = RenderStyle::FIRST_LETTER;
01605                     break;
01606                 case CSSSelector::PseudoSelection:
01607                     dynamicPseudo = RenderStyle::SELECTION;
01608                     break;
01609                 case CSSSelector::PseudoBefore:
01610                     dynamicPseudo = RenderStyle::BEFORE;
01611                     break;
01612                 case CSSSelector::PseudoAfter:
01613                     dynamicPseudo = RenderStyle::AFTER;
01614                     break;
01615                 case CSSSelector::PseudoMarker:
01616                     dynamicPseudo = RenderStyle::MARKER;
01617                     break;
01618                 case CSSSelector::PseudoReplaced:
01619                     dynamicPseudo = RenderStyle::REPLACED;
01620                     break;
01621                 default:
01622                     assert(false);
01623                 }
01624         return true;
01625         }
01626         break;
01627     case CSSSelector::PseudoNotParsed:
01628         assert(false);
01629         break;
01630     }
01631     return false;
01632     }
01633     // ### add the rest of the checks...
01634     return true;
01635 }
01636 
01637 void CSSStyleSelector::clearLists()
01638 {
01639     delete [] selectors;
01640     if ( selectorCache ) {
01641         for ( unsigned int i = 0; i < selectors_size; i++ )
01642             delete [] selectorCache[i].props;
01643 
01644         delete [] selectorCache;
01645     }
01646     if ( properties ) {
01647     CSSOrderedProperty **prop = properties;
01648     while ( *prop ) {
01649         delete (*prop);
01650         prop++;
01651     }
01652         delete [] properties;
01653     }
01654     selectors = 0;
01655     properties = 0;
01656     selectorCache = 0;
01657 }
01658 
01659 
01660 void CSSStyleSelector::buildLists()
01661 {
01662     clearLists();
01663     // collect all selectors and Properties in lists. Then transfer them to the array for faster lookup.
01664 
01665     QPtrList<CSSSelector> selectorList;
01666     CSSOrderedPropertyList propertyList;
01667 
01668     if(m_medium == "print" && defaultPrintStyle)
01669       defaultPrintStyle->collect( &selectorList, &propertyList, Default,
01670         Default );
01671     else if(defaultStyle) defaultStyle->collect( &selectorList, &propertyList,
01672       Default, Default );
01673 
01674     if (!strictParsing && defaultQuirksStyle)
01675         defaultQuirksStyle->collect( &selectorList, &propertyList, Default, Default );
01676 
01677     if(userStyle) userStyle->collect(&selectorList, &propertyList, User, UserImportant );
01678     if(authorStyle) authorStyle->collect(&selectorList, &propertyList, Author, AuthorImportant );
01679 
01680     selectors_size = selectorList.count();
01681     selectors = new CSSSelector *[selectors_size];
01682     CSSSelector *s = selectorList.first();
01683     CSSSelector **sel = selectors;
01684     while ( s ) {
01685     *sel = s;
01686     s = selectorList.next();
01687     ++sel;
01688     }
01689 
01690     selectorCache = new SelectorCache[selectors_size];
01691     for ( unsigned int i = 0; i < selectors_size; i++ ) {
01692         selectorCache[i].state = Unknown;
01693         selectorCache[i].props_size = 0;
01694         selectorCache[i].props = 0;
01695     }
01696 
01697     // presort properties. Should make the sort() calls in styleForElement faster.
01698     propertyList.sort();
01699     properties_size = propertyList.count() + 1;
01700     properties = new CSSOrderedProperty *[ properties_size ];
01701     CSSOrderedProperty *p = propertyList.first();
01702     CSSOrderedProperty **prop = properties;
01703     while ( p ) {
01704     *prop = p;
01705     p = propertyList.next();
01706     ++prop;
01707     }
01708     *prop = 0;
01709 
01710     unsigned int* offsets = new unsigned int[selectors_size];
01711     if(properties[0])
01712     offsets[properties[0]->selector] = 0;
01713     for(unsigned int p = 1; p < properties_size; ++p) {
01714 
01715     if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) {
01716         unsigned int sel = properties[p - 1]->selector;
01717             int* newprops = new int[selectorCache[sel].props_size+2];
01718             for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ )
01719                 newprops[i] = selectorCache[sel].props[i];
01720 
01721         newprops[selectorCache[sel].props_size] = offsets[sel];
01722         newprops[selectorCache[sel].props_size+1] = p - offsets[sel];
01723             delete [] selectorCache[sel].props;
01724             selectorCache[sel].props = newprops;
01725             selectorCache[sel].props_size += 2;
01726 
01727         if(properties[p]) {
01728         sel = properties[p]->selector;
01729         offsets[sel] = p;
01730             }
01731         }
01732     }
01733     delete [] offsets;
01734 }
01735 
01736 
01737 // ----------------------------------------------------------------------
01738 
01739 
01740 CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index)
01741 {
01742     rule = r;
01743     if(rule) r->ref();
01744     index = _index;
01745     selector = s;
01746 }
01747 
01748 CSSOrderedRule::~CSSOrderedRule()
01749 {
01750     if(rule) rule->deref();
01751 }
01752 
01753 // -----------------------------------------------------------------
01754 
01755 CSSStyleSelectorList::CSSStyleSelectorList()
01756     : QPtrList<CSSOrderedRule>()
01757 {
01758     setAutoDelete(true);
01759 }
01760 CSSStyleSelectorList::~CSSStyleSelectorList()
01761 {
01762 }
01763 
01764 void CSSStyleSelectorList::append( CSSStyleSheetImpl *sheet,
01765                                    const DOMString &medium )
01766 {
01767     if(!sheet || !sheet->isCSSStyleSheet()) return;
01768 
01769     // No media implies "all", but if a medialist exists it must
01770     // contain our current medium
01771     if( sheet->media() && !sheet->media()->contains( medium ) )
01772         return; // style sheet not applicable for this medium
01773 
01774     int len = sheet->length();
01775 
01776     for(int i = 0; i< len; i++)
01777     {
01778         StyleBaseImpl *item = sheet->item(i);
01779         if(item->isStyleRule())
01780         {
01781             CSSStyleRuleImpl *r = static_cast<CSSStyleRuleImpl *>(item);
01782             QPtrList<CSSSelector> *s = r->selector();
01783             for(int j = 0; j < (int)s->count(); j++)
01784             {
01785                 CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count());
01786         QPtrList<CSSOrderedRule>::append(rule);
01787                 //kdDebug( 6080 ) << "appending StyleRule!" << endl;
01788             }
01789         }
01790         else if(item->isImportRule())
01791         {
01792             CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
01793 
01794             //kdDebug( 6080 ) << "@import: Media: "
01795             //                << import->media()->mediaText().string() << endl;
01796 
01797             if( !import->media() || import->media()->contains( medium ) )
01798             {
01799                 CSSStyleSheetImpl *importedSheet = import->styleSheet();
01800                 append( importedSheet, medium );
01801             }
01802         }
01803         else if( item->isMediaRule() )
01804         {
01805             CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl *>( item );
01806             CSSRuleListImpl *rules = r->cssRules();
01807 
01808             //DOMString mediaText = media->mediaText();
01809             //kdDebug( 6080 ) << "@media: Media: "
01810             //                << r->media()->mediaText().string() << endl;
01811 
01812             if( ( !r->media() || r->media()->contains( medium ) ) && rules)
01813             {
01814                 // Traverse child elements of the @import rule. Since
01815                 // many elements are not allowed as child we do not use
01816                 // a recursive call to append() here
01817                 for( unsigned j = 0; j < rules->length(); j++ )
01818                 {
01819                     //kdDebug( 6080 ) << "*** Rule #" << j << endl;
01820 
01821                     CSSRuleImpl *childItem = rules->item( j );
01822                     if( childItem->isStyleRule() )
01823                     {
01824                         // It is a StyleRule, so append it to our list
01825                         CSSStyleRuleImpl *styleRule =
01826                                 static_cast<CSSStyleRuleImpl *>( childItem );
01827 
01828                         QPtrList<CSSSelector> *s = styleRule->selector();
01829                         for( int j = 0; j < ( int ) s->count(); j++ )
01830                         {
01831                             CSSOrderedRule *orderedRule = new CSSOrderedRule(
01832                                             styleRule, s->at( j ), count() );
01833                         QPtrList<CSSOrderedRule>::append( orderedRule );
01834                         }
01835                     }
01836                     else
01837                     {
01838                         //kdDebug( 6080 ) << "Ignoring child rule of "
01839                         //    "ImportRule: rule is not a StyleRule!" << endl;
01840                     }
01841                 }   // for rules
01842             }   // if rules
01843             else
01844             {
01845                 //kdDebug( 6080 ) << "CSSMediaRule not rendered: "
01846                 //                << "rule empty or wrong medium!" << endl;
01847             }
01848         }
01849         // ### include other rules
01850     }
01851 }
01852 
01853 
01854 void CSSStyleSelectorList::collect( QPtrList<CSSSelector> *selectorList, CSSOrderedPropertyList *propList,
01855                     Source regular, Source important )
01856 {
01857     CSSOrderedRule *r = first();
01858     while( r ) {
01859     CSSSelector *sel = selectorList->first();
01860     int selectorNum = 0;
01861     while( sel ) {
01862         if ( *sel == *(r->selector) )
01863         break;
01864         sel = selectorList->next();
01865         selectorNum++;
01866     }
01867     if ( !sel )
01868         selectorList->append( r->selector );
01869 //  else
01870 //      qDebug("merged one selector");
01871     propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important );
01872     r = next();
01873     }
01874 }
01875 
01876 // -------------------------------------------------------------------------
01877 
01878 int CSSOrderedPropertyList::compareItems(QPtrCollection::Item i1, QPtrCollection::Item i2)
01879 {
01880     int diff =  static_cast<CSSOrderedProperty *>(i1)->priority
01881         - static_cast<CSSOrderedProperty *>(i2)->priority;
01882     return diff ? diff : static_cast<CSSOrderedProperty *>(i1)->position
01883         - static_cast<CSSOrderedProperty *>(i2)->position;
01884 }
01885 
01886 void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
01887                     Source regular, Source important )
01888 {
01889     QPtrList<CSSProperty> *values = decl->values();
01890     if(!values) return;
01891     int len = values->count();
01892     for(int i = 0; i < len; i++)
01893     {
01894         CSSProperty *prop = values->at(i);
01895     Source source = regular;
01896 
01897     if( prop->m_important ) source = important;
01898     if( prop->nonCSSHint ) source = NonCSSHint;
01899 
01900     bool first = false;
01901         // give special priority to font-xxx, color properties
01902         switch(prop->m_id)
01903         {
01904         case CSS_PROP_FONT_STYLE:
01905     case CSS_PROP_FONT_SIZE:
01906     case CSS_PROP_FONT_WEIGHT:
01907         case CSS_PROP_FONT_FAMILY:
01908         case CSS_PROP_FONT_VARIANT:
01909         case CSS_PROP_FONT:
01910         case CSS_PROP_COLOR:
01911         case CSS_PROP_DIRECTION:
01912         case CSS_PROP_DISPLAY:
01913             // these have to be applied first, because other properties use the computed
01914             // values of these porperties.
01915         first = true;
01916             break;
01917         default:
01918             break;
01919         }
01920 
01921     QPtrList<CSSOrderedProperty>::append(new CSSOrderedProperty(prop, selector,
01922                                  first, source, specificity,
01923                                  count() ));
01924     }
01925 }
01926 
01927 // -------------------------------------------------------------------------------------
01928 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
01929 
01930 static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, QPaintDeviceMetrics *paintDeviceMetrics, bool *ok = 0 )
01931 {
01932     Length l;
01933     if ( !primitiveValue ) {
01934     if ( ok )
01935             *ok = false;
01936     } else {
01937     int type = primitiveValue->primitiveType();
01938     if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
01939         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
01940     else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
01941         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent);
01942     else if(type == CSSPrimitiveValue::CSS_NUMBER)
01943         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
01944     else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
01945         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
01946     else if ( ok )
01947         *ok = false;
01948     }
01949     return l;
01950 }
01951 
01952 
01953 // color mapping code
01954 struct colorMap {
01955     int css_value;
01956     QRgb color;
01957 };
01958 
01959 static const colorMap cmap[] = {
01960     { CSS_VAL_AQUA, 0xFF00FFFF },
01961     { CSS_VAL_BLACK, 0xFF000000 },
01962     { CSS_VAL_BLUE, 0xFF0000FF },
01963     { CSS_VAL_CRIMSON, 0xFFDC143C },
01964     { CSS_VAL_FUCHSIA, 0xFFFF00FF },
01965     { CSS_VAL_GRAY, 0xFF808080 },
01966     { CSS_VAL_GREEN, 0xFF008000  },
01967     { CSS_VAL_INDIGO, 0xFF4B0082 },
01968     { CSS_VAL_LIME, 0xFF00FF00 },
01969     { CSS_VAL_MAROON, 0xFF800000 },
01970     { CSS_VAL_NAVY, 0xFF000080 },
01971     { CSS_VAL_OLIVE, 0xFF808000  },
01972     { CSS_VAL_ORANGE, 0xFFFFA500 },
01973     { CSS_VAL_PURPLE, 0xFF800080 },
01974     { CSS_VAL_RED, 0xFFFF0000 },
01975     { CSS_VAL_SILVER, 0xFFC0C0C0 },
01976     { CSS_VAL_TEAL, 0xFF008080  },
01977     { CSS_VAL_WHITE, 0xFFFFFFFF },
01978     { CSS_VAL_YELLOW, 0xFFFFFF00 },
01979     { CSS_VAL_INVERT, invertedColor },
01980     { CSS_VAL_TRANSPARENT, transparentColor },
01981     { CSS_VAL_GREY, 0xff808080 },
01982     { 0, 0 }
01983 };
01984 
01985 struct uiColors {
01986     int css_value;
01987     const char * configGroup;
01988     const char * configEntry;
01989 QPalette::ColorGroup group;
01990 QColorGroup::ColorRole role;
01991 };
01992 
01993 const char * const wmgroup = "WM";
01994 const char * const generalgroup = "General";
01995 
01996 /* Mapping system settings to CSS 2
01997 * Tried hard to get an appropriate mapping - schlpbch
01998 */
01999 static const uiColors uimap[] = {
02000     // Active window border.
02001     { CSS_VAL_ACTIVEBORDER, wmgroup, "background", QPalette::Active, QColorGroup::Light },
02002     // Active window caption.
02003     { CSS_VAL_ACTIVECAPTION, wmgroup, "background", QPalette::Active, QColorGroup::Text },
02004         // Text in caption, size box, and scrollbar arrow box.
02005     { CSS_VAL_CAPTIONTEXT, wmgroup, "activeForeground", QPalette::Active, QColorGroup::Text },
02006     // Face color for three-dimensional display elements.
02007     { CSS_VAL_BUTTONFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
02008     // Dark shadow for three-dimensional display elements (for edges facing away from the light source).
02009     { CSS_VAL_BUTTONHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
02010     // Shadow color for three-dimensional display elements.
02011     { CSS_VAL_BUTTONSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
02012     // Text on push buttons.
02013     { CSS_VAL_BUTTONTEXT, wmgroup, "buttonForeground", QPalette::Inactive, QColorGroup::ButtonText },
02014     // Dark shadow for three-dimensional display elements.
02015     { CSS_VAL_THREEDDARKSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Dark },
02016     // Face color for three-dimensional display elements.
02017     { CSS_VAL_THREEDFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
02018     // Highlight color for three-dimensional display elements.
02019     { CSS_VAL_THREEDHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
02020     // Light color for three-dimensional display elements (for edges facing the light source).
02021     { CSS_VAL_THREEDLIGHTSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Midlight },
02022     // Dark shadow for three-dimensional display elements.
02023     { CSS_VAL_THREEDSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
02024 
02025     // Inactive window border.
02026     { CSS_VAL_INACTIVEBORDER, wmgroup, "background", QPalette::Disabled, QColorGroup::Background },
02027     // Inactive window caption.
02028     { CSS_VAL_INACTIVECAPTION, wmgroup, "inactiveBackground", QPalette::Disabled, QColorGroup::Background },
02029     // Color of text in an inactive caption.
02030     { CSS_VAL_INACTIVECAPTIONTEXT, wmgroup, "inactiveForeground", QPalette::Disabled, QColorGroup::Text },
02031     { CSS_VAL_GRAYTEXT, wmgroup, 0, QPalette::Disabled, QColorGroup::Text },
02032 
02033     // Menu background
02034     { CSS_VAL_MENU, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
02035     // Text in menus
02036     { CSS_VAL_MENUTEXT, generalgroup, "foreground", QPalette::Inactive, QColorGroup::Background },
02037 
02038         // Text of item(s) selected in a control.
02039     { CSS_VAL_HIGHLIGHT, generalgroup, "selectBackground", QPalette::Inactive, QColorGroup::Background },
02040 
02041     // Text of item(s) selected in a control.
02042     { CSS_VAL_HIGHLIGHTTEXT, generalgroup, "selectForeground", QPalette::Inactive, QColorGroup::Background },
02043 
02044     // Background color of multiple document interface.
02045     { CSS_VAL_APPWORKSPACE, generalgroup, "background", QPalette::Inactive, QColorGroup::Text },
02046 
02047     // Scroll bar gray area.
02048     { CSS_VAL_SCROLLBAR, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
02049 
02050     // Window background.
02051     { CSS_VAL_WINDOW, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
02052     // Window frame.
02053     { CSS_VAL_WINDOWFRAME, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
02054         // WindowText
02055     { CSS_VAL_WINDOWTEXT, generalgroup, "windowForeground", QPalette::Inactive, QColorGroup::Text },
02056     { CSS_VAL_TEXT, generalgroup, 0, QPalette::Inactive, QColorGroup::Text },
02057     { 0, 0, 0, QPalette::NColorGroups, QColorGroup::NColorRoles }
02058 };
02059 
02060 static QColor colorForCSSValue( int css_value )
02061 {
02062     // try the regular ones first
02063     const colorMap *col = cmap;
02064     while ( col->css_value && col->css_value != css_value )
02065     ++col;
02066     if ( col->css_value )
02067     return col->color;
02068 
02069     const uiColors *uicol = uimap;
02070     while ( uicol->css_value && uicol->css_value != css_value )
02071     ++uicol;
02072 #ifndef APPLE_CHANGES
02073     if ( !uicol->css_value ) {
02074     if ( css_value == CSS_VAL_INFOBACKGROUND )
02075         return QToolTip::palette().inactive().background();
02076     else if ( css_value == CSS_VAL_INFOTEXT )
02077         return QToolTip::palette().inactive().foreground();
02078     else if ( css_value == CSS_VAL_BACKGROUND ) {
02079         KConfig bckgrConfig("kdesktoprc", true, false); // No multi-screen support
02080         bckgrConfig.setGroup("Desktop0");
02081         // Desktop background.
02082         return bckgrConfig.readColorEntry("Color1", &qApp->palette().disabled().background());
02083     }
02084     return QColor();
02085     }
02086 #endif
02087 
02088     const QPalette &pal = qApp->palette();
02089     QColor c = pal.color( uicol->group, uicol->role );
02090 #ifndef APPLE_CHANGES
02091     if ( uicol->configEntry ) {
02092     KConfig *globalConfig = KGlobal::config();
02093     globalConfig->setGroup( uicol->configGroup );
02094     c = globalConfig->readColorEntry( uicol->configEntry, &c );
02095     }
02096 #endif
02097 
02098     return c;
02099 }
02100 
02101 static inline int nextFontSize(const QValueVector<int>& a, int v, bool smaller)
02102 {
02103     // return the nearest bigger/smaller value in scale a, when v is in range.
02104     // otherwise increase/decrease value using a 1.2 fixed ratio
02105     int m, l = 0, r = a.count()-1;
02106     while (l <= r) {
02107         m = (l+r)/2;
02108         if (a[m] == v)
02109             return smaller ? ( m ? a[m-1] : (v*5)/6 ) :
02110                              ( m+1<int(a.count()) ? a[m+1] : (v*6)/5 );
02111         else if (v < a[m])
02112             r = m-1;
02113         else
02114             l = m+1;
02115     }
02116     if (!l)
02117         return smaller ? (v*5)/6 : kMin((v*6)/5, a[0]);
02118     if (l == int(a.count()))
02119         return smaller ? kMax((v*5)/6, a[r]) : (v*6)/5;
02120 
02121     return smaller ? a[r] : a[l];
02122 }
02123 
02124 void CSSStyleSelector::applyRule( int id, DOM::CSSValueImpl *value )
02125 {
02126 //     kdDebug( 6080 ) << "applying property " << getPropertyName(id) << endl;
02127 
02128     CSSPrimitiveValueImpl *primitiveValue = 0;
02129     if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
02130 
02131     Length l;
02132     bool apply = false;
02133 
02134     bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
02135     bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) ||
02136                      (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
02137 
02138     // These properties are used to set the correct margins/padding on RTL lists.
02139     if (id == CSS_PROP__KHTML_MARGIN_START)
02140         id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
02141     else if (id == CSS_PROP__KHTML_PADDING_START)
02142         id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
02143 
02144     // What follows is a list that maps the CSS properties into their corresponding front-end
02145     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
02146     // are only hit when mapping "inherit" or "initial" into front-end values.
02147     switch(id)
02148     {
02149 // ident only properties
02150     case CSS_PROP_BACKGROUND_ATTACHMENT:
02151         HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
02152         break;
02153     case CSS_PROP__KHTML_BACKGROUND_CLIP:
02154         HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
02155         break;
02156     case CSS_PROP__KHTML_BACKGROUND_ORIGIN:
02157         HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
02158         break;
02159     case CSS_PROP_BACKGROUND_REPEAT:
02160         HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
02161         break;
02162     case CSS_PROP__KHTML_BACKGROUND_SIZE:
02163         HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
02164         break;
02165     case CSS_PROP_BORDER_COLLAPSE:
02166         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
02167         if(!primitiveValue) break;
02168         switch(primitiveValue->getIdent())
02169         {
02170         case CSS_VAL_COLLAPSE:
02171             style->setBorderCollapse(true);
02172             break;
02173         case CSS_VAL_SEPARATE:
02174             style->setBorderCollapse(false);
02175             break;
02176         default:
02177             return;
02178         }
02179         break;
02180 
02181     case CSS_PROP_BORDER_TOP_STYLE:
02182         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
02183         if (!primitiveValue) return;
02184         style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02185         break;
02186     case CSS_PROP_BORDER_RIGHT_STYLE:
02187         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
02188         if (!primitiveValue) return;
02189         style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02190         break;
02191     case CSS_PROP_BORDER_BOTTOM_STYLE:
02192         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
02193         if (!primitiveValue) return;
02194         style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02195         break;
02196     case CSS_PROP_BORDER_LEFT_STYLE:
02197         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
02198         if (!primitiveValue) return;
02199         style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02200         break;
02201     case CSS_PROP_OUTLINE_STYLE:
02202         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
02203         if (!primitiveValue) return;
02204         style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02205         break;
02206     case CSS_PROP_CAPTION_SIDE:
02207     {
02208         HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
02209         if(!primitiveValue) break;
02210         ECaptionSide c = RenderStyle::initialCaptionSide();
02211         switch(primitiveValue->getIdent())
02212         {
02213         case CSS_VAL_LEFT:
02214             c = CAPLEFT; break;
02215         case CSS_VAL_RIGHT:
02216             c = CAPRIGHT; break;
02217         case CSS_VAL_TOP:
02218             c = CAPTOP; break;
02219         case CSS_VAL_BOTTOM:
02220             c = CAPBOTTOM; break;
02221         default:
02222             return;
02223         }
02224         style->setCaptionSide(c);
02225         return;
02226     }
02227     case CSS_PROP_CLEAR:
02228     {
02229         HANDLE_INHERIT_AND_INITIAL(clear, Clear)
02230         if(!primitiveValue) break;
02231         EClear c = CNONE;
02232         switch(primitiveValue->getIdent())
02233         {
02234         case CSS_VAL_LEFT:
02235             c = CLEFT; break;
02236         case CSS_VAL_RIGHT:
02237             c = CRIGHT; break;
02238         case CSS_VAL_BOTH:
02239             c = CBOTH; break;
02240         case CSS_VAL_NONE:
02241             c = CNONE; break;
02242         default:
02243             return;
02244         }
02245         style->setClear(c);
02246         return;
02247     }
02248     case CSS_PROP_DIRECTION:
02249     {
02250         HANDLE_INHERIT_AND_INITIAL(direction, Direction)
02251         if(!primitiveValue) break;
02252         style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) );
02253         return;
02254     }
02255     case CSS_PROP_DISPLAY:
02256     {
02257         HANDLE_INHERIT_AND_INITIAL(display, Display)
02258         if(!primitiveValue) break;
02259     int id = primitiveValue->getIdent();
02260         style->setDisplay( id == CSS_VAL_NONE ? NONE : EDisplay(id - CSS_VAL_INLINE) );
02261         break;
02262     }
02263 
02264     case CSS_PROP_EMPTY_CELLS:
02265     {
02266         HANDLE_INHERIT(emptyCells, EmptyCells);
02267         if (!primitiveValue) break;
02268         int id = primitiveValue->getIdent();
02269         if (id == CSS_VAL_SHOW)
02270             style->setEmptyCells(SHOW);
02271         else if (id == CSS_VAL_HIDE)
02272             style->setEmptyCells(HIDE);
02273         break;
02274     }
02275     case CSS_PROP_FLOAT:
02276     {
02277         HANDLE_INHERIT_AND_INITIAL(floating, Floating)
02278         if(!primitiveValue) return;
02279         EFloat f;
02280         switch(primitiveValue->getIdent())
02281         {
02282         case CSS_VAL__KHTML_LEFT:
02283             f = FLEFT_ALIGN; break;
02284         case CSS_VAL_LEFT:
02285             f = FLEFT; break;
02286         case CSS_VAL__KHTML_RIGHT:
02287             f = FRIGHT_ALIGN; break;
02288         case CSS_VAL_RIGHT:
02289             f = FRIGHT; break;
02290         case CSS_VAL_NONE:
02291         case CSS_VAL_CENTER:  //Non standart CSS-Value
02292             f = FNONE; break;
02293         default:
02294             return;
02295         }
02296         if (f!=FNONE && style->display()==LIST_ITEM)
02297             style->setDisplay(BLOCK);
02298 
02299         style->setFloating(f);
02300         break;
02301     }
02302 
02303     case CSS_PROP_FONT_STYLE:
02304     {
02305         FontDef fontDef = style->htmlFont().fontDef;
02306         if (isInherit)
02307             fontDef.italic = parentStyle->htmlFont().fontDef.italic;
02308     else if (isInitial)
02309             fontDef.italic = false;
02310         else {
02311         if(!primitiveValue) return;
02312         switch(primitiveValue->getIdent()) {
02313         case CSS_VAL_OBLIQUE:
02314         // ### oblique is the same as italic for the moment...
02315         case CSS_VAL_ITALIC:
02316             fontDef.italic = true;
02317             break;
02318         case CSS_VAL_NORMAL:
02319             fontDef.italic = false;
02320             break;
02321         default:
02322             return;
02323         }
02324     }
02325         fontDirty |= style->setFontDef( fontDef );
02326         break;
02327     }
02328 
02329 
02330     case CSS_PROP_FONT_VARIANT:
02331     {
02332         FontDef fontDef = style->htmlFont().fontDef;
02333         if (isInherit)
02334             fontDef.smallCaps = parentStyle->htmlFont().fontDef.weight;
02335         else if (isInitial)
02336             fontDef.smallCaps = false;
02337         else {
02338         if(!primitiveValue) return;
02339         int id = primitiveValue->getIdent();
02340         if ( id == CSS_VAL_NORMAL )
02341         fontDef.smallCaps = false;
02342         else if ( id == CSS_VAL_SMALL_CAPS )
02343         fontDef.smallCaps = true;
02344         else
02345         return;
02346     }
02347     fontDirty |= style->setFontDef( fontDef );
02348     break;
02349     }
02350 
02351     case CSS_PROP_FONT_WEIGHT:
02352     {
02353         FontDef fontDef = style->htmlFont().fontDef;
02354         if (isInherit)
02355             fontDef.weight = parentStyle->htmlFont().fontDef.weight;
02356         else if (isInitial)
02357             fontDef.weight = QFont::Normal;
02358         else {
02359         if(!primitiveValue) return;
02360         if(primitiveValue->getIdent())
02361         {
02362         switch(primitiveValue->getIdent()) {
02363             // ### we just support normal and bold fonts at the moment...
02364             // setWeight can actually accept values between 0 and 99...
02365         case CSS_VAL_BOLD:
02366         case CSS_VAL_BOLDER:
02367         case CSS_VAL_600:
02368         case CSS_VAL_700:
02369         case CSS_VAL_800:
02370         case CSS_VAL_900:
02371             fontDef.weight = QFont::Bold;
02372             break;
02373         case CSS_VAL_NORMAL:
02374         case CSS_VAL_LIGHTER:
02375         case CSS_VAL_100:
02376         case CSS_VAL_200:
02377         case CSS_VAL_300:
02378         case CSS_VAL_400:
02379         case CSS_VAL_500:
02380             fontDef.weight = QFont::Normal;
02381             break;
02382         default:
02383             return;
02384         }
02385         }
02386         else
02387         {
02388         // ### fix parsing of 100-900 values in parser, apply them here
02389         }
02390     }
02391         fontDirty |= style->setFontDef( fontDef );
02392         break;
02393     }
02394 
02395     case CSS_PROP_LIST_STYLE_POSITION:
02396     {
02397         HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
02398         if (!primitiveValue) return;
02399         if (primitiveValue->getIdent())
02400             style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) );
02401         return;
02402     }
02403 
02404     case CSS_PROP_LIST_STYLE_TYPE:
02405     {
02406         HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
02407         if (!primitiveValue) return;
02408         if (primitiveValue->getIdent())
02409         {
02410             EListStyleType t;
02411         int id = primitiveValue->getIdent();
02412         if ( id == CSS_VAL_NONE) { // important!!
02413           t = LNONE;
02414         } else {
02415           t = EListStyleType(id - CSS_VAL_DISC);
02416         }
02417             style->setListStyleType(t);
02418         }
02419         return;
02420     }
02421 
02422     case CSS_PROP_OVERFLOW:
02423     {
02424         HANDLE_INHERIT_AND_INITIAL(overflow, Overflow)
02425         if (!primitiveValue) return;
02426         EOverflow o;
02427         switch(primitiveValue->getIdent())
02428         {
02429         case CSS_VAL_VISIBLE:
02430             o = OVISIBLE; break;
02431         case CSS_VAL_HIDDEN:
02432             o = OHIDDEN; break;
02433         case CSS_VAL_SCROLL:
02434         o = OSCROLL; break;
02435         case CSS_VAL_AUTO:
02436         o = OAUTO; break;
02437         case CSS_VAL_MARQUEE:
02438             o = OMARQUEE; break;
02439         default:
02440             return;
02441         }
02442         style->setOverflow(o);
02443         return;
02444     }
02445     break;
02446     case CSS_PROP_PAGE_BREAK_BEFORE:
02447     {
02448         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
02449         if (!primitiveValue) return;
02450         switch (primitiveValue->getIdent()) {
02451             case CSS_VAL_AUTO:
02452                 style->setPageBreakBefore(PBAUTO);
02453                 break;
02454             case CSS_VAL_LEFT:
02455             case CSS_VAL_RIGHT:
02456                 // CSS2.1: "Conforming user agents may map left/right to always."
02457             case CSS_VAL_ALWAYS:
02458                 style->setPageBreakBefore(PBALWAYS);
02459                 break;
02460             case CSS_VAL_AVOID:
02461                 style->setPageBreakBefore(PBAVOID);
02462                 break;
02463         }
02464         break;
02465     }
02466 
02467     case CSS_PROP_PAGE_BREAK_AFTER:
02468     {
02469         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
02470         if (!primitiveValue) return;
02471         switch (primitiveValue->getIdent()) {
02472             case CSS_VAL_AUTO:
02473                 style->setPageBreakAfter(PBAUTO);
02474                 break;
02475             case CSS_VAL_LEFT:
02476             case CSS_VAL_RIGHT:
02477                 // CSS2.1: "Conforming user agents may map left/right to always."
02478             case CSS_VAL_ALWAYS:
02479                 style->setPageBreakAfter(PBALWAYS);
02480                 break;
02481             case CSS_VAL_AVOID:
02482                 style->setPageBreakAfter(PBAVOID);
02483                 break;
02484         }
02485         break;
02486     }
02487 
02488     case CSS_PROP_PAGE_BREAK_INSIDE: {
02489         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
02490         if (!primitiveValue) return;
02491         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
02492             style->setPageBreakInside(true);
02493         else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
02494             style->setPageBreakInside(false);
02495         return;
02496     }
02497 //    case CSS_PROP_PAUSE_AFTER:
02498 //    case CSS_PROP_PAUSE_BEFORE:
02499         break;
02500 
02501     case CSS_PROP_POSITION:
02502     {
02503         HANDLE_INHERIT_AND_INITIAL(position, Position)
02504         if (!primitiveValue) return;
02505         EPosition p;
02506         switch(primitiveValue->getIdent())
02507         {
02508         case CSS_VAL_STATIC:
02509             p = STATIC; break;
02510         case CSS_VAL_RELATIVE:
02511             p = RELATIVE; break;
02512         case CSS_VAL_ABSOLUTE:
02513             p = ABSOLUTE; break;
02514         case CSS_VAL_FIXED:
02515             {
02516                 view->useSlowRepaints();
02517                 p = FIXED;
02518                 break;
02519             }
02520         default:
02521             return;
02522         }
02523         style->setPosition(p);
02524         return;
02525     }
02526 
02527     case CSS_PROP_TABLE_LAYOUT: {
02528         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
02529 
02530     if ( !primitiveValue )
02531         return;
02532 
02533     ETableLayout l = RenderStyle::initialTableLayout();
02534     switch( primitiveValue->getIdent() ) {
02535     case CSS_VAL_FIXED:
02536         l = TFIXED;
02537         // fall through
02538     case CSS_VAL_AUTO:
02539         style->setTableLayout( l );
02540     default:
02541         break;
02542     }
02543     break;
02544     }
02545 
02546     case CSS_PROP_UNICODE_BIDI: {
02547         HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
02548         if(!primitiveValue) break;
02549         switch (primitiveValue->getIdent()) {
02550             case CSS_VAL_NORMAL:
02551                 style->setUnicodeBidi(UBNormal);
02552                 break;
02553             case CSS_VAL_EMBED:
02554                 style->setUnicodeBidi(Embed);
02555                 break;
02556             case CSS_VAL_BIDI_OVERRIDE:
02557                 style->setUnicodeBidi(Override);
02558                 break;
02559             default:
02560                 return;
02561         }
02562     break;
02563     }
02564     case CSS_PROP_TEXT_TRANSFORM: {
02565         HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
02566 
02567         if(!primitiveValue) break;
02568         if(!primitiveValue->getIdent()) return;
02569 
02570         ETextTransform tt;
02571         switch(primitiveValue->getIdent()) {
02572         case CSS_VAL_CAPITALIZE:  tt = CAPITALIZE;  break;
02573         case CSS_VAL_UPPERCASE:   tt = UPPERCASE;   break;
02574         case CSS_VAL_LOWERCASE:   tt = LOWERCASE;   break;
02575         case CSS_VAL_NONE:
02576         default:                  tt = TTNONE;      break;
02577         }
02578         style->setTextTransform(tt);
02579         break;
02580         }
02581 
02582     case CSS_PROP_VISIBILITY:
02583     {
02584         HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
02585 
02586         if(!primitiveValue) break;
02587         switch( primitiveValue->getIdent() ) {
02588         case CSS_VAL_HIDDEN:
02589             style->setVisibility( HIDDEN );
02590             break;
02591         case CSS_VAL_VISIBLE:
02592             style->setVisibility( VISIBLE );
02593             break;
02594         case CSS_VAL_COLLAPSE:
02595             style->setVisibility( COLLAPSE );
02596         default:
02597             break;
02598         }
02599         break;
02600     }
02601     case CSS_PROP_WHITE_SPACE:
02602         HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
02603 
02604         if(!primitiveValue) break;
02605         if(!primitiveValue->getIdent()) return;
02606 
02607         EWhiteSpace s;
02608         switch(primitiveValue->getIdent()) {
02609         case CSS_VAL__KHTML_NOWRAP:
02610             s = KHTML_NOWRAP;
02611             break;
02612         case CSS_VAL_NOWRAP:
02613             s = NOWRAP;
02614             break;
02615         case CSS_VAL_PRE:
02616             s = PRE;
02617             break;
02618         case CSS_VAL_PRE_WRAP:
02619             s = PRE_WRAP;
02620             break;
02621         case CSS_VAL_PRE_LINE:
02622             s = PRE_LINE;
02623             break;
02624         case CSS_VAL_NORMAL:
02625         default:
02626             s = NORMAL;
02627             break;
02628         }
02629         style->setWhiteSpace(s);
02630         break;
02631 
02632     case CSS_PROP_BACKGROUND_POSITION:
02633         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
02634         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
02635         break;
02636     case CSS_PROP_BACKGROUND_POSITION_X: {
02637         HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
02638         break;
02639     }
02640     case CSS_PROP_BACKGROUND_POSITION_Y: {
02641         HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
02642         break;
02643     }
02644     case CSS_PROP_BORDER_SPACING: {
02645         if(value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return;
02646         style->setBorderHorizontalSpacing(parentStyle->borderHorizontalSpacing());
02647         style->setBorderVerticalSpacing(parentStyle->borderVerticalSpacing());
02648         break;
02649     }
02650     case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: {
02651         HANDLE_INHERIT_AND_INITIAL(borderHorizontalSpacing, BorderHorizontalSpacing)
02652         if (!primitiveValue) break;
02653         short spacing =  primitiveValue->computeLength(style, paintDeviceMetrics);
02654         style->setBorderHorizontalSpacing(spacing);
02655         break;
02656     }
02657     case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: {
02658         HANDLE_INHERIT_AND_INITIAL(borderVerticalSpacing, BorderVerticalSpacing)
02659         if (!primitiveValue) break;
02660         short spacing =  primitiveValue->computeLength(style, paintDeviceMetrics);
02661         style->setBorderVerticalSpacing(spacing);
02662         break;
02663     }
02664 
02665     case CSS_PROP_CURSOR:
02666         HANDLE_INHERIT_AND_INITIAL(cursor, Cursor)
02667         if(primitiveValue)
02668         style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) );
02669         break;
02670 // colors || inherit
02671     case CSS_PROP_BACKGROUND_COLOR:
02672     case CSS_PROP_BORDER_TOP_COLOR:
02673     case CSS_PROP_BORDER_RIGHT_COLOR:
02674     case CSS_PROP_BORDER_BOTTOM_COLOR:
02675     case CSS_PROP_BORDER_LEFT_COLOR:
02676     case CSS_PROP_COLOR:
02677     case CSS_PROP_OUTLINE_COLOR:
02678         // this property is an extension used to get HTML4 <font> right.
02679     case CSS_PROP_SCROLLBAR_BASE_COLOR:
02680     case CSS_PROP_SCROLLBAR_FACE_COLOR:
02681     case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
02682     case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
02683     case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
02684     case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
02685     case CSS_PROP_SCROLLBAR_TRACK_COLOR:
02686     case CSS_PROP_SCROLLBAR_ARROW_COLOR:
02687     {
02688         QColor col;
02689         if (isInherit) {
02690             HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
02691             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
02692             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
02693             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
02694             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
02695             HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
02696             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
02697             return;
02698         } else if (isInitial) {
02699             // The border/outline colors will just map to the invalid color |col| above.  This will have the
02700             // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
02701             // not painting the background since the color won't be valid).
02702             if (id == CSS_PROP_COLOR)
02703                 col = RenderStyle::initialColor();
02704         } else {
02705         if(!primitiveValue )
02706         return;
02707         int ident = primitiveValue->getIdent();
02708         if ( ident ) {
02709         if ( ident == CSS_VAL__KHTML_TEXT )
02710             col = element->getDocument()->textColor();
02711         // ### should be eliminated
02712         else if ( ident == CSS_VAL_TRANSPARENT
02713                     && id != CSS_PROP_BORDER_TOP_COLOR
02714                         && id != CSS_PROP_BORDER_RIGHT_COLOR
02715                 && id != CSS_PROP_BORDER_BOTTOM_COLOR
02716                 && id != CSS_PROP_BORDER_LEFT_COLOR )
02717             col = QColor();
02718         else
02719             col = colorForCSSValue( ident );
02720         } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR ) {
02721 #ifndef APPLE_CHANGES
02722         if(qAlpha(primitiveValue->getRGBColorValue()))
02723 #endif
02724             col.setRgb(primitiveValue->getRGBColorValue());
02725         } else {
02726         return;
02727         }
02728     }
02729         //kdDebug( 6080 ) << "applying color " << col.isValid() << endl;
02730         switch(id)
02731         {
02732         case CSS_PROP_BACKGROUND_COLOR:
02733         style->setBackgroundColor(col); break;
02734         case CSS_PROP_BORDER_TOP_COLOR:
02735             style->setBorderTopColor(col); break;
02736         case CSS_PROP_BORDER_RIGHT_COLOR:
02737             style->setBorderRightColor(col); break;
02738         case CSS_PROP_BORDER_BOTTOM_COLOR:
02739             style->setBorderBottomColor(col); break;
02740         case CSS_PROP_BORDER_LEFT_COLOR:
02741             style->setBorderLeftColor(col); break;
02742         case CSS_PROP_COLOR:
02743             style->setColor(col); break;
02744         case CSS_PROP_OUTLINE_COLOR:
02745             style->setOutlineColor(col); break;
02746 #ifndef APPLE_CHANGES
02747         case CSS_PROP_SCROLLBAR_FACE_COLOR:
02748             style->setPaletteColor(QPalette::Active, QColorGroup::Button, col);
02749             style->setPaletteColor(QPalette::Inactive, QColorGroup::Button, col);
02750             break;
02751         case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
02752             style->setPaletteColor(QPalette::Active, QColorGroup::Shadow, col);
02753             style->setPaletteColor(QPalette::Inactive, QColorGroup::Shadow, col);
02754             break;
02755         case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
02756             style->setPaletteColor(QPalette::Active, QColorGroup::Light, col);
02757             style->setPaletteColor(QPalette::Inactive, QColorGroup::Light, col);
02758             break;
02759         case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
02760             break;
02761         case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
02762             style->setPaletteColor(QPalette::Active, QColorGroup::Dark, col);
02763             style->setPaletteColor(QPalette::Inactive, QColorGroup::Dark, col);
02764             break;
02765         case CSS_PROP_SCROLLBAR_TRACK_COLOR:
02766             style->setPaletteColor(QPalette::Active, QColorGroup::Mid, col);
02767             style->setPaletteColor(QPalette::Inactive, QColorGroup::Mid, col);
02768             style->setPaletteColor(QPalette::Active, QColorGroup::Background, col);
02769             style->setPaletteColor(QPalette::Inactive, QColorGroup::Background, col);
02770             // fall through
02771         case CSS_PROP_SCROLLBAR_BASE_COLOR:
02772             style->setPaletteColor(QPalette::Active, QColorGroup::Base, col);
02773             style->setPaletteColor(QPalette::Inactive, QColorGroup::Base, col);
02774             break;
02775         case CSS_PROP_SCROLLBAR_ARROW_COLOR:
02776             style->setPaletteColor(QPalette::Active, QColorGroup::ButtonText, col);
02777             style->setPaletteColor(QPalette::Inactive, QColorGroup::ButtonText, col);
02778             break;
02779 #endif
02780         default:
02781             return;
02782         }
02783         return;
02784     }
02785     break;
02786 // uri || inherit
02787     case CSS_PROP_BACKGROUND_IMAGE:
02788         HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
02789         break;
02790     case CSS_PROP_LIST_STYLE_IMAGE:
02791     {
02792         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
02793         if (!primitiveValue) return;
02794     style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image());
02795         //kdDebug( 6080 ) << "setting image in list to " << image->image() << endl;
02796         break;
02797     }
02798 
02799 // length
02800     case CSS_PROP_BORDER_TOP_WIDTH:
02801     case CSS_PROP_BORDER_RIGHT_WIDTH:
02802     case CSS_PROP_BORDER_BOTTOM_WIDTH:
02803     case CSS_PROP_BORDER_LEFT_WIDTH:
02804     case CSS_PROP_OUTLINE_WIDTH:
02805     {
02806     if (isInherit) {
02807             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
02808             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
02809             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
02810             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
02811             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
02812             return;
02813         }
02814         else if (isInitial) {
02815             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
02816             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
02817             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
02818             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
02819             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
02820             return;
02821         }
02822 
02823         if(!primitiveValue) break;
02824         short width = 3;
02825         switch(primitiveValue->getIdent())
02826         {
02827         case CSS_VAL_THIN:
02828             width = 1;
02829             break;
02830         case CSS_VAL_MEDIUM:
02831             width = 3;
02832             break;
02833         case CSS_VAL_THICK:
02834             width = 5;
02835             break;
02836         case CSS_VAL_INVALID:
02837         {
02838             double widthd = primitiveValue->computeLengthFloat(style, paintDeviceMetrics);
02839             width = (int)widthd;
02840             // somewhat resemble Mozilla's granularity
02841             // this makes border-width: 0.5pt borders visible
02842             if (width == 0 && widthd >= 0.025) width++;
02843             break;
02844         }
02845         default:
02846             return;
02847         }
02848 
02849         if(width < 0) return;
02850         switch(id)
02851         {
02852         case CSS_PROP_BORDER_TOP_WIDTH:
02853             style->setBorderTopWidth(width);
02854             break;
02855         case CSS_PROP_BORDER_RIGHT_WIDTH:
02856             style->setBorderRightWidth(width);
02857             break;
02858         case CSS_PROP_BORDER_BOTTOM_WIDTH:
02859             style->setBorderBottomWidth(width);
02860             break;
02861         case CSS_PROP_BORDER_LEFT_WIDTH:
02862             style->setBorderLeftWidth(width);
02863             break;
02864         case CSS_PROP_OUTLINE_WIDTH:
02865             style->setOutlineWidth(width);
02866             break;
02867         default:
02868             return;
02869         }
02870         return;
02871     }
02872 
02873     case CSS_PROP_LETTER_SPACING:
02874     case CSS_PROP_WORD_SPACING:
02875     {
02876         if (isInherit) {
02877             HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
02878             HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
02879             return;
02880         } else if (isInitial) {
02881             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
02882             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
02883             return;
02884         }
02885         if(!primitiveValue) return;
02886 
02887         int width = 0;
02888         if (primitiveValue->getIdent() != CSS_VAL_NORMAL)
02889         width = primitiveValue->computeLength(style, paintDeviceMetrics);
02890 
02891         switch(id)
02892         {
02893         case CSS_PROP_LETTER_SPACING:
02894             style->setLetterSpacing(width);
02895             break;
02896         case CSS_PROP_WORD_SPACING:
02897             style->setWordSpacing(width);
02898             break;
02899             // ### needs the definitions in renderstyle
02900         default: break;
02901         }
02902         return;
02903     }
02904 
02905         // length, percent
02906     case CSS_PROP_MAX_WIDTH:
02907         // +none +inherit
02908         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
02909             apply = true;
02910     case CSS_PROP_TOP:
02911     case CSS_PROP_LEFT:
02912     case CSS_PROP_RIGHT:
02913     case CSS_PROP_BOTTOM:
02914     case CSS_PROP_WIDTH:
02915     case CSS_PROP_MIN_WIDTH:
02916     case CSS_PROP_MARGIN_TOP:
02917     case CSS_PROP_MARGIN_RIGHT:
02918     case CSS_PROP_MARGIN_BOTTOM:
02919     case CSS_PROP_MARGIN_LEFT:
02920         // +inherit +auto
02921         if(id != CSS_PROP_MAX_WIDTH && primitiveValue &&
02922            primitiveValue->getIdent() == CSS_VAL_AUTO)
02923         {
02924             //kdDebug( 6080 ) << "found value=auto" << endl;
02925             apply = true;
02926         }
02927     case CSS_PROP_PADDING_TOP:
02928     case CSS_PROP_PADDING_RIGHT:
02929     case CSS_PROP_PADDING_BOTTOM:
02930     case CSS_PROP_PADDING_LEFT:
02931     case CSS_PROP_TEXT_INDENT:
02932         // +inherit
02933     {
02934         if (isInherit) {
02935             HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
02936             HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
02937             HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
02938             HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
02939             HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
02940             HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
02941             HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
02942             HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
02943             HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
02944             HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
02945             HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
02946             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
02947             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
02948             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
02949             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
02950             HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
02951             return;
02952         } else if (isInitial) {
02953             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
02954             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
02955             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
02956             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
02957             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
02958             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
02959             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
02960             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
02961             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
02962             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
02963             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
02964             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
02965             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
02966             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
02967             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
02968             HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
02969             return;
02970         }
02971 
02972         if (primitiveValue && !apply) {
02973             int type = primitiveValue->primitiveType();
02974             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
02975                 // Handle our quirky margin units if we have them.
02976                 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed,
02977                            primitiveValue->isQuirkValue());
02978             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
02979                 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
02980         else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
02981         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
02982             else
02983                 return;
02984             apply = true;
02985         }
02986         if(!apply) return;
02987         switch(id)
02988             {
02989             case CSS_PROP_MAX_WIDTH:
02990                 style->setMaxWidth(l); break;
02991             case CSS_PROP_BOTTOM:
02992                 style->setBottom(l); break;
02993             case CSS_PROP_TOP:
02994                 style->setTop(l); break;
02995             case CSS_PROP_LEFT:
02996                 style->setLeft(l); break;
02997             case CSS_PROP_RIGHT:
02998                 style->setRight(l); break;
02999             case CSS_PROP_WIDTH:
03000                 style->setWidth(l); break;
03001             case CSS_PROP_MIN_WIDTH:
03002                 style->setMinWidth(l); break;
03003             case CSS_PROP_PADDING_TOP:
03004                 style->setPaddingTop(l); break;
03005             case CSS_PROP_PADDING_RIGHT:
03006                 style->setPaddingRight(l); break;
03007             case CSS_PROP_PADDING_BOTTOM:
03008                 style->setPaddingBottom(l); break;
03009             case CSS_PROP_PADDING_LEFT:
03010                 style->setPaddingLeft(l); break;
03011             case CSS_PROP_MARGIN_TOP:
03012                 style->setMarginTop(l); break;
03013             case CSS_PROP_MARGIN_RIGHT:
03014                 style->setMarginRight(l); break;
03015             case CSS_PROP_MARGIN_BOTTOM:
03016                 style->setMarginBottom(l); break;
03017             case CSS_PROP_MARGIN_LEFT:
03018                 style->setMarginLeft(l); break;
03019             case CSS_PROP_TEXT_INDENT:
03020                 style->setTextIndent(l); break;
03021             default: break;
03022             }
03023         return;
03024     }
03025 
03026     case CSS_PROP_MAX_HEIGHT:
03027         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
03028             apply = true;
03029     case CSS_PROP_HEIGHT:
03030     case CSS_PROP_MIN_HEIGHT:
03031         if(id != CSS_PROP_MAX_HEIGHT && primitiveValue &&
03032            primitiveValue->getIdent() == CSS_VAL_AUTO)
03033             apply = true;
03034         if (isInherit) {
03035             HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
03036             HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
03037             HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
03038             return;
03039         }
03040         else if (isInitial) {
03041             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
03042             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
03043             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
03044             return;
03045         }
03046 
03047         if (primitiveValue && !apply)
03048         {
03049             int type = primitiveValue->primitiveType();
03050             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
03051                 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
03052             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
03053                 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
03054             else
03055                 return;
03056             apply = true;
03057         }
03058         if(!apply) return;
03059         switch(id)
03060         {
03061         case CSS_PROP_MAX_HEIGHT:
03062             style->setMaxHeight(l); break;
03063         case CSS_PROP_HEIGHT:
03064             style->setHeight(l); break;
03065         case CSS_PROP_MIN_HEIGHT:
03066             style->setMinHeight(l); break;
03067         default:
03068             return;
03069         }
03070         return;
03071 
03072         break;
03073 
03074     case CSS_PROP_VERTICAL_ALIGN:
03075         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
03076         if (!primitiveValue) return;
03077         if (primitiveValue->getIdent()) {
03078       khtml::EVerticalAlign align;
03079 
03080       switch(primitiveValue->getIdent())
03081         {
03082         case CSS_VAL_TOP:
03083             align = TOP; break;
03084         case CSS_VAL_BOTTOM:
03085             align = BOTTOM; break;
03086         case CSS_VAL_MIDDLE:
03087             align = MIDDLE; break;
03088         case CSS_VAL_BASELINE:
03089             align = BASELINE; break;
03090         case CSS_VAL_TEXT_BOTTOM:
03091             align = TEXT_BOTTOM; break;
03092         case CSS_VAL_TEXT_TOP:
03093             align = TEXT_TOP; break;
03094         case CSS_VAL_SUB:
03095             align = SUB; break;
03096         case CSS_VAL_SUPER:
03097             align = SUPER; break;
03098         case CSS_VAL__KHTML_BASELINE_MIDDLE:
03099             align = BASELINE_MIDDLE; break;
03100         default:
03101             return;
03102         }
03103       style->setVerticalAlign(align);
03104       return;
03105         } else {
03106       int type = primitiveValue->primitiveType();
03107       Length l;
03108       if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
03109         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
03110       else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
03111         l = Length( int( primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent );
03112 
03113       style->setVerticalAlign( LENGTH );
03114       style->setVerticalAlignLength( l );
03115     }
03116         break;
03117 
03118     case CSS_PROP_FONT_SIZE:
03119     {
03120         FontDef fontDef = style->htmlFont().fontDef;
03121         int oldSize;
03122         int size = 0;
03123 
03124     float toPix = paintDeviceMetrics->logicalDpiY()/72.;
03125     if (toPix  < 96./72.) toPix = 96./72.;
03126 
03127         int minFontSize = int(settings->minFontSize() * toPix);
03128 
03129         if(parentNode) {
03130             oldSize = parentStyle->font().pixelSize();
03131         } else
03132             oldSize = m_fontSizes[3];
03133 
03134         if (isInherit )
03135             size = oldSize;
03136         else if (isInitial)
03137             size = m_fontSizes[3];
03138         else if(primitiveValue->getIdent()) {
03139         // keywords are being used.  Pick the correct default
03140         // based off the font family.
03141 #ifdef APPLE_CHANGES
03142         const QValueVector<int>& fontSizes = (fontDef.genericFamily == FontDef::eMonospace) ?
03143                      m_fixedFontSizes : m_fontSizes;
03144 #else
03145         const QValueVector<int>& fontSizes = m_fontSizes;
03146 #endif
03147             switch(primitiveValue->getIdent())
03148             {
03149             case CSS_VAL_XX_SMALL: size = int( fontSizes[0] ); break;
03150             case CSS_VAL_X_SMALL:  size = int( fontSizes[1] ); break;
03151             case CSS_VAL_SMALL:    size = int( fontSizes[2] ); break;
03152             case CSS_VAL_MEDIUM:   size = int( fontSizes[3] ); break;
03153             case CSS_VAL_LARGE:    size = int( fontSizes[4] ); break;
03154             case CSS_VAL_X_LARGE:  size = int( fontSizes[5] ); break;
03155             case CSS_VAL_XX_LARGE: size = int( fontSizes[6] ); break;
03156             case CSS_VAL__KHTML_XXX_LARGE: size = int( fontSizes[7] ); break;
03157             case CSS_VAL_LARGER:
03158                 size = nextFontSize(fontSizes, oldSize, false);
03159                 break;
03160             case CSS_VAL_SMALLER:
03161                 size = nextFontSize(fontSizes, oldSize, true);
03162                 break;
03163             default:
03164                 return;
03165             }
03166 
03167         } else {
03168             int type = primitiveValue->primitiveType();
03169             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
03170                 if ( !khtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS &&
03171                      view && view->part())
03172                     size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) *
03173                                 view->part()->zoomFactor() ) / 100;
03174         else
03175                     size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) );
03176             }
03177             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
03178                 size = int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)
03179                         * parentStyle->font().pixelSize()) / 100;
03180             else
03181                 return;
03182         }
03183 
03184         if (size < 0) return;
03185 
03186         // we never want to get smaller than the minimum font size to keep fonts readable
03187         // do not however maximize zero as that is commonly used for fancy layouting purposes
03188         if (size && size < minFontSize) size = minFontSize;
03189 
03190         //kdDebug( 6080 ) << "computed raw font size: " << size << endl;
03191 
03192     fontDef.size = size;
03193         fontDirty |= style->setFontDef( fontDef );
03194         return;
03195     }
03196 
03197     case CSS_PROP_Z_INDEX:
03198     {
03199         HANDLE_INHERIT(zIndex, ZIndex)
03200         else if (isInitial) {
03201             style->setHasAutoZIndex();
03202             return;
03203         }
03204 
03205         if (!primitiveValue)
03206             return;
03207 
03208         if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
03209             style->setHasAutoZIndex();
03210             return;
03211         }
03212 
03213         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03214             return; // Error case.
03215 
03216         style->setZIndex((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
03217         return;
03218     }
03219 
03220     case CSS_PROP_WIDOWS:
03221     {
03222         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
03223         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03224             return;
03225         style->setWidows((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
03226         break;
03227      }
03228 
03229     case CSS_PROP_ORPHANS:
03230     {
03231         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
03232         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03233             return;
03234         style->setOrphans((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
03235         break;
03236     }
03237 
03238 // length, percent, number
03239     case CSS_PROP_LINE_HEIGHT:
03240     {
03241         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
03242         if(!primitiveValue) return;
03243         Length lineHeight;
03244         int type = primitiveValue->primitiveType();
03245         if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
03246             lineHeight = Length( -100, Percent );
03247         else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
03248             // Scale for the font zoom factor only for types other than "em" and "ex", since those are
03249             // already based on the font size.
03250         if ( !khtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS &&
03251                     view && view->part())
03252                     lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics) *
03253                                         view->part()->zoomFactor()/100, Fixed );
03254                 else
03255                     lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
03256         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
03257             lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed );
03258         else if (type == CSSPrimitiveValue::CSS_NUMBER)
03259             lineHeight = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
03260         else
03261             return;
03262         style->setLineHeight(lineHeight);
03263         return;
03264     }
03265 
03266 // string
03267     case CSS_PROP_TEXT_ALIGN:
03268     {
03269         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
03270         if (!primitiveValue) return;
03271         if (primitiveValue->getIdent())
03272             style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) );
03273     return;
03274     }
03275 
03276 // rect
03277     case CSS_PROP_CLIP:
03278     {
03279         Length top = Length();
03280         Length right = Length();
03281         Length bottom = Length();
03282         Length left = Length();
03283 
03284         bool hasClip = false;
03285 
03286         if (isInherit && parentStyle->hasClip()) {
03287             hasClip = true;
03288         top = parentStyle->clipTop();
03289         right = parentStyle->clipRight();
03290         bottom = parentStyle->clipBottom();
03291         left = parentStyle->clipLeft();
03292         } else if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
03293             RectImpl *rect = primitiveValue->getRectValue();
03294             if (rect) {
03295                 hasClip = true;
03296                 top = convertToLength( rect->top(), style, paintDeviceMetrics );
03297                 right = convertToLength( rect->right(), style, paintDeviceMetrics );
03298                 bottom = convertToLength( rect->bottom(), style, paintDeviceMetrics );
03299                 left = convertToLength( rect->left(), style, paintDeviceMetrics );
03300             }
03301         }
03302 
03303         style->setClip(top, right, bottom, left);
03304         style->setHasClip(hasClip);
03305 
03306         // rect, ident
03307         break;
03308     }
03309 
03310 // lists
03311     case CSS_PROP_CONTENT:
03312         // list of string, uri, counter, attr, i
03313     {
03314         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
03315         // note is a reminder that eventually "inherit" needs to be supported.
03316 
03317         // not allowed on non-generated pseudo-elements:
03318         if ( style->styleType()==RenderStyle::FIRST_LETTER ||
03319              style->styleType()==RenderStyle::FIRST_LINE ||
03320              style->styleType()==RenderStyle::SELECTION )
03321             break;
03322 
03323         if (isInitial) {
03324             style->setContentNormal();
03325             return;
03326         }
03327 
03328         if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
03329             // normal | none
03330             if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
03331                 style->setContentNormal();
03332             else
03333             if (primitiveValue->getIdent() == CSS_VAL_NONE)
03334                 style->setContentNone();
03335             else
03336                 assert(false);
03337             return;
03338         }
03339 
03340         if(!value->isValueList()) return;
03341         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03342         int len = list->length();
03343 
03344         style->setContentNormal(); // clear the content
03345 
03346         for(int i = 0; i < len; i++) {
03347             CSSValueImpl *item = list->item(i);
03348             if(!item->isPrimitiveValue()) continue;
03349             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
03350             if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
03351             {
03352                 style->addContent(val->getStringValue());
03353             }
03354             else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR)
03355             {
03356                 // TODO: setup dynamic attribute dependencies
03357                 int attrID = element->getDocument()->getId(NodeImpl::AttributeId, val->getStringValue(), false, true);
03358                 if (attrID)
03359                     style->addContent(element->getAttribute(attrID).implementation());
03360                 else
03361                     kdDebug(6080) << "Attribute \"" << val->getStringValue() << "\" not found" << endl;
03362             }
03363             else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI)
03364             {
03365                 CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val);
03366                 style->addContent(image->image());
03367             }
03368             else if (val->primitiveType()==CSSPrimitiveValue::CSS_COUNTER)
03369             {
03370                 style->addContent(val->getCounterValue());
03371             }
03372             else if (val->primitiveType()==CSSPrimitiveValue::CSS_IDENT)
03373             {
03374                 EQuoteContent quote;
03375                 switch (val->getIdent()) {
03376                     case CSS_VAL_OPEN_QUOTE:
03377                         quote = OPEN_QUOTE;
03378                         break;
03379                     case CSS_VAL_NO_OPEN_QUOTE:
03380                         quote = NO_OPEN_QUOTE;
03381                         break;
03382                     case CSS_VAL_CLOSE_QUOTE:
03383                         quote = CLOSE_QUOTE;
03384                         break;
03385                     case CSS_VAL_NO_CLOSE_QUOTE:
03386                         quote = NO_CLOSE_QUOTE;
03387                         break;
03388                     default:
03389                         assert(false);
03390                 }
03391                 style->addContent(quote);
03392             } else
03393                 kdDebug(6080) << "Unrecognized CSS content" << endl;
03394 
03395         }
03396         break;
03397     }
03398 
03399     case CSS_PROP_COUNTER_INCREMENT: {
03400         if(!value->isValueList()) return;
03401 
03402         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03403         style->setCounterIncrement(list);
03404         break;
03405     }
03406     case CSS_PROP_COUNTER_RESET: {
03407         if(!value->isValueList()) return;
03408 
03409         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03410         style->setCounterReset(list);
03411         break;
03412     }
03413     case CSS_PROP_FONT_FAMILY:
03414         // list of strings and ids
03415     {
03416         if (isInherit) {
03417             FontDef parentFontDef = parentStyle->htmlFont().fontDef;
03418             FontDef fontDef = style->htmlFont().fontDef;
03419             fontDef.family = parentFontDef.family;
03420             if (style->setFontDef(fontDef))
03421                 fontDirty = true;
03422             return;
03423         }
03424         else if (isInitial) {
03425             FontDef fontDef = style->htmlFont().fontDef;
03426             FontDef initialDef = FontDef();
03427 #ifdef APPLE_CHANGES
03428             fontDef.family = initialDef.firstFamily();
03429 #else
03430             fontDef.family = QString::null;
03431 #endif
03432             if (style->setFontDef(fontDef))
03433                 fontDirty = true;
03434             return;
03435         }
03436         if(!value->isValueList()) return;
03437     FontDef fontDef = style->htmlFont().fontDef;
03438         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03439         int len = list->length();
03440         for(int i = 0; i < len; i++) {
03441             CSSValueImpl *item = list->item(i);
03442             if(!item->isPrimitiveValue()) continue;
03443             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
03444         QString face;
03445             if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING )
03446         face = static_cast<FontFamilyValueImpl *>(val)->fontName();
03447         else if ( val->primitiveType() == CSSPrimitiveValue::CSS_IDENT ) {
03448         switch( val->getIdent() ) {
03449         case CSS_VAL_SERIF:
03450             face = settings->serifFontName();
03451             break;
03452         case CSS_VAL_SANS_SERIF:
03453             face = settings->sansSerifFontName();
03454             break;
03455         case CSS_VAL_CURSIVE:
03456             face = settings->cursiveFontName();
03457             break;
03458         case CSS_VAL_FANTASY:
03459             face = settings->fantasyFontName();
03460             break;
03461         case CSS_VAL_MONOSPACE:
03462             face = settings->fixedFontName();
03463             break;
03464         default:
03465             return;
03466         }
03467         } else {
03468         return;
03469         }
03470         if ( !face.isEmpty() ) {
03471         fontDef.family = face;
03472         fontDirty |= style->setFontDef( fontDef );
03473                 return;
03474         }
03475     }
03476         break;
03477     }
03478     case CSS_PROP_QUOTES:
03479         HANDLE_INHERIT_AND_INITIAL(quotes, Quotes)
03480         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
03481             // set a set of empty quotes
03482             QuotesValueImpl* quotes = new QuotesValueImpl();
03483             style->setQuotes(quotes);
03484         } else {
03485             QuotesValueImpl* quotes = static_cast<QuotesValueImpl *>(value);
03486             style->setQuotes(quotes);
03487         }
03488         break;
03489     case CSS_PROP_SIZE:
03490         // ### look up
03491       break;
03492     case CSS_PROP_TEXT_DECORATION: {
03493         // list of ident
03494         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
03495         int t = RenderStyle::initialTextDecoration();
03496         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
03497         // do nothing
03498     } else {
03499         if(!value->isValueList()) return;
03500         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03501         int len = list->length();
03502         for(int i = 0; i < len; i++)
03503         {
03504         CSSValueImpl *item = list->item(i);
03505         if(!item->isPrimitiveValue()) continue;
03506         primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item);
03507         switch(primitiveValue->getIdent())
03508         {
03509             case CSS_VAL_NONE:
03510             t = TDNONE; break;
03511             case CSS_VAL_UNDERLINE:
03512             t |= UNDERLINE; break;
03513             case CSS_VAL_OVERLINE:
03514             t |= OVERLINE; break;
03515             case CSS_VAL_LINE_THROUGH:
03516             t |= LINE_THROUGH; break;
03517             case CSS_VAL_BLINK:
03518             t |= BLINK; break;
03519             default:
03520             return;
03521         }
03522         }
03523         }
03524     style->setTextDecoration(t);
03525         break;
03526     }
03527     case CSS_PROP__KHTML_FLOW_MODE:
03528         HANDLE_INHERIT_AND_INITIAL(flowAroundFloats, FlowAroundFloats)
03529         if (!primitiveValue) return;
03530         if (primitiveValue->getIdent()) {
03531             style->setFlowAroundFloats( primitiveValue->getIdent() == CSS_VAL__KHTML_AROUND_FLOATS );
03532             return;
03533         }
03534         break;
03535     case CSS_PROP__KHTML_USER_INPUT: {
03536         if(value->cssValueType() == CSSValue::CSS_INHERIT)
03537         {
03538             if(!parentNode) return;
03539             style->setUserInput(parentStyle->userInput());
03540 //      kdDebug() << "UI erm" << endl;
03541             return;
03542         }
03543         if(!primitiveValue) return;
03544         int id = primitiveValue->getIdent();
03545     if (id == CSS_VAL_NONE)
03546         style->setUserInput(UI_NONE);
03547     else
03548         style->setUserInput(EUserInput(id - CSS_VAL_ENABLED));
03549 //  kdDebug(6080) << "userInput: " << style->userEdit() << endl;
03550     return;
03551     }
03552 
03553 // shorthand properties
03554     case CSS_PROP_BACKGROUND:
03555         if (isInitial) {
03556             style->clearBackgroundLayers();
03557             return;
03558         }
03559         else if (isInherit) {
03560             if (parentStyle)
03561                 style->inheritBackgroundLayers(*parentStyle->backgroundLayers());
03562             else
03563                 style->clearBackgroundLayers();
03564             return;
03565         }
03566         break;
03567     case CSS_PROP_BORDER:
03568     case CSS_PROP_BORDER_STYLE:
03569     case CSS_PROP_BORDER_WIDTH:
03570     case CSS_PROP_BORDER_COLOR:
03571         if(id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
03572         {
03573              if (isInherit) {
03574                 style->setBorderTopColor(parentStyle->borderTopColor());
03575                 style->setBorderBottomColor(parentStyle->borderBottomColor());
03576                 style->setBorderLeftColor(parentStyle->borderLeftColor());
03577                 style->setBorderRightColor(parentStyle->borderRightColor());
03578             }
03579             else if (isInitial) {
03580                 style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead.
03581                 style->setBorderBottomColor(QColor());
03582                 style->setBorderLeftColor(QColor());
03583                 style->setBorderRightColor(QColor());
03584             }
03585         }
03586         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
03587         {
03588             if (isInherit) {
03589                 style->setBorderTopStyle(parentStyle->borderTopStyle());
03590                 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
03591                 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
03592                 style->setBorderRightStyle(parentStyle->borderRightStyle());
03593             }
03594             else if (isInitial) {
03595                 style->setBorderTopStyle(RenderStyle::initialBorderStyle());
03596                 style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
03597                 style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
03598                 style->setBorderRightStyle(RenderStyle::initialBorderStyle());
03599             }
03600         }
03601         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH)
03602         {
03603             if (isInherit) {
03604                 style->setBorderTopWidth(parentStyle->borderTopWidth());
03605                 style->setBorderBottomWidth(parentStyle->borderBottomWidth());
03606                 style->setBorderLeftWidth(parentStyle->borderLeftWidth());
03607                 style->setBorderRightWidth(parentStyle->borderRightWidth());
03608             }
03609             else if (isInitial) {
03610                 style->setBorderTopWidth(RenderStyle::initialBorderWidth());
03611                 style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
03612                 style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
03613                 style->setBorderRightWidth(RenderStyle::initialBorderWidth());
03614             }
03615         }
03616         return;
03617     case CSS_PROP_BORDER_TOP:
03618         if ( isInherit ) {
03619             style->setBorderTopColor(parentStyle->borderTopColor());
03620             style->setBorderTopStyle(parentStyle->borderTopStyle());
03621             style->setBorderTopWidth(parentStyle->borderTopWidth());
03622         } else if (isInitial)
03623             style->resetBorderTop();
03624         return;
03625     case CSS_PROP_BORDER_RIGHT:
03626         if (isInherit) {
03627             style->setBorderRightColor(parentStyle->borderRightColor());
03628             style->setBorderRightStyle(parentStyle->borderRightStyle());
03629             style->setBorderRightWidth(parentStyle->borderRightWidth());
03630         }
03631         else if (isInitial)
03632             style->resetBorderRight();
03633         return;
03634     case CSS_PROP_BORDER_BOTTOM:
03635         if (isInherit) {
03636             style->setBorderBottomColor(parentStyle->borderBottomColor());
03637             style->setBorderBottomStyle(parentStyle->borderBottomStyle());
03638             style->setBorderBottomWidth(parentStyle->borderBottomWidth());
03639         }
03640         else if (isInitial)
03641             style->resetBorderBottom();
03642         return;
03643     case CSS_PROP_BORDER_LEFT:
03644         if (isInherit) {
03645             style->setBorderLeftColor(parentStyle->borderLeftColor());
03646             style->setBorderLeftStyle(parentStyle->borderLeftStyle());
03647             style->setBorderLeftWidth(parentStyle->borderLeftWidth());
03648         }
03649         else if (isInitial)
03650             style->resetBorderLeft();
03651         return;
03652     case CSS_PROP_MARGIN:
03653         if (isInherit) {
03654             style->setMarginTop(parentStyle->marginTop());
03655             style->setMarginBottom(parentStyle->marginBottom());
03656             style->setMarginLeft(parentStyle->marginLeft());
03657             style->setMarginRight(parentStyle->marginRight());
03658         }
03659         else if (isInitial)
03660             style->resetMargin();
03661         return;
03662     case CSS_PROP_PADDING:
03663         if (isInherit) {
03664             style->setPaddingTop(parentStyle->paddingTop());
03665             style->setPaddingBottom(parentStyle->paddingBottom());
03666             style->setPaddingLeft(parentStyle->paddingLeft());
03667             style->setPaddingRight(parentStyle->paddingRight());
03668         }
03669         else if (isInitial)
03670             style->resetPadding();
03671         return;
03672     case CSS_PROP_FONT:
03673         if ( isInherit ) {
03674             FontDef fontDef = parentStyle->htmlFont().fontDef;
03675         style->setLineHeight( parentStyle->lineHeight() );
03676         fontDirty |= style->setFontDef( fontDef );
03677         } else if (isInitial) {
03678             FontDef fontDef;
03679             style->setLineHeight(RenderStyle::initialLineHeight());
03680             if (style->setFontDef( fontDef ))
03681                 fontDirty = true;
03682     } else if ( value->isFontValue() ) {
03683         FontValueImpl *font = static_cast<FontValueImpl *>(value);
03684         if ( !font->style || !font->variant || !font->weight ||
03685          !font->size || !font->lineHeight || !font->family )
03686         return;
03687         applyRule( CSS_PROP_FONT_STYLE, font->style );
03688         applyRule( CSS_PROP_FONT_VARIANT, font->variant );
03689         applyRule( CSS_PROP_FONT_WEIGHT, font->weight );
03690         applyRule( CSS_PROP_FONT_SIZE, font->size );
03691 
03692             // Line-height can depend on font().pixelSize(), so we have to update the font
03693             // before we evaluate line-height, e.g., font: 1em/1em.  FIXME: Still not
03694             // good enough: style="font:1em/1em; font-size:36px" should have a line-height of 36px.
03695             if (fontDirty)
03696                 CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
03697 
03698         applyRule( CSS_PROP_LINE_HEIGHT, font->lineHeight );
03699         applyRule( CSS_PROP_FONT_FAMILY, font->family );
03700     }
03701     return;
03702 
03703     case CSS_PROP_LIST_STYLE:
03704         if (isInherit) {
03705             style->setListStyleType(parentStyle->listStyleType());
03706             style->setListStyleImage(parentStyle->listStyleImage());
03707             style->setListStylePosition(parentStyle->listStylePosition());
03708         }
03709         else if (isInitial) {
03710             style->setListStyleType(RenderStyle::initialListStyleType());
03711             style->setListStyleImage(RenderStyle::initialListStyleImage());
03712             style->setListStylePosition(RenderStyle::initialListStylePosition());
03713         }
03714         break;
03715     case CSS_PROP_OUTLINE:
03716         if (isInherit) {
03717             style->setOutlineWidth(parentStyle->outlineWidth());
03718             style->setOutlineColor(parentStyle->outlineColor());
03719             style->setOutlineStyle(parentStyle->outlineStyle());
03720         }
03721         else if (isInitial)
03722             style->resetOutline();
03723         break;
03724     /* CSS3 properties */
03725     case CSS_PROP_BOX_SIZING:
03726         HANDLE_INHERIT(boxSizing, BoxSizing)
03727         if (!primitiveValue) return;
03728         if (primitiveValue->getIdent() == CSS_VAL_CONTENT_BOX)
03729             style->setBoxSizing(CONTENT_BOX);
03730         else
03731         if (primitiveValue->getIdent() == CSS_VAL_BORDER_BOX)
03732             style->setBoxSizing(BORDER_BOX);
03733         break;
03734     case CSS_PROP_OUTLINE_OFFSET: {
03735         HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
03736 
03737         int offset = primitiveValue->computeLength(style, paintDeviceMetrics);
03738         if (offset < 0) return;
03739 
03740         style->setOutlineOffset(offset);
03741         break;
03742     }
03743     case CSS_PROP_TEXT_SHADOW: {
03744         if (isInherit) {
03745             style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : 0);
03746             return;
03747         }
03748         else if (isInitial) {
03749             style->setTextShadow(0);
03750             return;
03751         }
03752 
03753         if (primitiveValue) { // none
03754             style->setTextShadow(0);
03755             return;
03756         }
03757 
03758         if (!value->isValueList()) return;
03759         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03760         int len = list->length();
03761         for (int i = 0; i < len; i++) {
03762             ShadowValueImpl *item = static_cast<ShadowValueImpl*>(list->item(i));
03763 
03764             int x = item->x->computeLength(style, paintDeviceMetrics);
03765             int y = item->y->computeLength(style, paintDeviceMetrics);
03766             int blur = item->blur ? item->blur->computeLength(style, paintDeviceMetrics) : 0;
03767             QColor col = khtml::transparentColor;
03768             if (item->color) {
03769                 int ident = item->color->getIdent();
03770                 if (ident)
03771                     col = colorForCSSValue( ident );
03772                 else if (item->color->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
03773                     col.setRgb(item->color->getRGBColorValue());
03774             }
03775             ShadowData* shadowData = new ShadowData(x, y, blur, col);
03776             style->setTextShadow(shadowData, i != 0);
03777         }
03778 
03779         break;
03780     }
03781     case CSS_PROP_OPACITY:
03782         HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
03783         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03784             return; // Error case.
03785 
03786         // Clamp opacity to the range 0-1
03787         style->setOpacity(kMin(1.0f, kMax(0.0f, (float)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))));
03788         break;
03789     case CSS_PROP__KHTML_MARQUEE:
03790         if (value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return;
03791         style->setMarqueeDirection(parentStyle->marqueeDirection());
03792         style->setMarqueeIncrement(parentStyle->marqueeIncrement());
03793         style->setMarqueeSpeed(parentStyle->marqueeSpeed());
03794         style->setMarqueeLoopCount(parentStyle->marqueeLoopCount());
03795         style->setMarqueeBehavior(parentStyle->marqueeBehavior());
03796         break;
03797     case CSS_PROP__KHTML_MARQUEE_REPETITION: {
03798         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
03799         if (!primitiveValue) return;
03800         if (primitiveValue->getIdent() == CSS_VAL_INFINITE)
03801             style->setMarqueeLoopCount(-1); // -1 means repeat forever.
03802         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
03803             style->setMarqueeLoopCount((int)(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
03804         break;
03805     }
03806     case CSS_PROP__KHTML_MARQUEE_SPEED: {
03807         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
03808         if (!primitiveValue) return;
03809         if (primitiveValue->getIdent()) {
03810             switch (primitiveValue->getIdent())
03811             {
03812                 case CSS_VAL_SLOW:
03813                     style->setMarqueeSpeed(500); // 500 msec.
03814                     break;
03815                 case CSS_VAL_NORMAL:
03816                     style->setMarqueeSpeed(85); // 85msec. The WinIE default.
03817                     break;
03818                 case CSS_VAL_FAST:
03819                     style->setMarqueeSpeed(10); // 10msec. Super fast.
03820                     break;
03821             }
03822         }
03823         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
03824             style->setMarqueeSpeed(int(1000*primitiveValue->floatValue(CSSPrimitiveValue::CSS_S)));
03825         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
03826             style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_MS)));
03827         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
03828             style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
03829         break;
03830     }
03831     case CSS_PROP__KHTML_MARQUEE_INCREMENT: {
03832         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
03833         if (!primitiveValue) return;
03834         if (primitiveValue->getIdent()) {
03835             switch (primitiveValue->getIdent())
03836             {
03837                 case CSS_VAL_SMALL:
03838                     style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
03839                     break;
03840                 case CSS_VAL_NORMAL:
03841                     style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
03842                     break;
03843                 case CSS_VAL_LARGE:
03844                     style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
03845                     break;
03846             }
03847         }
03848         else {
03849             bool ok = true;
03850             Length l = convertToLength(primitiveValue, style, paintDeviceMetrics, &ok);
03851             if (ok)
03852                 style->setMarqueeIncrement(l);
03853         }
03854         break;
03855     }
03856     case CSS_PROP__KHTML_MARQUEE_STYLE: {
03857         HANDLE_INHERIT_AND_INITIAL(marqueeBehavior, MarqueeBehavior)
03858         if (!primitiveValue || !primitiveValue->getIdent()) return;
03859         switch (primitiveValue->getIdent())
03860         {
03861             case CSS_VAL_NONE:
03862                 style->setMarqueeBehavior(MNONE);
03863                 break;
03864             case CSS_VAL_SCROLL:
03865                 style->setMarqueeBehavior(MSCROLL);
03866                 break;
03867             case CSS_VAL_SLIDE:
03868                 style->setMarqueeBehavior(MSLIDE);
03869                 break;
03870             case CSS_VAL_ALTERNATE:
03871                 style->setMarqueeBehavior(MALTERNATE);
03872                 break;
03873             case CSS_VAL_UNFURL:
03874                 style->setMarqueeBehavior(MUNFURL);
03875                 break;
03876         }
03877         break;
03878     }
03879     case CSS_PROP__KHTML_MARQUEE_DIRECTION: {
03880         HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection)
03881         if (!primitiveValue || !primitiveValue->getIdent()) return;
03882         switch (primitiveValue->getIdent())
03883         {
03884             case CSS_VAL_FORWARDS:
03885                 style->setMarqueeDirection(MFORWARD);
03886                 break;
03887             case CSS_VAL_BACKWARDS:
03888                 style->setMarqueeDirection(MBACKWARD);
03889                 break;
03890             case CSS_VAL_AUTO:
03891                 style->setMarqueeDirection(MAUTO);
03892                 break;
03893             case CSS_VAL_AHEAD:
03894             case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP.
03895                 style->setMarqueeDirection(MUP);
03896                 break;
03897             case CSS_VAL_REVERSE:
03898             case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text.
03899                 style->setMarqueeDirection(MDOWN);
03900                 break;
03901             case CSS_VAL_LEFT:
03902                 style->setMarqueeDirection(MLEFT);
03903                 break;
03904             case CSS_VAL_RIGHT:
03905                 style->setMarqueeDirection(MRIGHT);
03906                 break;
03907         }
03908         break;
03909     }
03910     default:
03911         return;
03912     }
03913 }
03914 
03915 void CSSStyleSelector::mapBackgroundAttachment(BackgroundLayer* layer, DOM::CSSValueImpl* value)
03916 {
03917     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03918         layer->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment());
03919         return;
03920     }
03921 
03922     if (!value->isPrimitiveValue()) return;
03923     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03924     switch (primitiveValue->getIdent()) {
03925         case CSS_VAL_FIXED:
03926             layer->setBackgroundAttachment(false);
03927             break;
03928         case CSS_VAL_SCROLL:
03929             layer->setBackgroundAttachment(true);
03930             break;
03931         default:
03932             return;
03933     }
03934 }
03935 
03936 void CSSStyleSelector::mapBackgroundClip(BackgroundLayer* layer, CSSValueImpl* value)
03937 {
03938     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03939         layer->setBackgroundClip(RenderStyle::initialBackgroundClip());
03940         return;
03941     }
03942 
03943     if (!value->isPrimitiveValue()) return;
03944     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03945     switch (primitiveValue->getIdent()) {
03946         case CSS_VAL_BORDER:
03947             layer->setBackgroundClip(BGBORDER);
03948             break;
03949         case CSS_VAL_PADDING:
03950             layer->setBackgroundClip(BGPADDING);
03951             break;
03952         default: // CSS_VAL_CONTENT
03953             layer->setBackgroundClip(BGCONTENT);
03954             break;
03955     }
03956 }
03957 
03958 void CSSStyleSelector::mapBackgroundOrigin(BackgroundLayer* layer, CSSValueImpl* value)
03959 {
03960     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03961         layer->setBackgroundOrigin(RenderStyle::initialBackgroundOrigin());
03962         return;
03963     }
03964 
03965     if (!value->isPrimitiveValue()) return;
03966     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03967     switch (primitiveValue->getIdent()) {
03968         case CSS_VAL_BORDER:
03969             layer->setBackgroundOrigin(BGBORDER);
03970             break;
03971         case CSS_VAL_PADDING:
03972             layer->setBackgroundOrigin(BGPADDING);
03973             break;
03974         default: // CSS_VAL_CONTENT
03975             layer->setBackgroundOrigin(BGCONTENT);
03976             break;
03977     }
03978 }
03979 
03980 void CSSStyleSelector::mapBackgroundImage(BackgroundLayer* layer, DOM::CSSValueImpl* value)
03981 {
03982     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03983         layer->setBackgroundImage(RenderStyle::initialBackgroundImage());
03984         return;
03985     }
03986 
03987     if (!value->isPrimitiveValue()) return;
03988     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03989     layer->setBackgroundImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image());
03990 }
03991 
03992 void CSSStyleSelector::mapBackgroundRepeat(BackgroundLayer* layer, DOM::CSSValueImpl* value)
03993 {
03994     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03995         layer->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat());
03996         return;
03997     }
03998 
03999     if (!value->isPrimitiveValue()) return;
04000     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
04001     switch(primitiveValue->getIdent()) {
04002     case CSS_VAL_REPEAT:
04003         layer->setBackgroundRepeat(REPEAT);
04004         break;
04005     case CSS_VAL_REPEAT_X:
04006         layer->setBackgroundRepeat(REPEAT_X);
04007         break;
04008     case CSS_VAL_REPEAT_Y:
04009         layer->setBackgroundRepeat(REPEAT_Y);
04010         break;
04011     case CSS_VAL_NO_REPEAT:
04012         layer->setBackgroundRepeat(NO_REPEAT);
04013         break;
04014     default:
04015         return;
04016     }
04017 }
04018 
04019 
04020 void CSSStyleSelector::mapBackgroundSize(BackgroundLayer* layer, CSSValueImpl* value)
04021 {
04022     LengthSize b = RenderStyle::initialBackgroundSize();
04023 
04024     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
04025         layer->setBackgroundSize(b);
04026         return;
04027     }
04028 
04029     if (!value->isPrimitiveValue())
04030         return;
04031 
04032     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
04033     PairImpl* pair = primitiveValue->getPairValue();
04034     if (!pair)
04035         return;
04036 
04037     CSSPrimitiveValueImpl* first = static_cast<CSSPrimitiveValueImpl*>(pair->first());
04038     CSSPrimitiveValueImpl* second = static_cast<CSSPrimitiveValueImpl*>(pair->second());
04039 
04040     if (!first || !second)
04041         return;
04042 
04043     Length firstLength, secondLength;
04044     int firstType = first->primitiveType();
04045     int secondType = second->primitiveType();
04046 
04047     if (firstType == CSSPrimitiveValue::CSS_UNKNOWN)
04048         firstLength = Length(Variable);
04049     else if (firstType > CSSPrimitiveValue::CSS_PERCENTAGE && firstType < CSSPrimitiveValue::CSS_DEG)
04050         firstLength = Length(first->computeLength(style, paintDeviceMetrics), Fixed);
04051     else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
04052         firstLength = Length((int)first->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04053     else
04054         return;
04055 
04056     if (secondType == CSSPrimitiveValue::CSS_UNKNOWN)
04057         secondLength = Length(Variable);
04058     else if (secondType > CSSPrimitiveValue::CSS_PERCENTAGE && secondType < CSSPrimitiveValue::CSS_DEG)
04059         secondLength = Length(second->computeLength(style, paintDeviceMetrics), Fixed);
04060     else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
04061         secondLength = Length((int)second->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04062     else
04063         return;
04064 
04065     b.width = firstLength;
04066     b.height = secondLength;
04067     layer->setBackgroundSize(b);
04068 }
04069 
04070 void CSSStyleSelector::mapBackgroundXPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value)
04071 {
04072     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
04073         layer->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
04074         return;
04075     }
04076 
04077     if (!value->isPrimitiveValue()) return;
04078     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
04079     Length l;
04080     int type = primitiveValue->primitiveType();
04081     if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
04082         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
04083     else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
04084         l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04085     else
04086         return;
04087     layer->setBackgroundXPosition(l);
04088 }
04089 
04090 void CSSStyleSelector::mapBackgroundYPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value)
04091 {
04092     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
04093         layer->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
04094         return;
04095     }
04096 
04097     if (!value->isPrimitiveValue()) return;
04098     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
04099     Length l;
04100     int type = primitiveValue->primitiveType();
04101     if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
04102         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
04103     else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
04104         l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04105     else
04106         return;
04107     layer->setBackgroundYPosition(l);
04108 }
04109 
04110 #ifdef APPLE_CHANGES
04111 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* aStyle, RenderStyle* aParentStyle)
04112 {
04113   const FontDef& childFont = aStyle->htmlFont().fontDef;
04114 
04115   if (childFont.sizeSpecified || !aParentStyle)
04116     return;
04117 
04118   const FontDef& parentFont = aParentStyle->htmlFont().fontDef;
04119 
04120   if (childFont.genericFamily == parentFont.genericFamily)
04121     return;
04122 
04123   // For now, lump all families but monospace together.
04124   if (childFont.genericFamily != FontDef::eMonospace &&
04125       parentFont.genericFamily != FontDef::eMonospace)
04126     return;
04127 
04128   // We know the parent is monospace or the child is monospace, and that font
04129   // size was unspecified.  We want to alter our font size to use the correct
04130   // "medium" font for our family.
04131   float size = 0;
04132   int minFontSize = settings->minFontSize();
04133   size = (childFont.genericFamily == FontDef::eMonospace) ? m_fixedFontSizes[3] : m_fontSizes[3];
04134   int isize = (int)size;
04135   if (isize < minFontSize)
04136     isize = minFontSize;
04137 
04138   FontDef newFontDef(childFont);
04139   newFontDef.size = isize;
04140   aStyle->setFontDef(newFontDef);
04141 }
04142 #endif
04143 
04144 } // namespace khtml
KDE Home | KDE Accessibility Home | Description of Access Keys