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