cssstyleselector.cpp

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