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