khtml Library API Documentation

cssstyleselector.cpp

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