css_valueimpl.cpp

00001 
00024 #include "dom/css_value.h"
00025 #include "dom/dom_exception.h"
00026 #include "dom/dom_string.h"
00027 
00028 #include "css/css_valueimpl.h"
00029 #include "css/css_ruleimpl.h"
00030 #include "css/css_stylesheetimpl.h"
00031 #include "css/cssparser.h"
00032 #include "css/cssproperties.h"
00033 #include "css/cssvalues.h"
00034 
00035 #include "xml/dom_stringimpl.h"
00036 #include "xml/dom_docimpl.h"
00037 
00038 #include "misc/loader.h"
00039 
00040 #include "rendering/font.h"
00041 #include "rendering/render_style.h"
00042 
00043 #include <kdebug.h>
00044 #include <qregexp.h>
00045 #include <qpaintdevice.h>
00046 #include <qpaintdevicemetrics.h>
00047 
00048 // Hack for debugging purposes
00049 extern DOM::DOMString getPropertyName(unsigned short id);
00050 
00051 using khtml::FontDef;
00052 
00053 using namespace DOM;
00054 
00055 // Quotes the string if it needs quoting.
00056 static DOMString quoteStringIfNeeded(const DOMString &string)
00057 {
00058     // FIXME: Also need to transform control characters into \ sequences.
00059     QString s = string.string();
00060     s.replace('\\', "\\\\");
00061     s.replace('\'', "\\'");
00062     return '\'' + s + '\'';
00063 }
00064 
00065 
00066 CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent)
00067     : StyleBaseImpl(parent)
00068 {
00069     m_lstValues = 0;
00070     m_node = 0;
00071 }
00072 
00073 CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent, QPtrList<CSSProperty> *lstValues)
00074     : StyleBaseImpl(parent)
00075 {
00076     m_lstValues = lstValues;
00077     m_node = 0;
00078 }
00079 
00080 CSSStyleDeclarationImpl&  CSSStyleDeclarationImpl::operator= (const CSSStyleDeclarationImpl& o)
00081 {
00082     // don't attach it to the same node, just leave the current m_node value
00083     delete m_lstValues;
00084     m_lstValues = 0;
00085     if (o.m_lstValues) {
00086         m_lstValues = new QPtrList<CSSProperty>;
00087         m_lstValues->setAutoDelete( true );
00088 
00089         QPtrListIterator<CSSProperty> lstValuesIt(*o.m_lstValues);
00090         for (lstValuesIt.toFirst(); lstValuesIt.current(); ++lstValuesIt)
00091             m_lstValues->append(new CSSProperty(*lstValuesIt.current()));
00092     }
00093 
00094     return *this;
00095 }
00096 
00097 CSSStyleDeclarationImpl::~CSSStyleDeclarationImpl()
00098 {
00099     delete m_lstValues;
00100     // we don't use refcounting for m_node, to avoid cyclic references (see ElementImpl)
00101 }
00102 
00103 DOMString CSSStyleDeclarationImpl::getPropertyValue( int propertyID ) const
00104 {
00105     if(!m_lstValues) return DOMString();
00106     CSSValueImpl* value = getPropertyCSSValue( propertyID );
00107     if ( value )
00108         return value->cssText();
00109 
00110     // Shorthand and 4-values properties
00111     switch ( propertyID ) {
00112     case CSS_PROP_BACKGROUND_POSITION:
00113     {
00114         // ## Is this correct? The code in cssparser.cpp is confusing
00115         const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X,
00116                                     CSS_PROP_BACKGROUND_POSITION_Y };
00117         return getShortHandValue( properties, 2 );
00118     }
00119     case CSS_PROP_BACKGROUND:
00120     {
00121         const int properties[5] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,
00122                                     CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION,
00123                                     CSS_PROP_BACKGROUND_COLOR };
00124         return getShortHandValue( properties, 5 );
00125     }
00126     case CSS_PROP_BORDER:
00127     {
00128         const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
00129                                     CSS_PROP_BORDER_COLOR };
00130         return getShortHandValue( properties, 3 );
00131     }
00132     case CSS_PROP_BORDER_TOP:
00133     {
00134         const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
00135                                     CSS_PROP_BORDER_TOP_COLOR};
00136         return getShortHandValue( properties, 3 );
00137     }
00138     case CSS_PROP_BORDER_RIGHT:
00139     {
00140         const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
00141                                     CSS_PROP_BORDER_RIGHT_COLOR};
00142         return getShortHandValue( properties, 3 );
00143     }
00144     case CSS_PROP_BORDER_BOTTOM:
00145     {
00146         const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
00147                                     CSS_PROP_BORDER_BOTTOM_COLOR};
00148         return getShortHandValue( properties, 3 );
00149     }
00150     case CSS_PROP_BORDER_LEFT:
00151     {
00152         const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
00153                                     CSS_PROP_BORDER_LEFT_COLOR};
00154         return getShortHandValue( properties, 3 );
00155     }
00156     case CSS_PROP_OUTLINE:
00157     {
00158         const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
00159                                     CSS_PROP_OUTLINE_COLOR };
00160         return getShortHandValue( properties, 3 );
00161     }
00162     case CSS_PROP_BORDER_COLOR:
00163     {
00164         const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
00165                                     CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
00166         return get4Values( properties );
00167     }
00168     case CSS_PROP_BORDER_WIDTH:
00169     {
00170         const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
00171                                     CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
00172         return get4Values( properties );
00173     }
00174     case CSS_PROP_BORDER_STYLE:
00175     {
00176         const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
00177                                     CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
00178         return get4Values( properties );
00179     }
00180     case CSS_PROP_MARGIN:
00181     {
00182         const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
00183                                     CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
00184         return get4Values( properties );
00185     }
00186     case CSS_PROP_PADDING:
00187     {
00188         const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
00189                                     CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
00190         return get4Values( properties );
00191     }
00192     case CSS_PROP_LIST_STYLE:
00193     {
00194         const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
00195                                     CSS_PROP_LIST_STYLE_IMAGE };
00196         return getShortHandValue( properties, 3 );
00197     }
00198     }
00199     //kdDebug() << k_funcinfo << "property not found:" << propertyID << endl;
00200     return DOMString();
00201 }
00202 
00203 DOMString CSSStyleDeclarationImpl::get4Values( const int* properties ) const
00204 {
00205     DOMString res;
00206     for ( int i = 0 ; i < 4 ; ++i ) {
00207         CSSValueImpl* value = getPropertyCSSValue( properties[i] );
00208         if ( !value ) { // apparently all 4 properties must be specified.
00209             return DOMString();
00210         }
00211         if ( i > 0 )
00212             res += " ";
00213         res += value->cssText();
00214     }
00215     return res;
00216 }
00217 
00218 DOMString CSSStyleDeclarationImpl::getShortHandValue( const int* properties, int number ) const
00219 {
00220     DOMString res;
00221     for ( int i = 0 ; i < number ; ++i ) {
00222         CSSValueImpl* value = getPropertyCSSValue( properties[i] );
00223         if ( value ) { // TODO provide default value if !value
00224             if ( !res.isNull() )
00225                 res += " ";
00226             res += value->cssText();
00227         }
00228     }
00229     return res;
00230 }
00231 
00232  CSSValueImpl *CSSStyleDeclarationImpl::getPropertyCSSValue( int propertyID ) const
00233 {
00234     if(!m_lstValues) return 0;
00235 
00236     QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
00237     CSSProperty *current;
00238     for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt )
00239         if (current->m_id == propertyID && !current->nonCSSHint)
00240             return current->value();
00241     return 0;
00242 }
00243 
00244 DOMString CSSStyleDeclarationImpl::removeProperty( int propertyID, bool NonCSSHint )
00245 {
00246     if(!m_lstValues) return DOMString();
00247     DOMString value;
00248 
00249     QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
00250      CSSProperty *current;
00251      for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt )  {
00252          if (current->m_id == propertyID && NonCSSHint == current->nonCSSHint) {
00253              value = current->value()->cssText();
00254              m_lstValues->removeRef(current);
00255              setChanged();
00256          break;
00257         }
00258      }
00259 
00260     return value;
00261 }
00262 
00263 void CSSStyleDeclarationImpl::setChanged()
00264 {
00265     if (m_node) {
00266         m_node->setChanged();
00267         return;
00268     }
00269 
00270     // ### quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk)
00271     for (StyleBaseImpl* stylesheet = this; stylesheet; stylesheet = stylesheet->parent())
00272         if (stylesheet->isCSSStyleSheet()) {
00273             static_cast<CSSStyleSheetImpl*>(stylesheet)->doc()->updateStyleSelector();
00274             break;
00275         }
00276 }
00277 
00278 void CSSStyleDeclarationImpl::removeCSSHints()
00279 {
00280     if (!m_lstValues)
00281     return;
00282 
00283     for (int i = (int)m_lstValues->count()-1; i >= 0; i--) {
00284     if (!m_lstValues->at(i)->nonCSSHint)
00285         m_lstValues->remove(i);
00286     }
00287 }
00288 
00289 bool CSSStyleDeclarationImpl::getPropertyPriority( int propertyID ) const
00290 {
00291     if ( m_lstValues) {
00292     QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
00293     CSSProperty *current;
00294     for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) {
00295         if( propertyID == current->m_id )
00296         return current->m_important;
00297     }
00298     }
00299     return false;
00300 }
00301 
00302 bool CSSStyleDeclarationImpl::setProperty(int id, const DOMString &value, bool important, bool nonCSSHint)
00303 {
00304     if(!m_lstValues) {
00305     m_lstValues = new QPtrList<CSSProperty>;
00306     m_lstValues->setAutoDelete(true);
00307     }
00308 
00309     CSSParser parser( strictParsing );
00310     bool success = parser.parseValue( this, id, value, important, nonCSSHint );
00311     if(!success)
00312     kdDebug( 6080 ) << "CSSStyleDeclarationImpl::setProperty invalid property: [" << getPropertyName(id).string()
00313             << "] value: [" << value.string() << "]"<< endl;
00314     else
00315         setChanged();
00316     return success;
00317 }
00318 
00319 void CSSStyleDeclarationImpl::setProperty(int id, int value, bool important, bool nonCSSHint)
00320 {
00321     if(!m_lstValues) {
00322     m_lstValues = new QPtrList<CSSProperty>;
00323     m_lstValues->setAutoDelete(true);
00324     }
00325     removeProperty(id, nonCSSHint );
00326 
00327     CSSValueImpl * cssValue = new CSSPrimitiveValueImpl(value);
00328     setParsedValue(id, cssValue, important, nonCSSHint, m_lstValues);
00329     setChanged();
00330 }
00331 
00332 void CSSStyleDeclarationImpl::setLengthProperty(int id, const DOM::DOMString &value, bool important, bool nonCSSHint, bool _multiLength )
00333 {
00334     bool parseMode = strictParsing;
00335     strictParsing = false;
00336     multiLength = _multiLength;
00337     setProperty( id, value, important, nonCSSHint);
00338     strictParsing = parseMode;
00339     multiLength = false;
00340 }
00341 
00342 void CSSStyleDeclarationImpl::setProperty ( const DOMString &propertyString)
00343 {
00344     if(!m_lstValues) {
00345     m_lstValues = new QPtrList<CSSProperty>;
00346     m_lstValues->setAutoDelete( true );
00347     }
00348 
00349     CSSParser parser( strictParsing );
00350     parser.parseDeclaration( this, propertyString, false );
00351     setChanged();
00352 }
00353 
00354 unsigned long CSSStyleDeclarationImpl::length() const
00355 {
00356     return m_lstValues ? m_lstValues->count() : 0;
00357 }
00358 
00359 DOMString CSSStyleDeclarationImpl::item( unsigned long index ) const
00360 {
00361     if(m_lstValues && index < m_lstValues->count() && m_lstValues->at(index))
00362     return getPropertyName(m_lstValues->at(index)->m_id);
00363     return DOMString();
00364 }
00365 
00366 CSSRuleImpl *CSSStyleDeclarationImpl::parentRule() const
00367 {
00368     return (m_parent && m_parent->isRule() ) ?
00369     static_cast<CSSRuleImpl *>(m_parent) : 0;
00370 }
00371 
00372 DOM::DOMString CSSStyleDeclarationImpl::cssText() const
00373 {
00374     DOMString result;
00375 
00376     if ( m_lstValues) {
00377     QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
00378     CSSProperty *current;
00379     for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) {
00380         result += current->cssText();
00381     }
00382     }
00383 
00384     return result;
00385 }
00386 
00387 void CSSStyleDeclarationImpl::setCssText(DOM::DOMString text)
00388 {
00389     if (m_lstValues) {
00390     m_lstValues->clear();
00391     } else {
00392     m_lstValues = new QPtrList<CSSProperty>;
00393     m_lstValues->setAutoDelete( true );
00394     }
00395 
00396     CSSParser parser( strictParsing );
00397     parser.parseDeclaration( this, text, false );
00398     setChanged();
00399 }
00400 
00401 bool CSSStyleDeclarationImpl::parseString( const DOMString &/*string*/, bool )
00402 {
00403     kdDebug() << "WARNING: CSSStyleDeclarationImpl::parseString, unimplemented, was called" << endl;
00404     return false;
00405     // ###
00406 }
00407 
00408 
00409 // --------------------------------------------------------------------------------------
00410 
00411 unsigned short CSSInheritedValueImpl::cssValueType() const
00412 {
00413     return CSSValue::CSS_INHERIT;
00414 }
00415 
00416 DOM::DOMString CSSInheritedValueImpl::cssText() const
00417 {
00418     return DOMString("inherit");
00419 }
00420 
00421 unsigned short CSSInitialValueImpl::cssValueType() const
00422 {
00423     return CSSValue::CSS_INITIAL;
00424 }
00425 
00426 DOM::DOMString CSSInitialValueImpl::cssText() const
00427 {
00428     return DOMString("initial");
00429 }
00430 
00431 // ----------------------------------------------------------------------------------------
00432 
00433 CSSValueListImpl::~CSSValueListImpl()
00434 {
00435     CSSValueImpl *val = m_values.first();
00436     while( val ) {
00437     val->deref();
00438     val = m_values.next();
00439     }
00440 }
00441 
00442 unsigned short CSSValueListImpl::cssValueType() const
00443 {
00444     return CSSValue::CSS_VALUE_LIST;
00445 }
00446 
00447 void CSSValueListImpl::append(CSSValueImpl *val)
00448 {
00449     m_values.append(val);
00450     val->ref();
00451 }
00452 
00453 DOM::DOMString CSSValueListImpl::cssText() const
00454 {
00455     DOMString result = "";
00456 
00457     for (QPtrListIterator<CSSValueImpl> iterator(m_values); iterator.current(); ++iterator) {
00458     result += iterator.current()->cssText();
00459     }
00460 
00461     return result;
00462 }
00463 
00464 // -------------------------------------------------------------------------------------
00465 
00466 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl()
00467     : CSSValueImpl()
00468 {
00469     m_type = 0;
00470 }
00471 
00472 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(int ident)
00473     : CSSValueImpl()
00474 {
00475     m_value.ident = ident;
00476     m_type = CSSPrimitiveValue::CSS_IDENT;
00477 }
00478 
00479 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type)
00480 {
00481     m_value.num = num;
00482     m_type = type;
00483 }
00484 
00485 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(const DOMString &str, CSSPrimitiveValue::UnitTypes type)
00486 {
00487     m_value.string = str.implementation();
00488     if(m_value.string) m_value.string->ref();
00489     m_type = type;
00490 }
00491 
00492 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(CounterImpl *c)
00493 {
00494     m_value.counter = c;
00495     if (m_value.counter)
00496     m_value.counter->ref();
00497     m_type = CSSPrimitiveValue::CSS_COUNTER;
00498 }
00499 
00500 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl( RectImpl *r)
00501 {
00502     m_value.rect = r;
00503     if (m_value.rect)
00504     m_value.rect->ref();
00505     m_type = CSSPrimitiveValue::CSS_RECT;
00506 }
00507 
00508 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(QRgb color)
00509 {
00510     m_value.rgbcolor = color;
00511     m_type = CSSPrimitiveValue::CSS_RGBCOLOR;
00512 }
00513 
00514 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(PairImpl *p)
00515 {
00516     m_value.pair = p;
00517     if (m_value.pair)
00518     m_value.pair->ref();
00519     m_type = CSSPrimitiveValue::CSS_PAIR;
00520 }
00521 
00522 
00523 CSSPrimitiveValueImpl::~CSSPrimitiveValueImpl()
00524 {
00525     cleanup();
00526 }
00527 
00528 void CSSPrimitiveValueImpl::cleanup()
00529 {
00530     switch(m_type) {
00531     case CSSPrimitiveValue::CSS_STRING:
00532     case CSSPrimitiveValue::CSS_URI:
00533     case CSSPrimitiveValue::CSS_ATTR:
00534     if(m_value.string) m_value.string->deref();
00535         break;
00536     case CSSPrimitiveValue::CSS_COUNTER:
00537     m_value.counter->deref();
00538         break;
00539     case CSSPrimitiveValue::CSS_RECT:
00540     m_value.rect->deref();
00541         break;
00542     case CSSPrimitiveValue::CSS_PAIR:
00543         m_value.pair->deref();
00544         break;
00545     default:
00546         break;
00547     }
00548 
00549     m_type = 0;
00550 }
00551 
00552 int CSSPrimitiveValueImpl::computeLength( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics )
00553 {
00554     double result = computeLengthFloat( style, devMetrics );
00555     // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We
00556     // need to go ahead and round if we're really close to the next integer value.
00557     int intResult = (int)(result + (result < 0 ? -0.01 : +0.01));
00558     return intResult;
00559 }
00560 
00561 double CSSPrimitiveValueImpl::computeLengthFloat( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics )
00562 {
00563     unsigned short type = primitiveType();
00564 
00565     double dpiY = 72.; // fallback
00566     if ( devMetrics )
00567         dpiY = devMetrics->logicalDpiY();
00568     if ( !khtml::printpainter && dpiY < 96 )
00569         dpiY = 96.;
00570 
00571     double factor = 1.;
00572     switch(type)
00573     {
00574     case CSSPrimitiveValue::CSS_EMS:
00575         factor = style->font().pixelSize();
00576         break;
00577     case CSSPrimitiveValue::CSS_EXS:
00578     {
00579         QFontMetrics fm = style->fontMetrics();
00580 #ifdef APPLE_CHANGES
00581         factor = fm.xHeight();
00582 #else
00583         QRect b = fm.boundingRect('x');
00584         factor = b.height();
00585 #endif
00586         break;
00587     }
00588     case CSSPrimitiveValue::CSS_PX:
00589         break;
00590     case CSSPrimitiveValue::CSS_CM:
00591     factor = dpiY/2.54; //72dpi/(2.54 cm/in)
00592         break;
00593     case CSSPrimitiveValue::CSS_MM:
00594     factor = dpiY/25.4;
00595         break;
00596     case CSSPrimitiveValue::CSS_IN:
00597         factor = dpiY;
00598         break;
00599     case CSSPrimitiveValue::CSS_PT:
00600         factor = dpiY/72.;
00601         break;
00602     case CSSPrimitiveValue::CSS_PC:
00603         // 1 pc == 12 pt
00604         factor = dpiY*12./72.;
00605         break;
00606     default:
00607         return -1;
00608     }
00609 
00610     return floatValue(type)*factor;
00611 }
00612 
00613 void CSSPrimitiveValueImpl::setFloatValue( unsigned short unitType, double floatValue, int &exceptioncode )
00614 {
00615     exceptioncode = 0;
00616     cleanup();
00617     // ### check if property supports this type
00618     if(m_type > CSSPrimitiveValue::CSS_DIMENSION) {
00619     exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
00620     return;
00621     }
00622     //if(m_type > CSSPrimitiveValue::CSS_DIMENSION) throw DOMException(DOMException::INVALID_ACCESS_ERR);
00623     m_value.num = floatValue;
00624     m_type = unitType;
00625 }
00626 
00627 void CSSPrimitiveValueImpl::setStringValue( unsigned short stringType, const DOMString &stringValue, int &exceptioncode )
00628 {
00629     exceptioncode = 0;
00630     cleanup();
00631     //if(m_type < CSSPrimitiveValue::CSS_STRING) throw DOMException(DOMException::INVALID_ACCESS_ERR);
00632     //if(m_type > CSSPrimitiveValue::CSS_ATTR) throw DOMException(DOMException::INVALID_ACCESS_ERR);
00633     if(m_type < CSSPrimitiveValue::CSS_STRING || m_type > CSSPrimitiveValue::CSS_ATTR) {
00634     exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
00635     return;
00636     }
00637     if(stringType != CSSPrimitiveValue::CSS_IDENT)
00638     {
00639     m_value.string = stringValue.implementation();
00640     m_value.string->ref();
00641     m_type = stringType;
00642     }
00643     // ### parse ident
00644 }
00645 
00646 unsigned short CSSPrimitiveValueImpl::cssValueType() const
00647 {
00648     return CSSValue::CSS_PRIMITIVE_VALUE;
00649 }
00650 
00651 bool CSSPrimitiveValueImpl::parseString( const DOMString &/*string*/, bool )
00652 {
00653     // ###
00654     kdDebug() << "WARNING: CSSPrimitiveValueImpl::parseString, unimplemented, was called" << endl;
00655     return false;
00656 }
00657 
00658 int CSSPrimitiveValueImpl::getIdent()
00659 {
00660     if(m_type != CSSPrimitiveValue::CSS_IDENT) return 0;
00661     return m_value.ident;
00662 }
00663 
00664 DOM::DOMString CSSPrimitiveValueImpl::cssText() const
00665 {
00666     // ### return the original value instead of a generated one (e.g. color
00667     // name if it was specified) - check what spec says about this
00668     DOMString text;
00669     switch ( m_type ) {
00670     case CSSPrimitiveValue::CSS_UNKNOWN:
00671         // ###
00672         break;
00673     case CSSPrimitiveValue::CSS_NUMBER:
00674         text = DOMString(QString::number( (int)m_value.num ));
00675         break;
00676     case CSSPrimitiveValue::CSS_PERCENTAGE:
00677         text = DOMString(QString::number( m_value.num ) + "%");
00678         break;
00679     case CSSPrimitiveValue::CSS_EMS:
00680         text = DOMString(QString::number( m_value.num ) + "em");
00681         break;
00682     case CSSPrimitiveValue::CSS_EXS:
00683         text = DOMString(QString::number( m_value.num ) + "ex");
00684         break;
00685     case CSSPrimitiveValue::CSS_PX:
00686         text = DOMString(QString::number( m_value.num ) + "px");
00687         break;
00688     case CSSPrimitiveValue::CSS_CM:
00689         text = DOMString(QString::number( m_value.num ) + "cm");
00690         break;
00691     case CSSPrimitiveValue::CSS_MM:
00692         text = DOMString(QString::number( m_value.num ) + "mm");
00693         break;
00694     case CSSPrimitiveValue::CSS_IN:
00695         text = DOMString(QString::number( m_value.num ) + "in");
00696         break;
00697     case CSSPrimitiveValue::CSS_PT:
00698         text = DOMString(QString::number( m_value.num ) + "pt");
00699         break;
00700     case CSSPrimitiveValue::CSS_PC:
00701         text = DOMString(QString::number( m_value.num ) + "pc");
00702         break;
00703     case CSSPrimitiveValue::CSS_DEG:
00704         text = DOMString(QString::number( m_value.num ) + "deg");
00705         break;
00706     case CSSPrimitiveValue::CSS_RAD:
00707         text = DOMString(QString::number( m_value.num ) + "rad");
00708         break;
00709     case CSSPrimitiveValue::CSS_GRAD:
00710         text = DOMString(QString::number( m_value.num ) + "grad");
00711         break;
00712     case CSSPrimitiveValue::CSS_MS:
00713         text = DOMString(QString::number( m_value.num ) + "ms");
00714         break;
00715     case CSSPrimitiveValue::CSS_S:
00716         text = DOMString(QString::number( m_value.num ) + "s");
00717         break;
00718     case CSSPrimitiveValue::CSS_HZ:
00719         text = DOMString(QString::number( m_value.num ) + "hz");
00720         break;
00721     case CSSPrimitiveValue::CSS_KHZ:
00722         text = DOMString(QString::number( m_value.num ) + "khz");
00723         break;
00724     case CSSPrimitiveValue::CSS_DIMENSION:
00725         // ###
00726         break;
00727     case CSSPrimitiveValue::CSS_STRING:
00728         text = quoteStringIfNeeded(m_value.string);
00729         break;
00730     case CSSPrimitiveValue::CSS_URI:
00731             text  = "url(";
00732         text += DOMString( m_value.string );
00733             text += ")";
00734         break;
00735     case CSSPrimitiveValue::CSS_IDENT:
00736         text = getValueName(m_value.ident);
00737         break;
00738     case CSSPrimitiveValue::CSS_ATTR:
00739             text = "attr(";
00740             text += DOMString( m_value.string );
00741             text += ")";
00742         break;
00743     case CSSPrimitiveValue::CSS_COUNTER:
00744             text = "counter(";
00745             text += m_value.counter->m_identifier;
00746             text += ")";
00747             // ### add list-style and separator
00748         break;
00749     case CSSPrimitiveValue::CSS_RECT:
00750         {
00751             RectImpl* rectVal = getRectValue();
00752             text = "rect(";
00753             text += rectVal->top()->cssText() + " ";
00754             text += rectVal->right()->cssText() + " ";
00755             text += rectVal->bottom()->cssText() + " ";
00756             text += rectVal->left()->cssText() + ")";
00757             break;
00758         }
00759     case CSSPrimitiveValue::CSS_RGBCOLOR:
00760         if (qAlpha(m_value.rgbcolor) != 0xFF) {
00761         if (m_value.rgbcolor == khtml::transparentColor)
00762             text = "transparent";
00763         else
00764             text = "rgba(" + QString::number(qRed  (m_value.rgbcolor)) + "," 
00765                    + QString::number(qBlue (m_value.rgbcolor)) + "," 
00766                    + QString::number(qGreen(m_value.rgbcolor)) + "," 
00767                    + QString::number(qAlpha(m_value.rgbcolor)/255.0) + ")";
00768         } else {
00769         text = QColor(m_value.rgbcolor).name();
00770         }
00771         break;
00772         case CSSPrimitiveValue::CSS_PAIR:
00773             text = m_value.pair->first()->cssText();
00774             text += " ";
00775             text += m_value.pair->second()->cssText();
00776             break;
00777     default:
00778         break;
00779     }
00780     return text;
00781 }
00782 
00783 // -----------------------------------------------------------------
00784 
00785 RectImpl::RectImpl()
00786 {
00787     m_top = 0;
00788     m_right = 0;
00789     m_bottom = 0;
00790     m_left = 0;
00791 }
00792 
00793 RectImpl::~RectImpl()
00794 {
00795     if (m_top) m_top->deref();
00796     if (m_right) m_right->deref();
00797     if (m_bottom) m_bottom->deref();
00798     if (m_left) m_left->deref();
00799 }
00800 
00801 void RectImpl::setTop( CSSPrimitiveValueImpl *top )
00802 {
00803     if( top ) top->ref();
00804     if ( m_top ) m_top->deref();
00805     m_top = top;
00806 }
00807 
00808 void RectImpl::setRight( CSSPrimitiveValueImpl *right )
00809 {
00810     if( right ) right->ref();
00811     if ( m_right ) m_right->deref();
00812     m_right = right;
00813 }
00814 
00815 void RectImpl::setBottom( CSSPrimitiveValueImpl *bottom )
00816 {
00817     if( bottom ) bottom->ref();
00818     if ( m_bottom ) m_bottom->deref();
00819     m_bottom = bottom;
00820 }
00821 
00822 void RectImpl::setLeft( CSSPrimitiveValueImpl *left )
00823 {
00824     if( left ) left->ref();
00825     if ( m_left ) m_left->deref();
00826     m_left = left;
00827 }
00828 
00829 // -----------------------------------------------------------------
00830 
00831 PairImpl::~PairImpl()
00832 {
00833     if (m_first) m_first->deref(); if (m_second) m_second->deref();
00834 }
00835 
00836 void PairImpl::setFirst(CSSPrimitiveValueImpl* first)
00837 {
00838     if (first == m_first) return;
00839     if (m_first) m_first->deref();
00840     m_first = first;
00841     if (m_first) m_first->ref();
00842 }
00843 
00844 void PairImpl::setSecond(CSSPrimitiveValueImpl* second)
00845 {
00846     if (second == m_second) return;
00847     if (m_second) m_second->deref();
00848     m_second = second;
00849     if (m_second) m_second->ref();
00850 }
00851 
00852 // -----------------------------------------------------------------
00853 
00854 CSSImageValueImpl::CSSImageValueImpl(const DOMString &url, const StyleBaseImpl* style)
00855     : CSSPrimitiveValueImpl(url, CSSPrimitiveValue::CSS_URI)
00856 {
00857     khtml::DocLoader *docLoader = 0;
00858     const StyleBaseImpl *root = style;
00859     while (root->parent())
00860     root = root->parent();
00861     if (root->isCSSStyleSheet())
00862     docLoader = static_cast<const CSSStyleSheetImpl*>(root)->docLoader();
00863 
00864     m_image = docLoader->requestImage(url);
00865     if(m_image) m_image->ref(this);
00866 }
00867 
00868 CSSImageValueImpl::CSSImageValueImpl()
00869     : CSSPrimitiveValueImpl(CSS_VAL_NONE)
00870 {
00871     m_image = 0;
00872 }
00873 
00874 CSSImageValueImpl::~CSSImageValueImpl()
00875 {
00876     if(m_image) m_image->deref(this);
00877 }
00878 
00879 // ------------------------------------------------------------------------
00880 
00881 FontFamilyValueImpl::FontFamilyValueImpl( const QString &string)
00882 : CSSPrimitiveValueImpl( DOMString(string), CSSPrimitiveValue::CSS_STRING)
00883 {
00884     static const QRegExp parenReg(" \\(.*\\)$");
00885     static const QRegExp braceReg(" \\[.*\\]$");
00886 
00887     parsedFontName = string;
00888     // a language tag is often added in braces at the end. Remove it.
00889     parsedFontName.replace(parenReg, QString::null);
00890     // remove [Xft] qualifiers
00891     parsedFontName.replace(braceReg, QString::null);
00892 
00893 #ifndef APPLE_CHANGES
00894     const QString &available = KHTMLSettings::availableFamilies();
00895 
00896     parsedFontName = parsedFontName.lower();
00897     // kdDebug(0) << "searching for face '" << parsedFontName << "'" << endl;
00898 
00899     int pos = available.find( ',' + parsedFontName + ',', 0, false );
00900     if ( pos == -1 ) {
00901         // many pages add extra MSs to make sure it's windows only ;(
00902         if ( parsedFontName.startsWith( "ms " ) )
00903             parsedFontName = parsedFontName.mid( 3 );
00904         if ( parsedFontName.endsWith( " ms" ) )
00905             parsedFontName.truncate( parsedFontName.length() - 3 );
00906         pos = available.find( ",ms " + parsedFontName + ',', 0, false );
00907         if ( pos == -1 )
00908             pos = available.find( ',' + parsedFontName + " ms,", 0, false );
00909     }
00910 
00911     if ( pos != -1 ) {
00912        ++pos;
00913        int p = available.find(',', pos);
00914        assert( p != -1 ); // available is supposed to start and end with ,
00915        parsedFontName = available.mid( pos, p - pos);
00916        // kdDebug(0) << "going for '" << parsedFontName << "'" << endl;
00917     } else
00918         parsedFontName = QString::null;
00919 
00920 #endif // !APPLE_CHANGES
00921 }
00922 
00923 FontValueImpl::FontValueImpl()
00924     : style(0), variant(0), weight(0), size(0), lineHeight(0), family(0)
00925 {
00926 }
00927 
00928 FontValueImpl::~FontValueImpl()
00929 {
00930     delete style;
00931     delete variant;
00932     delete weight;
00933     delete size;
00934     delete lineHeight;
00935     delete family;
00936 }
00937 
00938 DOMString FontValueImpl::cssText() const
00939 {
00940     // font variant weight size / line-height family
00941 
00942     DOMString result("");
00943 
00944     if (style) {
00945     result += style->cssText();
00946     }
00947     if (variant) {
00948     if (result.length() > 0) {
00949         result += " ";
00950     }
00951     result += variant->cssText();
00952     }
00953     if (weight) {
00954     if (result.length() > 0) {
00955         result += " ";
00956     }
00957     result += weight->cssText();
00958     }
00959     if (size) {
00960     if (result.length() > 0) {
00961         result += " ";
00962     }
00963     result += size->cssText();
00964     }
00965     if (lineHeight) {
00966     if (!size) {
00967         result += " ";
00968     }
00969     result += "/";
00970     result += lineHeight->cssText();
00971     }
00972     if (family) {
00973     if (result.length() > 0) {
00974         result += " ";
00975     }
00976     result += family->cssText();
00977     }
00978 
00979     return result;
00980 }
00981 
00982 QuotesValueImpl::QuotesValueImpl()
00983     : levels(0)
00984 {
00985 }
00986 
00987 DOMString QuotesValueImpl::cssText() const
00988 {
00989     return "\"" + data.join("\" \"") + "\"";
00990 }
00991 
00992 void QuotesValueImpl::addLevel(const QString& open, const QString& close)
00993 {
00994     data.append(open);
00995     data.append(close);
00996     levels++;
00997 }
00998 
00999 QString QuotesValueImpl::openQuote(int level) const
01000 {
01001     if (levels == 0) return "";
01002     level--; // increments are calculated before openQuote is called
01003 //     kdDebug( 6080 ) << "Open quote level:" << level << endl;
01004     if (level < 0) level = 0;
01005     else
01006     if (level >= (int) levels) level = (int) (levels-1);
01007     return data[level*2];
01008 }
01009 
01010 QString QuotesValueImpl::closeQuote(int level) const
01011 {
01012     if (levels == 0) return "";
01013 //     kdDebug( 6080 ) << "Close quote level:" << level << endl;
01014     if (level < 0) level = 0;
01015     else
01016     if (level >= (int) levels) level = (int) (levels-1);
01017     return data[level*2+1];
01018 }
01019 
01020 // Used for text-shadow and box-shadow
01021 ShadowValueImpl::ShadowValueImpl(CSSPrimitiveValueImpl* _x, CSSPrimitiveValueImpl* _y,
01022                                  CSSPrimitiveValueImpl* _blur, CSSPrimitiveValueImpl* _color)
01023     :x(_x), y(_y), blur(_blur), color(_color)
01024 {}
01025 
01026 ShadowValueImpl::~ShadowValueImpl()
01027 {
01028     delete x;
01029     delete y;
01030     delete blur;
01031     delete color;
01032 }
01033 
01034 DOMString ShadowValueImpl::cssText() const
01035 {
01036     DOMString text("");
01037     if (color) {
01038         text += color->cssText();
01039     }
01040     if (x) {
01041         if (text.length() > 0) {
01042             text += " ";
01043         }
01044         text += x->cssText();
01045     }
01046     if (y) {
01047         if (text.length() > 0) {
01048             text += " ";
01049         }
01050         text += y->cssText();
01051     }
01052     if (blur) {
01053         if (text.length() > 0) {
01054             text += " ";
01055         }
01056         text += blur->cssText();
01057     }
01058 
01059     return text;
01060 }
01061 
01062 DOMString CounterActImpl::cssText() const
01063 {
01064     DOMString text(m_counter);
01065     text += DOMString(QString::number(m_value));
01066 
01067     return text;
01068 }
01069 
01070 DOMString CSSProperty::cssText() const
01071 {
01072     return getPropertyName(m_id) + DOMString(": ") + m_value->cssText() + (m_important ? DOMString(" !important") : DOMString()) + DOMString("; ");
01073 }
KDE Home | KDE Accessibility Home | Description of Access Keys