khtml Library API Documentation

cssstyleselector.cpp

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