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