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 selectors and combinators
00966 DOM::ElementImpl* CSSStyleSelector::checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)
00967 {
00968     // The simple selector has to match
00969     if(!checkSimpleSelector(sel, e, isAncestor, isSubSelector)) return 0;
00970 
00971     // The rest of the selectors has to match
00972     CSSSelector::Relation relation = sel->relation;
00973 
00974     // Prepare next sel
00975     sel = sel->tagHistory;
00976     if (!sel) return e;
00977 
00978     switch(relation) {
00979         case CSSSelector::Descendant:
00980         {
00981             while(true)
00982             {
00983                 DOM::NodeImpl* n = e->parentNode();
00984                 if(!n || !n->isElementNode()) return 0;
00985                 e = static_cast<ElementImpl *>(n);
00986                 if(checkSelector(sel, e, true)) return e;
00987             }
00988             break;
00989         }
00990         case CSSSelector::Child:
00991         {
00992             DOM::NodeImpl* n = e->parentNode();
00993             if (!strictParsing)
00994                 while (n && n->implicitNode()) n = n->parentNode();
00995             if(!n || !n->isElementNode()) return 0;
00996             e = static_cast<ElementImpl *>(n);
00997             if(checkSelector(sel, e, true)) return e;
00998             break;
00999         }
01000         case CSSSelector::IndirectAdjacent:
01001         {
01002             // Sibling selectors always generate structural dependencies
01003             // because newly inserted element might fullfill them.
01004             if (e->parentNode()->isElementNode())
01005                 addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01006             while(true)
01007             {
01008                 DOM::NodeImpl* n = e->previousSibling();
01009                 while( n && !n->isElementNode() )
01010                     n = n->previousSibling();
01011                 if( !n ) return 0;
01012                 e = static_cast<ElementImpl *>(n);
01013                 if(checkSelector(sel, e, false)) return e;
01014             };
01015             break;
01016         }
01017         case CSSSelector::DirectAdjacent:
01018         {
01019             if (e->parentNode()->isElementNode())
01020                 addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01021             DOM::NodeImpl* n = e->previousSibling();
01022             while( n && !n->isElementNode() )
01023                 n = n->previousSibling();
01024             if( !n ) return 0;
01025             e = static_cast<ElementImpl *>(n);
01026             if(checkSelector(sel, e, false)) return e;
01027             break;
01028         }
01029         case CSSSelector::SubSelector:
01030             return checkSelector(sel, e, isAncestor, true);
01031     }
01032     return 0;
01033 }
01034 
01035 void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl * e)
01036 {
01037     assert(e == element); // yes, actually
01038 
01039     dynamicPseudo = RenderStyle::NOPSEUDO;
01040 
01041     selectorCache[ selIndex ].state = Invalid;
01042     CSSSelector *sel = selectors[ selIndex ];
01043 
01044     // Check the selector
01045     if(!checkSelector(sel, e, true)) return;
01046 
01047     if ( dynamicPseudo != RenderStyle::NOPSEUDO ) {
01048     selectorCache[selIndex].state = AppliesPseudo;
01049     selectors[ selIndex ]->pseudoId = dynamicPseudo;
01050     } else
01051     selectorCache[ selIndex ].state = Applies;
01052     //qDebug( "selector %d applies", selIndex );
01053     //selectors[ selIndex ]->print();
01054     return;
01055 }
01056 
01057 void CSSStyleSelector::addDependency(StructuralDependencyType dependencyType, ElementImpl* dependency)
01058 {
01059     element->getDocument()->dynamicDomRestyler().addDependency(element, dependency, dependencyType);
01060 }
01061 
01062 bool CSSStyleSelector::checkSimpleSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)
01063 {
01064     if(!e)
01065         return false;
01066 
01067     if (sel->tag != anyQName) {
01068         int eltID = e->id();
01069         Q_UINT16 localName = localNamePart(eltID);
01070         Q_UINT16 ns = namespacePart(eltID);
01071         Q_UINT16 selLocalName = localNamePart(sel->tag);
01072         Q_UINT16 selNS = namespacePart(sel->tag);
01073 
01074         if (localName <= ID_LAST_TAG && ns == defaultNamespace) {
01075             assert(e->isHTMLElement());
01076             ns = xhtmlNamespace;
01077         }
01078 
01079         // match on local
01080         if (selLocalName != anyLocalName && localName != selLocalName) return false;
01081         // match on namespace
01082         if (selNS != anyNamespace && ns != selNS) return false;
01083     }
01084 
01085     if(sel->attr)
01086     {
01087         DOMStringImpl* value = e->getAttributeImpl(sel->attr);
01088         if(!value) return false; // attribute is not set
01089 
01090         switch(sel->match)
01091         {
01092         case CSSSelector::Exact:
01093             /* attribute values are case insensitive in all HTML modes,
01094                even in the strict ones */
01095             if ( e->getDocument()->htmlMode() != DocumentImpl::XHtml ) {
01096                 if ( strcasecmp(sel->value, value) )
01097                     return false;
01098             } else {
01099                 if ( strcmp(sel->value, value) )
01100                     return false;
01101             }
01102             break;
01103         case CSSSelector::Id:
01104         if( (strictParsing && strcmp(sel->value, value) ) ||
01105                 (!strictParsing && strcasecmp(sel->value, value)))
01106                 return false;
01107             break;
01108         case CSSSelector::Set:
01109             break;
01110         case CSSSelector::Class:
01111             // no break
01112         case CSSSelector::List:
01113         {
01114             int sel_len = sel->value.length();
01115             int val_len = value->length();
01116             // Be smart compare on length first
01117             if (sel_len > val_len) return false;
01118             // Selector string may not contain spaces
01119             if ((sel->attr != ATTR_CLASS || e->hasClassList()) && sel->value.find(' ') != -1) return false;
01120             if (sel_len == val_len)
01121                 return (strictParsing && !strcmp(sel->value, value)) ||
01122                (!strictParsing && !strcasecmp(sel->value, value));
01123             // else the value is longer and can be a list
01124             if ( sel->match == CSSSelector::Class && !e->hasClassList() ) return false;
01125 
01126             QChar* sel_uc = sel->value.unicode();
01127             QChar* val_uc = value->unicode();
01128 
01129             QConstString sel_str(sel_uc, sel_len);
01130             QConstString val_str(val_uc, val_len);
01131 
01132             int pos = 0;
01133             for ( ;; ) {
01134                 pos = val_str.string().find(sel_str.string(), pos, strictParsing);
01135                 if ( pos == -1 ) return false;
01136                 if ( pos == 0 || val_uc[pos-1].isSpace() ) {
01137                     int endpos = pos + sel_len;
01138                     if ( endpos >= val_len || val_uc[endpos].isSpace() )
01139                         break; // We have a match.
01140                 }
01141                 ++pos;
01142             }
01143             break;
01144         }
01145         case CSSSelector::Contain:
01146         {
01147             //kdDebug( 6080 ) << "checking for contains match" << endl;
01148             QConstString val_str(value->unicode(), value->length());
01149             QConstString sel_str(sel->value.unicode(), sel->value.length());
01150             return val_str.string().contains(sel_str.string());
01151         }
01152         case CSSSelector::Begin:
01153         {
01154             //kdDebug( 6080 ) << "checking for beginswith match" << endl;
01155             QConstString val_str(value->unicode(), value->length());
01156             QConstString sel_str(sel->value.unicode(), sel->value.length());
01157             return val_str.string().startsWith(sel_str.string());
01158         }
01159         case CSSSelector::End:
01160         {
01161             //kdDebug( 6080 ) << "checking for endswith match" << endl;
01162             QConstString val_str(value->unicode(), value->length());
01163             QConstString sel_str(sel->value.unicode(), sel->value.length());
01164             return val_str.string().endsWith(sel_str.string());
01165         }
01166         case CSSSelector::Hyphen:
01167         {
01168             //kdDebug( 6080 ) << "checking for hyphen match" << endl;
01169             QConstString val_str(value->unicode(), value->length());
01170             QConstString sel_str(sel->value.unicode(), sel->value.length());
01171             const QString& str = val_str.string();
01172             const QString& selStr = sel_str.string();
01173             if(str.length() < selStr.length()) return false;
01174             // Check if str begins with selStr:
01175             if(str.find(selStr, 0, strictParsing) != 0) return false;
01176             // It does. Check for exact match or following '-':
01177             if(str.length() != selStr.length()
01178                 && str[selStr.length()] != '-') return false;
01179             break;
01180         }
01181         case CSSSelector::PseudoClass:
01182         case CSSSelector::PseudoElement:
01183         case CSSSelector::None:
01184             break;
01185         }
01186     }
01187 
01188     if(sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement)
01189     {
01190     switch (sel->pseudoType()) {
01191         // Pseudo classes:
01192     case CSSSelector::PseudoEmpty:
01193         addDependency(BackwardsStructuralDependency, e);
01194             // If e is not closed yet we don't know the number of children
01195             if (!e->closed()) {
01196                 return false;
01197             }
01198             if (!e->firstChild())
01199                 return true;
01200             else {
01201                 // check for empty text nodes
01202                 NodeImpl *t = e->firstChild();
01203 
01204                 while (t && t->isTextNode() && static_cast<TextImpl*>(t)->length() == 0) t = t->nextSibling();
01205 
01206                 if (t == 0)
01207                     return true;
01208                 else
01209                     return false;
01210             }
01211             break;
01212     case CSSSelector::PseudoFirstChild: {
01213         // first-child matches the first child that is an element!
01214             if (e->parentNode() && e->parentNode()->isElementNode()) {
01215                 // Handle dynamic DOM changes
01216                 addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01217                 DOM::NodeImpl* n = e->previousSibling();
01218                 while ( n && !n->isElementNode() )
01219                     n = n->previousSibling();
01220                 if ( !n )
01221                     return true;
01222             }
01223             break;
01224         }
01225         case CSSSelector::PseudoLastChild: {
01226             // last-child matches the last child that is an element!
01227             if (e->parentNode() && e->parentNode()->isElementNode()) {
01228                 // Handle unfinished parsing and dynamic DOM changes
01229                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01230                 if (!e->parentNode()->closed()) {
01231 //                     kdDebug(6080) << e->nodeName().string() << "::last-child: Parent unclosed" << endl;
01232                     return false;
01233                 }
01234                 DOM::NodeImpl* n = e->nextSibling();
01235                 while ( n && !n->isElementNode() )
01236                     n = n->nextSibling();
01237                 if ( !n )
01238                     return true;
01239             }
01240             break;
01241         }
01242         case CSSSelector::PseudoOnlyChild: {
01243             // If both first-child and last-child apply, then only-child applies.
01244             if (e->parentNode() && e->parentNode()->isElementNode()) {
01245                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01246                 if (!e->parentNode()->closed()) {
01247                     return false;
01248                 }
01249                 DOM::NodeImpl* n = e->previousSibling();
01250                 while ( n && !n->isElementNode() )
01251                     n = n->previousSibling();
01252                 if ( !n ) {
01253                     n = e->nextSibling();
01254                     while ( n && !n->isElementNode() )
01255                         n = n->nextSibling();
01256                     if ( !n )
01257                         return true;
01258                 }
01259             }
01260             break;
01261         }
01262         case CSSSelector::PseudoNthChild: {
01263         // nth-child matches every (a*n+b)th element!
01264             if (e->parentNode() && e->parentNode()->isElementNode()) {
01265                 addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01266                 int count = 1;
01267                 DOM::NodeImpl* n = e->previousSibling();
01268                 while ( n ) {
01269                     if (n->isElementNode()) count++;
01270                     n = n->previousSibling();
01271                 }
01272 //                 kdDebug(6080) << "NthChild " << count << "=" << sel->string_arg << endl;
01273                 if (matchNth(count,sel->string_arg.string()))
01274                     return true;
01275             }
01276             break;
01277         }
01278         case CSSSelector::PseudoNthLastChild: {
01279             if (e->parentNode() && e->parentNode()->isElementNode()) {
01280                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01281                 if (!e->parentNode()->closed()) {
01282                     return false;
01283                 }
01284                 int count = 1;
01285                 DOM::NodeImpl* n = e->nextSibling();
01286                 while ( n ) {
01287                     if (n->isElementNode()) count++;
01288                     n = n->nextSibling();
01289                 }
01290 //                kdDebug(6080) << "NthLastChild " << count << "=" << sel->string_arg << endl;
01291                 if (matchNth(count,sel->string_arg.string()))
01292                     return true;
01293             }
01294             break;
01295         }
01296     case CSSSelector::PseudoFirstOfType: {
01297         // first-of-type matches the first element of its type!
01298             if (e->parentNode() && e->parentNode()->isElementNode()) {
01299                 addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01300                 const DOMString& type = e->tagName();
01301                 DOM::NodeImpl* n = e->previousSibling();
01302                 while ( n ) {
01303                     if (n->isElementNode())
01304                         if (static_cast<ElementImpl*>(n)->tagName() == type) break;
01305                     n = n->previousSibling();
01306                 }
01307                 if ( !n )
01308                     return true;
01309             }
01310             break;
01311         }
01312         case CSSSelector::PseudoLastOfType: {
01313             // last-child matches the last child that is an element!
01314             if (e->parentNode() && e->parentNode()->isElementNode()) {
01315                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01316                 if (!e->parentNode()->closed()) {
01317                     return false;
01318                 }
01319                 const DOMString& type = e->tagName();
01320                 DOM::NodeImpl* n = e->nextSibling();
01321                 while ( n ) {
01322                     if (n->isElementNode())
01323                         if (static_cast<ElementImpl*>(n)->tagName() == type) break;
01324                     n = n->nextSibling();
01325                 }
01326                 if ( !n )
01327                     return true;
01328             }
01329             break;
01330         }
01331         case CSSSelector::PseudoOnlyOfType: {
01332             // If both first-of-type and last-of-type apply, then only-of-type applies.
01333             if (e->parentNode() && e->parentNode()->isElementNode()) {
01334                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01335                 if (!e->parentNode()->closed()) {
01336                     return false;
01337                 }
01338                 const DOMString& type = e->tagName();
01339                 DOM::NodeImpl* n = e->previousSibling();
01340                 while ( n && !(n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type))
01341                     n = n->previousSibling();
01342                 if ( !n ) {
01343                     n = e->nextSibling();
01344                     while ( n && !(n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type))
01345                         n = n->nextSibling();
01346                     if ( !n )
01347                         return true;
01348             }
01349             }
01350         break;
01351         }
01352         case CSSSelector::PseudoNthOfType: {
01353         // nth-of-type matches every (a*n+b)th element of this type!
01354             if (e->parentNode() && e->parentNode()->isElementNode()) {
01355                 addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01356                 int count = 1;
01357                 const DOMString& type = e->tagName();
01358                 DOM::NodeImpl* n = e->previousSibling();
01359                 while ( n ) {
01360                     if (n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type) count++;
01361                     n = n->previousSibling();
01362                 }
01363 //                kdDebug(6080) << "NthOfType " << count << "=" << sel->string_arg << endl;
01364                 if (matchNth(count,sel->string_arg.string()))
01365                     return true;
01366             }
01367             break;
01368         }
01369         case CSSSelector::PseudoNthLastOfType: {
01370             if (e->parentNode() && e->parentNode()->isElementNode()) {
01371                 addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
01372                 if (!e->parentNode()->closed()) {
01373                     return false;
01374                 }
01375                 int count = 1;
01376                 const DOMString& type = e->tagName();
01377                 DOM::NodeImpl* n = e->nextSibling();
01378                 while ( n ) {
01379                     if (n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type) count++;
01380                     n = n->nextSibling();
01381                 }
01382 //                kdDebug(6080) << "NthLastOfType " << count << "=" << sel->string_arg << endl;
01383                 if (matchNth(count,sel->string_arg.string()))
01384                     return true;
01385             }
01386             break;
01387         }
01388         case CSSSelector::PseudoTarget:
01389             if (e == e->getDocument()->getCSSTarget())
01390                 return true;
01391             break;
01392         case CSSSelector::PseudoRoot:
01393             if (e == e->getDocument()->documentElement())
01394                 return true;
01395             break;
01396     case CSSSelector::PseudoLink:
01397         if (e == element) {
01398            // cache pseudoState
01399            if ( pseudoState == PseudoUnknown )
01400                     pseudoState = checkPseudoState( encodedurl, e );
01401                if ( pseudoState == PseudoLink )
01402                     return true;
01403             } else
01404                 return checkPseudoState( encodedurl, e ) == PseudoLink;
01405         break;
01406     case CSSSelector::PseudoVisited:
01407         if (e == element) {
01408                 // cache pseudoState
01409                 if ( pseudoState == PseudoUnknown )
01410                     pseudoState = checkPseudoState( encodedurl, e );
01411                 if ( pseudoState == PseudoVisited )
01412                     return true;
01413             } else
01414                 return checkPseudoState( encodedurl, e ) == PseudoVisited;
01415         break;
01416         case CSSSelector::PseudoHover: {
01417         // If we're in quirks mode, then *:hover should only match focusable elements.
01418         if (strictParsing || (sel->tag != anyQName) || isSubSelector || e->isFocusable() ) {
01419                 addDependency(HoverDependency, e);
01420 
01421                 if (e->hovered())
01422                     return true;
01423             }
01424             break;
01425         }
01426     case CSSSelector::PseudoActive:
01427         // If we're in quirks mode, then *:active should only match focusable elements
01428         if (strictParsing || (sel->tag != anyQName) || isSubSelector || e->isFocusable()) {
01429                 addDependency(ActiveDependency, e);
01430 
01431         if (e->active())
01432             return true;
01433         }
01434         break;
01435     case CSSSelector::PseudoFocus:
01436         if (e != element && e->isFocusable()) {
01437                 // *:focus is a default style, no need to track it.
01438                 addDependency(OtherStateDependency, e);
01439             }
01440             if (e->focused()) return true;
01441             break;
01442         case CSSSelector::PseudoLang: {
01443             // Set dynamic attribute dependency
01444             if (e == element) {
01445                 e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, PersonalDependency);
01446                 e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
01447             }
01448             else if (isAncestor)
01449                 e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
01450             else
01451                 e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, PredecessorDependency);
01452             // ### check xml:lang attribute in XML and XHTML documents
01453             DOMString value = e->getAttribute(ATTR_LANG);
01454             // The LANG attribute is inherited like a property
01455             NodeImpl *n = e->parent();;
01456             while (n && value.isEmpty()) {
01457                 if (n->isElementNode()) {
01458                     value = static_cast<ElementImpl*>(n)->getAttribute(ATTR_LANG);
01459                 } else
01460                 if (n->isDocumentNode()) {
01461                     value = static_cast<DocumentImpl*>(n)->contentLanguage();
01462                 }
01463                 n = n->parent();
01464             }
01465             if (value.isEmpty()) return false;
01466 
01467             QString langAttr = value.string();
01468             QString langSel = sel->string_arg.string();
01469 
01470             if(langAttr.length() < langSel.length()) return false;
01471 
01472             langAttr = langAttr.lower();
01473             langSel = langSel.lower();
01474 //             kdDebug(6080) << ":lang " << langAttr << "=" << langSel << "?" << endl;
01475             return (langAttr == langSel || langAttr.startsWith(langSel+"-"));
01476         }
01477         case CSSSelector::PseudoNot: {
01478             // check the simple selector
01479             for (CSSSelector* subSel = sel->simpleSelector; subSel;
01480                  subSel = subSel->tagHistory) {
01481                 // :not cannot nest.  I don't really know why this is a restriction in CSS3,
01482                 // but it is, so let's honor it.
01483                 if (subSel->simpleSelector)
01484                     break;
01485                 if (!checkSimpleSelector(subSel, e, isAncestor, true))
01486                     return true;
01487             }
01488             break;
01489         }
01490         case CSSSelector::PseudoEnabled: {
01491             if (e->isGenericFormElement()) {
01492                 addDependency(OtherStateDependency, e);
01493                 HTMLGenericFormElementImpl *form;
01494                 form = static_cast<HTMLGenericFormElementImpl*>(e);
01495                 return !form->disabled();
01496             }
01497             break;
01498         }
01499         case CSSSelector::PseudoDisabled: {
01500             if (e->isGenericFormElement()) {
01501                 addDependency(OtherStateDependency, e);
01502                 HTMLGenericFormElementImpl *form;
01503                 form = static_cast<HTMLGenericFormElementImpl*>(e);
01504                 return form->disabled();
01505             }
01506             break;
01507         }
01508         case CSSSelector::PseudoContains: {
01509             if (e->isHTMLElement()) {
01510                 addDependency(BackwardsStructuralDependency, e);
01511                 if (!e->closed()) {
01512                    return false;
01513                 }
01514                 HTMLElementImpl *elem;
01515                 elem = static_cast<HTMLElementImpl*>(e);
01516                 DOMString s = elem->innerText();
01517                 QString selStr = sel->string_arg.string();
01518 //                kdDebug(6080) << ":contains(\"" << selStr << "\")" << " on \"" << s << "\"" << endl;
01519                 return s.string().contains(selStr);
01520             }
01521             break;
01522         }
01523     case CSSSelector::PseudoChecked: {
01524            if (e->isHTMLElement() && e->id() == ID_INPUT) {
01525                addDependency(OtherStateDependency, e);
01526                return (static_cast<HTMLInputElementImpl*>(e)->checked());
01527            }
01528            return false;
01529         }
01530     case CSSSelector::PseudoIndeterminate: {
01531 #if 0
01532            if (e->isHTMLElement() && e->id() == ID_INPUT) {
01533                return (static_cast<HTMLInputElementImpl*>(e)->indeterminate() &&
01534                       !static_cast<HTMLInputElementImpl*>(e)->checked());
01535            }
01536            return false;
01537 #endif
01538         }
01539     case CSSSelector::PseudoOther:
01540         break;
01541 
01542     // Pseudo-elements:
01543     case CSSSelector::PseudoFirstLine:
01544     case CSSSelector::PseudoFirstLetter:
01545     case CSSSelector::PseudoSelection:
01546     case CSSSelector::PseudoBefore:
01547     case CSSSelector::PseudoAfter:
01548     case CSSSelector::PseudoMarker:
01549     case CSSSelector::PseudoReplaced:
01550         // Pseudo-elements can only apply to subject
01551         if ( e == element ) {
01552                 // Pseudo-elements has to be the last sub-selector on subject
01553                 if (sel->tagHistory && sel->relation == CSSSelector::SubSelector) return false;
01554 
01555                 assert(dynamicPseudo == RenderStyle::NOPSEUDO);
01556 
01557                 switch (sel->pseudoType()) {
01558                 case CSSSelector::PseudoFirstLine:
01559                     dynamicPseudo = RenderStyle::FIRST_LINE;
01560                     break;
01561                 case CSSSelector::PseudoFirstLetter:
01562                     dynamicPseudo = RenderStyle::FIRST_LETTER;
01563                     break;
01564                 case CSSSelector::PseudoSelection:
01565                     dynamicPseudo = RenderStyle::SELECTION;
01566                     break;
01567                 case CSSSelector::PseudoBefore:
01568                     dynamicPseudo = RenderStyle::BEFORE;
01569                     break;
01570                 case CSSSelector::PseudoAfter:
01571                     dynamicPseudo = RenderStyle::AFTER;
01572                     break;
01573                 case CSSSelector::PseudoMarker:
01574                     dynamicPseudo = RenderStyle::MARKER;
01575                     break;
01576                 case CSSSelector::PseudoReplaced:
01577                     dynamicPseudo = RenderStyle::REPLACED;
01578                     break;
01579                 default:
01580                     assert(false);
01581                 }
01582         return true;
01583         }
01584         break;
01585     case CSSSelector::PseudoNotParsed:
01586         assert(false);
01587         break;
01588     }
01589     return false;
01590     }
01591     // ### add the rest of the checks...
01592     return true;
01593 }
01594 
01595 void CSSStyleSelector::clearLists()
01596 {
01597     delete [] selectors;
01598     if ( selectorCache ) {
01599         for ( unsigned int i = 0; i < selectors_size; i++ )
01600             delete [] selectorCache[i].props;
01601 
01602         delete [] selectorCache;
01603     }
01604     if ( properties ) {
01605     CSSOrderedProperty **prop = properties;
01606     while ( *prop ) {
01607         delete (*prop);
01608         prop++;
01609     }
01610         delete [] properties;
01611     }
01612     selectors = 0;
01613     properties = 0;
01614     selectorCache = 0;
01615 }
01616 
01617 
01618 void CSSStyleSelector::buildLists()
01619 {
01620     clearLists();
01621     // collect all selectors and Properties in lists. Then transfer them to the array for faster lookup.
01622 
01623     QPtrList<CSSSelector> selectorList;
01624     CSSOrderedPropertyList propertyList;
01625 
01626     if(m_medium == "print" && defaultPrintStyle)
01627       defaultPrintStyle->collect( &selectorList, &propertyList, Default,
01628         Default );
01629     else if(defaultStyle) defaultStyle->collect( &selectorList, &propertyList,
01630       Default, Default );
01631 
01632     if (!strictParsing && defaultQuirksStyle)
01633         defaultQuirksStyle->collect( &selectorList, &propertyList, Default, Default );
01634 
01635     if(userStyle) userStyle->collect(&selectorList, &propertyList, User, UserImportant );
01636     if(authorStyle) authorStyle->collect(&selectorList, &propertyList, Author, AuthorImportant );
01637 
01638     selectors_size = selectorList.count();
01639     selectors = new CSSSelector *[selectors_size];
01640     CSSSelector *s = selectorList.first();
01641     CSSSelector **sel = selectors;
01642     while ( s ) {
01643     *sel = s;
01644     s = selectorList.next();
01645     ++sel;
01646     }
01647 
01648     selectorCache = new SelectorCache[selectors_size];
01649     for ( unsigned int i = 0; i < selectors_size; i++ ) {
01650         selectorCache[i].state = Unknown;
01651         selectorCache[i].props_size = 0;
01652         selectorCache[i].props = 0;
01653     }
01654 
01655     // presort properties. Should make the sort() calls in styleForElement faster.
01656     propertyList.sort();
01657     properties_size = propertyList.count() + 1;
01658     properties = new CSSOrderedProperty *[ properties_size ];
01659     CSSOrderedProperty *p = propertyList.first();
01660     CSSOrderedProperty **prop = properties;
01661     while ( p ) {
01662     *prop = p;
01663     p = propertyList.next();
01664     ++prop;
01665     }
01666     *prop = 0;
01667 
01668     unsigned int* offsets = new unsigned int[selectors_size];
01669     if(properties[0])
01670     offsets[properties[0]->selector] = 0;
01671     for(unsigned int p = 1; p < properties_size; ++p) {
01672 
01673     if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) {
01674         unsigned int sel = properties[p - 1]->selector;
01675             int* newprops = new int[selectorCache[sel].props_size+2];
01676             for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ )
01677                 newprops[i] = selectorCache[sel].props[i];
01678 
01679         newprops[selectorCache[sel].props_size] = offsets[sel];
01680         newprops[selectorCache[sel].props_size+1] = p - offsets[sel];
01681             delete [] selectorCache[sel].props;
01682             selectorCache[sel].props = newprops;
01683             selectorCache[sel].props_size += 2;
01684 
01685         if(properties[p]) {
01686         sel = properties[p]->selector;
01687         offsets[sel] = p;
01688             }
01689         }
01690     }
01691     delete [] offsets;
01692 }
01693 
01694 
01695 // ----------------------------------------------------------------------
01696 
01697 
01698 CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index)
01699 {
01700     rule = r;
01701     if(rule) r->ref();
01702     index = _index;
01703     selector = s;
01704 }
01705 
01706 CSSOrderedRule::~CSSOrderedRule()
01707 {
01708     if(rule) rule->deref();
01709 }
01710 
01711 // -----------------------------------------------------------------
01712 
01713 CSSStyleSelectorList::CSSStyleSelectorList()
01714     : QPtrList<CSSOrderedRule>()
01715 {
01716     setAutoDelete(true);
01717 }
01718 CSSStyleSelectorList::~CSSStyleSelectorList()
01719 {
01720 }
01721 
01722 void CSSStyleSelectorList::append( CSSStyleSheetImpl *sheet,
01723                                    const DOMString &medium )
01724 {
01725     if(!sheet || !sheet->isCSSStyleSheet()) return;
01726 
01727     // No media implies "all", but if a medialist exists it must
01728     // contain our current medium
01729     if( sheet->media() && !sheet->media()->contains( medium ) )
01730         return; // style sheet not applicable for this medium
01731 
01732     int len = sheet->length();
01733 
01734     for(int i = 0; i< len; i++)
01735     {
01736         StyleBaseImpl *item = sheet->item(i);
01737         if(item->isStyleRule())
01738         {
01739             CSSStyleRuleImpl *r = static_cast<CSSStyleRuleImpl *>(item);
01740             QPtrList<CSSSelector> *s = r->selector();
01741             for(int j = 0; j < (int)s->count(); j++)
01742             {
01743                 CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count());
01744         QPtrList<CSSOrderedRule>::append(rule);
01745                 //kdDebug( 6080 ) << "appending StyleRule!" << endl;
01746             }
01747         }
01748         else if(item->isImportRule())
01749         {
01750             CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
01751 
01752             //kdDebug( 6080 ) << "@import: Media: "
01753             //                << import->media()->mediaText().string() << endl;
01754 
01755             if( !import->media() || import->media()->contains( medium ) )
01756             {
01757                 CSSStyleSheetImpl *importedSheet = import->styleSheet();
01758                 append( importedSheet, medium );
01759             }
01760         }
01761         else if( item->isMediaRule() )
01762         {
01763             CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl *>( item );
01764             CSSRuleListImpl *rules = r->cssRules();
01765 
01766             //DOMString mediaText = media->mediaText();
01767             //kdDebug( 6080 ) << "@media: Media: "
01768             //                << r->media()->mediaText().string() << endl;
01769 
01770             if( ( !r->media() || r->media()->contains( medium ) ) && rules)
01771             {
01772                 // Traverse child elements of the @import rule. Since
01773                 // many elements are not allowed as child we do not use
01774                 // a recursive call to append() here
01775                 for( unsigned j = 0; j < rules->length(); j++ )
01776                 {
01777                     //kdDebug( 6080 ) << "*** Rule #" << j << endl;
01778 
01779                     CSSRuleImpl *childItem = rules->item( j );
01780                     if( childItem->isStyleRule() )
01781                     {
01782                         // It is a StyleRule, so append it to our list
01783                         CSSStyleRuleImpl *styleRule =
01784                                 static_cast<CSSStyleRuleImpl *>( childItem );
01785 
01786                         QPtrList<CSSSelector> *s = styleRule->selector();
01787                         for( int j = 0; j < ( int ) s->count(); j++ )
01788                         {
01789                             CSSOrderedRule *orderedRule = new CSSOrderedRule(
01790                                             styleRule, s->at( j ), count() );
01791                         QPtrList<CSSOrderedRule>::append( orderedRule );
01792                         }
01793                     }
01794                     else
01795                     {
01796                         //kdDebug( 6080 ) << "Ignoring child rule of "
01797                         //    "ImportRule: rule is not a StyleRule!" << endl;
01798                     }
01799                 }   // for rules
01800             }   // if rules
01801             else
01802             {
01803                 //kdDebug( 6080 ) << "CSSMediaRule not rendered: "
01804                 //                << "rule empty or wrong medium!" << endl;
01805             }
01806         }
01807         // ### include other rules
01808     }
01809 }
01810 
01811 
01812 void CSSStyleSelectorList::collect( QPtrList<CSSSelector> *selectorList, CSSOrderedPropertyList *propList,
01813                     Source regular, Source important )
01814 {
01815     CSSOrderedRule *r = first();
01816     while( r ) {
01817     CSSSelector *sel = selectorList->first();
01818     int selectorNum = 0;
01819     while( sel ) {
01820         if ( *sel == *(r->selector) )
01821         break;
01822         sel = selectorList->next();
01823         selectorNum++;
01824     }
01825     if ( !sel )
01826         selectorList->append( r->selector );
01827 //  else
01828 //      qDebug("merged one selector");
01829     propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important );
01830     r = next();
01831     }
01832 }
01833 
01834 // -------------------------------------------------------------------------
01835 
01836 int CSSOrderedPropertyList::compareItems(QPtrCollection::Item i1, QPtrCollection::Item i2)
01837 {
01838     int diff =  static_cast<CSSOrderedProperty *>(i1)->priority
01839         - static_cast<CSSOrderedProperty *>(i2)->priority;
01840     return diff ? diff : static_cast<CSSOrderedProperty *>(i1)->position
01841         - static_cast<CSSOrderedProperty *>(i2)->position;
01842 }
01843 
01844 void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
01845                     Source regular, Source important )
01846 {
01847     QPtrList<CSSProperty> *values = decl->values();
01848     if(!values) return;
01849     int len = values->count();
01850     for(int i = 0; i < len; i++)
01851     {
01852         CSSProperty *prop = values->at(i);
01853     Source source = regular;
01854 
01855     if( prop->m_important ) source = important;
01856     if( prop->nonCSSHint ) source = NonCSSHint;
01857 
01858     bool first = false;
01859         // give special priority to font-xxx, color properties
01860         switch(prop->m_id)
01861         {
01862         case CSS_PROP_FONT_STYLE:
01863     case CSS_PROP_FONT_SIZE:
01864     case CSS_PROP_FONT_WEIGHT:
01865         case CSS_PROP_FONT_FAMILY:
01866         case CSS_PROP_FONT_VARIANT:
01867         case CSS_PROP_FONT:
01868         case CSS_PROP_COLOR:
01869         case CSS_PROP_DIRECTION:
01870         case CSS_PROP_DISPLAY:
01871             // these have to be applied first, because other properties use the computed
01872             // values of these porperties.
01873         first = true;
01874             break;
01875         default:
01876             break;
01877         }
01878 
01879     QPtrList<CSSOrderedProperty>::append(new CSSOrderedProperty(prop, selector,
01880                                  first, source, specificity,
01881                                  count() ));
01882     }
01883 }
01884 
01885 // -------------------------------------------------------------------------------------
01886 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
01887 
01888 static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, QPaintDeviceMetrics *paintDeviceMetrics, bool *ok = 0 )
01889 {
01890     Length l;
01891     if ( !primitiveValue ) {
01892     if ( ok )
01893             *ok = false;
01894     } else {
01895     int type = primitiveValue->primitiveType();
01896     if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
01897         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
01898     else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
01899         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent);
01900     else if(type == CSSPrimitiveValue::CSS_NUMBER)
01901         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
01902     else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
01903         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
01904     else if ( ok )
01905         *ok = false;
01906     }
01907     return l;
01908 }
01909 
01910 
01911 // color mapping code
01912 struct colorMap {
01913     int css_value;
01914     QRgb color;
01915 };
01916 
01917 static const colorMap cmap[] = {
01918     { CSS_VAL_AQUA, 0xFF00FFFF },
01919     { CSS_VAL_BLACK, 0xFF000000 },
01920     { CSS_VAL_BLUE, 0xFF0000FF },
01921     { CSS_VAL_CRIMSON, 0xFFDC143C },
01922     { CSS_VAL_FUCHSIA, 0xFFFF00FF },
01923     { CSS_VAL_GRAY, 0xFF808080 },
01924     { CSS_VAL_GREEN, 0xFF008000  },
01925     { CSS_VAL_INDIGO, 0xFF4B0082 },
01926     { CSS_VAL_LIME, 0xFF00FF00 },
01927     { CSS_VAL_MAROON, 0xFF800000 },
01928     { CSS_VAL_NAVY, 0xFF000080 },
01929     { CSS_VAL_OLIVE, 0xFF808000  },
01930     { CSS_VAL_ORANGE, 0xFFFFA500 },
01931     { CSS_VAL_PURPLE, 0xFF800080 },
01932     { CSS_VAL_RED, 0xFFFF0000 },
01933     { CSS_VAL_SILVER, 0xFFC0C0C0 },
01934     { CSS_VAL_TEAL, 0xFF008080  },
01935     { CSS_VAL_WHITE, 0xFFFFFFFF },
01936     { CSS_VAL_YELLOW, 0xFFFFFF00 },
01937     { CSS_VAL_INVERT, invertedColor },
01938     { CSS_VAL_TRANSPARENT, transparentColor },
01939     { CSS_VAL_GREY, 0xff808080 },
01940     { 0, 0 }
01941 };
01942 
01943 struct uiColors {
01944     int css_value;
01945     const char * configGroup;
01946     const char * configEntry;
01947 QPalette::ColorGroup group;
01948 QColorGroup::ColorRole role;
01949 };
01950 
01951 const char * const wmgroup = "WM";
01952 const char * const generalgroup = "General";
01953 
01954 /* Mapping system settings to CSS 2
01955 * Tried hard to get an appropriate mapping - schlpbch
01956 */
01957 static const uiColors uimap[] = {
01958     // Active window border.
01959     { CSS_VAL_ACTIVEBORDER, wmgroup, "background", QPalette::Active, QColorGroup::Light },
01960     // Active window caption.
01961     { CSS_VAL_ACTIVECAPTION, wmgroup, "background", QPalette::Active, QColorGroup::Text },
01962         // Text in caption, size box, and scrollbar arrow box.
01963     { CSS_VAL_CAPTIONTEXT, wmgroup, "activeForeground", QPalette::Active, QColorGroup::Text },
01964     // Face color for three-dimensional display elements.
01965     { CSS_VAL_BUTTONFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
01966     // Dark shadow for three-dimensional display elements (for edges facing away from the light source).
01967     { CSS_VAL_BUTTONHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
01968     // Shadow color for three-dimensional display elements.
01969     { CSS_VAL_BUTTONSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
01970     // Text on push buttons.
01971     { CSS_VAL_BUTTONTEXT, wmgroup, "buttonForeground", QPalette::Inactive, QColorGroup::ButtonText },
01972     // Dark shadow for three-dimensional display elements.
01973     { CSS_VAL_THREEDDARKSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Dark },
01974     // Face color for three-dimensional display elements.
01975     { CSS_VAL_THREEDFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
01976     // Highlight color for three-dimensional display elements.
01977     { CSS_VAL_THREEDHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
01978     // Light color for three-dimensional display elements (for edges facing the light source).
01979     { CSS_VAL_THREEDLIGHTSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Midlight },
01980     // Dark shadow for three-dimensional display elements.
01981     { CSS_VAL_THREEDSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
01982 
01983     // Inactive window border.
01984     { CSS_VAL_INACTIVEBORDER, wmgroup, "background", QPalette::Disabled, QColorGroup::Background },
01985     // Inactive window caption.
01986     { CSS_VAL_INACTIVECAPTION, wmgroup, "inactiveBackground", QPalette::Disabled, QColorGroup::Background },
01987     // Color of text in an inactive caption.
01988     { CSS_VAL_INACTIVECAPTIONTEXT, wmgroup, "inactiveForeground", QPalette::Disabled, QColorGroup::Text },
01989     { CSS_VAL_GRAYTEXT, wmgroup, 0, QPalette::Disabled, QColorGroup::Text },
01990 
01991     // Menu background
01992     { CSS_VAL_MENU, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
01993     // Text in menus
01994     { CSS_VAL_MENUTEXT, generalgroup, "foreground", QPalette::Inactive, QColorGroup::Background },
01995 
01996         // Text of item(s) selected in a control.
01997     { CSS_VAL_HIGHLIGHT, generalgroup, "selectBackground", QPalette::Inactive, QColorGroup::Background },
01998 
01999     // Text of item(s) selected in a control.
02000     { CSS_VAL_HIGHLIGHTTEXT, generalgroup, "selectForeground", QPalette::Inactive, QColorGroup::Background },
02001 
02002     // Background color of multiple document interface.
02003     { CSS_VAL_APPWORKSPACE, generalgroup, "background", QPalette::Inactive, QColorGroup::Text },
02004 
02005     // Scroll bar gray area.
02006     { CSS_VAL_SCROLLBAR, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
02007 
02008     // Window background.
02009     { CSS_VAL_WINDOW, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
02010     // Window frame.
02011     { CSS_VAL_WINDOWFRAME, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
02012         // WindowText
02013     { CSS_VAL_WINDOWTEXT, generalgroup, "windowForeground", QPalette::Inactive, QColorGroup::Text },
02014     { CSS_VAL_TEXT, generalgroup, 0, QPalette::Inactive, QColorGroup::Text },
02015     { 0, 0, 0, QPalette::NColorGroups, QColorGroup::NColorRoles }
02016 };
02017 
02018 static QColor colorForCSSValue( int css_value )
02019 {
02020     // try the regular ones first
02021     const colorMap *col = cmap;
02022     while ( col->css_value && col->css_value != css_value )
02023     ++col;
02024     if ( col->css_value )
02025     return col->color;
02026 
02027     const uiColors *uicol = uimap;
02028     while ( uicol->css_value && uicol->css_value != css_value )
02029     ++uicol;
02030 #ifndef APPLE_CHANGES
02031     if ( !uicol->css_value ) {
02032     if ( css_value == CSS_VAL_INFOBACKGROUND )
02033         return QToolTip::palette().inactive().background();
02034     else if ( css_value == CSS_VAL_INFOTEXT )
02035         return QToolTip::palette().inactive().foreground();
02036     else if ( css_value == CSS_VAL_BACKGROUND ) {
02037         KConfig bckgrConfig("kdesktoprc", true, false); // No multi-screen support
02038         bckgrConfig.setGroup("Desktop0");
02039         // Desktop background.
02040         return bckgrConfig.readColorEntry("Color1", &qApp->palette().disabled().background());
02041     }
02042     return QColor();
02043     }
02044 #endif
02045 
02046     const QPalette &pal = qApp->palette();
02047     QColor c = pal.color( uicol->group, uicol->role );
02048 #ifndef APPLE_CHANGES
02049     if ( uicol->configEntry ) {
02050     KConfig *globalConfig = KGlobal::config();
02051     globalConfig->setGroup( uicol->configGroup );
02052     c = globalConfig->readColorEntry( uicol->configEntry, &c );
02053     }
02054 #endif
02055 
02056     return c;
02057 }
02058 
02059 static inline int nextFontSize(const QValueVector<int>& a, int v, bool smaller)
02060 {
02061     // return the nearest bigger/smaller value in scale a, when v is in range.
02062     // otherwise increase/decrease value using a 1.2 fixed ratio
02063     int m, l = 0, r = a.count()-1;
02064     while (l <= r) {
02065         m = (l+r)/2;
02066         if (a[m] == v)
02067             return smaller ? ( m ? a[m-1] : (v*5)/6 ) :
02068                              ( m+1<int(a.count()) ? a[m+1] : (v*6)/5 );
02069         else if (v < a[m])
02070             r = m-1;
02071         else
02072             l = m+1;
02073     }
02074     if (!l)
02075         return smaller ? (v*5)/6 : kMin((v*6)/5, a[0]);
02076     if (l == int(a.count()))
02077         return smaller ? kMax((v*5)/6, a[r]) : (v*6)/5;
02078 
02079     return smaller ? a[r] : a[l];
02080 }
02081 
02082 void CSSStyleSelector::applyRule( int id, DOM::CSSValueImpl *value )
02083 {
02084 //     kdDebug( 6080 ) << "applying property " << getPropertyName(id) << endl;
02085 
02086     CSSPrimitiveValueImpl *primitiveValue = 0;
02087     if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
02088 
02089     Length l;
02090     bool apply = false;
02091 
02092     bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
02093     bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) ||
02094                      (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
02095 
02096     // These properties are used to set the correct margins/padding on RTL lists.
02097     if (id == CSS_PROP__KHTML_MARGIN_START)
02098         id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
02099     else if (id == CSS_PROP__KHTML_PADDING_START)
02100         id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
02101 
02102     // What follows is a list that maps the CSS properties into their corresponding front-end
02103     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
02104     // are only hit when mapping "inherit" or "initial" into front-end values.
02105     switch(id)
02106     {
02107 // ident only properties
02108     case CSS_PROP_BACKGROUND_ATTACHMENT:
02109         HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
02110         break;
02111     case CSS_PROP__KHTML_BACKGROUND_CLIP:
02112         HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
02113         break;
02114     case CSS_PROP__KHTML_BACKGROUND_ORIGIN:
02115         HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
02116         break;
02117     case CSS_PROP_BACKGROUND_REPEAT:
02118         HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
02119         break;
02120     case CSS_PROP__KHTML_BACKGROUND_SIZE:
02121         HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
02122         break;
02123     case CSS_PROP_BORDER_COLLAPSE:
02124         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
02125         if(!primitiveValue) break;
02126         switch(primitiveValue->getIdent())
02127         {
02128         case CSS_VAL_COLLAPSE:
02129             style->setBorderCollapse(true);
02130             break;
02131         case CSS_VAL_SEPARATE:
02132             style->setBorderCollapse(false);
02133             break;
02134         default:
02135             return;
02136         }
02137         break;
02138 
02139     case CSS_PROP_BORDER_TOP_STYLE:
02140         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
02141         if (!primitiveValue) return;
02142         style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02143         break;
02144     case CSS_PROP_BORDER_RIGHT_STYLE:
02145         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
02146         if (!primitiveValue) return;
02147         style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02148         break;
02149     case CSS_PROP_BORDER_BOTTOM_STYLE:
02150         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
02151         if (!primitiveValue) return;
02152         style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02153         break;
02154     case CSS_PROP_BORDER_LEFT_STYLE:
02155         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
02156         if (!primitiveValue) return;
02157         style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02158         break;
02159     case CSS_PROP_OUTLINE_STYLE:
02160         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
02161         if (!primitiveValue) return;
02162         style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
02163         break;
02164     case CSS_PROP_CAPTION_SIDE:
02165     {
02166         HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
02167         if(!primitiveValue) break;
02168         ECaptionSide c = RenderStyle::initialCaptionSide();
02169         switch(primitiveValue->getIdent())
02170         {
02171         case CSS_VAL_LEFT:
02172             c = CAPLEFT; break;
02173         case CSS_VAL_RIGHT:
02174             c = CAPRIGHT; break;
02175         case CSS_VAL_TOP:
02176             c = CAPTOP; break;
02177         case CSS_VAL_BOTTOM:
02178             c = CAPBOTTOM; break;
02179         default:
02180             return;
02181         }
02182         style->setCaptionSide(c);
02183         return;
02184     }
02185     case CSS_PROP_CLEAR:
02186     {
02187         HANDLE_INHERIT_AND_INITIAL(clear, Clear)
02188         if(!primitiveValue) break;
02189         EClear c = CNONE;
02190         switch(primitiveValue->getIdent())
02191         {
02192         case CSS_VAL_LEFT:
02193             c = CLEFT; break;
02194         case CSS_VAL_RIGHT:
02195             c = CRIGHT; break;
02196         case CSS_VAL_BOTH:
02197             c = CBOTH; break;
02198         case CSS_VAL_NONE:
02199             c = CNONE; break;
02200         default:
02201             return;
02202         }
02203         style->setClear(c);
02204         return;
02205     }
02206     case CSS_PROP_DIRECTION:
02207     {
02208         HANDLE_INHERIT_AND_INITIAL(direction, Direction)
02209         if(!primitiveValue) break;
02210         style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) );
02211         return;
02212     }
02213     case CSS_PROP_DISPLAY:
02214     {
02215         HANDLE_INHERIT_AND_INITIAL(display, Display)
02216         if(!primitiveValue) break;
02217     int id = primitiveValue->getIdent();
02218         style->setDisplay( id == CSS_VAL_NONE ? NONE : EDisplay(id - CSS_VAL_INLINE) );
02219         break;
02220     }
02221 
02222     case CSS_PROP_EMPTY_CELLS:
02223     {
02224         HANDLE_INHERIT(emptyCells, EmptyCells);
02225         if (!primitiveValue) break;
02226         int id = primitiveValue->getIdent();
02227         if (id == CSS_VAL_SHOW)
02228             style->setEmptyCells(SHOW);
02229         else if (id == CSS_VAL_HIDE)
02230             style->setEmptyCells(HIDE);
02231         break;
02232     }
02233     case CSS_PROP_FLOAT:
02234     {
02235         HANDLE_INHERIT_AND_INITIAL(floating, Floating)
02236         if(!primitiveValue) return;
02237         EFloat f;
02238         switch(primitiveValue->getIdent())
02239         {
02240         case CSS_VAL__KHTML_LEFT:
02241             f = FLEFT_ALIGN; break;
02242         case CSS_VAL_LEFT:
02243             f = FLEFT; break;
02244         case CSS_VAL__KHTML_RIGHT:
02245             f = FRIGHT_ALIGN; break;
02246         case CSS_VAL_RIGHT:
02247             f = FRIGHT; break;
02248         case CSS_VAL_NONE:
02249         case CSS_VAL_CENTER:  //Non standart CSS-Value
02250             f = FNONE; break;
02251         default:
02252             return;
02253         }
02254         if (f!=FNONE && style->display()==LIST_ITEM)
02255             style->setDisplay(BLOCK);
02256 
02257         style->setFloating(f);
02258         break;
02259     }
02260 
02261     case CSS_PROP_FONT_STYLE:
02262     {
02263         FontDef fontDef = style->htmlFont().fontDef;
02264         if (isInherit)
02265             fontDef.italic = parentStyle->htmlFont().fontDef.italic;
02266     else if (isInitial)
02267             fontDef.italic = false;
02268         else {
02269         if(!primitiveValue) return;
02270         switch(primitiveValue->getIdent()) {
02271         case CSS_VAL_OBLIQUE:
02272         // ### oblique is the same as italic for the moment...
02273         case CSS_VAL_ITALIC:
02274             fontDef.italic = true;
02275             break;
02276         case CSS_VAL_NORMAL:
02277             fontDef.italic = false;
02278             break;
02279         default:
02280             return;
02281         }
02282     }
02283         fontDirty |= style->setFontDef( fontDef );
02284         break;
02285     }
02286 
02287 
02288     case CSS_PROP_FONT_VARIANT:
02289     {
02290         FontDef fontDef = style->htmlFont().fontDef;
02291         if (isInherit)
02292             fontDef.smallCaps = parentStyle->htmlFont().fontDef.weight;
02293         else if (isInitial)
02294             fontDef.smallCaps = false;
02295         else {
02296         if(!primitiveValue) return;
02297         int id = primitiveValue->getIdent();
02298         if ( id == CSS_VAL_NORMAL )
02299         fontDef.smallCaps = false;
02300         else if ( id == CSS_VAL_SMALL_CAPS )
02301         fontDef.smallCaps = true;
02302         else
02303         return;
02304     }
02305     fontDirty |= style->setFontDef( fontDef );
02306     break;
02307     }
02308 
02309     case CSS_PROP_FONT_WEIGHT:
02310     {
02311         FontDef fontDef = style->htmlFont().fontDef;
02312         if (isInherit)
02313             fontDef.weight = parentStyle->htmlFont().fontDef.weight;
02314         else if (isInitial)
02315             fontDef.weight = QFont::Normal;
02316         else {
02317         if(!primitiveValue) return;
02318         if(primitiveValue->getIdent())
02319         {
02320         switch(primitiveValue->getIdent()) {
02321             // ### we just support normal and bold fonts at the moment...
02322             // setWeight can actually accept values between 0 and 99...
02323         case CSS_VAL_BOLD:
02324         case CSS_VAL_BOLDER:
02325         case CSS_VAL_600:
02326         case CSS_VAL_700:
02327         case CSS_VAL_800:
02328         case CSS_VAL_900:
02329             fontDef.weight = QFont::Bold;
02330             break;
02331         case CSS_VAL_NORMAL:
02332         case CSS_VAL_LIGHTER:
02333         case CSS_VAL_100:
02334         case CSS_VAL_200:
02335         case CSS_VAL_300:
02336         case CSS_VAL_400:
02337         case CSS_VAL_500:
02338             fontDef.weight = QFont::Normal;
02339             break;
02340         default:
02341             return;
02342         }
02343         }
02344         else
02345         {
02346         // ### fix parsing of 100-900 values in parser, apply them here
02347         }
02348     }
02349         fontDirty |= style->setFontDef( fontDef );
02350         break;
02351     }
02352 
02353     case CSS_PROP_LIST_STYLE_POSITION:
02354     {
02355         HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
02356         if (!primitiveValue) return;
02357         if (primitiveValue->getIdent())
02358             style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) );
02359         return;
02360     }
02361 
02362     case CSS_PROP_LIST_STYLE_TYPE:
02363     {
02364         HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
02365         if (!primitiveValue) return;
02366         if (primitiveValue->getIdent())
02367         {
02368             EListStyleType t;
02369         int id = primitiveValue->getIdent();
02370         if ( id == CSS_VAL_NONE) { // important!!
02371           t = LNONE;
02372         } else {
02373           t = EListStyleType(id - CSS_VAL_DISC);
02374         }
02375             style->setListStyleType(t);
02376         }
02377         return;
02378     }
02379 
02380     case CSS_PROP_OVERFLOW:
02381     {
02382         HANDLE_INHERIT_AND_INITIAL(overflow, Overflow)
02383         if (!primitiveValue) return;
02384         EOverflow o;
02385         switch(primitiveValue->getIdent())
02386         {
02387         case CSS_VAL_VISIBLE:
02388             o = OVISIBLE; break;
02389         case CSS_VAL_HIDDEN:
02390             o = OHIDDEN; break;
02391         case CSS_VAL_SCROLL:
02392         o = OSCROLL; break;
02393         case CSS_VAL_AUTO:
02394         o = OAUTO; break;
02395         case CSS_VAL_MARQUEE:
02396             o = OMARQUEE; break;
02397         default:
02398             return;
02399         }
02400         style->setOverflow(o);
02401         return;
02402     }
02403     break;
02404     case CSS_PROP_PAGE_BREAK_BEFORE:
02405     {
02406         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
02407         if (!primitiveValue) return;
02408         switch (primitiveValue->getIdent()) {
02409             case CSS_VAL_AUTO:
02410                 style->setPageBreakBefore(PBAUTO);
02411                 break;
02412             case CSS_VAL_LEFT:
02413             case CSS_VAL_RIGHT:
02414                 // CSS2.1: "Conforming user agents may map left/right to always."
02415             case CSS_VAL_ALWAYS:
02416                 style->setPageBreakBefore(PBALWAYS);
02417                 break;
02418             case CSS_VAL_AVOID:
02419                 style->setPageBreakBefore(PBAVOID);
02420                 break;
02421         }
02422         break;
02423     }
02424 
02425     case CSS_PROP_PAGE_BREAK_AFTER:
02426     {
02427         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
02428         if (!primitiveValue) return;
02429         switch (primitiveValue->getIdent()) {
02430             case CSS_VAL_AUTO:
02431                 style->setPageBreakAfter(PBAUTO);
02432                 break;
02433             case CSS_VAL_LEFT:
02434             case CSS_VAL_RIGHT:
02435                 // CSS2.1: "Conforming user agents may map left/right to always."
02436             case CSS_VAL_ALWAYS:
02437                 style->setPageBreakAfter(PBALWAYS);
02438                 break;
02439             case CSS_VAL_AVOID:
02440                 style->setPageBreakAfter(PBAVOID);
02441                 break;
02442         }
02443         break;
02444     }
02445 
02446     case CSS_PROP_PAGE_BREAK_INSIDE: {
02447         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
02448         if (!primitiveValue) return;
02449         if (primitiveValue->getIdent() == CSS_VAL_AUTO)
02450             style->setPageBreakInside(true);
02451         else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
02452             style->setPageBreakInside(false);
02453         return;
02454     }
02455 //    case CSS_PROP_PAUSE_AFTER:
02456 //    case CSS_PROP_PAUSE_BEFORE:
02457         break;
02458 
02459     case CSS_PROP_POSITION:
02460     {
02461         HANDLE_INHERIT_AND_INITIAL(position, Position)
02462         if (!primitiveValue) return;
02463         EPosition p;
02464         switch(primitiveValue->getIdent())
02465         {
02466         case CSS_VAL_STATIC:
02467             p = STATIC; break;
02468         case CSS_VAL_RELATIVE:
02469             p = RELATIVE; break;
02470         case CSS_VAL_ABSOLUTE:
02471             p = ABSOLUTE; break;
02472         case CSS_VAL_FIXED:
02473             {
02474                 view->useSlowRepaints();
02475                 p = FIXED;
02476                 break;
02477             }
02478         default:
02479             return;
02480         }
02481         style->setPosition(p);
02482         return;
02483     }
02484 
02485     case CSS_PROP_TABLE_LAYOUT: {
02486         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
02487 
02488     if ( !primitiveValue )
02489         return;
02490 
02491     ETableLayout l = RenderStyle::initialTableLayout();
02492     switch( primitiveValue->getIdent() ) {
02493     case CSS_VAL_FIXED:
02494         l = TFIXED;
02495         // fall through
02496     case CSS_VAL_AUTO:
02497         style->setTableLayout( l );
02498     default:
02499         break;
02500     }
02501     break;
02502     }
02503 
02504     case CSS_PROP_UNICODE_BIDI: {
02505         HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
02506         if(!primitiveValue) break;
02507         switch (primitiveValue->getIdent()) {
02508             case CSS_VAL_NORMAL:
02509                 style->setUnicodeBidi(UBNormal);
02510                 break;
02511             case CSS_VAL_EMBED:
02512                 style->setUnicodeBidi(Embed);
02513                 break;
02514             case CSS_VAL_BIDI_OVERRIDE:
02515                 style->setUnicodeBidi(Override);
02516                 break;
02517             default:
02518                 return;
02519         }
02520     break;
02521     }
02522     case CSS_PROP_TEXT_TRANSFORM: {
02523         HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
02524 
02525         if(!primitiveValue) break;
02526         if(!primitiveValue->getIdent()) return;
02527 
02528         ETextTransform tt;
02529         switch(primitiveValue->getIdent()) {
02530         case CSS_VAL_CAPITALIZE:  tt = CAPITALIZE;  break;
02531         case CSS_VAL_UPPERCASE:   tt = UPPERCASE;   break;
02532         case CSS_VAL_LOWERCASE:   tt = LOWERCASE;   break;
02533         case CSS_VAL_NONE:
02534         default:                  tt = TTNONE;      break;
02535         }
02536         style->setTextTransform(tt);
02537         break;
02538         }
02539 
02540     case CSS_PROP_VISIBILITY:
02541     {
02542         HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
02543 
02544         if(!primitiveValue) break;
02545         switch( primitiveValue->getIdent() ) {
02546         case CSS_VAL_HIDDEN:
02547             style->setVisibility( HIDDEN );
02548             break;
02549         case CSS_VAL_VISIBLE:
02550             style->setVisibility( VISIBLE );
02551             break;
02552         case CSS_VAL_COLLAPSE:
02553             style->setVisibility( COLLAPSE );
02554         default:
02555             break;
02556         }
02557         break;
02558     }
02559     case CSS_PROP_WHITE_SPACE:
02560         HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
02561 
02562         if(!primitiveValue) break;
02563         if(!primitiveValue->getIdent()) return;
02564 
02565         EWhiteSpace s;
02566         switch(primitiveValue->getIdent()) {
02567         case CSS_VAL__KHTML_NOWRAP:
02568             s = KHTML_NOWRAP;
02569             break;
02570         case CSS_VAL_NOWRAP:
02571             s = NOWRAP;
02572             break;
02573         case CSS_VAL_PRE:
02574             s = PRE;
02575             break;
02576         case CSS_VAL_PRE_WRAP:
02577             s = PRE_WRAP;
02578             break;
02579         case CSS_VAL_PRE_LINE:
02580             s = PRE_LINE;
02581             break;
02582         case CSS_VAL_NORMAL:
02583         default:
02584             s = NORMAL;
02585             break;
02586         }
02587         style->setWhiteSpace(s);
02588         break;
02589 
02590     case CSS_PROP_BACKGROUND_POSITION:
02591         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
02592         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
02593         break;
02594     case CSS_PROP_BACKGROUND_POSITION_X: {
02595         HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
02596         break;
02597     }
02598     case CSS_PROP_BACKGROUND_POSITION_Y: {
02599         HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
02600         break;
02601     }
02602     case CSS_PROP_BORDER_SPACING: {
02603         if(value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return;
02604         style->setBorderHorizontalSpacing(parentStyle->borderHorizontalSpacing());
02605         style->setBorderVerticalSpacing(parentStyle->borderVerticalSpacing());
02606         break;
02607     }
02608     case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: {
02609         HANDLE_INHERIT_AND_INITIAL(borderHorizontalSpacing, BorderHorizontalSpacing)
02610         if (!primitiveValue) break;
02611         short spacing =  primitiveValue->computeLength(style, paintDeviceMetrics);
02612         style->setBorderHorizontalSpacing(spacing);
02613         break;
02614     }
02615     case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: {
02616         HANDLE_INHERIT_AND_INITIAL(borderVerticalSpacing, BorderVerticalSpacing)
02617         if (!primitiveValue) break;
02618         short spacing =  primitiveValue->computeLength(style, paintDeviceMetrics);
02619         style->setBorderVerticalSpacing(spacing);
02620         break;
02621     }
02622 
02623     case CSS_PROP_CURSOR:
02624         HANDLE_INHERIT_AND_INITIAL(cursor, Cursor)
02625         if(primitiveValue)
02626         style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) );
02627         break;
02628 // colors || inherit
02629     case CSS_PROP_BACKGROUND_COLOR:
02630     case CSS_PROP_BORDER_TOP_COLOR:
02631     case CSS_PROP_BORDER_RIGHT_COLOR:
02632     case CSS_PROP_BORDER_BOTTOM_COLOR:
02633     case CSS_PROP_BORDER_LEFT_COLOR:
02634     case CSS_PROP_COLOR:
02635     case CSS_PROP_OUTLINE_COLOR:
02636         // this property is an extension used to get HTML4 <font> right.
02637     case CSS_PROP_SCROLLBAR_BASE_COLOR:
02638     case CSS_PROP_SCROLLBAR_FACE_COLOR:
02639     case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
02640     case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
02641     case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
02642     case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
02643     case CSS_PROP_SCROLLBAR_TRACK_COLOR:
02644     case CSS_PROP_SCROLLBAR_ARROW_COLOR:
02645     {
02646         QColor col;
02647         if (isInherit) {
02648             HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
02649             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
02650             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
02651             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
02652             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
02653             HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
02654             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
02655             return;
02656         } else if (isInitial) {
02657             // The border/outline colors will just map to the invalid color |col| above.  This will have the
02658             // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
02659             // not painting the background since the color won't be valid).
02660             if (id == CSS_PROP_COLOR)
02661                 col = RenderStyle::initialColor();
02662         } else {
02663         if(!primitiveValue )
02664         return;
02665         int ident = primitiveValue->getIdent();
02666         if ( ident ) {
02667         if ( ident == CSS_VAL__KHTML_TEXT )
02668             col = element->getDocument()->textColor();
02669         // ### should be eliminated
02670         else if ( ident == CSS_VAL_TRANSPARENT
02671                     && id != CSS_PROP_BORDER_TOP_COLOR
02672                         && id != CSS_PROP_BORDER_RIGHT_COLOR
02673                 && id != CSS_PROP_BORDER_BOTTOM_COLOR
02674                 && id != CSS_PROP_BORDER_LEFT_COLOR )
02675             col = QColor();
02676         else
02677             col = colorForCSSValue( ident );
02678         } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR ) {
02679 #ifndef APPLE_CHANGES
02680         if(qAlpha(primitiveValue->getRGBColorValue()))
02681 #endif
02682             col.setRgb(primitiveValue->getRGBColorValue());
02683         } else {
02684         return;
02685         }
02686     }
02687         //kdDebug( 6080 ) << "applying color " << col.isValid() << endl;
02688         switch(id)
02689         {
02690         case CSS_PROP_BACKGROUND_COLOR:
02691         style->setBackgroundColor(col); break;
02692         case CSS_PROP_BORDER_TOP_COLOR:
02693             style->setBorderTopColor(col); break;
02694         case CSS_PROP_BORDER_RIGHT_COLOR:
02695             style->setBorderRightColor(col); break;
02696         case CSS_PROP_BORDER_BOTTOM_COLOR:
02697             style->setBorderBottomColor(col); break;
02698         case CSS_PROP_BORDER_LEFT_COLOR:
02699             style->setBorderLeftColor(col); break;
02700         case CSS_PROP_COLOR:
02701             style->setColor(col); break;
02702         case CSS_PROP_OUTLINE_COLOR:
02703             style->setOutlineColor(col); break;
02704 #ifndef APPLE_CHANGES
02705         case CSS_PROP_SCROLLBAR_FACE_COLOR:
02706             style->setPaletteColor(QPalette::Active, QColorGroup::Button, col);
02707             style->setPaletteColor(QPalette::Inactive, QColorGroup::Button, col);
02708             break;
02709         case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
02710             style->setPaletteColor(QPalette::Active, QColorGroup::Shadow, col);
02711             style->setPaletteColor(QPalette::Inactive, QColorGroup::Shadow, col);
02712             break;
02713         case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
02714             style->setPaletteColor(QPalette::Active, QColorGroup::Light, col);
02715             style->setPaletteColor(QPalette::Inactive, QColorGroup::Light, col);
02716             break;
02717         case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
02718             break;
02719         case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
02720             style->setPaletteColor(QPalette::Active, QColorGroup::Dark, col);
02721             style->setPaletteColor(QPalette::Inactive, QColorGroup::Dark, col);
02722             break;
02723         case CSS_PROP_SCROLLBAR_TRACK_COLOR:
02724             style->setPaletteColor(QPalette::Active, QColorGroup::Mid, col);
02725             style->setPaletteColor(QPalette::Inactive, QColorGroup::Mid, col);
02726             style->setPaletteColor(QPalette::Active, QColorGroup::Background, col);
02727             style->setPaletteColor(QPalette::Inactive, QColorGroup::Background, col);
02728             // fall through
02729         case CSS_PROP_SCROLLBAR_BASE_COLOR:
02730             style->setPaletteColor(QPalette::Active, QColorGroup::Base, col);
02731             style->setPaletteColor(QPalette::Inactive, QColorGroup::Base, col);
02732             break;
02733         case CSS_PROP_SCROLLBAR_ARROW_COLOR:
02734             style->setPaletteColor(QPalette::Active, QColorGroup::ButtonText, col);
02735             style->setPaletteColor(QPalette::Inactive, QColorGroup::ButtonText, col);
02736             break;
02737 #endif
02738         default:
02739             return;
02740         }
02741         return;
02742     }
02743     break;
02744 // uri || inherit
02745     case CSS_PROP_BACKGROUND_IMAGE:
02746         HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
02747         break;
02748     case CSS_PROP_LIST_STYLE_IMAGE:
02749     {
02750         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
02751         if (!primitiveValue) return;
02752     style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image());
02753         //kdDebug( 6080 ) << "setting image in list to " << image->image() << endl;
02754         break;
02755     }
02756 
02757 // length
02758     case CSS_PROP_BORDER_TOP_WIDTH:
02759     case CSS_PROP_BORDER_RIGHT_WIDTH:
02760     case CSS_PROP_BORDER_BOTTOM_WIDTH:
02761     case CSS_PROP_BORDER_LEFT_WIDTH:
02762     case CSS_PROP_OUTLINE_WIDTH:
02763     {
02764     if (isInherit) {
02765             HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
02766             HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
02767             HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
02768             HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
02769             HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
02770             return;
02771         }
02772         else if (isInitial) {
02773             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
02774             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
02775             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
02776             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
02777             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
02778             return;
02779         }
02780 
02781         if(!primitiveValue) break;
02782         short width = 3;
02783         switch(primitiveValue->getIdent())
02784         {
02785         case CSS_VAL_THIN:
02786             width = 1;
02787             break;
02788         case CSS_VAL_MEDIUM:
02789             width = 3;
02790             break;
02791         case CSS_VAL_THICK:
02792             width = 5;
02793             break;
02794         case CSS_VAL_INVALID:
02795         {
02796             double widthd = primitiveValue->computeLengthFloat(style, paintDeviceMetrics);
02797             width = (int)widthd;
02798             // somewhat resemble Mozilla's granularity
02799             // this makes border-width: 0.5pt borders visible
02800             if (width == 0 && widthd >= 0.025) width++;
02801             break;
02802         }
02803         default:
02804             return;
02805         }
02806 
02807         if(width < 0) return;
02808         switch(id)
02809         {
02810         case CSS_PROP_BORDER_TOP_WIDTH:
02811             style->setBorderTopWidth(width);
02812             break;
02813         case CSS_PROP_BORDER_RIGHT_WIDTH:
02814             style->setBorderRightWidth(width);
02815             break;
02816         case CSS_PROP_BORDER_BOTTOM_WIDTH:
02817             style->setBorderBottomWidth(width);
02818             break;
02819         case CSS_PROP_BORDER_LEFT_WIDTH:
02820             style->setBorderLeftWidth(width);
02821             break;
02822         case CSS_PROP_OUTLINE_WIDTH:
02823             style->setOutlineWidth(width);
02824             break;
02825         default:
02826             return;
02827         }
02828         return;
02829     }
02830 
02831     case CSS_PROP_LETTER_SPACING:
02832     case CSS_PROP_WORD_SPACING:
02833     {
02834         if (isInherit) {
02835             HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
02836             HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
02837             return;
02838         } else if (isInitial) {
02839             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
02840             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
02841             return;
02842         }
02843         if(!primitiveValue) return;
02844 
02845         int width = 0;
02846         if (primitiveValue->getIdent() != CSS_VAL_NORMAL)
02847         width = primitiveValue->computeLength(style, paintDeviceMetrics);
02848 
02849         switch(id)
02850         {
02851         case CSS_PROP_LETTER_SPACING:
02852             style->setLetterSpacing(width);
02853             break;
02854         case CSS_PROP_WORD_SPACING:
02855             style->setWordSpacing(width);
02856             break;
02857             // ### needs the definitions in renderstyle
02858         default: break;
02859         }
02860         return;
02861     }
02862 
02863         // length, percent
02864     case CSS_PROP_MAX_WIDTH:
02865         // +none +inherit
02866         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
02867             apply = true;
02868     case CSS_PROP_TOP:
02869     case CSS_PROP_LEFT:
02870     case CSS_PROP_RIGHT:
02871     case CSS_PROP_BOTTOM:
02872     case CSS_PROP_WIDTH:
02873     case CSS_PROP_MIN_WIDTH:
02874     case CSS_PROP_MARGIN_TOP:
02875     case CSS_PROP_MARGIN_RIGHT:
02876     case CSS_PROP_MARGIN_BOTTOM:
02877     case CSS_PROP_MARGIN_LEFT:
02878         // +inherit +auto
02879         if(id != CSS_PROP_MAX_WIDTH && primitiveValue &&
02880            primitiveValue->getIdent() == CSS_VAL_AUTO)
02881         {
02882             //kdDebug( 6080 ) << "found value=auto" << endl;
02883             apply = true;
02884         }
02885     case CSS_PROP_PADDING_TOP:
02886     case CSS_PROP_PADDING_RIGHT:
02887     case CSS_PROP_PADDING_BOTTOM:
02888     case CSS_PROP_PADDING_LEFT:
02889     case CSS_PROP_TEXT_INDENT:
02890         // +inherit
02891     {
02892         if (isInherit) {
02893             HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
02894             HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
02895             HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
02896             HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
02897             HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
02898             HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
02899             HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
02900             HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
02901             HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
02902             HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
02903             HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
02904             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
02905             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
02906             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
02907             HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
02908             HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
02909             return;
02910         } else if (isInitial) {
02911             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
02912             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
02913             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
02914             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
02915             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
02916             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
02917             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
02918             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
02919             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
02920             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
02921             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
02922             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
02923             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
02924             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
02925             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
02926             HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
02927             return;
02928         }
02929 
02930         if (primitiveValue && !apply) {
02931             int type = primitiveValue->primitiveType();
02932             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
02933                 // Handle our quirky margin units if we have them.
02934                 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed,
02935                            primitiveValue->isQuirkValue());
02936             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
02937                 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
02938         else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
02939         l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
02940             else
02941                 return;
02942             apply = true;
02943         }
02944         if(!apply) return;
02945         switch(id)
02946             {
02947             case CSS_PROP_MAX_WIDTH:
02948                 style->setMaxWidth(l); break;
02949             case CSS_PROP_BOTTOM:
02950                 style->setBottom(l); break;
02951             case CSS_PROP_TOP:
02952                 style->setTop(l); break;
02953             case CSS_PROP_LEFT:
02954                 style->setLeft(l); break;
02955             case CSS_PROP_RIGHT:
02956                 style->setRight(l); break;
02957             case CSS_PROP_WIDTH:
02958                 style->setWidth(l); break;
02959             case CSS_PROP_MIN_WIDTH:
02960                 style->setMinWidth(l); break;
02961             case CSS_PROP_PADDING_TOP:
02962                 style->setPaddingTop(l); break;
02963             case CSS_PROP_PADDING_RIGHT:
02964                 style->setPaddingRight(l); break;
02965             case CSS_PROP_PADDING_BOTTOM:
02966                 style->setPaddingBottom(l); break;
02967             case CSS_PROP_PADDING_LEFT:
02968                 style->setPaddingLeft(l); break;
02969             case CSS_PROP_MARGIN_TOP:
02970                 style->setMarginTop(l); break;
02971             case CSS_PROP_MARGIN_RIGHT:
02972                 style->setMarginRight(l); break;
02973             case CSS_PROP_MARGIN_BOTTOM:
02974                 style->setMarginBottom(l); break;
02975             case CSS_PROP_MARGIN_LEFT:
02976                 style->setMarginLeft(l); break;
02977             case CSS_PROP_TEXT_INDENT:
02978                 style->setTextIndent(l); break;
02979             default: break;
02980             }
02981         return;
02982     }
02983 
02984     case CSS_PROP_MAX_HEIGHT:
02985         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
02986             apply = true;
02987     case CSS_PROP_HEIGHT:
02988     case CSS_PROP_MIN_HEIGHT:
02989         if(id != CSS_PROP_MAX_HEIGHT && primitiveValue &&
02990            primitiveValue->getIdent() == CSS_VAL_AUTO)
02991             apply = true;
02992         if (isInherit) {
02993             HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
02994             HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
02995             HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
02996             return;
02997         }
02998         else if (isInitial) {
02999             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
03000             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
03001             HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
03002             return;
03003         }
03004 
03005         if (primitiveValue && !apply)
03006         {
03007             int type = primitiveValue->primitiveType();
03008             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
03009                 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
03010             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
03011                 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
03012             else
03013                 return;
03014             apply = true;
03015         }
03016         if(!apply) return;
03017         switch(id)
03018         {
03019         case CSS_PROP_MAX_HEIGHT:
03020             style->setMaxHeight(l); break;
03021         case CSS_PROP_HEIGHT:
03022             style->setHeight(l); break;
03023         case CSS_PROP_MIN_HEIGHT:
03024             style->setMinHeight(l); break;
03025         default:
03026             return;
03027         }
03028         return;
03029 
03030         break;
03031 
03032     case CSS_PROP_VERTICAL_ALIGN:
03033         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
03034         if (!primitiveValue) return;
03035         if (primitiveValue->getIdent()) {
03036       khtml::EVerticalAlign align;
03037 
03038       switch(primitiveValue->getIdent())
03039         {
03040         case CSS_VAL_TOP:
03041             align = TOP; break;
03042         case CSS_VAL_BOTTOM:
03043             align = BOTTOM; break;
03044         case CSS_VAL_MIDDLE:
03045             align = MIDDLE; break;
03046         case CSS_VAL_BASELINE:
03047             align = BASELINE; break;
03048         case CSS_VAL_TEXT_BOTTOM:
03049             align = TEXT_BOTTOM; break;
03050         case CSS_VAL_TEXT_TOP:
03051             align = TEXT_TOP; break;
03052         case CSS_VAL_SUB:
03053             align = SUB; break;
03054         case CSS_VAL_SUPER:
03055             align = SUPER; break;
03056         case CSS_VAL__KHTML_BASELINE_MIDDLE:
03057             align = BASELINE_MIDDLE; break;
03058         default:
03059             return;
03060         }
03061       style->setVerticalAlign(align);
03062       return;
03063         } else {
03064       int type = primitiveValue->primitiveType();
03065       Length l;
03066       if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
03067         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
03068       else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
03069         l = Length( int( primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent );
03070 
03071       style->setVerticalAlign( LENGTH );
03072       style->setVerticalAlignLength( l );
03073     }
03074         break;
03075 
03076     case CSS_PROP_FONT_SIZE:
03077     {
03078         FontDef fontDef = style->htmlFont().fontDef;
03079         int oldSize;
03080         int size = 0;
03081 
03082     float toPix = paintDeviceMetrics->logicalDpiY()/72.;
03083     if (toPix  < 96./72.) toPix = 96./72.;
03084 
03085         int minFontSize = int(settings->minFontSize() * toPix);
03086 
03087         if(parentNode) {
03088             oldSize = parentStyle->font().pixelSize();
03089         } else
03090             oldSize = m_fontSizes[3];
03091 
03092         if (isInherit )
03093             size = oldSize;
03094         else if (isInitial)
03095             size = m_fontSizes[3];
03096         else if(primitiveValue->getIdent()) {
03097         // keywords are being used.  Pick the correct default
03098         // based off the font family.
03099 #ifdef APPLE_CHANGES
03100         const QValueVector<int>& fontSizes = (fontDef.genericFamily == FontDef::eMonospace) ?
03101                      m_fixedFontSizes : m_fontSizes;
03102 #else
03103         const QValueVector<int>& fontSizes = m_fontSizes;
03104 #endif
03105             switch(primitiveValue->getIdent())
03106             {
03107             case CSS_VAL_XX_SMALL: size = int( fontSizes[0] ); break;
03108             case CSS_VAL_X_SMALL:  size = int( fontSizes[1] ); break;
03109             case CSS_VAL_SMALL:    size = int( fontSizes[2] ); break;
03110             case CSS_VAL_MEDIUM:   size = int( fontSizes[3] ); break;
03111             case CSS_VAL_LARGE:    size = int( fontSizes[4] ); break;
03112             case CSS_VAL_X_LARGE:  size = int( fontSizes[5] ); break;
03113             case CSS_VAL_XX_LARGE: size = int( fontSizes[6] ); break;
03114             case CSS_VAL__KHTML_XXX_LARGE: size = int( fontSizes[7] ); break;
03115             case CSS_VAL_LARGER:
03116                 size = nextFontSize(fontSizes, oldSize, false);
03117                 break;
03118             case CSS_VAL_SMALLER:
03119                 size = nextFontSize(fontSizes, oldSize, true);
03120                 break;
03121             default:
03122                 return;
03123             }
03124 
03125         } else {
03126             int type = primitiveValue->primitiveType();
03127             if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
03128                 if ( !khtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS &&
03129                      view && view->part())
03130                     size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) *
03131                                 view->part()->zoomFactor() ) / 100;
03132         else
03133                     size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) );
03134             }
03135             else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
03136                 size = int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)
03137                         * parentStyle->font().pixelSize()) / 100;
03138             else
03139                 return;
03140         }
03141 
03142         if (size < 0) return;
03143 
03144         // we never want to get smaller than the minimum font size to keep fonts readable
03145         // do not however maximize zero as that is commonly used for fancy layouting purposes
03146         if (size && size < minFontSize) size = minFontSize;
03147 
03148         //kdDebug( 6080 ) << "computed raw font size: " << size << endl;
03149 
03150     fontDef.size = size;
03151         fontDirty |= style->setFontDef( fontDef );
03152         return;
03153     }
03154 
03155     case CSS_PROP_Z_INDEX:
03156     {
03157         HANDLE_INHERIT(zIndex, ZIndex)
03158         else if (isInitial) {
03159             style->setHasAutoZIndex();
03160             return;
03161         }
03162 
03163         if (!primitiveValue)
03164             return;
03165 
03166         if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
03167             style->setHasAutoZIndex();
03168             return;
03169         }
03170 
03171         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03172             return; // Error case.
03173 
03174         style->setZIndex((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
03175         return;
03176     }
03177 
03178     case CSS_PROP_WIDOWS:
03179     {
03180         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
03181         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03182             return;
03183         style->setWidows((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
03184         break;
03185      }
03186 
03187     case CSS_PROP_ORPHANS:
03188     {
03189         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
03190         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03191             return;
03192         style->setOrphans((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
03193         break;
03194     }
03195 
03196 // length, percent, number
03197     case CSS_PROP_LINE_HEIGHT:
03198     {
03199         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
03200         if(!primitiveValue) return;
03201         Length lineHeight;
03202         int type = primitiveValue->primitiveType();
03203         if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
03204             lineHeight = Length( -100, Percent );
03205         else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
03206             // Scale for the font zoom factor only for types other than "em" and "ex", since those are
03207             // already based on the font size.
03208         if ( !khtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS &&
03209                     view && view->part())
03210                     lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics) *
03211                                         view->part()->zoomFactor()/100, Fixed );
03212                 else
03213                     lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
03214         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
03215             lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed );
03216         else if (type == CSSPrimitiveValue::CSS_NUMBER)
03217             lineHeight = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
03218         else
03219             return;
03220         style->setLineHeight(lineHeight);
03221         return;
03222     }
03223 
03224 // string
03225     case CSS_PROP_TEXT_ALIGN:
03226     {
03227         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
03228         if (!primitiveValue) return;
03229         if (primitiveValue->getIdent())
03230             style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) );
03231     return;
03232     }
03233 
03234 // rect
03235     case CSS_PROP_CLIP:
03236     {
03237         Length top = Length();
03238         Length right = Length();
03239         Length bottom = Length();
03240         Length left = Length();
03241 
03242         bool hasClip = false;
03243 
03244         if (isInherit && parentStyle->hasClip()) {
03245             hasClip = true;
03246         top = parentStyle->clipTop();
03247         right = parentStyle->clipRight();
03248         bottom = parentStyle->clipBottom();
03249         left = parentStyle->clipLeft();
03250         } else if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
03251             RectImpl *rect = primitiveValue->getRectValue();
03252             if (rect) {
03253                 hasClip = true;
03254                 top = convertToLength( rect->top(), style, paintDeviceMetrics );
03255                 right = convertToLength( rect->right(), style, paintDeviceMetrics );
03256                 bottom = convertToLength( rect->bottom(), style, paintDeviceMetrics );
03257                 left = convertToLength( rect->left(), style, paintDeviceMetrics );
03258             }
03259         }
03260 
03261         style->setClip(top, right, bottom, left);
03262         style->setHasClip(hasClip);
03263 
03264         // rect, ident
03265         break;
03266     }
03267 
03268 // lists
03269     case CSS_PROP_CONTENT:
03270         // list of string, uri, counter, attr, i
03271     {
03272         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
03273         // note is a reminder that eventually "inherit" needs to be supported.
03274 
03275         // not allowed on non-generated pseudo-elements:
03276         if ( style->styleType()==RenderStyle::FIRST_LETTER ||
03277              style->styleType()==RenderStyle::FIRST_LINE ||
03278              style->styleType()==RenderStyle::SELECTION )
03279             break;
03280 
03281         if (isInitial) {
03282             style->setContentNormal();
03283             return;
03284         }
03285 
03286         if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
03287             // normal | none
03288             if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
03289                 style->setContentNormal();
03290             else
03291             if (primitiveValue->getIdent() == CSS_VAL_NONE)
03292                 style->setContentNone();
03293             else
03294                 assert(false);
03295             return;
03296         }
03297 
03298         if(!value->isValueList()) return;
03299         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03300         int len = list->length();
03301 
03302         style->setContentNormal(); // clear the content
03303 
03304         for(int i = 0; i < len; i++) {
03305             CSSValueImpl *item = list->item(i);
03306             if(!item->isPrimitiveValue()) continue;
03307             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
03308             if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
03309             {
03310                 style->addContent(val->getStringValue());
03311             }
03312             else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR)
03313             {
03314                 // TODO: setup dynamic attribute dependencies
03315                 int attrID = element->getDocument()->getId(NodeImpl::AttributeId, val->getStringValue(), false, true);
03316                 if (attrID)
03317                     style->addContent(element->getAttribute(attrID).implementation());
03318                 else
03319                     kdDebug(6080) << "Attribute \"" << val->getStringValue() << "\" not found" << endl;
03320             }
03321             else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI)
03322             {
03323                 CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val);
03324                 style->addContent(image->image());
03325             }
03326             else if (val->primitiveType()==CSSPrimitiveValue::CSS_COUNTER)
03327             {
03328                 style->addContent(val->getCounterValue());
03329             }
03330             else if (val->primitiveType()==CSSPrimitiveValue::CSS_IDENT)
03331             {
03332                 EQuoteContent quote;
03333                 switch (val->getIdent()) {
03334                     case CSS_VAL_OPEN_QUOTE:
03335                         quote = OPEN_QUOTE;
03336                         break;
03337                     case CSS_VAL_NO_OPEN_QUOTE:
03338                         quote = NO_OPEN_QUOTE;
03339                         break;
03340                     case CSS_VAL_CLOSE_QUOTE:
03341                         quote = CLOSE_QUOTE;
03342                         break;
03343                     case CSS_VAL_NO_CLOSE_QUOTE:
03344                         quote = NO_CLOSE_QUOTE;
03345                         break;
03346                     default:
03347                         assert(false);
03348                 }
03349                 style->addContent(quote);
03350             } else
03351                 kdDebug(6080) << "Unrecognized CSS content" << endl;
03352 
03353         }
03354         break;
03355     }
03356 
03357     case CSS_PROP_COUNTER_INCREMENT: {
03358         if(!value->isValueList()) return;
03359 
03360         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03361         style->setCounterIncrement(list);
03362         break;
03363     }
03364     case CSS_PROP_COUNTER_RESET: {
03365         if(!value->isValueList()) return;
03366 
03367         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03368         style->setCounterReset(list);
03369         break;
03370     }
03371     case CSS_PROP_FONT_FAMILY:
03372         // list of strings and ids
03373     {
03374         if (isInherit) {
03375             FontDef parentFontDef = parentStyle->htmlFont().fontDef;
03376             FontDef fontDef = style->htmlFont().fontDef;
03377             fontDef.family = parentFontDef.family;
03378             if (style->setFontDef(fontDef))
03379                 fontDirty = true;
03380             return;
03381         }
03382         else if (isInitial) {
03383             FontDef fontDef = style->htmlFont().fontDef;
03384             FontDef initialDef = FontDef();
03385 #ifdef APPLE_CHANGES
03386             fontDef.family = initialDef.firstFamily();
03387 #else
03388             fontDef.family = QString::null;
03389 #endif
03390             if (style->setFontDef(fontDef))
03391                 fontDirty = true;
03392             return;
03393         }
03394         if(!value->isValueList()) return;
03395     FontDef fontDef = style->htmlFont().fontDef;
03396         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03397         int len = list->length();
03398         for(int i = 0; i < len; i++) {
03399             CSSValueImpl *item = list->item(i);
03400             if(!item->isPrimitiveValue()) continue;
03401             CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
03402         QString face;
03403             if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING )
03404         face = static_cast<FontFamilyValueImpl *>(val)->fontName();
03405         else if ( val->primitiveType() == CSSPrimitiveValue::CSS_IDENT ) {
03406         switch( val->getIdent() ) {
03407         case CSS_VAL_SERIF:
03408             face = settings->serifFontName();
03409             break;
03410         case CSS_VAL_SANS_SERIF:
03411             face = settings->sansSerifFontName();
03412             break;
03413         case CSS_VAL_CURSIVE:
03414             face = settings->cursiveFontName();
03415             break;
03416         case CSS_VAL_FANTASY:
03417             face = settings->fantasyFontName();
03418             break;
03419         case CSS_VAL_MONOSPACE:
03420             face = settings->fixedFontName();
03421             break;
03422         default:
03423             return;
03424         }
03425         } else {
03426         return;
03427         }
03428         if ( !face.isEmpty() ) {
03429         fontDef.family = face;
03430         fontDirty |= style->setFontDef( fontDef );
03431                 return;
03432         }
03433     }
03434         break;
03435     }
03436     case CSS_PROP_QUOTES:
03437         HANDLE_INHERIT_AND_INITIAL(quotes, Quotes)
03438         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
03439             // set a set of empty quotes
03440             QuotesValueImpl* quotes = new QuotesValueImpl();
03441             style->setQuotes(quotes);
03442         } else {
03443             QuotesValueImpl* quotes = static_cast<QuotesValueImpl *>(value);
03444             style->setQuotes(quotes);
03445         }
03446         break;
03447     case CSS_PROP_SIZE:
03448         // ### look up
03449       break;
03450     case CSS_PROP_TEXT_DECORATION: {
03451         // list of ident
03452         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
03453         int t = RenderStyle::initialTextDecoration();
03454         if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
03455         // do nothing
03456     } else {
03457         if(!value->isValueList()) return;
03458         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03459         int len = list->length();
03460         for(int i = 0; i < len; i++)
03461         {
03462         CSSValueImpl *item = list->item(i);
03463         if(!item->isPrimitiveValue()) continue;
03464         primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item);
03465         switch(primitiveValue->getIdent())
03466         {
03467             case CSS_VAL_NONE:
03468             t = TDNONE; break;
03469             case CSS_VAL_UNDERLINE:
03470             t |= UNDERLINE; break;
03471             case CSS_VAL_OVERLINE:
03472             t |= OVERLINE; break;
03473             case CSS_VAL_LINE_THROUGH:
03474             t |= LINE_THROUGH; break;
03475             case CSS_VAL_BLINK:
03476             t |= BLINK; break;
03477             default:
03478             return;
03479         }
03480         }
03481         }
03482     style->setTextDecoration(t);
03483         break;
03484     }
03485     case CSS_PROP__KHTML_FLOW_MODE:
03486         HANDLE_INHERIT_AND_INITIAL(flowAroundFloats, FlowAroundFloats)
03487         if (!primitiveValue) return;
03488         if (primitiveValue->getIdent()) {
03489             style->setFlowAroundFloats( primitiveValue->getIdent() == CSS_VAL__KHTML_AROUND_FLOATS );
03490             return;
03491         }
03492         break;
03493     case CSS_PROP__KHTML_USER_INPUT: {
03494         if(value->cssValueType() == CSSValue::CSS_INHERIT)
03495         {
03496             if(!parentNode) return;
03497             style->setUserInput(parentStyle->userInput());
03498 //      kdDebug() << "UI erm" << endl;
03499             return;
03500         }
03501         if(!primitiveValue) return;
03502         int id = primitiveValue->getIdent();
03503     if (id == CSS_VAL_NONE)
03504         style->setUserInput(UI_NONE);
03505     else
03506         style->setUserInput(EUserInput(id - CSS_VAL_ENABLED));
03507 //  kdDebug(6080) << "userInput: " << style->userEdit() << endl;
03508     return;
03509     }
03510 
03511 // shorthand properties
03512     case CSS_PROP_BACKGROUND:
03513         if (isInitial) {
03514             style->clearBackgroundLayers();
03515             return;
03516         }
03517         else if (isInherit) {
03518             if (parentStyle)
03519                 style->inheritBackgroundLayers(*parentStyle->backgroundLayers());
03520             else
03521                 style->clearBackgroundLayers();
03522             return;
03523         }
03524         break;
03525     case CSS_PROP_BORDER:
03526     case CSS_PROP_BORDER_STYLE:
03527     case CSS_PROP_BORDER_WIDTH:
03528     case CSS_PROP_BORDER_COLOR:
03529         if(id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
03530         {
03531              if (isInherit) {
03532                 style->setBorderTopColor(parentStyle->borderTopColor());
03533                 style->setBorderBottomColor(parentStyle->borderBottomColor());
03534                 style->setBorderLeftColor(parentStyle->borderLeftColor());
03535                 style->setBorderRightColor(parentStyle->borderRightColor());
03536             }
03537             else if (isInitial) {
03538                 style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead.
03539                 style->setBorderBottomColor(QColor());
03540                 style->setBorderLeftColor(QColor());
03541                 style->setBorderRightColor(QColor());
03542             }
03543         }
03544         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
03545         {
03546             if (isInherit) {
03547                 style->setBorderTopStyle(parentStyle->borderTopStyle());
03548                 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
03549                 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
03550                 style->setBorderRightStyle(parentStyle->borderRightStyle());
03551             }
03552             else if (isInitial) {
03553                 style->setBorderTopStyle(RenderStyle::initialBorderStyle());
03554                 style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
03555                 style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
03556                 style->setBorderRightStyle(RenderStyle::initialBorderStyle());
03557             }
03558         }
03559         if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH)
03560         {
03561             if (isInherit) {
03562                 style->setBorderTopWidth(parentStyle->borderTopWidth());
03563                 style->setBorderBottomWidth(parentStyle->borderBottomWidth());
03564                 style->setBorderLeftWidth(parentStyle->borderLeftWidth());
03565                 style->setBorderRightWidth(parentStyle->borderRightWidth());
03566             }
03567             else if (isInitial) {
03568                 style->setBorderTopWidth(RenderStyle::initialBorderWidth());
03569                 style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
03570                 style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
03571                 style->setBorderRightWidth(RenderStyle::initialBorderWidth());
03572             }
03573         }
03574         return;
03575     case CSS_PROP_BORDER_TOP:
03576         if ( isInherit ) {
03577             style->setBorderTopColor(parentStyle->borderTopColor());
03578             style->setBorderTopStyle(parentStyle->borderTopStyle());
03579             style->setBorderTopWidth(parentStyle->borderTopWidth());
03580         } else if (isInitial)
03581             style->resetBorderTop();
03582         return;
03583     case CSS_PROP_BORDER_RIGHT:
03584         if (isInherit) {
03585             style->setBorderRightColor(parentStyle->borderRightColor());
03586             style->setBorderRightStyle(parentStyle->borderRightStyle());
03587             style->setBorderRightWidth(parentStyle->borderRightWidth());
03588         }
03589         else if (isInitial)
03590             style->resetBorderRight();
03591         return;
03592     case CSS_PROP_BORDER_BOTTOM:
03593         if (isInherit) {
03594             style->setBorderBottomColor(parentStyle->borderBottomColor());
03595             style->setBorderBottomStyle(parentStyle->borderBottomStyle());
03596             style->setBorderBottomWidth(parentStyle->borderBottomWidth());
03597         }
03598         else if (isInitial)
03599             style->resetBorderBottom();
03600         return;
03601     case CSS_PROP_BORDER_LEFT:
03602         if (isInherit) {
03603             style->setBorderLeftColor(parentStyle->borderLeftColor());
03604             style->setBorderLeftStyle(parentStyle->borderLeftStyle());
03605             style->setBorderLeftWidth(parentStyle->borderLeftWidth());
03606         }
03607         else if (isInitial)
03608             style->resetBorderLeft();
03609         return;
03610     case CSS_PROP_MARGIN:
03611         if (isInherit) {
03612             style->setMarginTop(parentStyle->marginTop());
03613             style->setMarginBottom(parentStyle->marginBottom());
03614             style->setMarginLeft(parentStyle->marginLeft());
03615             style->setMarginRight(parentStyle->marginRight());
03616         }
03617         else if (isInitial)
03618             style->resetMargin();
03619         return;
03620     case CSS_PROP_PADDING:
03621         if (isInherit) {
03622             style->setPaddingTop(parentStyle->paddingTop());
03623             style->setPaddingBottom(parentStyle->paddingBottom());
03624             style->setPaddingLeft(parentStyle->paddingLeft());
03625             style->setPaddingRight(parentStyle->paddingRight());
03626         }
03627         else if (isInitial)
03628             style->resetPadding();
03629         return;
03630     case CSS_PROP_FONT:
03631         if ( isInherit ) {
03632             FontDef fontDef = parentStyle->htmlFont().fontDef;
03633         style->setLineHeight( parentStyle->lineHeight() );
03634         fontDirty |= style->setFontDef( fontDef );
03635         } else if (isInitial) {
03636             FontDef fontDef;
03637             style->setLineHeight(RenderStyle::initialLineHeight());
03638             if (style->setFontDef( fontDef ))
03639                 fontDirty = true;
03640     } else if ( value->isFontValue() ) {
03641         FontValueImpl *font = static_cast<FontValueImpl *>(value);
03642         if ( !font->style || !font->variant || !font->weight ||
03643          !font->size || !font->lineHeight || !font->family )
03644         return;
03645         applyRule( CSS_PROP_FONT_STYLE, font->style );
03646         applyRule( CSS_PROP_FONT_VARIANT, font->variant );
03647         applyRule( CSS_PROP_FONT_WEIGHT, font->weight );
03648         applyRule( CSS_PROP_FONT_SIZE, font->size );
03649 
03650             // Line-height can depend on font().pixelSize(), so we have to update the font
03651             // before we evaluate line-height, e.g., font: 1em/1em.  FIXME: Still not
03652             // good enough: style="font:1em/1em; font-size:36px" should have a line-height of 36px.
03653             if (fontDirty)
03654                 CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
03655 
03656         applyRule( CSS_PROP_LINE_HEIGHT, font->lineHeight );
03657         applyRule( CSS_PROP_FONT_FAMILY, font->family );
03658     }
03659     return;
03660 
03661     case CSS_PROP_LIST_STYLE:
03662         if (isInherit) {
03663             style->setListStyleType(parentStyle->listStyleType());
03664             style->setListStyleImage(parentStyle->listStyleImage());
03665             style->setListStylePosition(parentStyle->listStylePosition());
03666         }
03667         else if (isInitial) {
03668             style->setListStyleType(RenderStyle::initialListStyleType());
03669             style->setListStyleImage(RenderStyle::initialListStyleImage());
03670             style->setListStylePosition(RenderStyle::initialListStylePosition());
03671         }
03672         break;
03673     case CSS_PROP_OUTLINE:
03674         if (isInherit) {
03675             style->setOutlineWidth(parentStyle->outlineWidth());
03676             style->setOutlineColor(parentStyle->outlineColor());
03677             style->setOutlineStyle(parentStyle->outlineStyle());
03678         }
03679         else if (isInitial)
03680             style->resetOutline();
03681         break;
03682     /* CSS3 properties */
03683     case CSS_PROP_BOX_SIZING:
03684         HANDLE_INHERIT(boxSizing, BoxSizing)
03685         if (!primitiveValue) return;
03686         if (primitiveValue->getIdent() == CSS_VAL_CONTENT_BOX)
03687             style->setBoxSizing(CONTENT_BOX);
03688         else
03689         if (primitiveValue->getIdent() == CSS_VAL_BORDER_BOX)
03690             style->setBoxSizing(BORDER_BOX);
03691         break;
03692     case CSS_PROP_OUTLINE_OFFSET: {
03693         HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
03694 
03695         int offset = primitiveValue->computeLength(style, paintDeviceMetrics);
03696         if (offset < 0) return;
03697 
03698         style->setOutlineOffset(offset);
03699         break;
03700     }
03701     case CSS_PROP_TEXT_SHADOW: {
03702         if (isInherit) {
03703             style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : 0);
03704             return;
03705         }
03706         else if (isInitial) {
03707             style->setTextShadow(0);
03708             return;
03709         }
03710 
03711         if (primitiveValue) { // none
03712             style->setTextShadow(0);
03713             return;
03714         }
03715 
03716         if (!value->isValueList()) return;
03717         CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
03718         int len = list->length();
03719         for (int i = 0; i < len; i++) {
03720             ShadowValueImpl *item = static_cast<ShadowValueImpl*>(list->item(i));
03721 
03722             int x = item->x->computeLength(style, paintDeviceMetrics);
03723             int y = item->y->computeLength(style, paintDeviceMetrics);
03724             int blur = item->blur ? item->blur->computeLength(style, paintDeviceMetrics) : 0;
03725             QColor col = khtml::transparentColor;
03726             if (item->color) {
03727                 int ident = item->color->getIdent();
03728                 if (ident)
03729                     col = colorForCSSValue( ident );
03730                 else if (item->color->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
03731                     col.setRgb(item->color->getRGBColorValue());
03732             }
03733             ShadowData* shadowData = new ShadowData(x, y, blur, col);
03734             style->setTextShadow(shadowData, i != 0);
03735         }
03736 
03737         break;
03738     }
03739     case CSS_PROP_OPACITY:
03740         HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
03741         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
03742             return; // Error case.
03743 
03744         // Clamp opacity to the range 0-1
03745         style->setOpacity(kMin(1.0f, kMax(0.0f, (float)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))));
03746         break;
03747     case CSS_PROP__KHTML_MARQUEE:
03748         if (value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return;
03749         style->setMarqueeDirection(parentStyle->marqueeDirection());
03750         style->setMarqueeIncrement(parentStyle->marqueeIncrement());
03751         style->setMarqueeSpeed(parentStyle->marqueeSpeed());
03752         style->setMarqueeLoopCount(parentStyle->marqueeLoopCount());
03753         style->setMarqueeBehavior(parentStyle->marqueeBehavior());
03754         break;
03755     case CSS_PROP__KHTML_MARQUEE_REPETITION: {
03756         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
03757         if (!primitiveValue) return;
03758         if (primitiveValue->getIdent() == CSS_VAL_INFINITE)
03759             style->setMarqueeLoopCount(-1); // -1 means repeat forever.
03760         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
03761             style->setMarqueeLoopCount((int)(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
03762         break;
03763     }
03764     case CSS_PROP__KHTML_MARQUEE_SPEED: {
03765         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
03766         if (!primitiveValue) return;
03767         if (primitiveValue->getIdent()) {
03768             switch (primitiveValue->getIdent())
03769             {
03770                 case CSS_VAL_SLOW:
03771                     style->setMarqueeSpeed(500); // 500 msec.
03772                     break;
03773                 case CSS_VAL_NORMAL:
03774                     style->setMarqueeSpeed(85); // 85msec. The WinIE default.
03775                     break;
03776                 case CSS_VAL_FAST:
03777                     style->setMarqueeSpeed(10); // 10msec. Super fast.
03778                     break;
03779             }
03780         }
03781         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
03782             style->setMarqueeSpeed(int(1000*primitiveValue->floatValue(CSSPrimitiveValue::CSS_S)));
03783         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
03784             style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_MS)));
03785         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
03786             style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
03787         break;
03788     }
03789     case CSS_PROP__KHTML_MARQUEE_INCREMENT: {
03790         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
03791         if (!primitiveValue) return;
03792         if (primitiveValue->getIdent()) {
03793             switch (primitiveValue->getIdent())
03794             {
03795                 case CSS_VAL_SMALL:
03796                     style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
03797                     break;
03798                 case CSS_VAL_NORMAL:
03799                     style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
03800                     break;
03801                 case CSS_VAL_LARGE:
03802                     style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
03803                     break;
03804             }
03805         }
03806         else {
03807             bool ok = true;
03808             Length l = convertToLength(primitiveValue, style, paintDeviceMetrics, &ok);
03809             if (ok)
03810                 style->setMarqueeIncrement(l);
03811         }
03812         break;
03813     }
03814     case CSS_PROP__KHTML_MARQUEE_STYLE: {
03815         HANDLE_INHERIT_AND_INITIAL(marqueeBehavior, MarqueeBehavior)
03816         if (!primitiveValue || !primitiveValue->getIdent()) return;
03817         switch (primitiveValue->getIdent())
03818         {
03819             case CSS_VAL_NONE:
03820                 style->setMarqueeBehavior(MNONE);
03821                 break;
03822             case CSS_VAL_SCROLL:
03823                 style->setMarqueeBehavior(MSCROLL);
03824                 break;
03825             case CSS_VAL_SLIDE:
03826                 style->setMarqueeBehavior(MSLIDE);
03827                 break;
03828             case CSS_VAL_ALTERNATE:
03829                 style->setMarqueeBehavior(MALTERNATE);
03830                 break;
03831             case CSS_VAL_UNFURL:
03832                 style->setMarqueeBehavior(MUNFURL);
03833                 break;
03834         }
03835         break;
03836     }
03837     case CSS_PROP__KHTML_MARQUEE_DIRECTION: {
03838         HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection)
03839         if (!primitiveValue || !primitiveValue->getIdent()) return;
03840         switch (primitiveValue->getIdent())
03841         {
03842             case CSS_VAL_FORWARDS:
03843                 style->setMarqueeDirection(MFORWARD);
03844                 break;
03845             case CSS_VAL_BACKWARDS:
03846                 style->setMarqueeDirection(MBACKWARD);
03847                 break;
03848             case CSS_VAL_AUTO:
03849                 style->setMarqueeDirection(MAUTO);
03850                 break;
03851             case CSS_VAL_AHEAD:
03852             case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP.
03853                 style->setMarqueeDirection(MUP);
03854                 break;
03855             case CSS_VAL_REVERSE:
03856             case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text.
03857                 style->setMarqueeDirection(MDOWN);
03858                 break;
03859             case CSS_VAL_LEFT:
03860                 style->setMarqueeDirection(MLEFT);
03861                 break;
03862             case CSS_VAL_RIGHT:
03863                 style->setMarqueeDirection(MRIGHT);
03864                 break;
03865         }
03866         break;
03867     }
03868     default:
03869         return;
03870     }
03871 }
03872 
03873 void CSSStyleSelector::mapBackgroundAttachment(BackgroundLayer* layer, DOM::CSSValueImpl* value)
03874 {
03875     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03876         layer->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment());
03877         return;
03878     }
03879 
03880     if (!value->isPrimitiveValue()) return;
03881     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03882     switch (primitiveValue->getIdent()) {
03883         case CSS_VAL_FIXED:
03884             layer->setBackgroundAttachment(false);
03885             break;
03886         case CSS_VAL_SCROLL:
03887             layer->setBackgroundAttachment(true);
03888             break;
03889         default:
03890             return;
03891     }
03892 }
03893 
03894 void CSSStyleSelector::mapBackgroundClip(BackgroundLayer* layer, CSSValueImpl* value)
03895 {
03896     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03897         layer->setBackgroundClip(RenderStyle::initialBackgroundClip());
03898         return;
03899     }
03900 
03901     if (!value->isPrimitiveValue()) return;
03902     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03903     switch (primitiveValue->getIdent()) {
03904         case CSS_VAL_BORDER:
03905             layer->setBackgroundClip(BGBORDER);
03906             break;
03907         case CSS_VAL_PADDING:
03908             layer->setBackgroundClip(BGPADDING);
03909             break;
03910         default: // CSS_VAL_CONTENT
03911             layer->setBackgroundClip(BGCONTENT);
03912             break;
03913     }
03914 }
03915 
03916 void CSSStyleSelector::mapBackgroundOrigin(BackgroundLayer* layer, CSSValueImpl* value)
03917 {
03918     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03919         layer->setBackgroundOrigin(RenderStyle::initialBackgroundOrigin());
03920         return;
03921     }
03922 
03923     if (!value->isPrimitiveValue()) return;
03924     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03925     switch (primitiveValue->getIdent()) {
03926         case CSS_VAL_BORDER:
03927             layer->setBackgroundOrigin(BGBORDER);
03928             break;
03929         case CSS_VAL_PADDING:
03930             layer->setBackgroundOrigin(BGPADDING);
03931             break;
03932         default: // CSS_VAL_CONTENT
03933             layer->setBackgroundOrigin(BGCONTENT);
03934             break;
03935     }
03936 }
03937 
03938 void CSSStyleSelector::mapBackgroundImage(BackgroundLayer* layer, DOM::CSSValueImpl* value)
03939 {
03940     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03941         layer->setBackgroundImage(RenderStyle::initialBackgroundImage());
03942         return;
03943     }
03944 
03945     if (!value->isPrimitiveValue()) return;
03946     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03947     layer->setBackgroundImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image());
03948 }
03949 
03950 void CSSStyleSelector::mapBackgroundRepeat(BackgroundLayer* layer, DOM::CSSValueImpl* value)
03951 {
03952     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03953         layer->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat());
03954         return;
03955     }
03956 
03957     if (!value->isPrimitiveValue()) return;
03958     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03959     switch(primitiveValue->getIdent()) {
03960     case CSS_VAL_REPEAT:
03961         layer->setBackgroundRepeat(REPEAT);
03962         break;
03963     case CSS_VAL_REPEAT_X:
03964         layer->setBackgroundRepeat(REPEAT_X);
03965         break;
03966     case CSS_VAL_REPEAT_Y:
03967         layer->setBackgroundRepeat(REPEAT_Y);
03968         break;
03969     case CSS_VAL_NO_REPEAT:
03970         layer->setBackgroundRepeat(NO_REPEAT);
03971         break;
03972     default:
03973         return;
03974     }
03975 }
03976 
03977 
03978 void CSSStyleSelector::mapBackgroundSize(BackgroundLayer* layer, CSSValueImpl* value)
03979 {
03980     LengthSize b = RenderStyle::initialBackgroundSize();
03981 
03982     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
03983         layer->setBackgroundSize(b);
03984         return;
03985     }
03986 
03987     if (!value->isPrimitiveValue())
03988         return;
03989 
03990     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
03991     PairImpl* pair = primitiveValue->getPairValue();
03992     if (!pair)
03993         return;
03994 
03995     CSSPrimitiveValueImpl* first = static_cast<CSSPrimitiveValueImpl*>(pair->first());
03996     CSSPrimitiveValueImpl* second = static_cast<CSSPrimitiveValueImpl*>(pair->second());
03997 
03998     if (!first || !second)
03999         return;
04000 
04001     Length firstLength, secondLength;
04002     int firstType = first->primitiveType();
04003     int secondType = second->primitiveType();
04004 
04005     if (firstType == CSSPrimitiveValue::CSS_UNKNOWN)
04006         firstLength = Length(Variable);
04007     else if (firstType > CSSPrimitiveValue::CSS_PERCENTAGE && firstType < CSSPrimitiveValue::CSS_DEG)
04008         firstLength = Length(first->computeLength(style, paintDeviceMetrics), Fixed);
04009     else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
04010         firstLength = Length((int)first->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04011     else
04012         return;
04013 
04014     if (secondType == CSSPrimitiveValue::CSS_UNKNOWN)
04015         secondLength = Length(Variable);
04016     else if (secondType > CSSPrimitiveValue::CSS_PERCENTAGE && secondType < CSSPrimitiveValue::CSS_DEG)
04017         secondLength = Length(second->computeLength(style, paintDeviceMetrics), Fixed);
04018     else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
04019         secondLength = Length((int)second->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04020     else
04021         return;
04022 
04023     b.width = firstLength;
04024     b.height = secondLength;
04025     layer->setBackgroundSize(b);
04026 }
04027 
04028 void CSSStyleSelector::mapBackgroundXPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value)
04029 {
04030     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
04031         layer->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
04032         return;
04033     }
04034 
04035     if (!value->isPrimitiveValue()) return;
04036     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
04037     Length l;
04038     int type = primitiveValue->primitiveType();
04039     if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
04040         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
04041     else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
04042         l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04043     else
04044         return;
04045     layer->setBackgroundXPosition(l);
04046 }
04047 
04048 void CSSStyleSelector::mapBackgroundYPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value)
04049 {
04050     if (value->cssValueType() == CSSValue::CSS_INITIAL) {
04051         layer->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
04052         return;
04053     }
04054 
04055     if (!value->isPrimitiveValue()) return;
04056     CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
04057     Length l;
04058     int type = primitiveValue->primitiveType();
04059     if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
04060         l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
04061     else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
04062         l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
04063     else
04064         return;
04065     layer->setBackgroundYPosition(l);
04066 }
04067 
04068 #ifdef APPLE_CHANGES
04069 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* aStyle, RenderStyle* aParentStyle)
04070 {
04071   const FontDef& childFont = aStyle->htmlFont().fontDef;
04072 
04073   if (childFont.sizeSpecified || !aParentStyle)
04074     return;
04075 
04076   const FontDef& parentFont = aParentStyle->htmlFont().fontDef;
04077 
04078   if (childFont.genericFamily == parentFont.genericFamily)
04079     return;
04080 
04081   // For now, lump all families but monospace together.
04082   if (childFont.genericFamily != FontDef::eMonospace &&
04083       parentFont.genericFamily != FontDef::eMonospace)
04084     return;
04085 
04086   // We know the parent is monospace or the child is monospace, and that font
04087   // size was unspecified.  We want to alter our font size to use the correct
04088   // "medium" font for our family.
04089   float size = 0;
04090   int minFontSize = settings->minFontSize();
04091   size = (childFont.genericFamily == FontDef::eMonospace) ? m_fixedFontSizes[3] : m_fontSizes[3];
04092   int isize = (int)size;
04093   if (isize < minFontSize)
04094     isize = minFontSize;
04095 
04096   FontDef newFontDef(childFont);
04097   newFontDef.size = isize;
04098   aStyle->setFontDef(newFontDef);
04099 }
04100 #endif
04101 
04102 } // namespace khtml
KDE Home | KDE Accessibility Home | Description of Access Keys