File indexing completed on 2024-04-21 14:57:11

0001 /*
0002  *  This file is part of the KDE libraries
0003  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
0004  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
0005  *  Copyright (C) 2003 Apple Computer, Inc.
0006  *
0007  *  This library is free software; you can redistribute it and/or
0008  *  modify it under the terms of the GNU Library General Public
0009  *  License as published by the Free Software Foundation; either
0010  *  version 2 of the License, or (at your option) any later version.
0011  *
0012  *  This library is distributed in the hope that it will be useful,
0013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  *  Library General Public License for more details.
0016  *
0017  *  You should have received a copy of the GNU Library General Public
0018  *  License along with this library; if not, write to the Free Software
0019  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0020  */
0021 
0022 #include "kjs_css.h"
0023 #include "kjs_css.lut.h"
0024 
0025 #include "html/html_headimpl.h" // for HTMLStyleElementImpl
0026 
0027 #include "dom/css_value.h"
0028 #include "dom/css_rule.h"
0029 
0030 #include "css/css_renderstyledeclarationimpl.h"
0031 #include "css/cssproperties.h"
0032 
0033 #include "kjs_dom.h"
0034 
0035 using DOM::CSSCharsetRuleImpl;
0036 using DOM::CSSFontFaceRuleImpl;
0037 using DOM::CSSImportRuleImpl;
0038 using DOM::CSSMediaRuleImpl;
0039 using DOM::CSSPageRuleImpl;
0040 using DOM::CSSPrimitiveValue;
0041 using DOM::CSSPrimitiveValueImpl;
0042 using DOM::CSSRule;
0043 using DOM::CSSRuleImpl;
0044 using DOM::CSSRuleListImpl;
0045 using DOM::CSSStyleDeclarationImpl;
0046 using DOM::CSSStyleRuleImpl;
0047 using DOM::CSSStyleSheetImpl;
0048 using DOM::CSSValue;
0049 using DOM::CSSValueImpl;
0050 using DOM::CSSValueListImpl;
0051 using DOM::CounterImpl;
0052 using DOM::DocumentImpl;
0053 using DOM::DOMString;
0054 using DOM::ElementImpl;
0055 using DOM::HTMLStyleElementImpl;
0056 using DOM::MediaListImpl;
0057 using DOM::RectImpl;
0058 using DOM::StyleSheetImpl;
0059 using DOM::StyleSheetListImpl;
0060 
0061 #include "khtml_debug.h"
0062 #include <QList>
0063 
0064 namespace KJS
0065 {
0066 
0067 static QString cssPropertyName(const Identifier &p, bool *hadPixelPrefix)
0068 {
0069     // The point here is to provide compatibility with IE
0070     // syntax for accessing properties, which camel-cases them
0071     // and can add prefixes to produce things like pixelFoo
0072     QString prop = p.qstring();
0073     for (int i = prop.length() - 1; i >= 0; --i) {
0074         char c = prop[i].toLatin1();
0075         if (c >= 'A' && c <= 'Z') {
0076             prop.insert(i, '-');
0077         }
0078     }
0079 
0080     prop = prop.toLower();
0081     *hadPixelPrefix = false;
0082 
0083     if (prop.startsWith(QLatin1String("css-"))) {
0084         prop = prop.mid(4);
0085     } else if (prop.startsWith(QLatin1String("pixel-"))) {
0086         prop = prop.mid(6);
0087         *hadPixelPrefix = true;
0088     } else if (prop.startsWith(QLatin1String("pos-"))) {
0089         prop = prop.mid(4);
0090         *hadPixelPrefix = true;
0091     }
0092 
0093     return prop;
0094 }
0095 
0096 static int cssPropertyId(const QString &p)
0097 {
0098     return DOM::getPropertyID(p.toLatin1().constData(), p.length());
0099 }
0100 
0101 static bool isCSSPropertyName(const Identifier &JSPropertyName)
0102 {
0103     bool dummy;
0104     QString p = cssPropertyName(JSPropertyName, &dummy);
0105     return cssPropertyId(p) != 0;
0106 }
0107 
0108 /*
0109 @begin DOMCSSStyleDeclarationProtoTable 7
0110   getPropertyValue  DOMCSSStyleDeclaration::GetPropertyValue    DontDelete|Function 1
0111   getPropertyCSSValue   DOMCSSStyleDeclaration::GetPropertyCSSValue DontDelete|Function 1
0112   removeProperty    DOMCSSStyleDeclaration::RemoveProperty      DontDelete|Function 1
0113   getPropertyPriority   DOMCSSStyleDeclaration::GetPropertyPriority DontDelete|Function 1
0114   setProperty       DOMCSSStyleDeclaration::SetProperty     DontDelete|Function 3
0115   item          DOMCSSStyleDeclaration::Item            DontDelete|Function 1
0116 # IE names for it (#36063)
0117   getAttribute          DOMCSSStyleDeclaration::GetPropertyValue    DontDelete|Function 1
0118   removeAttribute       DOMCSSStyleDeclaration::RemoveProperty      DontDelete|Function 1
0119   setAttribute      DOMCSSStyleDeclaration::SetProperty     DontDelete|Function 3
0120 @end
0121 @begin DOMCSSStyleDeclarationTable 3
0122   cssText       DOMCSSStyleDeclaration::CssText     DontDelete
0123   length        DOMCSSStyleDeclaration::Length      DontDelete|ReadOnly
0124   parentRule        DOMCSSStyleDeclaration::ParentRule  DontDelete|ReadOnly
0125 @end
0126 */
0127 KJS_DEFINE_PROTOTYPE(DOMCSSStyleDeclarationProto)
0128 KJS_IMPLEMENT_PROTOFUNC(DOMCSSStyleDeclarationProtoFunc)
0129 KJS_IMPLEMENT_PROTOTYPE("DOMCSSStyleDeclaration", DOMCSSStyleDeclarationProto, DOMCSSStyleDeclarationProtoFunc, ObjectPrototype)
0130 
0131 IMPLEMENT_PSEUDO_CONSTRUCTOR(CSSStyleDeclarationPseudoCtor, "DOMCSSStyleDeclaration", DOMCSSStyleDeclarationProto)
0132 
0133 const ClassInfo DOMCSSStyleDeclaration::info = { "CSSStyleDeclaration", nullptr, &DOMCSSStyleDeclarationTable, nullptr };
0134 
0135 DOMCSSStyleDeclaration::DOMCSSStyleDeclaration(ExecState *exec, DOM::CSSStyleDeclarationImpl *s)
0136     : DOMObject(), m_impl(s)
0137 {
0138     setPrototype(DOMCSSStyleDeclarationProto::self(exec));
0139 }
0140 
0141 DOMCSSStyleDeclaration::~DOMCSSStyleDeclaration()
0142 {
0143     ScriptInterpreter::forgetDOMObject(m_impl.get());
0144 }
0145 
0146 JSValue *DOMCSSStyleDeclaration::getValueProperty(ExecState *exec, int token)
0147 {
0148     //### null decls?
0149     switch (token) {
0150     case CssText:
0151         return jsString(m_impl->cssText());
0152     case Length:
0153         return jsNumber(m_impl->length());
0154     case ParentRule:
0155         return getDOMCSSRule(exec, m_impl->parentRule());
0156     }
0157 
0158     assert(0);
0159     return jsUndefined();
0160 }
0161 
0162 JSValue *DOMCSSStyleDeclaration::indexGetter(ExecState *, unsigned index)
0163 {
0164     return jsString(m_impl->item(index));
0165 }
0166 
0167 bool DOMCSSStyleDeclaration::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0168 {
0169 #ifdef KJS_VERBOSE
0170     qCDebug(KHTML_LOG) << "DOMCSSStyleDeclaration::getOwnPropertySlot " << propertyName.qstring();
0171 #endif
0172 
0173     if (getStaticOwnValueSlot(&DOMCSSStyleDeclarationTable, this, propertyName, slot)) {
0174         return true;
0175     }
0176 
0177     //Check whether it's an index
0178     if (getIndexSlot(this, propertyName, slot)) {
0179         return true;
0180     }
0181 
0182     if (isCSSPropertyName(propertyName)) {
0183         // Set up pixelOrPos boolean to handle the fact that
0184         // pixelTop returns "CSS Top" as number value in unit pixels
0185         // posTop returns "CSS top" as number value in unit pixels _if_ its a
0186         // positioned element. if it is not a positioned element, return 0
0187         // from MSIE documentation ### IMPLEMENT THAT (Dirk)
0188         bool asNumber;
0189         DOMString p   = cssPropertyName(propertyName, &asNumber);
0190 
0191         if (asNumber) {
0192             CSSValueImpl *v = m_impl->getPropertyCSSValue(p);
0193             if (v && v->cssValueType() == DOM::CSSValue::CSS_PRIMITIVE_VALUE)
0194                 //### FIXME: should this not set exception when type is wrong, or convert?
0195                 return getImmediateValueSlot(this,
0196                                              jsNumber(static_cast<CSSPrimitiveValueImpl *>(v)->floatValue(DOM::CSSPrimitiveValue::CSS_PX)), slot);
0197         }
0198 
0199         DOM::DOMString str = m_impl->getPropertyValue(p);
0200 
0201         // We want to return at least an empty string here --- see #152791
0202         return getImmediateValueSlot(this, jsString(str), slot);
0203     }
0204 
0205     return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
0206 }
0207 
0208 void DOMCSSStyleDeclaration::getOwnPropertyNames(ExecState *exec, PropertyNameArray &arr, PropertyMap::PropertyMode mode)
0209 {
0210     DOMObject::getOwnPropertyNames(exec, arr, mode);
0211 
0212     // Add in all properties we support.
0213     for (int p = 1; p < CSS_PROP_TOTAL; ++p) {
0214         QString dashName = getPropertyName(p).string();
0215         QString camelName;
0216 
0217         bool capitalize = false;
0218         for (int c = 0; c < dashName.length(); ++c) {
0219             if (dashName[c] == QLatin1Char('-')) {
0220                 capitalize = true;
0221             } else {
0222                 camelName += capitalize ? dashName[c].toUpper() : dashName[c];
0223                 capitalize = false;
0224             }
0225         } // char
0226 
0227         arr.add(KJS::Identifier(camelName));
0228     } // prop
0229 }
0230 
0231 void DOMCSSStyleDeclaration::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
0232 {
0233 #ifdef KJS_VERBOSE
0234     qCDebug(KHTML_LOG) << "DOMCSSStyleDeclaration::put " << propertyName.qstring();
0235 #endif
0236     DOMExceptionTranslator exception(exec);
0237     CSSStyleDeclarationImpl &styleDecl = *m_impl;
0238 
0239     if (propertyName == "cssText") {
0240         styleDecl.setCssText(valueToStringWithNullCheck(exec, value));
0241     } else {
0242         bool pxSuffix;
0243         QString prop = cssPropertyName(propertyName, &pxSuffix);
0244         QString propvalue = valueToStringWithNullCheck(exec, value).string();
0245 
0246         if (pxSuffix) {
0247             propvalue += QLatin1String("px");
0248         }
0249 #ifdef KJS_VERBOSE
0250         qCDebug(KHTML_LOG) << "DOMCSSStyleDeclaration: prop=" << prop << " propvalue=" << propvalue;
0251 #endif
0252         // Look whether the property is known. In that case add it as a CSS property.
0253         if (int pId = cssPropertyId(prop)) {
0254             if (propvalue.isEmpty()) {
0255                 styleDecl.removeProperty(pId);
0256             } else {
0257                 int important = propvalue.indexOf("!important", 0, Qt::CaseInsensitive);
0258                 if (important == -1) {
0259                     styleDecl.setProperty(pId, DOM::DOMString(propvalue), false /*important*/, exception);
0260                 } else {
0261                     styleDecl.setProperty(pId, DOM::DOMString(propvalue.left(important - 1)), true /*important*/, exception);
0262                 }
0263             }
0264         } else
0265             // otherwise add it as a JS property
0266         {
0267             DOMObject::put(exec, propertyName, value, attr);
0268         }
0269     }
0270 }
0271 
0272 JSValue *DOMCSSStyleDeclarationProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0273 {
0274     KJS_CHECK_THIS(KJS::DOMCSSStyleDeclaration, thisObj);
0275     CSSStyleDeclarationImpl &styleDecl = *static_cast<DOMCSSStyleDeclaration *>(thisObj)->impl();
0276 
0277     const DOM::DOMString cssProp = args[0]->toString(exec).domString();
0278 
0279     switch (id) {
0280     case DOMCSSStyleDeclaration::GetPropertyValue:
0281         return jsString(styleDecl.getPropertyValue(cssProp));
0282     case DOMCSSStyleDeclaration::GetPropertyCSSValue:
0283         return getDOMCSSValue(exec, styleDecl.getPropertyCSSValue(cssProp));
0284     case DOMCSSStyleDeclaration::RemoveProperty:
0285         return jsString(styleDecl.removeProperty(cssProp));
0286     case DOMCSSStyleDeclaration::GetPropertyPriority:
0287         return jsString(styleDecl.getPropertyPriority(cssProp));
0288     case DOMCSSStyleDeclaration::SetProperty: {
0289         const DOM::DOMString cssVal = args[1]->toString(exec).domString();
0290         if (cssVal.isEmpty()) {
0291             styleDecl.removeProperty(cssProp);
0292         } else {
0293             styleDecl.setProperty(cssProp, cssVal, args[2]->toString(exec).domString());
0294         }
0295         return jsUndefined();
0296     }
0297     case DOMCSSStyleDeclaration::Item:
0298         return jsString(styleDecl.item(args[0]->toInteger(exec)));
0299     default:
0300         return jsUndefined();
0301     }
0302 }
0303 
0304 JSValue *getDOMCSSStyleDeclaration(ExecState *exec, CSSStyleDeclarationImpl *s)
0305 {
0306     return cacheDOMObject<CSSStyleDeclarationImpl, DOMCSSStyleDeclaration>(exec, s);
0307 }
0308 
0309 // -------------------------------------------------------------------------
0310 
0311 const ClassInfo DOMStyleSheet::info = { "StyleSheet", nullptr, &DOMStyleSheetTable, nullptr };
0312 /*
0313 @begin DOMStyleSheetTable 7
0314   type      DOMStyleSheet::Type     DontDelete|ReadOnly
0315   disabled  DOMStyleSheet::Disabled     DontDelete
0316   ownerNode DOMStyleSheet::OwnerNode    DontDelete|ReadOnly
0317   parentStyleSheet DOMStyleSheet::ParentStyleSheet  DontDelete|ReadOnly
0318   href      DOMStyleSheet::Href     DontDelete|ReadOnly
0319   title     DOMStyleSheet::Title        DontDelete|ReadOnly
0320   media     DOMStyleSheet::Media        DontDelete|ReadOnly
0321 @end
0322 */
0323 KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("StyleSheet", DOMStyleSheetProto, ObjectPrototype)
0324 IMPLEMENT_PSEUDO_CONSTRUCTOR(DOMStyleSheetPseudoCtor, "StyleSheet", DOMStyleSheetProto)
0325 
0326 DOMStyleSheet::DOMStyleSheet(ExecState *exec, DOM::StyleSheetImpl *ss)
0327     : m_impl(ss)
0328 {
0329     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
0330 }
0331 
0332 DOMStyleSheet::~DOMStyleSheet()
0333 {
0334     ScriptInterpreter::forgetDOMObject(m_impl.get());
0335 }
0336 
0337 bool DOMStyleSheet::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0338 {
0339     return getStaticValueSlot<DOMStyleSheet, DOMObject>(exec, &DOMStyleSheetTable, this, propertyName, slot);
0340 }
0341 
0342 JSValue *DOMStyleSheet::getValueProperty(ExecState *exec, int token) const
0343 {
0344     StyleSheetImpl &styleSheet = *m_impl;
0345     switch (token) {
0346     case Type:
0347         return jsString(styleSheet.type());
0348     case Disabled:
0349         return jsBoolean(styleSheet.disabled());
0350     case OwnerNode:
0351         return getDOMNode(exec, styleSheet.ownerNode());
0352     case ParentStyleSheet:
0353         return getDOMStyleSheet(exec, styleSheet.parentStyleSheet());
0354     case Href:
0355         return getStringOrNull(styleSheet.href());
0356     case Title:
0357         return jsString(styleSheet.title());
0358     case Media:
0359         return getDOMMediaList(exec, styleSheet.media());
0360     }
0361     return nullptr;
0362 }
0363 
0364 void DOMStyleSheet::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
0365 {
0366     StyleSheetImpl &styleSheet = *m_impl;
0367     if (propertyName == "disabled") {
0368         styleSheet.setDisabled(value->toBoolean(exec));
0369     } else {
0370         DOMObject::put(exec, propertyName, value, attr);
0371     }
0372 }
0373 
0374 JSValue *getDOMStyleSheet(ExecState *exec, DOM::StyleSheetImpl *ss)
0375 {
0376     if (!ss) {
0377         return jsNull();
0378     }
0379 
0380     DOMObject *ret;
0381     ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
0382     if ((ret = interp->getDOMObject(ss))) {
0383         return ret;
0384     } else {
0385         if (ss->isCSSStyleSheet()) {
0386             CSSStyleSheetImpl *cs = static_cast<CSSStyleSheetImpl *>(ss);
0387             ret = new DOMCSSStyleSheet(exec, cs);
0388         } else {
0389             ret = new DOMStyleSheet(exec, ss);
0390         }
0391         interp->putDOMObject(ss, ret);
0392         return ret;
0393     }
0394 }
0395 
0396 // -------------------------------------------------------------------------
0397 
0398 const ClassInfo DOMStyleSheetList::info = { "StyleSheetList", nullptr, &DOMStyleSheetListTable, nullptr };
0399 
0400 /*
0401 @begin DOMStyleSheetListTable 2
0402   length    DOMStyleSheetList::Length   DontDelete|ReadOnly
0403   item      DOMStyleSheetList::Item     DontDelete|Function 1
0404 @end
0405 */
0406 KJS_IMPLEMENT_PROTOFUNC(DOMStyleSheetListFunc) // not really a proto, but doesn't matter
0407 
0408 DOMStyleSheetList::DOMStyleSheetList(ExecState *exec, DOM::StyleSheetListImpl *ssl, DOM::DocumentImpl *doc)
0409     : m_impl(ssl), m_doc(doc)
0410 {
0411     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
0412 }
0413 
0414 DOMStyleSheetList::~DOMStyleSheetList()
0415 {
0416     ScriptInterpreter::forgetDOMObject(m_impl.get());
0417 }
0418 
0419 JSValue *DOMStyleSheetList::getValueProperty(ExecState *, int token) const
0420 {
0421     switch (token) {
0422     case Length:
0423         return jsNumber(m_impl->length());
0424     default:
0425         assert(0);
0426         return jsUndefined();
0427     }
0428 }
0429 
0430 JSValue *DOMStyleSheetList::indexGetter(ExecState *exec, unsigned index)
0431 {
0432     return getDOMStyleSheet(exec, m_impl->item(index));
0433 }
0434 
0435 JSValue *DOMStyleSheetList::nameGetter(ExecState *exec, JSObject *, const Identifier &propertyName, const PropertySlot &slot)
0436 {
0437     DOMStyleSheetList *thisObj = static_cast<DOMStyleSheetList *>(slot.slotBase());
0438     ElementImpl *element = thisObj->m_doc->getElementById(propertyName.domString());
0439     assert(element->id() == ID_STYLE); //Should be from existence check
0440     return getDOMStyleSheet(exec, static_cast<HTMLStyleElementImpl *>(element)->sheet());
0441 }
0442 
0443 bool DOMStyleSheetList::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0444 {
0445 #ifdef KJS_VERBOSE
0446     qCDebug(KHTML_LOG) << "DOMStyleSheetList::getOwnPropertySlot " << propertyName.qstring();
0447 #endif
0448     if (getStaticOwnPropertySlot<DOMStyleSheetListFunc, DOMStyleSheetList>(&DOMStyleSheetListTable, this, propertyName, slot)) {
0449         return true;
0450     }
0451 
0452     StyleSheetListImpl &styleSheetList = *m_impl;
0453 
0454     // Retrieve stylesheet by index
0455     if (getIndexSlot(this, styleSheetList, propertyName, slot)) {
0456         return true;
0457     }
0458 
0459     // IE also supports retrieving a stylesheet by name, using the name/id of the <style> tag
0460     // (this is consistent with all the other collections)
0461     // ### Bad implementation because returns a single element (are IDs always unique?)
0462     // and doesn't look for name attribute (see implementation above).
0463     // But unicity of stylesheet ids is good practice anyway ;)
0464     ElementImpl *element = m_doc->getElementById(propertyName.domString());
0465     if (element && element->id() == ID_STYLE) {
0466         slot.setCustom(this, nameGetter);
0467         return true;
0468     }
0469 
0470     return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
0471 }
0472 
0473 JSValue *DOMStyleSheetList::callAsFunction(ExecState *exec, JSObject * /*thisObj*/, const List &args)
0474 {
0475     if (args.size() == 1) {
0476         // support for styleSheets(<index>) and styleSheets(<name>)
0477         return get(exec, Identifier(args[0]->toString(exec)));
0478     }
0479     return jsUndefined();
0480 }
0481 
0482 JSValue *getDOMStyleSheetList(ExecState *exec, DOM::StyleSheetListImpl *ssl, DOM::DocumentImpl *doc)
0483 {
0484     // Can't use the cacheDOMObject macro because of the doc argument
0485     DOMObject *ret;
0486     if (!ssl) {
0487         return jsNull();
0488     }
0489     ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
0490     if ((ret = interp->getDOMObject(ssl))) {
0491         return ret;
0492     } else {
0493         ret = new DOMStyleSheetList(exec, ssl, doc);
0494         interp->putDOMObject(ssl, ret);
0495         return ret;
0496     }
0497 }
0498 
0499 JSValue *DOMStyleSheetListFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0500 {
0501     KJS_CHECK_THIS(KJS::DOMStyleSheetList, thisObj);
0502     DOM::StyleSheetListImpl *styleSheetList = static_cast<DOMStyleSheetList *>(thisObj)->impl();
0503     if (id == DOMStyleSheetList::Item) {
0504         return getDOMStyleSheet(exec, styleSheetList->item(args[0]->toInteger(exec)));
0505     }
0506     return jsUndefined();
0507 }
0508 
0509 // -------------------------------------------------------------------------
0510 
0511 const ClassInfo DOMMediaList::info = { "MediaList", nullptr, &DOMMediaListTable, nullptr };
0512 
0513 /*
0514 @begin DOMMediaListTable 2
0515   mediaText DOMMediaList::MediaText     DontDelete|ReadOnly
0516   length    DOMMediaList::Length        DontDelete|ReadOnly
0517 @end
0518 @begin DOMMediaListProtoTable 3
0519   item      DOMMediaList::Item      DontDelete|Function 1
0520   deleteMedium  DOMMediaList::DeleteMedium  DontDelete|Function 1
0521   appendMedium  DOMMediaList::AppendMedium  DontDelete|Function 1
0522 @end
0523 */
0524 KJS_DEFINE_PROTOTYPE(DOMMediaListProto)
0525 KJS_IMPLEMENT_PROTOFUNC(DOMMediaListProtoFunc)
0526 KJS_IMPLEMENT_PROTOTYPE("DOMMediaList", DOMMediaListProto, DOMMediaListProtoFunc, ObjectPrototype)
0527 
0528 DOMMediaList::DOMMediaList(ExecState *exec, DOM::MediaListImpl *ml)
0529     : m_impl(ml)
0530 {
0531     setPrototype(DOMMediaListProto::self(exec));
0532 }
0533 
0534 DOMMediaList::~DOMMediaList()
0535 {
0536     ScriptInterpreter::forgetDOMObject(m_impl.get());
0537 }
0538 
0539 JSValue *DOMMediaList::getValueProperty(ExecState *, int token) const
0540 {
0541     const MediaListImpl &mediaList = *m_impl;
0542     switch (token) {
0543     case MediaText:
0544         return jsString(mediaList.mediaText());
0545     case Length:
0546         return jsNumber(mediaList.length());
0547     default:
0548         assert(0);
0549         return jsUndefined();
0550     }
0551 }
0552 
0553 JSValue *DOMMediaList::indexGetter(ExecState *, unsigned index)
0554 {
0555     return jsString(m_impl->item(index));
0556 }
0557 
0558 bool DOMMediaList::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0559 {
0560     if (getStaticOwnValueSlot(&DOMMediaListTable, this, propertyName, slot)) {
0561         return true;
0562     }
0563 
0564     if (getIndexSlot(this, *m_impl, propertyName, slot)) {
0565         return true;
0566     }
0567 
0568     return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
0569 }
0570 
0571 void DOMMediaList::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
0572 {
0573     if (propertyName == "mediaText") {
0574         DOMExceptionTranslator exception(exec);
0575         m_impl->setMediaText(value->toString(exec).domString(), exception);
0576     } else {
0577         DOMObject::put(exec, propertyName, value, attr);
0578     }
0579 }
0580 
0581 JSValue *getDOMMediaList(ExecState *exec, DOM::MediaListImpl *ml)
0582 {
0583     return cacheDOMObject<DOM::MediaListImpl, KJS::DOMMediaList>(exec, ml);
0584 }
0585 
0586 JSValue *DOMMediaListProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0587 {
0588     KJS_CHECK_THIS(KJS::DOMMediaList, thisObj);
0589     DOM::MediaListImpl &mediaList = *static_cast<DOMMediaList *>(thisObj)->impl();
0590     DOMExceptionTranslator exception(exec);
0591     switch (id) {
0592     case DOMMediaList::Item:
0593         return jsString(mediaList.item(args[0]->toInteger(exec)));
0594     case DOMMediaList::DeleteMedium:
0595         mediaList.deleteMedium(args[0]->toString(exec).domString(), exception);
0596         return jsUndefined();
0597     case DOMMediaList::AppendMedium:
0598         mediaList.appendMedium(args[0]->toString(exec).domString(), exception);
0599         return jsUndefined();
0600     default:
0601         return jsUndefined();
0602     }
0603 }
0604 
0605 // -------------------------------------------------------------------------
0606 
0607 const ClassInfo DOMCSSStyleSheet::info = { "CSSStyleSheet", nullptr, &DOMCSSStyleSheetTable, nullptr };
0608 
0609 /*
0610 @begin DOMCSSStyleSheetTable 2
0611   ownerRule DOMCSSStyleSheet::OwnerRule DontDelete|ReadOnly
0612   cssRules  DOMCSSStyleSheet::CssRules  DontDelete|ReadOnly
0613 # MSIE extension
0614   rules     DOMCSSStyleSheet::Rules     DontDelete|ReadOnly
0615 @end
0616 @begin DOMCSSStyleSheetProtoTable 2
0617   insertRule    DOMCSSStyleSheet::InsertRule    DontDelete|Function 2
0618   deleteRule    DOMCSSStyleSheet::DeleteRule    DontDelete|Function 1
0619 # IE extensions
0620   addRule   DOMCSSStyleSheet::AddRule   DontDelete|Function 3
0621   removeRule    DOMCSSStyleSheet::RemoveRule    DontDelete|Function 1
0622 @end
0623 */
0624 KJS_DEFINE_PROTOTYPE(DOMCSSStyleSheetProto)
0625 KJS_IMPLEMENT_PROTOFUNC(DOMCSSStyleSheetProtoFunc)
0626 KJS_IMPLEMENT_PROTOTYPE("DOMCSSStyleSheet", DOMCSSStyleSheetProto, DOMCSSStyleSheetProtoFunc, DOMStyleSheetProto)
0627 
0628 DOMCSSStyleSheet::DOMCSSStyleSheet(ExecState *exec, DOM::CSSStyleSheetImpl *ss): DOMStyleSheet(exec, ss)
0629 {
0630     setPrototype(DOMCSSStyleSheetProto::self(exec));
0631 }
0632 
0633 DOMCSSStyleSheet::~DOMCSSStyleSheet()
0634 {}
0635 
0636 JSValue *DOMCSSStyleSheet::getValueProperty(ExecState *exec, int token)
0637 {
0638     CSSStyleSheetImpl &cssStyleSheet = *impl();
0639     // MSIE does not list the charset rules in its proprietary extension
0640     bool omitCharsetRules = true;
0641     switch (token) {
0642     case OwnerRule:
0643         return getDOMCSSRule(exec, cssStyleSheet.ownerRule());
0644     case CssRules:
0645         omitCharsetRules = false;
0646     // nobreak
0647     case Rules: {
0648         return getDOMCSSRuleList(exec, cssStyleSheet.cssRules(omitCharsetRules));
0649     }
0650     default:
0651         assert(0);
0652         return jsUndefined();
0653     }
0654 }
0655 
0656 bool DOMCSSStyleSheet::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0657 {
0658     return getStaticValueSlot<DOMCSSStyleSheet, DOMStyleSheet>(exec, &DOMCSSStyleSheetTable, this, propertyName, slot);
0659 }
0660 
0661 JSValue *DOMCSSStyleSheetProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0662 {
0663     KJS_CHECK_THIS(KJS::DOMCSSStyleSheet, thisObj);
0664     DOM::CSSStyleSheetImpl &styleSheet = *static_cast<DOMCSSStyleSheet *>(thisObj)->impl();
0665     DOMExceptionTranslator exception(exec);
0666 
0667     switch (id) {
0668     case DOMCSSStyleSheet::InsertRule:
0669         return jsNumber(styleSheet.insertRule(args[0]->toString(exec).domString(), (long unsigned int)args[1]->toInteger(exec), exception));
0670     case DOMCSSStyleSheet::DeleteRule:
0671         styleSheet.deleteRule(args[0]->toInteger(exec), exception);
0672         return jsUndefined();
0673     // IE extensions
0674     case DOMCSSStyleSheet::AddRule: {
0675         //Unpassed/-1 means append. Since insertRule is picky (throws exceptions)
0676         //we adjust it to the desired length
0677         unsigned long index  = args[2]->toInteger(exec);
0678         unsigned long length = styleSheet.length();
0679         if (args[2]->type() == UndefinedType) {
0680             index = length;
0681         }
0682         if (index > length) {
0683             index = length;
0684         }
0685         DOM::DOMString str = args[0]->toString(exec).domString() + " { " + args[1]->toString(exec).domString() + " } ";
0686         return jsNumber(styleSheet.insertRule(str, index, exception));
0687     }
0688     case DOMCSSStyleSheet::RemoveRule: {
0689         int index = args.size() > 0 ? args[0]->toInteger(exec) : 0 /*first one*/;
0690         styleSheet.deleteRule(index, exception);
0691         return jsUndefined();
0692     }
0693     default:
0694         return jsUndefined();
0695     }
0696 }
0697 
0698 // -------------------------------------------------------------------------
0699 
0700 const ClassInfo DOMCSSRuleList::info = { "CSSRuleList", nullptr, &DOMCSSRuleListTable, nullptr };
0701 /*
0702 @begin DOMCSSRuleListTable 3
0703   length        DOMCSSRuleList::Length      DontDelete|ReadOnly
0704   item          DOMCSSRuleList::Item        DontDelete|Function 1
0705 @end
0706 */
0707 KJS_IMPLEMENT_PROTOFUNC(DOMCSSRuleListFunc) // not really a proto, but doesn't matter
0708 
0709 DOMCSSRuleList::DOMCSSRuleList(ExecState *exec, DOM::CSSRuleListImpl *rl)
0710     : m_impl(rl)
0711 {
0712     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
0713 }
0714 
0715 DOMCSSRuleList::~DOMCSSRuleList()
0716 {
0717     ScriptInterpreter::forgetDOMObject(m_impl.get());
0718 }
0719 
0720 JSValue *DOMCSSRuleList::getValueProperty(ExecState *, int token) const
0721 {
0722     switch (token) {
0723     case Length:
0724         return jsNumber(m_impl->length());
0725     default:
0726         assert(0);
0727         return jsUndefined();
0728     }
0729 }
0730 
0731 JSValue *DOMCSSRuleList::indexGetter(ExecState *exec, unsigned index)
0732 {
0733     return getDOMCSSRule(exec, m_impl->item(index));
0734 }
0735 
0736 bool DOMCSSRuleList::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0737 {
0738     if (getStaticOwnPropertySlot<DOMCSSRuleListFunc, DOMCSSRuleList>(&DOMCSSRuleListTable, this, propertyName, slot)) {
0739         return true;
0740     }
0741 
0742     //Check whether it's an index
0743     //CSSRuleListImpl &cssRuleList = *m_impl;
0744 
0745     if (getIndexSlot(this, *m_impl, propertyName, slot)) {
0746         return true;
0747     }
0748 
0749     return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
0750 }
0751 
0752 JSValue *DOMCSSRuleListFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0753 {
0754     KJS_CHECK_THIS(KJS::DOMCSSRuleList, thisObj);
0755     DOM::CSSRuleListImpl &cssRuleList = *static_cast<DOMCSSRuleList *>(thisObj)->impl();
0756     switch (id) {
0757     case DOMCSSRuleList::Item:
0758         return getDOMCSSRule(exec, cssRuleList.item(args[0]->toInteger(exec)));
0759     default:
0760         return jsUndefined();
0761     }
0762 }
0763 
0764 JSValue *getDOMCSSRuleList(ExecState *exec, DOM::CSSRuleListImpl *rl)
0765 {
0766     return cacheDOMObject<DOM::CSSRuleListImpl, KJS::DOMCSSRuleList>(exec, rl);
0767 }
0768 
0769 // -------------------------------------------------------------------------
0770 
0771 KJS_IMPLEMENT_PROTOFUNC(DOMCSSRuleFunc) // Not a proto, but doesn't matter
0772 
0773 DOMCSSRule::DOMCSSRule(ExecState *exec, DOM::CSSRuleImpl *r)
0774     : m_impl(r)
0775 {
0776     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
0777 }
0778 
0779 DOMCSSRule::~DOMCSSRule()
0780 {
0781     ScriptInterpreter::forgetDOMObject(m_impl.get());
0782 }
0783 
0784 const ClassInfo DOMCSSRule::info = { "CSSRule", nullptr, &DOMCSSRuleTable, nullptr };
0785 const ClassInfo DOMCSSRule::style_info = { "CSSStyleRule", &DOMCSSRule::info, &DOMCSSStyleRuleTable, nullptr };
0786 const ClassInfo DOMCSSRule::media_info = { "CSSMediaRule", &DOMCSSRule::info, &DOMCSSMediaRuleTable, nullptr };
0787 const ClassInfo DOMCSSRule::fontface_info = { "CSSFontFaceRule", &DOMCSSRule::info, &DOMCSSFontFaceRuleTable, nullptr };
0788 const ClassInfo DOMCSSRule::page_info = { "CSSPageRule", &DOMCSSRule::info, &DOMCSSPageRuleTable, nullptr };
0789 const ClassInfo DOMCSSRule::import_info = { "CSSImportRule", &DOMCSSRule::info, &DOMCSSImportRuleTable, nullptr };
0790 const ClassInfo DOMCSSRule::charset_info = { "CSSCharsetRule", &DOMCSSRule::info, &DOMCSSCharsetRuleTable, nullptr };
0791 const ClassInfo DOMCSSRule::namespace_info = { "CSSNamespaceRule", &DOMCSSRule::info, &DOMCSSNamespaceRuleTable, nullptr };
0792 
0793 const ClassInfo *DOMCSSRule::classInfo() const
0794 {
0795     switch (m_impl->type()) {
0796     case DOM::CSSRule::STYLE_RULE:
0797         return &style_info;
0798     case DOM::CSSRule::MEDIA_RULE:
0799         return &media_info;
0800     case DOM::CSSRule::FONT_FACE_RULE:
0801         return &fontface_info;
0802     case DOM::CSSRule::PAGE_RULE:
0803         return &page_info;
0804     case DOM::CSSRule::IMPORT_RULE:
0805         return &import_info;
0806     case DOM::CSSRule::CHARSET_RULE:
0807         return &charset_info;
0808     case DOM::CSSRule::NAMESPACE_RULE:
0809         return &namespace_info;
0810     case DOM::CSSRule::UNKNOWN_RULE:
0811     default:
0812         return &info;
0813     }
0814 }
0815 /*
0816 @begin DOMCSSRuleTable 4
0817   type          DOMCSSRule::Type    DontDelete|ReadOnly
0818   cssText       DOMCSSRule::CssText DontDelete|ReadOnly
0819   parentStyleSheet  DOMCSSRule::ParentStyleSheet    DontDelete|ReadOnly
0820   parentRule        DOMCSSRule::ParentRule  DontDelete|ReadOnly
0821 @end
0822 @begin DOMCSSStyleRuleTable 2
0823   selectorText      DOMCSSRule::Style_SelectorText  DontDelete
0824   style         DOMCSSRule::Style_Style     DontDelete|ReadOnly
0825 @end
0826 @begin DOMCSSMediaRuleTable 4
0827   media         DOMCSSRule::Media_Media     DontDelete|ReadOnly
0828   cssRules      DOMCSSRule::Media_CssRules  DontDelete|ReadOnly
0829   insertRule        DOMCSSRule::Media_InsertRule    DontDelete|Function 2
0830   deleteRule        DOMCSSRule::Media_DeleteRule    DontDelete|Function 1
0831 @end
0832 @begin DOMCSSFontFaceRuleTable 1
0833   style         DOMCSSRule::FontFace_Style  DontDelete|ReadOnly
0834 @end
0835 @begin DOMCSSPageRuleTable 2
0836   selectorText      DOMCSSRule::Page_SelectorText   DontDelete
0837   style         DOMCSSRule::Page_Style      DontDelete|ReadOnly
0838 @end
0839 @begin DOMCSSImportRuleTable 3
0840   href          DOMCSSRule::Import_Href     DontDelete|ReadOnly
0841   media         DOMCSSRule::Import_Media    DontDelete|ReadOnly
0842   styleSheet        DOMCSSRule::Import_StyleSheet   DontDelete|ReadOnly
0843 @end
0844 @begin DOMCSSCharsetRuleTable 1
0845   encoding      DOMCSSRule::Charset_Encoding    DontDelete
0846 @end
0847 @begin DOMCSSNamespaceRuleTable 2
0848   namespaceURI      DOMCSSRule::Namespace_NamespaceURI  DontDelete|ReadOnly
0849   prefix                DOMCSSRule::Namespace_Prefix            DontDelete|ReadOnly
0850 @end
0851 */
0852 bool DOMCSSRule::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0853 {
0854 #ifdef KJS_VERBOSE
0855     qCDebug(KHTML_LOG) << "DOMCSSRule::tryGet " << propertyName.qstring();
0856 #endif
0857     //First do the rule-type-specific stuff
0858     const HashTable *table = classInfo()->propHashTable; // get the right hashtable
0859     if (getStaticOwnPropertySlot<DOMCSSRuleFunc, DOMCSSRule>(table, this, propertyName, slot)) {
0860         return true;
0861     }
0862 
0863     //Now do generic stuff
0864     return getStaticPropertySlot<DOMCSSRuleFunc, DOMCSSRule, DOMObject>(exec, &DOMCSSRuleTable, this, propertyName, slot);
0865 }
0866 
0867 JSValue *DOMCSSRule::getValueProperty(ExecState *exec, int token) const
0868 {
0869     CSSRuleImpl &cssRule = *m_impl;
0870     switch (token) {
0871     case Type:
0872         return jsNumber(cssRule.type());
0873     case CssText:
0874         return jsString(cssRule.cssText());
0875     case ParentStyleSheet:
0876         return getDOMStyleSheet(exec, cssRule.parentStyleSheet());
0877     case ParentRule:
0878         return getDOMCSSRule(exec, cssRule.parentRule());
0879 
0880     // for DOM::CSSRule::STYLE_RULE:
0881     case Style_SelectorText:
0882         return jsString(static_cast<CSSStyleRuleImpl *>(m_impl.get())->selectorText());
0883     case Style_Style:
0884         return getDOMCSSStyleDeclaration(exec, static_cast<CSSStyleRuleImpl *>(m_impl.get())->style());
0885 
0886     // for DOM::CSSRule::MEDIA_RULE:
0887     case Media_Media:
0888         return getDOMMediaList(exec, static_cast<CSSMediaRuleImpl *>(m_impl.get())->media());
0889     case Media_CssRules:
0890         return getDOMCSSRuleList(exec, static_cast<CSSMediaRuleImpl *>(m_impl.get())->cssRules());
0891 
0892     // for DOM::CSSRule::FONT_FACE_RULE:
0893     case FontFace_Style:
0894         return getDOMCSSStyleDeclaration(exec, static_cast<CSSFontFaceRuleImpl *>(m_impl.get())->style());
0895 
0896     // for DOM::CSSRule::PAGE_RULE:
0897     case Page_SelectorText:
0898         return jsString(static_cast<CSSPageRuleImpl *>(m_impl.get())->selectorText());
0899     case Page_Style:
0900         return getDOMCSSStyleDeclaration(exec, static_cast<CSSPageRuleImpl *>(m_impl.get())->style());
0901 
0902     // for DOM::CSSRule::IMPORT_RULE:
0903     case Import_Href:
0904         return jsString(static_cast<CSSImportRuleImpl *>(m_impl.get())->href());
0905     case Import_Media:
0906         return getDOMMediaList(exec, static_cast<CSSImportRuleImpl *>(m_impl.get())->media());
0907     case Import_StyleSheet:
0908         return getDOMStyleSheet(exec, static_cast<CSSImportRuleImpl *>(m_impl.get())->styleSheet());
0909 
0910     // for DOM::CSSRule::CHARSET_RULE:
0911     case Charset_Encoding:
0912         return jsString(static_cast<CSSCharsetRuleImpl *>(m_impl.get())->encoding());
0913 
0914     // for DOM::CSSRule::NAMESPACE_RULE:
0915     case Namespace_Prefix:
0916         return jsString(static_cast<DOM::CSSNamespaceRuleImpl *>(m_impl.get())->prefix());
0917     case Namespace_NamespaceURI:
0918         return jsString(static_cast<DOM::CSSNamespaceRuleImpl *>(m_impl.get())->namespaceURI());
0919     default:
0920         assert(0);
0921     }
0922     return jsUndefined();
0923 }
0924 
0925 void DOMCSSRule::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
0926 {
0927     const HashTable *table = classInfo()->propHashTable; // get the right hashtable
0928     const HashEntry *entry = Lookup::findEntry(table, propertyName);
0929     if (entry) {
0930         if (entry->attr & Function) { // function: put as override property
0931             JSObject::put(exec, propertyName, value, attr);
0932             return;
0933         } else if ((entry->attr & ReadOnly) == 0) { // let lookupPut print the warning if not
0934             putValueProperty(exec, entry->value, value, attr);
0935             return;
0936         }
0937     }
0938     lookupPut<DOMCSSRule, DOMObject>(exec, propertyName, value, attr, &DOMCSSRuleTable, this);
0939 }
0940 
0941 void DOMCSSRule::putValueProperty(ExecState *exec, int token, JSValue *value, int)
0942 {
0943     switch (token) {
0944     // for DOM::CSSRule::STYLE_RULE:
0945     case Style_SelectorText:
0946         static_cast<CSSStyleRuleImpl *>(m_impl.get())->setSelectorText(value->toString(exec).domString());
0947         return;
0948 
0949     // for DOM::CSSRule::PAGE_RULE:
0950     case Page_SelectorText:
0951         static_cast<CSSPageRuleImpl *>(m_impl.get())->setSelectorText(value->toString(exec).domString());
0952         return;
0953 
0954     // for DOM::CSSRule::CHARSET_RULE:
0955     case Charset_Encoding:
0956         static_cast<CSSCharsetRuleImpl *>(m_impl.get())->setEncoding(value->toString(exec).domString());
0957         return;
0958 
0959     default:
0960         // qCDebug(KHTML_LOG) << "DOMCSSRule::putValueProperty unhandled token " << token;
0961         return;
0962     }
0963 }
0964 
0965 JSValue *DOMCSSRuleFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0966 {
0967     KJS_CHECK_THIS(KJS::DOMCSSRule, thisObj);
0968     DOM::CSSRuleImpl &cssRule = *static_cast<DOMCSSRule *>(thisObj)->impl();
0969 
0970     if (cssRule.type() == DOM::CSSRule::MEDIA_RULE) {
0971         DOM::CSSMediaRuleImpl &rule = static_cast<DOM::CSSMediaRuleImpl &>(cssRule);
0972         if (id == DOMCSSRule::Media_InsertRule) {
0973             return jsNumber(rule.insertRule(args[0]->toString(exec).domString(), args[1]->toInteger(exec)));
0974         } else if (id == DOMCSSRule::Media_DeleteRule) {
0975             rule.deleteRule(args[0]->toInteger(exec));
0976         }
0977     }
0978 
0979     return jsUndefined();
0980 }
0981 
0982 JSValue *getDOMCSSRule(ExecState *exec, DOM::CSSRuleImpl *r)
0983 {
0984     return cacheDOMObject<DOM::CSSRuleImpl, KJS::DOMCSSRule>(exec, r);
0985 }
0986 
0987 // -------------------------------------------------------------------------
0988 
0989 const ClassInfo CSSRuleConstructor::info = { "CSSRuleConstructor", nullptr, &CSSRuleConstructorTable, nullptr };
0990 /*
0991 @begin CSSRuleConstructorTable 7
0992   UNKNOWN_RULE  CSSRuleConstructor::UNKNOWN_RULE    DontDelete|ReadOnly
0993   STYLE_RULE    CSSRuleConstructor::STYLE_RULE      DontDelete|ReadOnly
0994   CHARSET_RULE  CSSRuleConstructor::CHARSET_RULE    DontDelete|ReadOnly
0995   IMPORT_RULE   CSSRuleConstructor::IMPORT_RULE     DontDelete|ReadOnly
0996   MEDIA_RULE    CSSRuleConstructor::MEDIA_RULE      DontDelete|ReadOnly
0997   FONT_FACE_RULE CSSRuleConstructor::FONT_FACE_RULE DontDelete|ReadOnly
0998   PAGE_RULE CSSRuleConstructor::PAGE_RULE       DontDelete|ReadOnly
0999 @end
1000 */
1001 
1002 CSSRuleConstructor::CSSRuleConstructor(ExecState *exec)
1003 {
1004     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1005 }
1006 
1007 bool CSSRuleConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1008 {
1009     return getStaticValueSlot<CSSRuleConstructor, DOMObject>(exec, &CSSRuleConstructorTable, this, propertyName, slot);
1010 }
1011 
1012 JSValue *CSSRuleConstructor::getValueProperty(ExecState *, int token) const
1013 {
1014     switch (token) {
1015     case UNKNOWN_RULE:
1016         return jsNumber(DOM::CSSRule::UNKNOWN_RULE);
1017     case STYLE_RULE:
1018         return jsNumber(DOM::CSSRule::STYLE_RULE);
1019     case CHARSET_RULE:
1020         return jsNumber(DOM::CSSRule::CHARSET_RULE);
1021     case IMPORT_RULE:
1022         return jsNumber(DOM::CSSRule::IMPORT_RULE);
1023     case MEDIA_RULE:
1024         return jsNumber(DOM::CSSRule::MEDIA_RULE);
1025     case FONT_FACE_RULE:
1026         return jsNumber(DOM::CSSRule::FONT_FACE_RULE);
1027     case PAGE_RULE:
1028         return jsNumber(DOM::CSSRule::PAGE_RULE);
1029     }
1030     return nullptr;
1031 }
1032 
1033 JSValue *getCSSRuleConstructor(ExecState *exec)
1034 {
1035     return cacheGlobalObject<CSSRuleConstructor>(exec, "[[cssRule.constructor]]");
1036 }
1037 
1038 // -------------------------------------------------------------------------
1039 
1040 const ClassInfo DOMCSSValue::info = { "CSSValue", nullptr, &DOMCSSValueTable, nullptr };
1041 
1042 /*
1043 @begin DOMCSSValueTable 2
1044   cssText   DOMCSSValue::CssText        DontDelete|ReadOnly
1045   cssValueType  DOMCSSValue::CssValueType   DontDelete|ReadOnly
1046 @end
1047 */
1048 
1049 DOMCSSValue::DOMCSSValue(ExecState *exec, DOM::CSSValueImpl *val)
1050     : m_impl(val)
1051 {
1052     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1053 }
1054 
1055 DOMCSSValue::~DOMCSSValue()
1056 {
1057     ScriptInterpreter::forgetDOMObject(m_impl.get());
1058 }
1059 
1060 JSValue *DOMCSSValue::getValueProperty(ExecState *, int token) const
1061 {
1062     CSSValueImpl &cssValue = *m_impl;
1063     switch (token) {
1064     case CssText:
1065         return jsString(cssValue.cssText());
1066     case CssValueType:
1067         return jsNumber(cssValue.cssValueType());
1068     default:
1069         assert(0);
1070         return jsUndefined();
1071     }
1072 }
1073 
1074 bool DOMCSSValue::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1075 {
1076     return getStaticValueSlot<DOMCSSValue, DOMObject>(exec, &DOMCSSValueTable, this, propertyName, slot);
1077 }
1078 
1079 void DOMCSSValue::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
1080 {
1081     CSSValueImpl &cssValue = *m_impl;
1082     if (propertyName == "cssText") {
1083         cssValue.setCssText(value->toString(exec).domString());
1084     } else {
1085         DOMObject::put(exec, propertyName, value, attr);
1086     }
1087 }
1088 
1089 JSValue *getDOMCSSValue(ExecState *exec, DOM::CSSValueImpl *v)
1090 {
1091     DOMObject *ret;
1092     if (!v) {
1093         return jsNull();
1094     }
1095     ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1096     if ((ret = interp->getDOMObject(v))) {
1097         return ret;
1098     } else {
1099         if (v->isValueList()) {
1100             ret = new DOMCSSValueList(exec, static_cast<CSSValueListImpl *>(v));
1101         } else if (v->isPrimitiveValue()) {
1102             ret = new DOMCSSPrimitiveValue(exec, static_cast<CSSPrimitiveValueImpl *>(v));
1103         } else {
1104             ret = new DOMCSSValue(exec, v);
1105         }
1106         interp->putDOMObject(v, ret);
1107         return ret;
1108     }
1109 }
1110 
1111 // -------------------------------------------------------------------------
1112 
1113 const ClassInfo CSSValueConstructor::info = { "CSSValueConstructor", nullptr, &CSSValueConstructorTable, nullptr };
1114 /*
1115 @begin CSSValueConstructorTable 5
1116   CSS_INHERIT       CSSValueConstructor::CSS_INHERIT        DontDelete|ReadOnly
1117   CSS_PRIMITIVE_VALUE   CSSValueConstructor::CSS_PRIMITIVE_VALUE    DontDelete|ReadOnly
1118   CSS_VALUE_LIST    CSSValueConstructor::CSS_VALUE_LIST     DontDelete|ReadOnly
1119   CSS_CUSTOM        CSSValueConstructor::CSS_CUSTOM         DontDelete|ReadOnly
1120 @end
1121 */
1122 
1123 CSSValueConstructor::CSSValueConstructor(ExecState *exec)
1124 {
1125     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1126 }
1127 
1128 bool CSSValueConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1129 {
1130     return getStaticValueSlot<CSSValueConstructor, DOMObject>(exec, &CSSValueConstructorTable, this, propertyName, slot);
1131 }
1132 
1133 JSValue *CSSValueConstructor::getValueProperty(ExecState *, int token) const
1134 {
1135     switch (token) {
1136     case CSS_INHERIT:
1137         return jsNumber(DOM::CSSValue::CSS_INHERIT);
1138     case CSS_PRIMITIVE_VALUE:
1139         return jsNumber(DOM::CSSValue::CSS_PRIMITIVE_VALUE);
1140     case CSS_VALUE_LIST:
1141         return jsNumber(DOM::CSSValue::CSS_VALUE_LIST);
1142     case CSS_CUSTOM:
1143         return jsNumber(DOM::CSSValue::CSS_CUSTOM);
1144     }
1145     return nullptr;
1146 }
1147 
1148 JSValue *getCSSValueConstructor(ExecState *exec)
1149 {
1150     return cacheGlobalObject<CSSValueConstructor>(exec, "[[cssValue.constructor]]");
1151 }
1152 
1153 // -------------------------------------------------------------------------
1154 
1155 const ClassInfo DOMCSSPrimitiveValue::info = { "CSSPrimitiveValue", nullptr, &DOMCSSPrimitiveValueTable, nullptr };
1156 /*
1157 @begin DOMCSSPrimitiveValueTable 1
1158   primitiveType     DOMCSSPrimitiveValue::PrimitiveType DontDelete|ReadOnly
1159 @end
1160 @begin DOMCSSPrimitiveValueProtoTable 3
1161   setFloatValue     DOMCSSPrimitiveValue::SetFloatValue DontDelete|Function 2
1162   getFloatValue     DOMCSSPrimitiveValue::GetFloatValue DontDelete|Function 1
1163   setStringValue    DOMCSSPrimitiveValue::SetStringValue    DontDelete|Function 2
1164   getStringValue    DOMCSSPrimitiveValue::GetStringValue    DontDelete|Function 0
1165   getCounterValue   DOMCSSPrimitiveValue::GetCounterValue   DontDelete|Function 0
1166   getRectValue      DOMCSSPrimitiveValue::GetRectValue  DontDelete|Function 0
1167   getRGBColorValue  DOMCSSPrimitiveValue::GetRGBColorValue  DontDelete|Function 0
1168 @end
1169 */
1170 KJS_DEFINE_PROTOTYPE(DOMCSSPrimitiveValueProto)
1171 KJS_IMPLEMENT_PROTOFUNC(DOMCSSPrimitiveValueProtoFunc)
1172 KJS_IMPLEMENT_PROTOTYPE("DOMCSSPrimitiveValue", DOMCSSPrimitiveValueProto, DOMCSSPrimitiveValueProtoFunc, ObjectPrototype)
1173 
1174 DOMCSSPrimitiveValue::DOMCSSPrimitiveValue(ExecState *exec, DOM::CSSPrimitiveValueImpl *v)
1175     : DOMCSSValue(exec, v)
1176 {
1177     setPrototype(DOMCSSPrimitiveValueProto::self(exec));
1178 }
1179 
1180 JSValue *DOMCSSPrimitiveValue::getValueProperty(ExecState *, int token)
1181 {
1182     assert(token == PrimitiveType);
1183     Q_UNUSED(token);
1184     return jsNumber(static_cast<CSSPrimitiveValueImpl *>(impl())->primitiveType());
1185 }
1186 
1187 bool DOMCSSPrimitiveValue::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1188 {
1189     return getStaticValueSlot<DOMCSSPrimitiveValue, DOMCSSValue>(exec, &DOMCSSPrimitiveValueTable, this, propertyName, slot);
1190 }
1191 
1192 JSValue *DOMCSSPrimitiveValueProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1193 {
1194     KJS_CHECK_THIS(KJS::DOMCSSPrimitiveValue, thisObj);
1195     CSSPrimitiveValueImpl &val = *static_cast<CSSPrimitiveValueImpl *>(static_cast<DOMCSSPrimitiveValue *>(thisObj)->impl());
1196     DOMExceptionTranslator exception(exec);
1197     switch (id) {
1198     case DOMCSSPrimitiveValue::SetFloatValue:
1199         val.setFloatValue(args[0]->toInteger(exec), args[1]->toNumber(exec), exception);
1200         return jsUndefined();
1201     case DOMCSSPrimitiveValue::GetFloatValue:
1202         //### FIXME: exception?
1203         return jsNumber(val.floatValue(args[0]->toInteger(exec)));
1204     case DOMCSSPrimitiveValue::SetStringValue:
1205         val.setStringValue(args[0]->toInteger(exec), args[1]->toString(exec).domString(), exception);
1206         return jsUndefined();
1207     case DOMCSSPrimitiveValue::GetStringValue:
1208         return jsString(DOM::DOMString(val.getStringValue()));
1209     case DOMCSSPrimitiveValue::GetCounterValue:
1210         return getDOMCounter(exec, val.getCounterValue());
1211     case DOMCSSPrimitiveValue::GetRectValue:
1212         return getDOMRect(exec, val.getRectValue());
1213     case DOMCSSPrimitiveValue::GetRGBColorValue:
1214         return getDOMRGBColor(exec, val.getRGBColorValue());
1215     default:
1216         return jsUndefined();
1217     }
1218 }
1219 
1220 // -------------------------------------------------------------------------
1221 
1222 const ClassInfo CSSPrimitiveValueConstructor::info = { "CSSPrimitiveValueConstructor", nullptr, &CSSPrimitiveValueConstructorTable, nullptr };
1223 
1224 /*
1225 @begin CSSPrimitiveValueConstructorTable 28
1226   CSS_UNKNOWN       DOM::CSSPrimitiveValue::CSS_UNKNOWN DontDelete|ReadOnly
1227   CSS_NUMBER        DOM::CSSPrimitiveValue::CSS_NUMBER  DontDelete|ReadOnly
1228   CSS_PERCENTAGE    DOM::CSSPrimitiveValue::CSS_PERCENTAGE  DontDelete|ReadOnly
1229   CSS_EMS           DOM::CSSPrimitiveValue::CSS_EMS     DontDelete|ReadOnly
1230   CSS_EXS           DOM::CSSPrimitiveValue::CSS_EXS     DontDelete|ReadOnly
1231   CSS_CHS           DOM::CSSPrimitiveValue::CSS_CHS     DontDelete|ReadOnly
1232   CSS_REMS          DOM::CSSPrimitiveValue::CSS_REMS    DontDelete|ReadOnly
1233   CSS_PX            DOM::CSSPrimitiveValue::CSS_PX      DontDelete|ReadOnly
1234   CSS_CM            DOM::CSSPrimitiveValue::CSS_CM      DontDelete|ReadOnly
1235   CSS_MM            DOM::CSSPrimitiveValue::CSS_MM      DontDelete|ReadOnly
1236   CSS_IN            DOM::CSSPrimitiveValue::CSS_IN      DontDelete|ReadOnly
1237   CSS_PT            DOM::CSSPrimitiveValue::CSS_PT      DontDelete|ReadOnly
1238   CSS_PC            DOM::CSSPrimitiveValue::CSS_PC      DontDelete|ReadOnly
1239   CSS_DEG           DOM::CSSPrimitiveValue::CSS_DEG     DontDelete|ReadOnly
1240   CSS_RAD           DOM::CSSPrimitiveValue::CSS_RAD     DontDelete|ReadOnly
1241   CSS_GRAD          DOM::CSSPrimitiveValue::CSS_GRAD    DontDelete|ReadOnly
1242   CSS_MS            DOM::CSSPrimitiveValue::CSS_MS      DontDelete|ReadOnly
1243   CSS_S         DOM::CSSPrimitiveValue::CSS_S       DontDelete|ReadOnly
1244   CSS_HZ            DOM::CSSPrimitiveValue::CSS_HZ      DontDelete|ReadOnly
1245   CSS_KHZ           DOM::CSSPrimitiveValue::CSS_KHZ     DontDelete|ReadOnly
1246   CSS_DIMENSION     DOM::CSSPrimitiveValue::CSS_DIMENSION   DontDelete|ReadOnly
1247   CSS_STRING        DOM::CSSPrimitiveValue::CSS_STRING  DontDelete|ReadOnly
1248   CSS_URI           DOM::CSSPrimitiveValue::CSS_URI     DontDelete|ReadOnly
1249   CSS_IDENT         DOM::CSSPrimitiveValue::CSS_IDENT   DontDelete|ReadOnly
1250   CSS_ATTR          DOM::CSSPrimitiveValue::CSS_ATTR    DontDelete|ReadOnly
1251   CSS_COUNTER       DOM::CSSPrimitiveValue::CSS_COUNTER DontDelete|ReadOnly
1252   CSS_RECT          DOM::CSSPrimitiveValue::CSS_RECT    DontDelete|ReadOnly
1253   CSS_RGBCOLOR      DOM::CSSPrimitiveValue::CSS_RGBCOLOR    DontDelete|ReadOnly
1254 @end
1255 */
1256 
1257 bool CSSPrimitiveValueConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1258 {
1259     return getStaticValueSlot<CSSPrimitiveValueConstructor, DOMObject>(exec, &CSSPrimitiveValueConstructorTable, this, propertyName, slot);
1260 }
1261 
1262 JSValue *CSSPrimitiveValueConstructor::getValueProperty(ExecState *, int token) const
1263 {
1264     // We use the token as the value to return directly
1265     return jsNumber(token);
1266 }
1267 
1268 JSValue *getCSSPrimitiveValueConstructor(ExecState *exec)
1269 {
1270     return cacheGlobalObject<CSSPrimitiveValueConstructor>(exec, "[[cssPrimitiveValue.constructor]]");
1271 }
1272 
1273 // -------------------------------------------------------------------------
1274 
1275 const ClassInfo DOMCSSValueList::info = { "CSSValueList", nullptr, &DOMCSSValueListTable, nullptr };
1276 
1277 /*
1278 @begin DOMCSSValueListTable 3
1279   length        DOMCSSValueList::Length     DontDelete|ReadOnly
1280   item          DOMCSSValueList::Item       DontDelete|Function 1
1281 @end
1282 */
1283 KJS_IMPLEMENT_PROTOFUNC(DOMCSSValueListFunc) // not really a proto, but doesn't matter
1284 
1285 DOMCSSValueList::DOMCSSValueList(ExecState *exec, DOM::CSSValueListImpl *v)
1286     : DOMCSSValue(exec, v) { }
1287 
1288 JSValue *DOMCSSValueList::indexGetter(ExecState *exec, unsigned index)
1289 {
1290     return getDOMCSSValue(exec, impl()->item(index));
1291 }
1292 
1293 bool DOMCSSValueList::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1294 {
1295     if (getStaticOwnPropertySlot<DOMCSSValueListFunc, DOMCSSValueList>(
1296                 &DOMCSSValueListTable, this, propertyName, slot)) {
1297         return true;
1298     }
1299 
1300     CSSValueListImpl &valueList = *static_cast<CSSValueListImpl *>(impl());
1301     if (getIndexSlot(this, valueList, propertyName, slot)) {
1302         return true;
1303     }
1304 
1305     return DOMCSSValue::getOwnPropertySlot(exec, propertyName, slot);
1306 }
1307 
1308 JSValue *DOMCSSValueListFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1309 {
1310     KJS_CHECK_THIS(KJS::DOMCSSValueList, thisObj);
1311     CSSValueListImpl &valueList = *static_cast<CSSValueListImpl *>(static_cast<DOMCSSValueList *>(thisObj)->impl());
1312     switch (id) {
1313     case DOMCSSValueList::Item:
1314         return getDOMCSSValue(exec, valueList.item(args[0]->toInteger(exec)));
1315     default:
1316         return jsUndefined();
1317     }
1318 }
1319 
1320 // -------------------------------------------------------------------------
1321 
1322 const ClassInfo DOMRGBColor::info = { "RGBColor", nullptr, &DOMRGBColorTable, nullptr };
1323 
1324 /*
1325 @begin DOMRGBColorTable 3
1326   red   DOMRGBColor::Red    DontDelete|ReadOnly
1327   green DOMRGBColor::Green  DontDelete|ReadOnly
1328   blue  DOMRGBColor::Blue   DontDelete|ReadOnly
1329 @end
1330 */
1331 
1332 DOMRGBColor::DOMRGBColor(ExecState *exec, QRgb c)
1333     : m_color(c)
1334 {
1335     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1336 }
1337 
1338 bool DOMRGBColor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1339 {
1340     return getStaticValueSlot<DOMRGBColor, DOMObject>(exec, &DOMRGBColorTable, this, propertyName, slot);
1341 }
1342 
1343 JSValue *DOMRGBColor::getValueProperty(ExecState *exec, int token) const
1344 {
1345     int color;
1346     switch (token) {
1347     case Red:
1348         color = qRed(m_color); break;
1349     case Green:
1350         color = qGreen(m_color); break;
1351     case Blue:
1352         color = qBlue(m_color); break;
1353     default:
1354         assert(0);
1355         return jsUndefined();
1356     }
1357 
1358     return new DOMCSSPrimitiveValue(exec, new CSSPrimitiveValueImpl(color, CSSPrimitiveValue::CSS_NUMBER));
1359 }
1360 
1361 JSValue *getDOMRGBColor(ExecState *exec, unsigned color)
1362 {
1363     // ### implement equals for RGBColor since they're not refcounted objects
1364     return new DOMRGBColor(exec, color);
1365 }
1366 
1367 // -------------------------------------------------------------------------
1368 
1369 const ClassInfo DOMRect::info = { "Rect", nullptr, &DOMRectTable, nullptr };
1370 /*
1371 @begin DOMRectTable 4
1372   top   DOMRect::Top    DontDelete|ReadOnly
1373   right DOMRect::Right  DontDelete|ReadOnly
1374   bottom DOMRect::Bottom DontDelete|ReadOnly
1375   left  DOMRect::Left   DontDelete|ReadOnly
1376 @end
1377 */
1378 
1379 DOMRect::DOMRect(ExecState *exec, DOM::RectImpl *r)
1380     : m_impl(r)
1381 {
1382     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1383 }
1384 
1385 DOMRect::~DOMRect()
1386 {
1387     ScriptInterpreter::forgetDOMObject(m_impl.get());
1388 }
1389 
1390 bool DOMRect::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1391 {
1392     return getStaticValueSlot<DOMRect, DOMObject>(exec, &DOMRectTable, this, propertyName, slot);
1393 }
1394 
1395 JSValue *DOMRect::getValueProperty(ExecState *exec, int token) const
1396 {
1397     DOM::RectImpl &rect = *m_impl;
1398     switch (token) {
1399     case Top:
1400         return getDOMCSSValue(exec, rect.top());
1401     case Right:
1402         return getDOMCSSValue(exec, rect.right());
1403     case Bottom:
1404         return getDOMCSSValue(exec, rect.bottom());
1405     case Left:
1406         return getDOMCSSValue(exec, rect.left());
1407     default:
1408         return nullptr;
1409     }
1410 }
1411 
1412 JSValue *getDOMRect(ExecState *exec, DOM::RectImpl *r)
1413 {
1414     return cacheDOMObject<DOM::RectImpl, KJS::DOMRect>(exec, r);
1415 }
1416 
1417 // -------------------------------------------------------------------------
1418 
1419 const ClassInfo DOMCounter::info = { "Counter", nullptr, &DOMCounterTable, nullptr };
1420 /*
1421 @begin DOMCounterTable 3
1422   identifier    DOMCounter::identifier  DontDelete|ReadOnly
1423   listStyle DOMCounter::listStyle   DontDelete|ReadOnly
1424   separator DOMCounter::separator   DontDelete|ReadOnly
1425 @end
1426 */
1427 DOMCounter::DOMCounter(ExecState *exec, DOM::CounterImpl *c)
1428     : m_impl(c)
1429 {
1430     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1431 }
1432 
1433 DOMCounter::~DOMCounter()
1434 {
1435     ScriptInterpreter::forgetDOMObject(m_impl.get());
1436 }
1437 
1438 bool DOMCounter::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1439 {
1440     return getStaticValueSlot<DOMCounter, DOMObject>(exec, &DOMCounterTable, this, propertyName, slot);
1441 }
1442 
1443 JSValue *DOMCounter::getValueProperty(ExecState *, int token) const
1444 {
1445     CounterImpl &counter = *m_impl;
1446     switch (token) {
1447     case identifier:
1448         return jsString(counter.identifier());
1449     case listStyle:
1450         return jsString(khtml::stringForListStyleType((khtml::EListStyleType)counter.listStyle()));
1451     case separator:
1452         return jsString(counter.separator());
1453     default:
1454         return nullptr;
1455     }
1456 }
1457 
1458 JSValue *getDOMCounter(ExecState *exec, DOM::CounterImpl *c)
1459 {
1460     return cacheDOMObject<DOM::CounterImpl, KJS::DOMCounter>(exec, c);
1461 }
1462 
1463 }
1464