JavaScriptCore:
[WebKit-https.git] / WebCore / khtml / ecma / kjs_css.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
6  *  Copyright (C) 2004 Apple Computer, Inc.
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "kjs_css.h"
25
26 #include "css/css_base.h"
27 #include "css/css_ruleimpl.h"
28 #include "css/css_stylesheetimpl.h"
29 #include "css/css_valueimpl.h"
30 #include "xml/dom_docimpl.h"
31 #include "html/html_headimpl.h" // for HTMLStyleElement
32 #include "kjs_dom.h"
33 #include "htmlnames.h"
34
35 #include <kdebug.h>
36
37 #include "kjs_css.lut.h"
38
39 using namespace DOM::HTMLNames;
40
41 using DOM::CSSCharsetRuleImpl;
42 using DOM::CSSFontFaceRuleImpl;
43 using DOM::CSSImportRuleImpl;
44 using DOM::CSSMediaRuleImpl;
45 using DOM::CSSPageRuleImpl;
46 using DOM::CSSPrimitiveValue;
47 using DOM::CSSPrimitiveValueImpl;
48 using DOM::CSSRule;
49 using DOM::CSSRuleImpl;
50 using DOM::CSSRuleListImpl;
51 using DOM::CSSStyleDeclarationImpl;
52 using DOM::CSSStyleRuleImpl;
53 using DOM::CSSStyleSheetImpl;
54 using DOM::CSSValue;
55 using DOM::CSSValueImpl;
56 using DOM::CSSValueListImpl;
57 using DOM::CounterImpl;
58 using DOM::DocumentImpl;
59 using DOM::DOMString;
60 using DOM::ElementImpl;
61 using DOM::HTMLStyleElementImpl;
62 using DOM::MediaListImpl;
63 using DOM::RectImpl;
64 using DOM::StyleSheetImpl;
65 using DOM::StyleSheetListImpl;
66
67 namespace KJS {
68
69 static DOMString cssPropertyName(const Identifier &p, bool *hadPixelOrPosPrefix = 0)
70 {
71     QString prop = p.qstring();
72
73     int i = prop.length();
74     while (--i) {
75         char c = prop[i].latin1();
76         if (c >= 'A' && c <= 'Z')
77             prop.insert(i, '-');
78     }
79
80     prop = prop.lower();
81
82     if (hadPixelOrPosPrefix)
83         *hadPixelOrPosPrefix = false;
84
85     if (prop.startsWith("css-")) {
86         prop = prop.mid(4);
87     } else if (prop.startsWith("pixel-")) {
88         prop = prop.mid(6);
89         if (hadPixelOrPosPrefix)
90             *hadPixelOrPosPrefix = true;
91     } else if (prop.startsWith("pos-")) {
92         prop = prop.mid(4);
93         if (hadPixelOrPosPrefix)
94             *hadPixelOrPosPrefix = true;
95     } else if (prop.startsWith("khtml-") || prop.startsWith("apple-") || prop.startsWith("moz-")) {
96         prop.insert(0, '-');
97     }
98
99     return prop;
100 }
101
102 static bool isCSSPropertyName(const Identifier &JSPropertyName)
103 {
104     return CSSStyleDeclarationImpl::isPropertyName(cssPropertyName(JSPropertyName));
105 }
106
107 /*
108 @begin DOMCSSStyleDeclarationProtoTable 7
109   getPropertyValue      DOMCSSStyleDeclaration::GetPropertyValue        DontDelete|Function 1
110   getPropertyCSSValue   DOMCSSStyleDeclaration::GetPropertyCSSValue     DontDelete|Function 1
111   removeProperty        DOMCSSStyleDeclaration::RemoveProperty          DontDelete|Function 1
112   getPropertyPriority   DOMCSSStyleDeclaration::GetPropertyPriority     DontDelete|Function 1
113   getPropertyShorthand  DOMCSSStyleDeclaration::GetPropertyShorthand    DontDelete|Function 1
114   isPropertyImplicit    DOMCSSStyleDeclaration::IsPropertyImplicit      DontDelete|Function 1
115   setProperty           DOMCSSStyleDeclaration::SetProperty             DontDelete|Function 3
116   item                  DOMCSSStyleDeclaration::Item                    DontDelete|Function 1
117 @end
118 @begin DOMCSSStyleDeclarationTable 3
119   cssText               DOMCSSStyleDeclaration::CssText         DontDelete
120   length                DOMCSSStyleDeclaration::Length          DontDelete|ReadOnly
121   parentRule            DOMCSSStyleDeclaration::ParentRule      DontDelete|ReadOnly
122 @end
123 */
124 DEFINE_PROTOTYPE("DOMCSSStyleDeclaration", DOMCSSStyleDeclarationProto)
125 IMPLEMENT_PROTOFUNC(DOMCSSStyleDeclarationProtoFunc)
126 IMPLEMENT_PROTOTYPE(DOMCSSStyleDeclarationProto, DOMCSSStyleDeclarationProtoFunc)
127
128 const ClassInfo DOMCSSStyleDeclaration::info = { "CSSStyleDeclaration", 0, &DOMCSSStyleDeclarationTable, 0 };
129
130 DOMCSSStyleDeclaration::DOMCSSStyleDeclaration(ExecState *exec, CSSStyleDeclarationImpl *s)
131   : m_impl(s)
132
133   setPrototype(DOMCSSStyleDeclarationProto::self(exec));
134 }
135
136 DOMCSSStyleDeclaration::~DOMCSSStyleDeclaration()
137 {
138   ScriptInterpreter::forgetDOMObject(m_impl.get());
139 }
140
141 ValueImp *DOMCSSStyleDeclaration::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
142 {
143   DOMCSSStyleDeclaration *thisObj = static_cast<DOMCSSStyleDeclaration *>(slot.slotBase());
144   return jsStringOrNull(thisObj->m_impl->item(slot.index()));
145 }
146
147 ValueImp *DOMCSSStyleDeclaration::cssPropertyGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
148 {
149   DOMCSSStyleDeclaration *thisObj = static_cast<DOMCSSStyleDeclaration *>(slot.slotBase());
150
151   // Set up pixelOrPos boolean to handle the fact that
152   // pixelTop returns "CSS Top" as number value in unit pixels
153   // posTop returns "CSS top" as number value in unit pixels _if_ its a
154   // positioned element. if it is not a positioned element, return 0
155   // from MSIE documentation ### IMPLEMENT THAT (Dirk)
156   bool pixelOrPos;
157   DOMString prop = cssPropertyName(propertyName, &pixelOrPos);
158   CSSValueImpl *v = thisObj->m_impl->getPropertyCSSValue(prop);
159   if (v) {
160     if (pixelOrPos && v->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE)
161       return jsNumber(static_cast<CSSPrimitiveValueImpl *>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX));
162     else
163       return jsStringOrNull(v->cssText());
164   } else
165     return jsString("");
166 }
167
168 bool DOMCSSStyleDeclaration::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
169 {
170   const HashEntry* entry = Lookup::findEntry(&DOMCSSStyleDeclarationTable, propertyName);
171
172   if (entry) {
173     slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSStyleDeclaration>);
174     return true;
175   }
176
177   bool ok;
178   unsigned u = propertyName.toUInt32(&ok);
179   if (ok) {
180     slot.setCustomIndex(this, u, indexGetter);
181     return true;
182   }
183
184   if (isCSSPropertyName(propertyName)) {
185     slot.setCustom(this, cssPropertyGetter);
186     return true;
187   }
188
189   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
190 }
191
192 ValueImp *DOMCSSStyleDeclaration::getValueProperty(ExecState *exec, int token)
193 {
194   switch (token) {
195   case CssText:
196     return jsStringOrNull(m_impl->cssText());
197   case Length:
198     return jsNumber(m_impl->length());
199   case ParentRule:
200     return getDOMCSSRule(exec, m_impl->parentRule());
201   default:
202     assert(0);
203     return jsUndefined();
204   }
205 }
206
207 void DOMCSSStyleDeclaration::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr )
208 {
209 #ifdef KJS_VERBOSE
210   kdDebug(6070) << "DOMCSSStyleDeclaration::put " << propertyName.qstring() << endl;
211 #endif
212   DOMExceptionTranslator exception(exec);
213   CSSStyleDeclarationImpl &styleDecl = *m_impl;
214   if (propertyName == "cssText") {
215     styleDecl.setCssText(value->toString(exec).domString(), exception);
216   } else {
217     if (isCSSPropertyName(propertyName)) {
218       bool pixelOrPos;
219       DOMString prop = cssPropertyName(propertyName, &pixelOrPos);
220       QString propvalue = value->toString(exec).qstring();
221       if (pixelOrPos)
222         propvalue += "px";
223 #ifdef KJS_VERBOSE
224       kdDebug(6070) << "DOMCSSStyleDeclaration: prop=" << prop << " propvalue=" << propvalue << endl;
225 #endif
226       styleDecl.removeProperty(prop, exception);
227       if (!exception && !propvalue.isEmpty()) {
228         // We have to ignore exceptions here, because of the following unfortunate situation:
229         //   1) Older versions ignored exceptions here by accident, because the put function
230         //      that translated exceptions did not translate CSS exceptions.
231         //   2) Gecko does not raise an exception in this case, although WinIE does.
232         //   3) At least some Dashboard widgets are depending on this behavior.
233         // It would be nice to fix this some day, perhaps with some kind of "quirks mode",
234         // but it's likely that the Dashboard widgets are already using a strict mode DOCTYPE.
235         int ignoreException = 0;
236         styleDecl.setProperty(prop, DOMString(propvalue), "", ignoreException);
237       }
238     } else {
239       DOMObject::put(exec, propertyName, value, attr);
240     }
241   }
242 }
243
244 ValueImp *DOMCSSStyleDeclarationProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
245 {
246   if (!thisObj->inherits(&KJS::DOMCSSStyleDeclaration::info))
247     return throwError(exec, TypeError);
248   DOMExceptionTranslator exception(exec);
249   CSSStyleDeclarationImpl &styleDecl = *static_cast<DOMCSSStyleDeclaration *>(thisObj)->impl();
250   UString str = args[0]->toString(exec);
251   DOM::DOMString s = str.domString();
252
253   switch (id) {
254     case DOMCSSStyleDeclaration::GetPropertyValue:
255       return jsStringOrNull(styleDecl.getPropertyValue(s));
256     case DOMCSSStyleDeclaration::GetPropertyCSSValue:
257       return getDOMCSSValue(exec,styleDecl.getPropertyCSSValue(s));
258     case DOMCSSStyleDeclaration::RemoveProperty:
259       return jsStringOrNull(styleDecl.removeProperty(s, exception));
260     case DOMCSSStyleDeclaration::GetPropertyPriority:
261       return jsStringOrNull(styleDecl.getPropertyPriority(s));
262     case DOMCSSStyleDeclaration::GetPropertyShorthand:
263       return jsStringOrNull(styleDecl.getPropertyShorthand(s));
264     case DOMCSSStyleDeclaration::IsPropertyImplicit:
265       return jsBoolean(styleDecl.isPropertyImplicit(s));
266     case DOMCSSStyleDeclaration::SetProperty:
267       styleDecl.setProperty(s, args[1]->toString(exec).domString(), args[2]->toString(exec).domString(), exception);
268       return jsUndefined();
269     case DOMCSSStyleDeclaration::Item:
270       return jsStringOrNull(styleDecl.item(args[0]->toInt32(exec)));
271     default:
272       return jsUndefined();
273   }
274 }
275
276 ValueImp *getDOMCSSStyleDeclaration(ExecState *exec, CSSStyleDeclarationImpl *s)
277 {
278   return cacheDOMObject<CSSStyleDeclarationImpl, DOMCSSStyleDeclaration>(exec, s);
279 }
280
281 // -------------------------------------------------------------------------
282
283 const ClassInfo DOMStyleSheet::info = { "StyleSheet", 0, &DOMStyleSheetTable, 0 };
284 /*
285 @begin DOMStyleSheetTable 7
286   type          DOMStyleSheet::Type             DontDelete|ReadOnly
287   disabled      DOMStyleSheet::Disabled         DontDelete
288   ownerNode     DOMStyleSheet::OwnerNode        DontDelete|ReadOnly
289   parentStyleSheet DOMStyleSheet::ParentStyleSheet      DontDelete|ReadOnly
290   href          DOMStyleSheet::Href             DontDelete|ReadOnly
291   title         DOMStyleSheet::Title            DontDelete|ReadOnly
292   media         DOMStyleSheet::Media            DontDelete|ReadOnly
293 @end
294 */
295
296 DOMStyleSheet::~DOMStyleSheet()
297 {
298   ScriptInterpreter::forgetDOMObject(m_impl.get());
299 }
300
301 bool DOMStyleSheet::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
302 {
303   return getStaticValueSlot<DOMStyleSheet, DOMObject>(exec, &DOMStyleSheetTable, this, propertyName, slot);
304 }
305
306 ValueImp *DOMStyleSheet::getValueProperty(ExecState *exec, int token) const
307 {
308   StyleSheetImpl &styleSheet = *m_impl;
309   switch (token) {
310   case Type:
311     return jsStringOrNull(styleSheet.type());
312   case Disabled:
313     return jsBoolean(styleSheet.disabled());
314   case OwnerNode:
315     return getDOMNode(exec,styleSheet.ownerNode());
316   case ParentStyleSheet:
317     return getDOMStyleSheet(exec,styleSheet.parentStyleSheet());
318   case Href:
319     return jsStringOrNull(styleSheet.href());
320   case Title:
321     return jsStringOrNull(styleSheet.title());
322   case Media:
323     return getDOMMediaList(exec, styleSheet.media());
324   }
325   return NULL;
326 }
327
328 void DOMStyleSheet::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
329 {
330   if (propertyName == "disabled") {
331     m_impl->setDisabled(value->toBoolean(exec));
332   }
333   else
334     DOMObject::put(exec, propertyName, value, attr);
335 }
336
337 ValueImp *getDOMStyleSheet(ExecState *exec, StyleSheetImpl *ss)
338 {
339   DOMObject *ret;
340   if (!ss)
341     return jsNull();
342   ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
343   if ((ret = interp->getDOMObject(ss)))
344     return ret;
345   else {
346     if (ss->isCSSStyleSheet())
347       ret = new DOMCSSStyleSheet(exec, static_cast<CSSStyleSheetImpl *>(ss));
348     else
349       ret = new DOMStyleSheet(exec,ss);
350     interp->putDOMObject(ss, ret);
351     return ret;
352   }
353 }
354
355 // -------------------------------------------------------------------------
356
357 const ClassInfo DOMStyleSheetList::info = { "StyleSheetList", 0, &DOMStyleSheetListTable, 0 };
358
359 /*
360 @begin DOMStyleSheetListTable 2
361   length        DOMStyleSheetList::Length       DontDelete|ReadOnly
362   item          DOMStyleSheetList::Item         DontDelete|Function 1
363 @end
364 */
365 IMPLEMENT_PROTOFUNC(DOMStyleSheetListFunc) // not really a proto, but doesn't matter
366
367 DOMStyleSheetList::~DOMStyleSheetList()
368 {
369   ScriptInterpreter::forgetDOMObject(m_impl.get());
370 }
371
372 ValueImp *DOMStyleSheetList::getValueProperty(ExecState *exec, int token) const
373 {
374     switch(token) {
375     case Length:
376       return jsNumber(m_impl->length());
377     default:
378       assert(0);
379       return jsUndefined();
380     }
381 }
382
383 ValueImp *DOMStyleSheetList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
384 {
385   DOMStyleSheetList *thisObj = static_cast<DOMStyleSheetList *>(slot.slotBase());
386   return getDOMStyleSheet(exec, thisObj->m_impl->item(slot.index()));
387 }
388
389 ValueImp *DOMStyleSheetList::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
390 {
391   DOMStyleSheetList *thisObj = static_cast<DOMStyleSheetList *>(slot.slotBase());
392   ElementImpl *element = thisObj->m_doc->getElementById(propertyName.domString());
393   return getDOMStyleSheet(exec, static_cast<HTMLStyleElementImpl *>(element)->sheet());
394 }
395
396 bool DOMStyleSheetList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
397 {
398   const HashEntry* entry = Lookup::findEntry(&DOMStyleSheetListTable, propertyName);
399   
400   if (entry) {
401     switch(entry->value) {
402     case Length:
403       slot.setStaticEntry(this, entry, staticValueGetter<DOMStyleSheetList>);
404       return true;
405     case Item:
406       slot.setStaticEntry(this, entry, staticFunctionGetter<DOMStyleSheetListFunc>);
407       return true;
408     }
409   }
410
411   StyleSheetListImpl &styleSheetList = *m_impl;
412
413   // Retrieve stylesheet by index
414   bool ok;
415   unsigned u = propertyName.toUInt32(&ok);
416   if (ok && u < styleSheetList.length()) {
417     slot.setCustomIndex(this, u, indexGetter);
418     return true;
419   }
420
421   // IE also supports retrieving a stylesheet by name, using the name/id of the <style> tag
422   // (this is consistent with all the other collections)
423   // ### Bad implementation because returns a single element (are IDs always unique?)
424   // and doesn't look for name attribute (see implementation above).
425   // But unicity of stylesheet ids is good practice anyway ;)
426   ElementImpl *element = m_doc->getElementById(propertyName.domString());
427   if (element && element->hasTagName(styleTag)) {
428     slot.setCustom(this, nameGetter);
429     return true;
430   }
431
432   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
433 }
434
435 ValueImp *getDOMStyleSheetList(ExecState *exec, StyleSheetListImpl *ssl, DocumentImpl *doc)
436 {
437   // Can't use the cacheDOMObject macro because of the doc argument
438   DOMObject *ret;
439   if (!ssl)
440     return jsNull();
441   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
442   if ((ret = interp->getDOMObject(ssl)))
443     return ret;
444   else {
445     ret = new DOMStyleSheetList(exec, ssl, doc);
446     interp->putDOMObject(ssl, ret);
447     return ret;
448   }
449 }
450
451 ValueImp *DOMStyleSheetListFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
452 {
453   if (!thisObj->inherits(&KJS::DOMStyleSheetList::info))
454     return throwError(exec, TypeError);
455   StyleSheetListImpl &styleSheetList = *static_cast<DOMStyleSheetList *>(thisObj)->impl();
456   if (id == DOMStyleSheetList::Item)
457     return getDOMStyleSheet(exec, styleSheetList.item(args[0]->toInt32(exec)));
458   return jsUndefined();
459 }
460
461 // -------------------------------------------------------------------------
462
463 const ClassInfo DOMMediaList::info = { "MediaList", 0, &DOMMediaListTable, 0 };
464
465 /*
466 @begin DOMMediaListTable 2
467   mediaText     DOMMediaList::MediaText         DontDelete|ReadOnly
468   length        DOMMediaList::Length            DontDelete|ReadOnly
469 @end
470 @begin DOMMediaListProtoTable 3
471   item          DOMMediaList::Item              DontDelete|Function 1
472   deleteMedium  DOMMediaList::DeleteMedium      DontDelete|Function 1
473   appendMedium  DOMMediaList::AppendMedium      DontDelete|Function 1
474 @end
475 */
476 DEFINE_PROTOTYPE("DOMMediaList", DOMMediaListProto)
477 IMPLEMENT_PROTOFUNC(DOMMediaListProtoFunc)
478 IMPLEMENT_PROTOTYPE(DOMMediaListProto, DOMMediaListProtoFunc)
479
480 DOMMediaList::DOMMediaList(ExecState *exec, MediaListImpl *ml)
481     : m_impl(ml)
482 {
483   setPrototype(DOMMediaListProto::self(exec));
484 }
485
486 DOMMediaList::~DOMMediaList()
487 {
488   ScriptInterpreter::forgetDOMObject(m_impl.get());
489 }
490
491 ValueImp *DOMMediaList::getValueProperty(ExecState *exec, int token)
492 {
493   switch (token) {
494   case MediaText:
495     return jsStringOrNull(m_impl->mediaText());
496   case Length:
497     return jsNumber(m_impl->length());
498   default:
499     assert(0);
500     return jsUndefined();
501   }
502 }
503
504 ValueImp *DOMMediaList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
505 {
506   DOMMediaList *thisObj = static_cast<DOMMediaList *>(slot.slotBase());
507   return jsStringOrNull(thisObj->m_impl->item(slot.index()));
508 }
509
510 bool DOMMediaList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
511 {
512   const HashEntry* entry = Lookup::findEntry(&DOMMediaListTable, propertyName);
513   if (entry) {
514     slot.setStaticEntry(this, entry, staticValueGetter<DOMMediaList>);
515     return true;
516   }
517
518   bool ok;
519   unsigned u = propertyName.toUInt32(&ok);
520   if (ok && u < m_impl->length()) {
521     slot.setCustomIndex(this, u, indexGetter);
522     return true;
523   }
524
525   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
526 }
527
528 void DOMMediaList::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
529 {
530   MediaListImpl &mediaList = *m_impl;
531   if (propertyName == "mediaText")
532     mediaList.setMediaText(value->toString(exec).domString());
533   else
534     DOMObject::put(exec, propertyName, value, attr);
535 }
536
537 ValueImp *getDOMMediaList(ExecState *exec, MediaListImpl *ml)
538 {
539   return cacheDOMObject<MediaListImpl, DOMMediaList>(exec, ml);
540 }
541
542 ValueImp *KJS::DOMMediaListProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
543 {
544   if (!thisObj->inherits(&KJS::DOMMediaList::info))
545     return throwError(exec, TypeError);
546   MediaListImpl &mediaList = *static_cast<DOMMediaList *>(thisObj)->impl();
547   switch (id) {
548     case DOMMediaList::Item:
549       return jsStringOrNull(mediaList.item(args[0]->toInt32(exec)));
550     case DOMMediaList::DeleteMedium:
551       mediaList.deleteMedium(args[0]->toString(exec).domString());
552       return jsUndefined();
553     case DOMMediaList::AppendMedium:
554       mediaList.appendMedium(args[0]->toString(exec).domString());
555       return jsUndefined();
556     default:
557       return jsUndefined();
558   }
559 }
560
561 // -------------------------------------------------------------------------
562
563 const ClassInfo DOMCSSStyleSheet::info = { "CSSStyleSheet", 0, &DOMCSSStyleSheetTable, 0 };
564
565 /*
566 @begin DOMCSSStyleSheetTable 5
567   ownerRule     DOMCSSStyleSheet::OwnerRule     DontDelete|ReadOnly
568   cssRules      DOMCSSStyleSheet::CssRules      DontDelete|ReadOnly
569 # MSIE extension
570   rules         DOMCSSStyleSheet::Rules         DontDelete|ReadOnly
571 @end
572 @begin DOMCSSStyleSheetProtoTable 6
573   insertRule    DOMCSSStyleSheet::InsertRule    DontDelete|Function 2
574   deleteRule    DOMCSSStyleSheet::DeleteRule    DontDelete|Function 1
575 # MSIE extension
576   addRule       DOMCSSStyleSheet::AddRule       DontDelete|Function 2
577 @end
578 */
579 DEFINE_PROTOTYPE("DOMCSSStyleSheet",DOMCSSStyleSheetProto)
580 IMPLEMENT_PROTOFUNC(DOMCSSStyleSheetProtoFunc)
581 IMPLEMENT_PROTOTYPE(DOMCSSStyleSheetProto,DOMCSSStyleSheetProtoFunc) // warning, use _WITH_PARENT if DOMStyleSheet gets a proto
582
583 DOMCSSStyleSheet::DOMCSSStyleSheet(ExecState *exec, CSSStyleSheetImpl *ss)
584   : DOMStyleSheet(ss) 
585 {
586   setPrototype(DOMCSSStyleSheetProto::self(exec));
587 }
588
589 DOMCSSStyleSheet::~DOMCSSStyleSheet()
590 {
591 }
592
593 ValueImp *DOMCSSStyleSheet::getValueProperty(ExecState *exec, int token) const
594 {
595   switch (token) {
596   case OwnerRule:
597     return getDOMCSSRule(exec, static_cast<CSSStyleSheetImpl *>(impl())->ownerRule());
598   case CssRules:
599   case Rules:
600     return getDOMCSSRuleList(exec, static_cast<CSSStyleSheetImpl *>(impl())->cssRules());
601   default:
602     assert(0);
603     return jsUndefined();
604   }
605 }
606
607 bool DOMCSSStyleSheet::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
608 {
609   return getStaticValueSlot<DOMCSSStyleSheet, DOMStyleSheet>(exec, &DOMCSSStyleSheetTable, this, propertyName, slot);
610 }
611
612 ValueImp *DOMCSSStyleSheetProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
613 {
614   if (!thisObj->inherits(&KJS::DOMCSSStyleSheet::info))
615     return throwError(exec, TypeError);
616   DOMExceptionTranslator exception(exec);
617   CSSStyleSheetImpl &styleSheet = *static_cast<CSSStyleSheetImpl *>(static_cast<DOMCSSStyleSheet *>(thisObj)->impl());
618   switch (id) {
619     case DOMCSSStyleSheet::InsertRule:
620       return jsNumber(styleSheet.insertRule(args[0]->toString(exec).domString(), args[1]->toInt32(exec), exception));
621     case DOMCSSStyleSheet::DeleteRule:
622       styleSheet.deleteRule(args[0]->toInt32(exec), exception);
623       return jsUndefined();
624     case DOMCSSStyleSheet::AddRule: {
625       int index = args.size() >= 3 ? args[2]->toInt32(exec) : -1;
626       styleSheet.addRule(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), index, exception);
627       // As per Microsoft documentation, always return -1.
628       return jsNumber(-1);
629     }
630   }
631   return jsUndefined();
632 }
633
634 // -------------------------------------------------------------------------
635
636 const ClassInfo DOMCSSRuleList::info = { "CSSRuleList", 0, &DOMCSSRuleListTable, 0 };
637 /*
638 @begin DOMCSSRuleListTable 2
639   length                DOMCSSRuleList::Length          DontDelete|ReadOnly
640   item                  DOMCSSRuleList::Item            DontDelete|Function 1
641 @end
642 */
643 IMPLEMENT_PROTOFUNC(DOMCSSRuleListFunc) // not really a proto, but doesn't matter
644
645 DOMCSSRuleList::~DOMCSSRuleList()
646 {
647   ScriptInterpreter::forgetDOMObject(m_impl.get());
648 }
649
650 ValueImp *DOMCSSRuleList::getValueProperty(ExecState *exec, int token) const
651 {
652   switch (token) {
653   case Length:
654     return jsNumber(m_impl->length());
655   default:
656     assert(0);
657     return jsUndefined();
658   }
659 }
660
661 ValueImp *DOMCSSRuleList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
662 {
663   DOMCSSRuleList *thisObj = static_cast<DOMCSSRuleList *>(slot.slotBase());
664   return getDOMCSSRule(exec, thisObj->m_impl->item(slot.index()));
665 }
666
667 bool DOMCSSRuleList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
668 {
669   const HashEntry* entry = Lookup::findEntry(&DOMCSSRuleListTable, propertyName);
670
671   if (entry) {
672     if (entry->attr & Function)
673       slot.setStaticEntry(this, entry, staticFunctionGetter<DOMCSSRuleListFunc>);
674     else
675       slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSRuleList>);
676     return true;
677   }
678
679   CSSRuleListImpl &cssRuleList = *m_impl;
680
681   bool ok;
682   unsigned u = propertyName.toUInt32(&ok);
683   if (ok && u < cssRuleList.length()) {
684     slot.setCustomIndex(this, u, indexGetter);
685     return true;
686   }
687
688   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
689 }
690
691 ValueImp *DOMCSSRuleListFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
692 {
693   if (!thisObj->inherits(&KJS::DOMCSSRuleList::info))
694     return throwError(exec, TypeError);
695   CSSRuleListImpl &cssRuleList = *static_cast<DOMCSSRuleList *>(thisObj)->impl();
696   switch (id) {
697     case DOMCSSRuleList::Item:
698       return getDOMCSSRule(exec,cssRuleList.item(args[0]->toInt32(exec)));
699     default:
700       return jsUndefined();
701   }
702 }
703
704 ValueImp *getDOMCSSRuleList(ExecState *exec, CSSRuleListImpl *rl)
705 {
706   return cacheDOMObject<CSSRuleListImpl, DOMCSSRuleList>(exec, rl);
707 }
708
709 // -------------------------------------------------------------------------
710
711 IMPLEMENT_PROTOFUNC(DOMCSSRuleFunc) // Not a proto, but doesn't matter
712
713 DOMCSSRule::~DOMCSSRule()
714 {
715   ScriptInterpreter::forgetDOMObject(m_impl.get());
716 }
717
718 const ClassInfo DOMCSSRule::info = { "CSSRule", 0, &DOMCSSRuleTable, 0 };
719 const ClassInfo DOMCSSRule::style_info = { "CSSStyleRule", &DOMCSSRule::info, &DOMCSSStyleRuleTable, 0 };
720 const ClassInfo DOMCSSRule::media_info = { "CSSMediaRule", &DOMCSSRule::info, &DOMCSSMediaRuleTable, 0 };
721 const ClassInfo DOMCSSRule::fontface_info = { "CSSFontFaceRule", &DOMCSSRule::info, &DOMCSSFontFaceRuleTable, 0 };
722 const ClassInfo DOMCSSRule::page_info = { "CSSPageRule", &DOMCSSRule::info, &DOMCSSPageRuleTable, 0 };
723 const ClassInfo DOMCSSRule::import_info = { "CSSImportRule", &DOMCSSRule::info, &DOMCSSImportRuleTable, 0 };
724 const ClassInfo DOMCSSRule::charset_info = { "CSSCharsetRule", &DOMCSSRule::info, &DOMCSSCharsetRuleTable, 0 };
725
726 const ClassInfo* DOMCSSRule::classInfo() const
727 {
728   CSSRuleImpl &cssRule = *m_impl;
729   switch (cssRule.type()) {
730   case DOM::CSSRule::STYLE_RULE:
731     return &style_info;
732   case DOM::CSSRule::MEDIA_RULE:
733     return &media_info;
734   case DOM::CSSRule::FONT_FACE_RULE:
735     return &fontface_info;
736   case DOM::CSSRule::PAGE_RULE:
737     return &page_info;
738   case DOM::CSSRule::IMPORT_RULE:
739     return &import_info;
740   case DOM::CSSRule::CHARSET_RULE:
741     return &charset_info;
742   case DOM::CSSRule::UNKNOWN_RULE:
743   default:
744     return &info;
745   }
746 }
747 /*
748 @begin DOMCSSRuleTable 4
749   type                  DOMCSSRule::Type        DontDelete|ReadOnly
750   cssText               DOMCSSRule::CssText     DontDelete|ReadOnly
751   parentStyleSheet      DOMCSSRule::ParentStyleSheet    DontDelete|ReadOnly
752   parentRule            DOMCSSRule::ParentRule  DontDelete|ReadOnly
753 @end
754 @begin DOMCSSStyleRuleTable 2
755   selectorText          DOMCSSRule::Style_SelectorText  DontDelete
756   style                 DOMCSSRule::Style_Style         DontDelete|ReadOnly
757 @end
758 @begin DOMCSSMediaRuleTable 4
759   media                 DOMCSSRule::Media_Media         DontDelete|ReadOnly
760   cssRules              DOMCSSRule::Media_CssRules      DontDelete|ReadOnly
761   insertRule            DOMCSSRule::Media_InsertRule    DontDelete|Function 2
762   deleteRule            DOMCSSRule::Media_DeleteRule    DontDelete|Function 1
763 @end
764 @begin DOMCSSFontFaceRuleTable 1
765   style                 DOMCSSRule::FontFace_Style      DontDelete|ReadOnly
766 @end
767 @begin DOMCSSPageRuleTable 2
768   selectorText          DOMCSSRule::Page_SelectorText   DontDelete
769   style                 DOMCSSRule::Page_Style          DontDelete|ReadOnly
770 @end
771 @begin DOMCSSImportRuleTable 3
772   href                  DOMCSSRule::Import_Href         DontDelete|ReadOnly
773   media                 DOMCSSRule::Import_Media        DontDelete|ReadOnly
774   styleSheet            DOMCSSRule::Import_StyleSheet   DontDelete|ReadOnly
775 @end
776 @begin DOMCSSCharsetRuleTable 1
777   encoding              DOMCSSRule::Charset_Encoding    DontDelete
778 @end
779 */
780 bool DOMCSSRule::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
781 {
782   // first try the properties specific to this rule type
783   const HashEntry* entry = Lookup::findEntry(classInfo()->propHashTable, propertyName);
784   if (entry) {
785     slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSRule>);
786     return true;
787   }
788   
789   // now the stuff that applies to all rules
790   return getStaticPropertySlot<DOMCSSRuleFunc, DOMCSSRule, DOMObject>(exec, &DOMCSSRuleTable, this, propertyName, slot);
791 }
792
793 ValueImp *DOMCSSRule::getValueProperty(ExecState *exec, int token) const
794 {
795   CSSRuleImpl &cssRule = *m_impl;
796   switch (token) {
797   case Type:
798     return jsNumber(cssRule.type());
799   case CssText:
800     return jsStringOrNull(cssRule.cssText());
801   case ParentStyleSheet:
802     return getDOMStyleSheet(exec,cssRule.parentStyleSheet());
803   case ParentRule:
804     return getDOMCSSRule(exec,cssRule.parentRule());
805
806   // for DOM::CSSRule::STYLE_RULE:
807   case Style_SelectorText:
808     return jsStringOrNull(static_cast<CSSStyleRuleImpl *>(m_impl.get())->selectorText());
809   case Style_Style:
810     return getDOMCSSStyleDeclaration(exec, static_cast<CSSStyleRuleImpl *>(m_impl.get())->style());
811
812   // for DOM::CSSRule::MEDIA_RULE:
813   case Media_Media:
814     return getDOMMediaList(exec, static_cast<CSSMediaRuleImpl *>(m_impl.get())->media());
815   case Media_CssRules:
816     return getDOMCSSRuleList(exec, static_cast<CSSMediaRuleImpl *>(m_impl.get())->cssRules());
817
818   // for DOM::CSSRule::FONT_FACE_RULE:
819   case FontFace_Style:
820     return getDOMCSSStyleDeclaration(exec, static_cast<CSSFontFaceRuleImpl *>(m_impl.get())->style());
821
822   // for DOM::CSSRule::PAGE_RULE:
823   case Page_SelectorText:
824     return jsStringOrNull(static_cast<CSSPageRuleImpl *>(m_impl.get())->selectorText());
825   case Page_Style:
826     return getDOMCSSStyleDeclaration(exec, static_cast<CSSPageRuleImpl *>(m_impl.get())->style());
827
828   // for DOM::CSSRule::IMPORT_RULE:
829   case Import_Href:
830     return jsStringOrNull(static_cast<CSSImportRuleImpl *>(m_impl.get())->href());
831   case Import_Media:
832     return getDOMMediaList(exec, static_cast<CSSImportRuleImpl *>(m_impl.get())->media());
833   case Import_StyleSheet:
834     return getDOMStyleSheet(exec, static_cast<CSSImportRuleImpl *>(m_impl.get())->styleSheet());
835
836   // for DOM::CSSRule::CHARSET_RULE:
837   case Charset_Encoding:
838     return jsStringOrNull(static_cast<CSSCharsetRuleImpl *>(m_impl.get())->encoding());
839
840   default:
841     assert(0);
842   }
843   return jsUndefined();
844 }
845
846 void DOMCSSRule::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
847 {
848   const HashTable* table = classInfo()->propHashTable; // get the right hashtable
849   const HashEntry* entry = Lookup::findEntry(table, propertyName);
850   if (entry) {
851     if (entry->attr & Function) // function: put as override property
852     {
853       ObjectImp::put(exec, propertyName, value, attr);
854       return;
855     }
856     else if ((entry->attr & ReadOnly) == 0) // let lookupPut print the warning if not
857     {
858       putValueProperty(exec, entry->value, value, attr);
859       return;
860     }
861   }
862   lookupPut<DOMCSSRule, DOMObject>(exec, propertyName, value, attr, &DOMCSSRuleTable, this);
863 }
864
865 void DOMCSSRule::putValueProperty(ExecState *exec, int token, ValueImp *value, int)
866 {
867   switch (token) {
868   // for DOM::CSSRule::STYLE_RULE:
869   case Style_SelectorText:
870     static_cast<CSSStyleRuleImpl *>(m_impl.get())->setSelectorText(value->toString(exec).domString());
871     return;
872
873   // for DOM::CSSRule::PAGE_RULE:
874   case Page_SelectorText:
875     static_cast<CSSPageRuleImpl *>(m_impl.get())->setSelectorText(value->toString(exec).domString());
876     return;
877
878   // for DOM::CSSRule::CHARSET_RULE:
879   case Charset_Encoding:
880     static_cast<CSSCharsetRuleImpl *>(m_impl.get())->setEncoding(value->toString(exec).domString());
881     return;
882
883   default:
884     kdWarning() << "DOMCSSRule::putValueProperty unhandled token " << token << endl;
885   }
886 }
887
888 ValueImp *DOMCSSRuleFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
889 {
890   if (!thisObj->inherits(&KJS::DOMCSSRule::info))
891     return throwError(exec, TypeError);
892   CSSRuleImpl &cssRule = *static_cast<DOMCSSRule *>(thisObj)->impl();
893
894   if (cssRule.type() == DOM::CSSRule::MEDIA_RULE) {
895     CSSMediaRuleImpl &rule = static_cast<CSSMediaRuleImpl &>(cssRule);
896     if (id == DOMCSSRule::Media_InsertRule)
897       return jsNumber(rule.insertRule(args[0]->toString(exec).domString(), args[1]->toInt32(exec)));
898     else if (id == DOMCSSRule::Media_DeleteRule)
899       rule.deleteRule(args[0]->toInt32(exec));
900   }
901
902   return jsUndefined();
903 }
904
905 ValueImp *getDOMCSSRule(ExecState *exec, CSSRuleImpl *r)
906 {
907   return cacheDOMObject<CSSRuleImpl, DOMCSSRule>(exec, r);
908 }
909
910 // -------------------------------------------------------------------------
911
912 const ClassInfo CSSRuleConstructor::info = { "CSSRuleConstructor", 0, &CSSRuleConstructorTable, 0 };
913 /*
914 @begin CSSRuleConstructorTable 7
915   UNKNOWN_RULE  CSSRuleConstructor::UNKNOWN_RULE        DontDelete|ReadOnly
916   STYLE_RULE    CSSRuleConstructor::STYLE_RULE          DontDelete|ReadOnly
917   CHARSET_RULE  CSSRuleConstructor::CHARSET_RULE        DontDelete|ReadOnly
918   IMPORT_RULE   CSSRuleConstructor::IMPORT_RULE         DontDelete|ReadOnly
919   MEDIA_RULE    CSSRuleConstructor::MEDIA_RULE          DontDelete|ReadOnly
920   FONT_FACE_RULE CSSRuleConstructor::FONT_FACE_RULE     DontDelete|ReadOnly
921   PAGE_RULE     CSSRuleConstructor::PAGE_RULE           DontDelete|ReadOnly
922 @end
923 */
924
925 bool CSSRuleConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
926 {
927   return getStaticValueSlot<CSSRuleConstructor, DOMObject>(exec, &CSSRuleConstructorTable, this, propertyName, slot);
928 }
929
930 ValueImp *CSSRuleConstructor::getValueProperty(ExecState *, int token) const
931 {
932   switch (token) {
933   case UNKNOWN_RULE:
934     return jsNumber(DOM::CSSRule::UNKNOWN_RULE);
935   case STYLE_RULE:
936     return jsNumber(DOM::CSSRule::STYLE_RULE);
937   case CHARSET_RULE:
938     return jsNumber(DOM::CSSRule::CHARSET_RULE);
939   case IMPORT_RULE:
940     return jsNumber(DOM::CSSRule::IMPORT_RULE);
941   case MEDIA_RULE:
942     return jsNumber(DOM::CSSRule::MEDIA_RULE);
943   case FONT_FACE_RULE:
944     return jsNumber(DOM::CSSRule::FONT_FACE_RULE);
945   case PAGE_RULE:
946     return jsNumber(DOM::CSSRule::PAGE_RULE);
947   }
948   return NULL;
949 }
950
951 ValueImp *getCSSRuleConstructor(ExecState *exec)
952 {
953   return cacheGlobalObject<CSSRuleConstructor>( exec, "[[cssRule.constructor]]" );
954 }
955
956 // -------------------------------------------------------------------------
957
958 const ClassInfo DOMCSSValue::info = { "CSSValue", 0, &DOMCSSValueTable, 0 };
959
960 /*
961 @begin DOMCSSValueTable 2
962   cssText       DOMCSSValue::CssText            DontDelete|ReadOnly
963   cssValueType  DOMCSSValue::CssValueType       DontDelete|ReadOnly
964 @end
965 */
966 DOMCSSValue::~DOMCSSValue()
967 {
968   ScriptInterpreter::forgetDOMObject(m_impl.get());
969 }
970
971 ValueImp *DOMCSSValue::getValueProperty(ExecState *exec, int token) const
972 {
973   CSSValueImpl &cssValue = *m_impl;
974   switch (token) {
975   case CssText:
976     return jsStringOrNull(cssValue.cssText());
977   case CssValueType:
978     return jsNumber(cssValue.cssValueType());
979   default:
980     assert(0);
981     return jsUndefined();
982   }
983 }
984
985 bool DOMCSSValue::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
986 {
987   return getStaticValueSlot<DOMCSSValue, DOMObject>(exec, &DOMCSSValueTable, this, propertyName, slot);
988 }
989
990 void DOMCSSValue::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
991 {
992   CSSValueImpl &cssValue = *m_impl;
993   if (propertyName == "cssText")
994     cssValue.setCssText(value->toString(exec).domString());
995   else
996     DOMObject::put(exec, propertyName, value, attr);
997 }
998
999 ValueImp *getDOMCSSValue(ExecState *exec, CSSValueImpl *v)
1000 {
1001   DOMObject *ret;
1002   if (!v)
1003     return jsNull();
1004   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1005   if ((ret = interp->getDOMObject(v)))
1006     return ret;
1007   else {
1008     if (v->isValueList())
1009       ret = new DOMCSSValueList(exec, static_cast<CSSValueListImpl *>(v));
1010     else if (v->isPrimitiveValue())
1011       ret = new DOMCSSPrimitiveValue(exec, static_cast<CSSPrimitiveValueImpl *>(v));
1012     else
1013       ret = new DOMCSSValue(exec,v);
1014     interp->putDOMObject(v, ret);
1015     return ret;
1016   }
1017 }
1018
1019 // -------------------------------------------------------------------------
1020
1021 const ClassInfo CSSValueConstructor::info = { "CSSValueConstructor", 0, &CSSValueConstructorTable, 0 };
1022 /*
1023 @begin CSSValueConstructorTable 5
1024   CSS_INHERIT           CSSValueConstructor::CSS_INHERIT                DontDelete|ReadOnly
1025   CSS_PRIMITIVE_VALUE   CSSValueConstructor::CSS_PRIMITIVE_VALUE        DontDelete|ReadOnly
1026   CSS_VALUE_LIST        CSSValueConstructor::CSS_VALUE_LIST             DontDelete|ReadOnly
1027   CSS_CUSTOM            CSSValueConstructor::CSS_CUSTOM                 DontDelete|ReadOnly
1028 @end
1029 */
1030 bool CSSValueConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1031 {
1032   return getStaticValueSlot<CSSValueConstructor, DOMObject>(exec, &CSSValueConstructorTable, this, propertyName, slot);
1033 }
1034
1035 ValueImp *CSSValueConstructor::getValueProperty(ExecState *, int token) const
1036 {
1037   switch (token) {
1038   case CSS_INHERIT:
1039     return jsNumber(DOM::CSSValue::CSS_INHERIT);
1040   case CSS_PRIMITIVE_VALUE:
1041     return jsNumber(DOM::CSSValue::CSS_PRIMITIVE_VALUE);
1042   case CSS_VALUE_LIST:
1043     return jsNumber(DOM::CSSValue::CSS_VALUE_LIST);
1044   case CSS_CUSTOM:
1045     return jsNumber(DOM::CSSValue::CSS_CUSTOM);
1046   }
1047   return NULL;
1048 }
1049
1050 ValueImp *getCSSValueConstructor(ExecState *exec)
1051 {
1052   return cacheGlobalObject<CSSValueConstructor>( exec, "[[cssValue.constructor]]" );
1053 }
1054
1055 // -------------------------------------------------------------------------
1056
1057 const ClassInfo DOMCSSPrimitiveValue::info = { "CSSPrimitiveValue", 0, &DOMCSSPrimitiveValueTable, 0 };
1058 /*
1059 @begin DOMCSSPrimitiveValueTable 1
1060   primitiveType         DOMCSSPrimitiveValue::PrimitiveType     DontDelete|ReadOnly
1061 @end
1062 @begin DOMCSSPrimitiveValueProtoTable 3
1063   setFloatValue         DOMCSSPrimitiveValue::SetFloatValue     DontDelete|Function 2
1064   getFloatValue         DOMCSSPrimitiveValue::GetFloatValue     DontDelete|Function 1
1065   setStringValue        DOMCSSPrimitiveValue::SetStringValue    DontDelete|Function 2
1066   getStringValue        DOMCSSPrimitiveValue::GetStringValue    DontDelete|Function 0
1067   getCounterValue       DOMCSSPrimitiveValue::GetCounterValue   DontDelete|Function 0
1068   getRectValue          DOMCSSPrimitiveValue::GetRectValue      DontDelete|Function 0
1069   getRGBColorValue      DOMCSSPrimitiveValue::GetRGBColorValue  DontDelete|Function 0
1070 @end
1071 */
1072 DEFINE_PROTOTYPE("DOMCSSPrimitiveValue",DOMCSSPrimitiveValueProto)
1073 IMPLEMENT_PROTOFUNC(DOMCSSPrimitiveValueProtoFunc)
1074 IMPLEMENT_PROTOTYPE(DOMCSSPrimitiveValueProto,DOMCSSPrimitiveValueProtoFunc)
1075
1076 DOMCSSPrimitiveValue::DOMCSSPrimitiveValue(ExecState *exec, CSSPrimitiveValueImpl *v)
1077   : DOMCSSValue(v) 
1078
1079   setPrototype(DOMCSSPrimitiveValueProto::self(exec));
1080 }
1081
1082 ValueImp *DOMCSSPrimitiveValue::getValueProperty(ExecState *exec, int token)
1083 {
1084   assert(token == PrimitiveType);
1085   return jsNumber(static_cast<CSSPrimitiveValueImpl *>(impl())->primitiveType());
1086 }
1087
1088 bool DOMCSSPrimitiveValue::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1089 {
1090   return getStaticValueSlot<DOMCSSPrimitiveValue, DOMCSSValue>(exec, &DOMCSSPrimitiveValueTable, this, propertyName, slot);
1091 }
1092
1093 ValueImp *DOMCSSPrimitiveValueProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1094 {
1095   if (!thisObj->inherits(&KJS::DOMCSSPrimitiveValue::info))
1096     return throwError(exec, TypeError);
1097   DOMExceptionTranslator exception(exec);
1098   CSSPrimitiveValueImpl &val = *static_cast<CSSPrimitiveValueImpl *>(static_cast<DOMCSSPrimitiveValue *>(thisObj)->impl());
1099   switch (id) {
1100     case DOMCSSPrimitiveValue::SetFloatValue:
1101       val.setFloatValue(args[0]->toInt32(exec), args[1]->toNumber(exec), exception);
1102       return jsUndefined();
1103     case DOMCSSPrimitiveValue::GetFloatValue:
1104       return jsNumber(val.getFloatValue(args[0]->toInt32(exec)));
1105     case DOMCSSPrimitiveValue::SetStringValue:
1106       val.setStringValue(args[0]->toInt32(exec), args[1]->toString(exec).domString(), exception);
1107       return jsUndefined();
1108     case DOMCSSPrimitiveValue::GetStringValue:
1109       return jsStringOrNull(val.getStringValue());
1110     case DOMCSSPrimitiveValue::GetCounterValue:
1111       return getDOMCounter(exec,val.getCounterValue());
1112     case DOMCSSPrimitiveValue::GetRectValue:
1113       return getDOMRect(exec,val.getRectValue());
1114     case DOMCSSPrimitiveValue::GetRGBColorValue:
1115       return getDOMRGBColor(exec,val.getRGBColorValue());
1116     default:
1117       return jsUndefined();
1118   }
1119 }
1120
1121 // -------------------------------------------------------------------------
1122
1123 const ClassInfo CSSPrimitiveValueConstructor::info = { "CSSPrimitiveValueConstructor", 0, &CSSPrimitiveValueConstructorTable, 0 };
1124
1125 /*
1126 @begin CSSPrimitiveValueConstructorTable 27
1127   CSS_UNKNOWN           DOM::CSSPrimitiveValue::CSS_UNKNOWN     DontDelete|ReadOnly
1128   CSS_NUMBER            DOM::CSSPrimitiveValue::CSS_NUMBER      DontDelete|ReadOnly
1129   CSS_PERCENTAGE        DOM::CSSPrimitiveValue::CSS_PERCENTAGE  DontDelete|ReadOnly
1130   CSS_EMS               DOM::CSSPrimitiveValue::CSS_EMS         DontDelete|ReadOnly
1131   CSS_EXS               DOM::CSSPrimitiveValue::CSS_EXS         DontDelete|ReadOnly
1132   CSS_PX                DOM::CSSPrimitiveValue::CSS_PX          DontDelete|ReadOnly
1133   CSS_CM                DOM::CSSPrimitiveValue::CSS_CM          DontDelete|ReadOnly
1134   CSS_MM                DOM::CSSPrimitiveValue::CSS_MM          DontDelete|ReadOnly
1135   CSS_IN                DOM::CSSPrimitiveValue::CSS_IN          DontDelete|ReadOnly
1136   CSS_PT                DOM::CSSPrimitiveValue::CSS_PT          DontDelete|ReadOnly
1137   CSS_PC                DOM::CSSPrimitiveValue::CSS_PC          DontDelete|ReadOnly
1138   CSS_DEG               DOM::CSSPrimitiveValue::CSS_DEG         DontDelete|ReadOnly
1139   CSS_RAD               DOM::CSSPrimitiveValue::CSS_RAD         DontDelete|ReadOnly
1140   CSS_GRAD              DOM::CSSPrimitiveValue::CSS_GRAD        DontDelete|ReadOnly
1141   CSS_MS                DOM::CSSPrimitiveValue::CSS_MS          DontDelete|ReadOnly
1142   CSS_S                 DOM::CSSPrimitiveValue::CSS_S           DontDelete|ReadOnly
1143   CSS_HZ                DOM::CSSPrimitiveValue::CSS_HZ          DontDelete|ReadOnly
1144   CSS_KHZ               DOM::CSSPrimitiveValue::CSS_KHZ         DontDelete|ReadOnly
1145   CSS_DIMENSION         DOM::CSSPrimitiveValue::CSS_DIMENSION   DontDelete|ReadOnly
1146   CSS_STRING            DOM::CSSPrimitiveValue::CSS_STRING      DontDelete|ReadOnly
1147   CSS_URI               DOM::CSSPrimitiveValue::CSS_URI         DontDelete|ReadOnly
1148   CSS_IDENT             DOM::CSSPrimitiveValue::CSS_IDENT       DontDelete|ReadOnly
1149   CSS_ATTR              DOM::CSSPrimitiveValue::CSS_ATTR        DontDelete|ReadOnly
1150   CSS_COUNTER           DOM::CSSPrimitiveValue::CSS_COUNTER     DontDelete|ReadOnly
1151   CSS_RECT              DOM::CSSPrimitiveValue::CSS_RECT        DontDelete|ReadOnly
1152   CSS_RGBCOLOR          DOM::CSSPrimitiveValue::CSS_RGBCOLOR    DontDelete|ReadOnly
1153 @end
1154 */
1155
1156 bool CSSPrimitiveValueConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1157 {
1158   return getStaticValueSlot<CSSPrimitiveValueConstructor, CSSValueConstructor>(exec, &CSSPrimitiveValueConstructorTable, this, propertyName, slot);
1159 }
1160
1161 ValueImp *CSSPrimitiveValueConstructor::getValueProperty(ExecState *, int token) const
1162 {
1163   // We use the token as the value to return directly
1164   return jsNumber(token);
1165 }
1166
1167 ValueImp *getCSSPrimitiveValueConstructor(ExecState *exec)
1168 {
1169   return cacheGlobalObject<CSSPrimitiveValueConstructor>( exec, "[[cssPrimitiveValue.constructor]]" );
1170 }
1171
1172 // -------------------------------------------------------------------------
1173
1174 const ClassInfo DOMCSSValueList::info = { "CSSValueList", 0, &DOMCSSValueListTable, 0 };
1175
1176 /*
1177 @begin DOMCSSValueListTable 3
1178   length                DOMCSSValueList::Length         DontDelete|ReadOnly
1179   item                  DOMCSSValueList::Item           DontDelete|Function 1
1180 @end
1181 */
1182 IMPLEMENT_PROTOFUNC(DOMCSSValueListFunc) // not really a proto, but doesn't matter
1183
1184 DOMCSSValueList::DOMCSSValueList(ExecState *exec, CSSValueListImpl *v)
1185   : DOMCSSValue(exec, v) 
1186
1187 }
1188
1189 ValueImp *DOMCSSValueList::getValueProperty(ExecState *exec, int token) const
1190 {
1191   assert(token == Length);
1192   return jsNumber(static_cast<CSSValueListImpl *>(impl())->length());
1193 }
1194
1195 ValueImp *DOMCSSValueList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
1196 {
1197   DOMCSSValueList *thisObj = static_cast<DOMCSSValueList *>(slot.slotBase());
1198   return getDOMCSSValue(exec, static_cast<CSSValueListImpl *>(thisObj->impl())->item(slot.index()));
1199 }
1200
1201 bool DOMCSSValueList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1202 {
1203   CSSValueListImpl &valueList = *static_cast<CSSValueListImpl *>(impl());
1204   const HashEntry* entry = Lookup::findEntry(&DOMCSSValueListTable, propertyName);
1205   if (entry) {
1206     if (entry->attr & Function)
1207       slot.setStaticEntry(this, entry, staticFunctionGetter<DOMCSSValueListFunc>);
1208     else
1209       slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSValueList>);
1210   }
1211
1212   bool ok;
1213   unsigned u = propertyName.toUInt32(&ok);
1214   if (ok && u < valueList.length()) {
1215     slot.setCustomIndex(this, u, indexGetter);
1216     return true;
1217   }
1218
1219   return DOMCSSValue::getOwnPropertySlot(exec, propertyName, slot);
1220 }
1221
1222 ValueImp *DOMCSSValueListFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1223 {
1224   if (!thisObj->inherits(&KJS::DOMCSSValue::info))
1225     return throwError(exec, TypeError);
1226   CSSValueListImpl &valueList = *static_cast<CSSValueListImpl *>(static_cast<DOMCSSValueList *>(thisObj)->impl());
1227   switch (id) {
1228     case DOMCSSValueList::Item:
1229       return getDOMCSSValue(exec,valueList.item(args[0]->toInt32(exec)));
1230     default:
1231       return jsUndefined();
1232   }
1233 }
1234
1235 // -------------------------------------------------------------------------
1236
1237 const ClassInfo DOMRGBColor::info = { "RGBColor", 0, &DOMRGBColorTable, 0 };
1238
1239 /*
1240 @begin DOMRGBColorTable 3
1241   red   DOMRGBColor::Red        DontDelete|ReadOnly
1242   green DOMRGBColor::Green      DontDelete|ReadOnly
1243   blue  DOMRGBColor::Blue       DontDelete|ReadOnly
1244 @end
1245 */
1246 DOMRGBColor::~DOMRGBColor()
1247 {
1248   //rgbColors.remove(rgbColor.handle());
1249 }
1250
1251 bool DOMRGBColor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1252 {
1253   return getStaticValueSlot<DOMRGBColor, DOMObject>(exec, &DOMRGBColorTable, this, propertyName, slot);
1254 }
1255
1256 ValueImp *DOMRGBColor::getValueProperty(ExecState *exec, int token) const
1257 {
1258   int color = m_color;
1259   switch (token) {
1260   case Red:
1261     color >>= 8;
1262     // fall through
1263   case Green:
1264     color >>= 8;
1265     // fall through
1266   case Blue:
1267     return new DOMCSSPrimitiveValue(exec, new CSSPrimitiveValueImpl(color & 0xFF, CSSPrimitiveValue::CSS_NUMBER));
1268   default:
1269     return NULL;
1270   }
1271 }
1272
1273 ValueImp *getDOMRGBColor(ExecState *, unsigned c)
1274 {
1275   // ### implement equals for RGBColor since they're not refcounted objects
1276   return new DOMRGBColor(c);
1277 }
1278
1279 // -------------------------------------------------------------------------
1280
1281 const ClassInfo DOMRect::info = { "Rect", 0, &DOMRectTable, 0 };
1282 /*
1283 @begin DOMRectTable 4
1284   top   DOMRect::Top    DontDelete|ReadOnly
1285   right DOMRect::Right  DontDelete|ReadOnly
1286   bottom DOMRect::Bottom DontDelete|ReadOnly
1287   left  DOMRect::Left   DontDelete|ReadOnly
1288 @end
1289 */
1290 DOMRect::~DOMRect()
1291 {
1292   ScriptInterpreter::forgetDOMObject(m_rect.get());
1293 }
1294
1295 bool DOMRect::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1296 {
1297   return getStaticValueSlot<DOMRect, DOMObject>(exec,  &DOMRectTable, this, propertyName, slot);
1298 }
1299
1300 ValueImp *DOMRect::getValueProperty(ExecState *exec, int token) const
1301 {
1302   RectImpl &rect = *m_rect;
1303   switch (token) {
1304   case Top:
1305     return getDOMCSSValue(exec, rect.top());
1306   case Right:
1307     return getDOMCSSValue(exec, rect.right());
1308   case Bottom:
1309     return getDOMCSSValue(exec, rect.bottom());
1310   case Left:
1311     return getDOMCSSValue(exec, rect.left());
1312   default:
1313     return NULL;
1314   }
1315 }
1316
1317 ValueImp *getDOMRect(ExecState *exec, RectImpl *r)
1318 {
1319   return cacheDOMObject<RectImpl, DOMRect>(exec, r);
1320 }
1321
1322 // -------------------------------------------------------------------------
1323
1324 const ClassInfo DOMCounter::info = { "Counter", 0, &DOMCounterTable, 0 };
1325 /*
1326 @begin DOMCounterTable 3
1327   identifier    DOMCounter::identifier  DontDelete|ReadOnly
1328   listStyle     DOMCounter::listStyle   DontDelete|ReadOnly
1329   separator     DOMCounter::separator   DontDelete|ReadOnly
1330 @end
1331 */
1332
1333 DOMCounter::~DOMCounter()
1334 {
1335   ScriptInterpreter::forgetDOMObject(m_counter.get());
1336 }
1337
1338 bool DOMCounter::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1339 {
1340   return getStaticValueSlot<DOMCounter, DOMObject>(exec, &DOMCounterTable, this, propertyName, slot);
1341 }
1342
1343 ValueImp *DOMCounter::getValueProperty(ExecState *, int token) const
1344 {
1345   CounterImpl &counter = *m_counter;
1346   switch (token) {
1347   case identifier:
1348     return jsStringOrNull(counter.identifier());
1349   case listStyle:
1350     return jsStringOrNull(counter.listStyle());
1351   case separator:
1352     return jsStringOrNull(counter.separator());
1353   default:
1354     return NULL;
1355   }
1356 }
1357
1358 ValueImp *getDOMCounter(ExecState *exec, CounterImpl *c)
1359 {
1360   return cacheDOMObject<CounterImpl, DOMCounter>(exec, c);
1361 }
1362
1363 }