2006-07-27 Eric Seidel <eric@eseidel.com>
[WebKit-https.git] / WebCore / bindings / js / kjs_html.cpp
1 // -*- c-basic-offset: 4 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "kjs_html.h"
24
25 #include "DocLoader.h"
26 #include "EventNames.h"
27 #include "Frame.h"
28 #include "HTMLAppletElement.h"
29 #include "HTMLAreaElement.h"
30 #include "HTMLBRElement.h"
31 #include "HTMLBaseFontElement.h"
32 #include "HTMLBlockquoteElement.h"
33 #include "HTMLBodyElement.h"
34 #include "HTMLDocument.h"
35 #include "HTMLEmbedElement.h"
36 #include "HTMLFieldSetElement.h"
37 #include "HTMLFontElement.h"
38 #include "HTMLFormElement.h"
39 #include "HTMLFrameSetElement.h"
40 #include "HTMLHRElement.h"
41 #include "HTMLHeadingElement.h"
42 #include "HTMLHtmlElement.h"
43 #include "HTMLIFrameElement.h"
44 #include "HTMLImageElement.h"
45 #include "HTMLIsIndexElement.h"
46 #include "HTMLLIElement.h"
47 #include "HTMLLabelElement.h"
48 #include "HTMLLegendElement.h"
49 #include "HTMLMapElement.h"
50 #include "HTMLMenuElement.h"
51 #include "HTMLModElement.h"
52 #include "HTMLNames.h"
53 #include "HTMLObjectElement.h"
54 #include "HTMLOptionElement.h"
55 #include "HTMLOptionsCollection.h"
56 #include "HTMLParagraphElement.h"
57 #include "HTMLParamElement.h"
58 #include "HTMLPreElement.h"
59 #include "HTMLQuoteElement.h"
60 #include "HTMLScriptElement.h"
61 #include "HTMLSelectElement.h"
62 #include "HTMLTableCaptionElement.h"
63 #include "HTMLTableCellElement.h"
64 #include "HTMLTableColElement.h"
65 #include "HTMLTableElement.h"
66 #include "HTMLTableRowElement.h"
67 #include "HTMLTableSectionElement.h"
68 #include "JSHTMLImageElement.h"
69 #include "JSHTMLOptionsCollection.h"
70 #include "NameNodeList.h"
71 #include "RenderLayer.h"
72 #include "Text.h"
73 #include "kjs_css.h"
74 #include "kjs_events.h"
75 #include "kjs_proxy.h"
76 #include "kjs_window.h"
77 #include <math.h>
78
79 #if SVG_SUPPORT
80 #include "SVGDocument.h"
81 #endif
82
83 #include "kjs_html.lut.h"
84
85 using namespace WebCore;
86 using namespace HTMLNames;
87 using namespace EventNames;
88
89 namespace KJS {
90
91 class HTMLElementFunction : public InternalFunctionImp {
92 public:
93   HTMLElementFunction(ExecState* exec, int i, int len, const Identifier& name);
94   virtual JSValue *callAsFunction(ExecState* exec, JSObject* thisObj, const List&args);
95 private:
96   int id;
97 };
98
99 /* 
100 @begin JSHTMLDocumentProtoTable 8
101 clear                 JSHTMLDocument::Clear             DontDelete|Function 0
102 open                  JSHTMLDocument::Open              DontDelete|Function 0
103 close                 JSHTMLDocument::Close             DontDelete|Function 0
104 write                 JSHTMLDocument::Write             DontDelete|Function 1
105 writeln               JSHTMLDocument::WriteLn           DontDelete|Function 1
106 getElementsByName     JSHTMLDocument::GetElementsByName DontDelete|Function 1
107 captureEvents         JSHTMLDocument::CaptureEvents     DontDelete|Function 0
108 releaseEvents         JSHTMLDocument::ReleaseEvents     DontDelete|Function 0
109 @end
110 */
111 KJS_IMPLEMENT_PROTOFUNC(JSHTMLDocumentProtoFunc)
112 KJS_IMPLEMENT_PROTOTYPE("HTMLDocument", JSHTMLDocumentProto, JSHTMLDocumentProtoFunc)
113
114 JSValue *JSHTMLDocumentProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
115 {
116     if (!thisObj->inherits(&JSHTMLDocument::info))
117         return throwError(exec, TypeError);
118     HTMLDocument &doc = *static_cast<HTMLDocument*>(static_cast<JSHTMLDocument*>(thisObj)->impl());
119     
120     switch (id) {
121         case JSHTMLDocument::Clear: // even IE doesn't support that one...
122                                     //doc.clear(); // TODO
123             return jsUndefined();
124         case JSHTMLDocument::Open:
125             // For compatibility with other browsers, pass open calls with more than 2 parameters to the window.
126             if (args.size() > 2) {
127                 Frame *frame = doc.frame();
128                 if (frame) {
129                     Window *window = Window::retrieveWindow(frame);
130                     if (window) {
131                         JSObject* functionObject = window->get(exec, "open")->getObject();
132                         if (!functionObject || !functionObject->implementsCall())
133                             return throwError(exec, TypeError);
134                         return functionObject->call(exec, window, args);
135                     }
136                 }
137                 return jsUndefined();
138             }
139             // In the case of two parameters or fewer, do a normal document open.
140             doc.open();
141             return jsUndefined();
142         case JSHTMLDocument::Close:
143             doc.close();
144             return jsUndefined();
145         case JSHTMLDocument::Write:
146         case JSHTMLDocument::WriteLn: {
147             // DOM only specifies single string argument, but NS & IE allow multiple
148             // or no arguments
149             String str = "";
150             for (int i = 0; i < args.size(); i++)
151                 str += args[i]->toString(exec);
152             if (id == JSHTMLDocument::WriteLn)
153                 str += "\n";
154             doc.write(str);
155             return jsUndefined();
156         }
157         case JSHTMLDocument::GetElementsByName:
158             return toJS(exec, doc.getElementsByName(args[0]->toString(exec)).get());
159         case JSHTMLDocument::CaptureEvents:
160         case JSHTMLDocument::ReleaseEvents:
161             // Do nothing for now. These are NS-specific legacy calls.
162             break;
163     }
164     
165     return jsUndefined();
166 }
167
168
169 // FIXME: functions should be in the prototype
170 const ClassInfo JSHTMLDocument::info =
171   { "HTMLDocument", &JSDocument::info, &HTMLDocumentTable, 0 };
172 /* Source for HTMLDocumentTable. Use "make hashtables" to regenerate.
173 @begin HTMLDocumentTable 30
174   title                 JSHTMLDocument::Title             DontDelete
175   referrer              JSHTMLDocument::Referrer          DontDelete|ReadOnly
176   domain                JSHTMLDocument::Domain            DontDelete
177   URL                   JSHTMLDocument::URL               DontDelete|ReadOnly
178   body                  JSHTMLDocument::Body              DontDelete
179   location              JSHTMLDocument::Location          DontDelete
180   cookie                JSHTMLDocument::Cookie            DontDelete
181   images                JSHTMLDocument::Images            DontDelete|ReadOnly
182   embeds                JSHTMLDocument::Embeds            DontDelete|ReadOnly
183   plugins               JSHTMLDocument::Embeds            DontDelete|ReadOnly
184   applets               JSHTMLDocument::Applets           DontDelete|ReadOnly
185   links                 JSHTMLDocument::Links             DontDelete|ReadOnly
186   forms                 JSHTMLDocument::Forms             DontDelete|ReadOnly
187   anchors               JSHTMLDocument::Anchors           DontDelete|ReadOnly
188   scripts               JSHTMLDocument::Scripts           DontDelete|ReadOnly
189   all                   JSHTMLDocument::All               
190   bgColor               JSHTMLDocument::BgColor           DontDelete
191   fgColor               JSHTMLDocument::FgColor           DontDelete
192   alinkColor            JSHTMLDocument::AlinkColor        DontDelete
193   linkColor             JSHTMLDocument::LinkColor         DontDelete
194   vlinkColor            JSHTMLDocument::VlinkColor        DontDelete
195   lastModified          JSHTMLDocument::LastModified      DontDelete|ReadOnly
196   height                JSHTMLDocument::Height            DontDelete|ReadOnly
197   width                 JSHTMLDocument::Width             DontDelete|ReadOnly
198   dir                   JSHTMLDocument::Dir               DontDelete
199   designMode            JSHTMLDocument::DesignMode        DontDelete
200 #potentially obsolete array properties
201 # layers
202 # plugins
203 # tags
204 #potentially obsolete properties
205 # embeds
206 # ids
207 @end
208 */
209
210 JSHTMLDocument::JSHTMLDocument(ExecState* exec, HTMLDocument *d)
211   : JSDocument(exec, d)
212 {
213     setPrototype(JSHTMLDocumentProto::self(exec));
214 }
215
216 JSValue *JSHTMLDocument::namedItemGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
217 {
218   JSHTMLDocument *thisObj = static_cast<JSHTMLDocument*>(slot.slotBase());
219   HTMLDocument &doc = *static_cast<HTMLDocument*>(thisObj->impl());
220
221   String name = propertyName;
222   RefPtr<WebCore::HTMLCollection> collection = doc.documentNamedItems(name);
223
224   if (collection->length() == 1) {
225     WebCore::Node* node = collection->firstItem();
226     Frame *frame;
227     if (node->hasTagName(iframeTag) && (frame = static_cast<WebCore::HTMLIFrameElement*>(node)->contentFrame()))
228       return Window::retrieve(frame);
229     return toJS(exec, node);
230   }
231
232   return getHTMLCollection(exec, collection.get());
233 }
234
235 JSValue *JSHTMLDocument::getValueProperty(ExecState* exec, int token) const
236 {
237   HTMLDocument& doc = *static_cast<HTMLDocument*>(impl());
238
239   FrameView* view = doc.view();
240   Frame* frame = doc.frame();
241
242   HTMLElement* body = doc.body();
243   HTMLBodyElement* bodyElement = (body && body->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(body) : 0;
244     
245   switch (token) {
246   case Title:
247     return jsString(doc.title());
248   case Referrer:
249     return jsString(doc.referrer());
250   case Domain:
251     return jsString(doc.domain());
252   case URL:
253     return jsString(doc.URL());
254   case Body:
255     return toJS(exec, body);
256   case Location:
257     if (Window* win = Window::retrieveWindow(frame))
258       return win->location();
259     return jsUndefined();
260   case Cookie:
261     return jsString(doc.cookie());
262   case Images:
263     return getHTMLCollection(exec, doc.images().get());
264   case Embeds:
265     return getHTMLCollection(exec, doc.embeds().get());
266   case Applets:
267     return getHTMLCollection(exec, doc.applets().get());
268   case Links:
269     return getHTMLCollection(exec, doc.links().get());
270   case Forms:
271     return getHTMLCollection(exec, doc.forms().get());
272   case Anchors:
273     return getHTMLCollection(exec, doc.anchors().get());
274   case Scripts:
275     return getHTMLCollection(exec, doc.scripts().get());
276   case All:
277     // If "all" has been overwritten, return the overwritten value
278     if (JSValue *v = getDirect("all"))
279       return v;
280     else
281       return getAllHTMLCollection(exec, doc.all().get());
282   case BgColor:
283     if (!bodyElement)
284       return jsUndefined();
285     return jsString(bodyElement->bgColor());
286   case FgColor:
287     if (!bodyElement)
288       return jsUndefined();
289     return jsString(bodyElement->text());
290   case AlinkColor:
291     if (!bodyElement)
292       return jsUndefined();
293     return jsString(bodyElement->aLink());
294   case LinkColor:
295     if (!bodyElement)
296       return jsUndefined();
297     return jsString(bodyElement->link());
298   case VlinkColor:
299     if (!bodyElement)
300       return jsUndefined();
301     return jsString(bodyElement->vLink());
302   case LastModified:
303     return jsString(doc.lastModified());
304   case Height:
305     return jsNumber(view ? view->contentsHeight() : 0);
306   case Width:
307     return jsNumber(view ? view->contentsWidth() : 0);
308   case Dir:
309     if (!body)
310       return jsString("");
311     return jsString(body->dir());
312   case DesignMode:
313     return jsString(doc.inDesignMode() ? "on" : "off");
314   default:
315     assert(0);
316     return jsUndefined();
317   }
318 }
319
320 bool JSHTMLDocument::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
321 {
322   HTMLDocument &doc = *static_cast<HTMLDocument*>(impl());
323
324   String name = propertyName;
325   if (doc.hasNamedItem(name) || doc.hasDocExtraNamedItem(name)) {
326     slot.setCustom(this, namedItemGetter);
327     return true;
328   }
329
330   return getStaticValueSlot<JSHTMLDocument, JSDocument>(exec, &HTMLDocumentTable, this, propertyName, slot);
331 }
332
333 void JSHTMLDocument::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
334 {
335     lookupPut<JSHTMLDocument, JSDocument>(exec, propertyName, value, attr, &HTMLDocumentTable, this);
336 }
337
338 void JSHTMLDocument::putValueProperty(ExecState* exec, int token, JSValue *value, int /*attr*/)
339 {
340   DOMExceptionTranslator exception(exec);
341   HTMLDocument &doc = *static_cast<HTMLDocument*>(impl());
342   HTMLElement* body = doc.body();
343   HTMLBodyElement* bodyElement = (body && body->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(body) : 0;
344
345   switch (token) {
346   case Title:
347     doc.setTitle(value->toString(exec));
348     break;
349   case Body:
350     doc.setBody(toHTMLElement(value), exception);
351     break;
352   case Domain: // not part of the DOM
353     doc.setDomain(value->toString(exec));
354     break;
355   case Cookie:
356     doc.setCookie(value->toString(exec));
357     break;
358   case Location: {
359     Frame *frame = doc.frame();
360     if (frame)
361     {
362       DeprecatedString str = value->toString(exec);
363
364       // When assigning location, IE and Mozilla both resolve the URL
365       // relative to the frame where the JavaScript is executing not
366       // the target frame.
367       Frame *activePart = static_cast<ScriptInterpreter*>( exec->dynamicInterpreter() )->frame();
368       if (activePart)
369         str = activePart->document()->completeURL(str);
370
371       // We want a new history item if this JS was called via a user gesture
372       bool userGesture = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->wasRunByUserGesture();
373       frame->scheduleLocationChange(str, activePart->referrer(), !userGesture);
374     }
375     break;
376   }
377   case BgColor:
378     if (bodyElement)
379       bodyElement->setBgColor(value->toString(exec));
380     break;
381   case FgColor:
382     if (bodyElement)
383       bodyElement->setText(value->toString(exec));
384     break;
385   case AlinkColor:
386     if (bodyElement) {
387       // this check is a bit silly, but some benchmarks like to set the
388       // document's link colors over and over to the same value and we
389       // don't want to incur a style update each time.
390       String newColor = value->toString(exec);
391       if (bodyElement->aLink() != newColor)
392         bodyElement->setALink(newColor);
393     }
394     break;
395   case LinkColor:
396     if (bodyElement) {
397       // this check is a bit silly, but some benchmarks like to set the
398       // document's link colors over and over to the same value and we
399       // don't want to incur a style update each time.
400       String newColor = value->toString(exec);
401       if (bodyElement->link() != newColor)
402         bodyElement->setLink(newColor);
403     }
404     break;
405   case VlinkColor:
406     if (bodyElement) {
407       // this check is a bit silly, but some benchmarks like to set the
408       // document's link colors over and over to the same value and we
409       // don't want to incur a style update each time.
410       String newColor = value->toString(exec);
411       if (bodyElement->vLink() != newColor)
412         bodyElement->setVLink(newColor);
413     }
414     break;
415   case Dir:
416     if (body)
417       body->setDir(value->toString(exec));
418     break;
419   case DesignMode:
420     {
421       String modeString = value->toString(exec);
422       Document::InheritedBool mode;
423       if (equalIgnoringCase(modeString, "on"))
424         mode = Document::on;
425       else if (equalIgnoringCase(modeString, "off"))
426         mode = Document::off;
427       else
428         mode = Document::inherit;
429       doc.setDesignMode(mode);
430       break;
431     }
432   case All:
433     // Add "all" to the property map.
434     putDirect("all", value);
435     break;
436   }
437 }
438
439 // -------------------------------------------------------------------------
440
441 const ClassInfo JSHTMLElement::caption_info = { "HTMLTableCaptionElement", &JSHTMLElement::info, &HTMLTableCaptionElementTable, 0 };
442 const ClassInfo JSHTMLElement::col_info = { "HTMLTableColElement", &JSHTMLElement::info, &HTMLTableColElementTable, 0 };
443 const ClassInfo JSHTMLElement::embed_info = { "HTMLEmbedElement", &JSHTMLElement::info, &HTMLEmbedElementTable, 0 };
444 const ClassInfo JSHTMLElement::frameSet_info = { "HTMLFrameSetElement", &JSHTMLElement::info, &HTMLFrameSetElementTable, 0 };
445 const ClassInfo JSHTMLElement::frame_info = { "HTMLFrameElement", &JSHTMLElement::info, &HTMLFrameElementTable, 0 };
446 const ClassInfo JSHTMLElement::iFrame_info = { "HTMLIFrameElement", &JSHTMLElement::info, &HTMLIFrameElementTable, 0 };
447 const ClassInfo JSHTMLElement::info = { "HTMLElement", &JSElement::info, &HTMLElementTable, 0 };
448 const ClassInfo JSHTMLElement::marquee_info = { "HTMLMarqueeElement", &JSHTMLElement::info, &HTMLMarqueeElementTable, 0 };
449 const ClassInfo JSHTMLElement::object_info = { "HTMLObjectElement", &JSHTMLElement::info, &HTMLObjectElementTable, 0 };
450 const ClassInfo JSHTMLElement::select_info = { "HTMLSelectElement", &JSHTMLElement::info, &HTMLSelectElementTable, 0 };
451 const ClassInfo JSHTMLElement::table_info = { "HTMLTableElement", &JSHTMLElement::info, &HTMLTableElementTable, 0 };
452 const ClassInfo JSHTMLElement::tablecell_info = { "HTMLTableCellElement", &JSHTMLElement::info, &HTMLTableCellElementTable, 0 };
453 const ClassInfo JSHTMLElement::tablesection_info = { "HTMLTableSectionElement", &JSHTMLElement::info, &HTMLTableSectionElementTable, 0 };
454 const ClassInfo JSHTMLElement::tr_info = { "HTMLTableRowElement", &JSHTMLElement::info, &HTMLTableRowElementTable, 0 };
455
456 const ClassInfo* JSHTMLElement::classInfo() const
457 {
458     static HashMap<WebCore::AtomicStringImpl*, const ClassInfo*> classInfoMap;
459     if (classInfoMap.isEmpty()) {
460         classInfoMap.set(captionTag.localName().impl(), &caption_info);
461         classInfoMap.set(colTag.localName().impl(), &col_info);
462         classInfoMap.set(colgroupTag.localName().impl(), &col_info);
463         classInfoMap.set(embedTag.localName().impl(), &embed_info);
464         classInfoMap.set(frameTag.localName().impl(), &frame_info);
465         classInfoMap.set(framesetTag.localName().impl(), &frameSet_info);
466         classInfoMap.set(iframeTag.localName().impl(), &iFrame_info);
467         classInfoMap.set(marqueeTag.localName().impl(), &marquee_info);
468         classInfoMap.set(objectTag.localName().impl(), &object_info);
469         classInfoMap.set(selectTag.localName().impl(), &select_info);
470         classInfoMap.set(tableTag.localName().impl(), &table_info);
471         classInfoMap.set(tbodyTag.localName().impl(), &tablesection_info);
472         classInfoMap.set(tdTag.localName().impl(), &tablecell_info);
473         classInfoMap.set(tfootTag.localName().impl(), &tablesection_info);
474         classInfoMap.set(thTag.localName().impl(), &tablecell_info);
475         classInfoMap.set(theadTag.localName().impl(), &tablesection_info);
476         classInfoMap.set(trTag.localName().impl(), &tr_info);
477     }
478     
479     HTMLElement* element = static_cast<HTMLElement*>(impl());
480     const ClassInfo* result = classInfoMap.get(element->localName().impl());
481     if (result)
482         return result;
483     return &info;
484 }
485
486 const JSHTMLElement::Accessors JSHTMLElement::select_accessors = { &JSHTMLElement::selectGetter, &JSHTMLElement::selectSetter };
487 const JSHTMLElement::Accessors JSHTMLElement::object_accessors = { &JSHTMLElement::objectGetter, &JSHTMLElement::objectSetter };
488 const JSHTMLElement::Accessors JSHTMLElement::embed_accessors = { &JSHTMLElement::embedGetter, &JSHTMLElement::embedSetter };
489 const JSHTMLElement::Accessors JSHTMLElement::table_accessors = { &JSHTMLElement::tableGetter, &JSHTMLElement::tableSetter };
490 const JSHTMLElement::Accessors JSHTMLElement::caption_accessors = { &JSHTMLElement::tableCaptionGetter, &JSHTMLElement::tableCaptionSetter };
491 const JSHTMLElement::Accessors JSHTMLElement::col_accessors = { &JSHTMLElement::tableColGetter, &JSHTMLElement::tableColSetter };
492 const JSHTMLElement::Accessors JSHTMLElement::tablesection_accessors = { &JSHTMLElement::tableSectionGetter, &JSHTMLElement::tableSectionSetter };
493 const JSHTMLElement::Accessors JSHTMLElement::tr_accessors = { &JSHTMLElement::tableRowGetter, &JSHTMLElement::tableRowSetter };
494 const JSHTMLElement::Accessors JSHTMLElement::tablecell_accessors = { &JSHTMLElement::tableCellGetter, &JSHTMLElement::tableCellSetter };
495 const JSHTMLElement::Accessors JSHTMLElement::frameSet_accessors = { &JSHTMLElement::frameSetGetter, &JSHTMLElement::frameSetSetter };
496 const JSHTMLElement::Accessors JSHTMLElement::frame_accessors = { &JSHTMLElement::frameGetter, &JSHTMLElement::frameSetter };
497 const JSHTMLElement::Accessors JSHTMLElement::iFrame_accessors = { &JSHTMLElement::iFrameGetter, &JSHTMLElement::iFrameSetter };
498 const JSHTMLElement::Accessors JSHTMLElement::marquee_accessors = { &JSHTMLElement::marqueeGetter, &JSHTMLElement::marqueeSetter };
499
500 const JSHTMLElement::Accessors* JSHTMLElement::accessors() const
501 {
502     static HashMap<WebCore::AtomicStringImpl*, const Accessors*> accessorMap;
503     if (accessorMap.isEmpty()) {
504         accessorMap.add(captionTag.localName().impl(), &caption_accessors);
505         accessorMap.add(colTag.localName().impl(), &col_accessors);
506         accessorMap.add(colgroupTag.localName().impl(), &col_accessors);
507         accessorMap.add(embedTag.localName().impl(), &embed_accessors);
508         accessorMap.add(frameTag.localName().impl(), &frame_accessors);
509         accessorMap.add(framesetTag.localName().impl(), &frameSet_accessors);
510         accessorMap.add(iframeTag.localName().impl(), &iFrame_accessors);
511         accessorMap.add(marqueeTag.localName().impl(), &marquee_accessors);
512         accessorMap.add(objectTag.localName().impl(), &object_accessors);
513         accessorMap.add(selectTag.localName().impl(), &select_accessors);
514         accessorMap.add(tableTag.localName().impl(), &table_accessors);
515         accessorMap.add(tbodyTag.localName().impl(), &tablesection_accessors);
516         accessorMap.add(tdTag.localName().impl(), &tablecell_accessors);
517         accessorMap.add(thTag.localName().impl(), &tablecell_accessors);
518         accessorMap.add(theadTag.localName().impl(), &tablesection_accessors);
519         accessorMap.add(tfootTag.localName().impl(), &tablesection_accessors);
520         accessorMap.add(trTag.localName().impl(), &tr_accessors);
521     }
522     
523     HTMLElement* element = static_cast<HTMLElement*>(impl());
524     return accessorMap.get(element->localName().impl());
525 }
526
527 /*
528
529 @begin JSHTMLElementProtoTable 0
530 @end
531
532 @begin HTMLElementTable 14
533   id            KJS::JSHTMLElement::ElementId     DontDelete
534   lang          KJS::JSHTMLElement::ElementLang   DontDelete
535   dir           KJS::JSHTMLElement::ElementDir    DontDelete
536 ### isn't this "class" in the HTML spec?
537   className     KJS::JSHTMLElement::ElementClassName DontDelete
538   innerHTML     KJS::JSHTMLElement::ElementInnerHTML DontDelete
539   innerText     KJS::JSHTMLElement::ElementInnerText DontDelete
540   outerHTML     KJS::JSHTMLElement::ElementOuterHTML DontDelete
541   outerText     KJS::JSHTMLElement::ElementOuterText DontDelete
542   document      KJS::JSHTMLElement::ElementDocument  DontDelete|ReadOnly
543 # IE extension
544   children      KJS::JSHTMLElement::ElementChildren  DontDelete|ReadOnly
545   contentEditable   KJS::JSHTMLElement::ElementContentEditable  DontDelete
546   isContentEditable KJS::JSHTMLElement::ElementIsContentEditable  DontDelete|ReadOnly
547 @end
548 @begin HTMLSelectElementTable 11
549 # Also supported, by index
550   type          KJS::JSHTMLElement::SelectType    DontDelete|ReadOnly
551   selectedIndex KJS::JSHTMLElement::SelectSelectedIndex   DontDelete
552   value         KJS::JSHTMLElement::SelectValue   DontDelete
553   length        KJS::JSHTMLElement::SelectLength  DontDelete
554   form          KJS::JSHTMLElement::SelectForm    DontDelete|ReadOnly
555   options       KJS::JSHTMLElement::SelectOptions DontDelete|ReadOnly
556   namedItem     KJS::JSHTMLElement::SelectNamedItem       DontDelete|Function 1
557   disabled      KJS::JSHTMLElement::SelectDisabled        DontDelete
558   multiple      KJS::JSHTMLElement::SelectMultiple        DontDelete
559   name          KJS::JSHTMLElement::SelectName    DontDelete
560   size          KJS::JSHTMLElement::SelectSize    DontDelete
561   tabIndex      KJS::JSHTMLElement::SelectTabIndex        DontDelete
562   add           KJS::JSHTMLElement::SelectAdd     DontDelete|Function 2
563   remove        KJS::JSHTMLElement::SelectRemove  DontDelete|Function 1
564   blur          KJS::JSHTMLElement::SelectBlur    DontDelete|Function 0
565   focus         KJS::JSHTMLElement::SelectFocus   DontDelete|Function 0
566 @end
567 @begin HTMLObjectElementTable 20
568   form            KJS::JSHTMLElement::ObjectForm            DontDelete|ReadOnly
569   code            KJS::JSHTMLElement::ObjectCode            DontDelete
570   align           KJS::JSHTMLElement::ObjectAlign           DontDelete
571   archive         KJS::JSHTMLElement::ObjectArchive         DontDelete
572   border          KJS::JSHTMLElement::ObjectBorder          DontDelete
573   codeBase        KJS::JSHTMLElement::ObjectCodeBase        DontDelete
574   codeType        KJS::JSHTMLElement::ObjectCodeType        DontDelete
575   contentDocument KJS::JSHTMLElement::ObjectContentDocument DontDelete|ReadOnly
576   data            KJS::JSHTMLElement::ObjectData            DontDelete
577   declare         KJS::JSHTMLElement::ObjectDeclare         DontDelete
578   height          KJS::JSHTMLElement::ObjectHeight          DontDelete
579   hspace          KJS::JSHTMLElement::ObjectHspace          DontDelete
580   getSVGDocument  KJS::JSHTMLElement::ObjectGetSVGDocument  DontDelete|Function 0
581   name            KJS::JSHTMLElement::ObjectName            DontDelete
582   standby         KJS::JSHTMLElement::ObjectStandby         DontDelete
583   tabIndex        KJS::JSHTMLElement::ObjectTabIndex        DontDelete
584   type            KJS::JSHTMLElement::ObjectType            DontDelete
585   useMap          KJS::JSHTMLElement::ObjectUseMap          DontDelete
586   vspace          KJS::JSHTMLElement::ObjectVspace          DontDelete
587   width           KJS::JSHTMLElement::ObjectWidth           DontDelete
588 @end
589 @begin HTMLEmbedElementTable 6
590   align         KJS::JSHTMLElement::EmbedAlign           DontDelete
591   height        KJS::JSHTMLElement::EmbedHeight          DontDelete
592   getSVGDocument KJS::JSHTMLElement::EmbedGetSVGDocument DontDelete|Function 0
593   name          KJS::JSHTMLElement::EmbedName            DontDelete
594   src           KJS::JSHTMLElement::EmbedSrc             DontDelete
595   type          KJS::JSHTMLElement::EmbedType            DontDelete
596   width         KJS::JSHTMLElement::EmbedWidth           DontDelete
597 @end
598 @begin HTMLTableElementTable 23
599   caption       KJS::JSHTMLElement::TableCaption          DontDelete
600   tHead         KJS::JSHTMLElement::TableTHead            DontDelete
601   tFoot         KJS::JSHTMLElement::TableTFoot            DontDelete
602   rows          KJS::JSHTMLElement::TableRows             DontDelete|ReadOnly
603   tBodies       KJS::JSHTMLElement::TableTBodies          DontDelete|ReadOnly
604   align         KJS::JSHTMLElement::TableAlign            DontDelete
605   bgColor       KJS::JSHTMLElement::TableBgColor          DontDelete
606   border        KJS::JSHTMLElement::TableBorder           DontDelete
607   cellPadding   KJS::JSHTMLElement::TableCellPadding      DontDelete
608   cellSpacing   KJS::JSHTMLElement::TableCellSpacing      DontDelete
609   frame         KJS::JSHTMLElement::TableFrame            DontDelete
610   rules         KJS::JSHTMLElement::TableRules            DontDelete
611   summary       KJS::JSHTMLElement::TableSummary          DontDelete
612   width         KJS::JSHTMLElement::TableWidth            DontDelete
613   createTHead   KJS::JSHTMLElement::TableCreateTHead      DontDelete|Function 0
614   deleteTHead   KJS::JSHTMLElement::TableDeleteTHead      DontDelete|Function 0
615   createTFoot   KJS::JSHTMLElement::TableCreateTFoot      DontDelete|Function 0
616   deleteTFoot   KJS::JSHTMLElement::TableDeleteTFoot      DontDelete|Function 0
617   createCaption KJS::JSHTMLElement::TableCreateCaption    DontDelete|Function 0
618   deleteCaption KJS::JSHTMLElement::TableDeleteCaption    DontDelete|Function 0
619   insertRow     KJS::JSHTMLElement::TableInsertRow        DontDelete|Function 1
620   deleteRow     KJS::JSHTMLElement::TableDeleteRow        DontDelete|Function 1
621 @end
622 @begin HTMLTableCaptionElementTable 1
623   align         KJS::JSHTMLElement::TableCaptionAlign     DontDelete
624 @end
625 @begin HTMLTableColElementTable 7
626   align         KJS::JSHTMLElement::TableColAlign         DontDelete
627   ch            KJS::JSHTMLElement::TableColCh            DontDelete
628   chOff         KJS::JSHTMLElement::TableColChOff         DontDelete
629   span          KJS::JSHTMLElement::TableColSpan          DontDelete
630   vAlign        KJS::JSHTMLElement::TableColVAlign        DontDelete
631   width         KJS::JSHTMLElement::TableColWidth         DontDelete
632 @end
633 @begin HTMLTableSectionElementTable 7
634   align         KJS::JSHTMLElement::TableSectionAlign             DontDelete
635   ch            KJS::JSHTMLElement::TableSectionCh                DontDelete
636   chOff         KJS::JSHTMLElement::TableSectionChOff             DontDelete
637   vAlign        KJS::JSHTMLElement::TableSectionVAlign            DontDelete
638   rows          KJS::JSHTMLElement::TableSectionRows              DontDelete|ReadOnly
639   insertRow     KJS::JSHTMLElement::TableSectionInsertRow         DontDelete|Function 1
640   deleteRow     KJS::JSHTMLElement::TableSectionDeleteRow         DontDelete|Function 1
641 @end
642 @begin HTMLTableRowElementTable 11
643   rowIndex      KJS::JSHTMLElement::TableRowRowIndex              DontDelete|ReadOnly
644   sectionRowIndex KJS::JSHTMLElement::TableRowSectionRowIndex     DontDelete|ReadOnly
645   cells         KJS::JSHTMLElement::TableRowCells                 DontDelete|ReadOnly
646   align         KJS::JSHTMLElement::TableRowAlign                 DontDelete
647   bgColor       KJS::JSHTMLElement::TableRowBgColor               DontDelete
648   ch            KJS::JSHTMLElement::TableRowCh                    DontDelete
649   chOff         KJS::JSHTMLElement::TableRowChOff                 DontDelete
650   vAlign        KJS::JSHTMLElement::TableRowVAlign                DontDelete
651   insertCell    KJS::JSHTMLElement::TableRowInsertCell            DontDelete|Function 1
652   deleteCell    KJS::JSHTMLElement::TableRowDeleteCell            DontDelete|Function 1
653 @end
654 @begin HTMLTableCellElementTable 15
655   cellIndex     KJS::JSHTMLElement::TableCellCellIndex            DontDelete|ReadOnly
656   abbr          KJS::JSHTMLElement::TableCellAbbr                 DontDelete
657   align         KJS::JSHTMLElement::TableCellAlign                DontDelete
658   axis          KJS::JSHTMLElement::TableCellAxis                 DontDelete
659   bgColor       KJS::JSHTMLElement::TableCellBgColor              DontDelete
660   ch            KJS::JSHTMLElement::TableCellCh                   DontDelete
661   chOff         KJS::JSHTMLElement::TableCellChOff                DontDelete
662   colSpan       KJS::JSHTMLElement::TableCellColSpan              DontDelete
663   headers       KJS::JSHTMLElement::TableCellHeaders              DontDelete
664   height        KJS::JSHTMLElement::TableCellHeight               DontDelete
665   noWrap        KJS::JSHTMLElement::TableCellNoWrap               DontDelete
666   rowSpan       KJS::JSHTMLElement::TableCellRowSpan              DontDelete
667   scope         KJS::JSHTMLElement::TableCellScope                DontDelete
668   vAlign        KJS::JSHTMLElement::TableCellVAlign               DontDelete
669   width         KJS::JSHTMLElement::TableCellWidth                DontDelete
670 @end
671 @begin HTMLFrameSetElementTable 2
672 cols          KJS::JSHTMLElement::FrameSetCols                  DontDelete
673 rows          KJS::JSHTMLElement::FrameSetRows                  DontDelete
674 @end
675 @begin HTMLFrameElementTable 9
676   contentDocument KJS::JSHTMLElement::FrameContentDocument        DontDelete|ReadOnly
677   contentWindow   KJS::JSHTMLElement::FrameContentWindow          DontDelete|ReadOnly
678   frameBorder     KJS::JSHTMLElement::FrameFrameBorder            DontDelete
679   longDesc        KJS::JSHTMLElement::FrameLongDesc               DontDelete
680   marginHeight    KJS::JSHTMLElement::FrameMarginHeight           DontDelete
681   marginWidth     KJS::JSHTMLElement::FrameMarginWidth            DontDelete
682   name            KJS::JSHTMLElement::FrameName                   DontDelete
683   noResize        KJS::JSHTMLElement::FrameNoResize               DontDelete
684   width           KJS::JSHTMLElement::FrameWidth                  DontDelete|ReadOnly
685   height          KJS::JSHTMLElement::FrameHeight                 DontDelete|ReadOnly
686   scrolling       KJS::JSHTMLElement::FrameScrolling              DontDelete
687   src             KJS::JSHTMLElement::FrameSrc                    DontDelete
688   location        KJS::JSHTMLElement::FrameLocation               DontDelete
689 @end
690 @begin HTMLIFrameElementTable 12
691   align           KJS::JSHTMLElement::IFrameAlign                 DontDelete
692   contentDocument KJS::JSHTMLElement::IFrameContentDocument       DontDelete|ReadOnly
693   contentWindow   KJS::JSHTMLElement::IFrameContentWindow         DontDelete|ReadOnly
694   document        KJS::JSHTMLElement::IFrameDocument              DontDelete|ReadOnly
695   frameBorder     KJS::JSHTMLElement::IFrameFrameBorder           DontDelete
696   height          KJS::JSHTMLElement::IFrameHeight                DontDelete
697   longDesc        KJS::JSHTMLElement::IFrameLongDesc              DontDelete
698   marginHeight    KJS::JSHTMLElement::IFrameMarginHeight          DontDelete
699   marginWidth     KJS::JSHTMLElement::IFrameMarginWidth           DontDelete
700   name            KJS::JSHTMLElement::IFrameName                  DontDelete
701   scrolling       KJS::JSHTMLElement::IFrameScrolling             DontDelete
702   src             KJS::JSHTMLElement::IFrameSrc                   DontDelete
703   width           KJS::JSHTMLElement::IFrameWidth                 DontDelete
704 @end
705
706 @begin HTMLMarqueeElementTable 2
707   start           KJS::JSHTMLElement::MarqueeStart                DontDelete|Function 0
708   stop            KJS::JSHTMLElement::MarqueeStop                 DontDelete|Function 0
709 @end
710 */
711
712 KJS_IMPLEMENT_PROTOFUNC(JSHTMLElementProtoFunc)
713 KJS_IMPLEMENT_PROTOTYPE("HTMLElement", JSHTMLElementProto, JSHTMLElementProtoFunc)
714
715 JSValue* JSHTMLElementProtoFunc::callAsFunction(ExecState*, JSObject*, const List&)
716 {
717     return 0;
718 }
719
720 JSHTMLElement::JSHTMLElement(ExecState* exec, HTMLElement* e)
721     : WebCore::JSHTMLElement(exec, e)
722 {
723     setPrototype(JSHTMLElementProto::self(exec));
724 }
725
726 JSValue *JSHTMLElement::selectIndexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
727 {
728     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
729     HTMLSelectElement* select = static_cast<HTMLSelectElement*>(thisObj->impl());
730
731     return toJS(exec, select->options()->item(slot.index()));
732 }
733
734 JSValue *JSHTMLElement::framesetNameGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
735 {
736     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
737     HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl());
738
739     WebCore::Node *frame = element->children()->namedItem(propertyName);
740     if (Document* doc = static_cast<HTMLFrameElement*>(frame)->contentDocument())
741         if (Window *window = Window::retrieveWindow(doc->frame()))
742             return window;
743
744     return jsUndefined();
745 }
746
747 JSValue *JSHTMLElement::runtimeObjectGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
748 {
749     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
750     HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl());
751
752     return getRuntimeObject(exec, element);
753 }
754
755 JSValue *JSHTMLElement::runtimeObjectPropertyGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
756 {
757     JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
758     HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl());
759
760     if (JSValue *runtimeObject = getRuntimeObject(exec, element))
761         return static_cast<JSObject*>(runtimeObject)->get(exec, propertyName);
762     return jsUndefined();
763 }
764
765 bool JSHTMLElement::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
766 {
767     HTMLElement &element = *static_cast<HTMLElement*>(impl());
768
769     // First look at dynamic properties
770     if (element.hasLocalName(selectTag)) {
771         bool ok;
772         unsigned u = propertyName.toUInt32(&ok);
773         if (ok) {
774             // not specified by DOM(?) but supported in netscape/IE
775             slot.setCustomIndex(this, u, selectIndexGetter);
776             return true;
777         }
778     } else if (element.hasLocalName(framesetTag)) {
779         WebCore::Node *frame = element.children()->namedItem(propertyName);
780         if (frame && frame->hasTagName(frameTag)) {
781             slot.setCustom(this, framesetNameGetter);
782             return true;
783         }
784     } else if (element.hasLocalName(embedTag) || element.hasLocalName(objectTag) || element.hasLocalName(appletTag)) {
785         if (propertyName == "__apple_runtime_object") {
786             slot.setCustom(this, runtimeObjectGetter);
787             return true;
788         }
789         JSValue *runtimeObject = getRuntimeObject(exec,&element);
790         if (runtimeObject) {
791             JSObject* imp = static_cast<JSObject*>(runtimeObject);
792             if (imp->hasProperty(exec, propertyName)) {
793                 slot.setCustom(this, runtimeObjectPropertyGetter);
794                 return true;
795             }
796         }
797     }
798
799     const HashTable* table = classInfo()->propHashTable; // get the right hashtable
800     const HashEntry* entry = Lookup::findEntry(table, propertyName);
801     if (entry) {
802         if (entry->attr & Function)
803             slot.setStaticEntry(this, entry, staticFunctionGetter<HTMLElementFunction>); 
804         else
805             slot.setStaticEntry(this, entry, staticValueGetter<JSHTMLElement>);
806         return true;
807     }
808
809     // Base JSHTMLElement stuff or parent class forward, as usual
810     return getStaticPropertySlot<HTMLElementFunction, JSHTMLElement, WebCore::JSHTMLElement>(exec, &HTMLElementTable, this, propertyName, slot);
811 }
812
813 bool JSHTMLElement::implementsCall() const
814 {
815     HTMLElement* element = static_cast<HTMLElement*>(impl());
816     if (element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) {
817         Document* doc = element->document();
818         KJSProxy *proxy = doc->frame()->jScript();
819         ExecState* exec = proxy->interpreter()->globalExec();
820         if (JSValue *runtimeObject = getRuntimeObject(exec, element))
821             return static_cast<JSObject*>(runtimeObject)->implementsCall();
822     }
823     return false;
824 }
825
826 JSValue *JSHTMLElement::callAsFunction(ExecState* exec, JSObject* thisObj, const List&args)
827 {
828     HTMLElement* element = static_cast<HTMLElement*>(impl());
829     if (element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) {
830         if (JSValue *runtimeObject = getRuntimeObject(exec, element))
831             return static_cast<JSObject*>(runtimeObject)->call(exec, thisObj, args);
832     }
833     return jsUndefined();
834 }
835
836 JSValue *JSHTMLElement::selectGetter(ExecState* exec, int token) const
837 {
838     HTMLSelectElement& select = *static_cast<HTMLSelectElement*>(impl());
839     switch (token) {
840         case SelectType:            return jsString(select.type());
841         case SelectSelectedIndex:   return jsNumber(select.selectedIndex());
842         case SelectValue:           return jsString(select.value());
843         case SelectLength:          return jsNumber(select.length());
844         case SelectForm:            return toJS(exec, select.form()); // type HTMLFormElement
845         case SelectOptions:         return getHTMLOptionsCollection(exec, select.options().get());
846         case SelectDisabled:        return jsBoolean(select.disabled());
847         case SelectMultiple:        return jsBoolean(select.multiple());
848         case SelectName:            return jsString(select.name());
849         case SelectSize:            return jsNumber(select.size());
850         case SelectTabIndex:        return jsNumber(select.tabIndex());
851     }
852     return jsUndefined();
853 }
854
855 JSValue *JSHTMLElement::objectGetter(ExecState* exec, int token) const
856 {
857     HTMLObjectElement& object = *static_cast<HTMLObjectElement*>(impl());
858     switch (token) {
859         case ObjectForm:            return toJS(exec,object.form()); // type HTMLFormElement
860         case ObjectCode:            return jsString(object.code());
861         case ObjectAlign:           return jsString(object.align());
862         case ObjectArchive:         return jsString(object.archive());
863         case ObjectBorder:          return jsString(object.border());
864         case ObjectCodeBase:        return jsString(object.codeBase());
865         case ObjectCodeType:        return jsString(object.codeType());
866         case ObjectContentDocument: return checkNodeSecurity(exec,object.contentDocument()) ? 
867                                            toJS(exec, object.contentDocument()) : jsUndefined();
868         case ObjectData:            return jsString(object.data());
869         case ObjectDeclare:         return jsBoolean(object.declare());
870         case ObjectHeight:          return jsString(object.height());
871         case ObjectHspace:          return jsNumber(object.hspace());
872         case ObjectName:            return jsString(object.name());
873         case ObjectStandby:         return jsString(object.standby());
874         case ObjectTabIndex:        return jsNumber(object.tabIndex());
875         case ObjectType:            return jsString(object.type());
876         case ObjectUseMap:          return jsString(object.useMap());
877         case ObjectVspace:          return jsNumber(object.vspace());
878         case ObjectWidth:           return jsString(object.width());
879     }
880     return jsUndefined();
881 }
882
883 JSValue *JSHTMLElement::embedGetter(ExecState* exec, int token) const
884 {
885     HTMLEmbedElement& embed = *static_cast<HTMLEmbedElement*>(impl());
886     switch (token) {
887         case EmbedAlign:           return jsString(embed.align());
888         case EmbedHeight:          return jsString(embed.height());
889         case EmbedName:            return jsString(embed.name());
890         case EmbedSrc:             return jsString(embed.src());
891         case EmbedType:            return jsString(embed.type());
892         case EmbedWidth:           return jsString(embed.width());
893     }
894     return jsUndefined();
895 }
896
897 #ifdef FIXME
898     HTMLAreaElement& area = *static_cast<HTMLAreaElement*>(impl());
899     switch (token) {
900         case AreaAccessKey:       return jsString(area.accessKey());
901         case AreaAlt:             return jsString(area.alt());
902         case AreaCoords:          return jsString(area.coords());
903         case AreaHref:            return jsString(area.href());
904         case AreaHash:            return jsString('#'+KURL(area.href().deprecatedString()).ref());
905         case AreaHost:            return jsString(KURL(area.href().deprecatedString()).host());
906         case AreaHostName: {
907             KURL url(area.href().deprecatedString());
908             if (url.port()==0)
909                 return jsString(url.host());
910             else
911                 return jsString(url.host() + ":" + DeprecatedString::number(url.port()));
912         }
913         case AreaPathName:        return jsString(KURL(area.href().deprecatedString()).path());
914         case AreaPort:            return jsString(DeprecatedString::number(KURL(area.href().deprecatedString()).port()));
915         case AreaProtocol:        return jsString(KURL(area.href().deprecatedString()).protocol()+":");
916         case AreaSearch:          return jsString(KURL(area.href().deprecatedString()).query());
917         case AreaNoHref:          return jsBoolean(area.noHref());
918         case AreaShape:           return jsString(area.shape());
919         case AreaTabIndex:        return jsNumber(area.tabIndex());
920         case AreaTarget:          return jsString(area.target());
921     }
922 #endif
923
924 JSValue *JSHTMLElement::tableGetter(ExecState* exec, int token) const
925 {
926     HTMLTableElement& table = *static_cast<HTMLTableElement*>(impl());
927     switch (token) {
928         case TableCaption:         return toJS(exec,table.caption()); // type HTMLTableCaptionElement
929         case TableTHead:           return toJS(exec,table.tHead()); // type HTMLTableSectionElement
930         case TableTFoot:           return toJS(exec,table.tFoot()); // type HTMLTableSectionElement
931         case TableRows:            return getHTMLCollection(exec, table.rows().get()); // type JSHTMLCollection
932         case TableTBodies:         return getHTMLCollection(exec, table.tBodies().get()); // type JSHTMLCollection
933         case TableAlign:           return jsString(table.align());
934         case TableBgColor:         return jsString(table.bgColor());
935         case TableBorder:          return jsString(table.border());
936         case TableCellPadding:     return jsString(table.cellPadding());
937         case TableCellSpacing:     return jsString(table.cellSpacing());
938         case TableFrame:           return jsString(table.frame());
939         case TableRules:           return jsString(table.rules());
940         case TableSummary:         return jsString(table.summary());
941         case TableWidth:           return jsString(table.width());
942     }
943     return jsUndefined();
944 }
945
946 JSValue *JSHTMLElement::tableCaptionGetter(ExecState* exec, int token) const
947 {
948     HTMLTableCaptionElement& tableCaption = *static_cast<HTMLTableCaptionElement*>(impl());
949     if (token == TableCaptionAlign)
950         return jsString(tableCaption.align());
951     return jsUndefined();
952 }
953
954 JSValue *JSHTMLElement::tableColGetter(ExecState* exec, int token) const
955 {
956     HTMLTableColElement& tableCol = *static_cast<HTMLTableColElement*>(impl());
957     switch (token) {
958         case TableColAlign:           return jsString(tableCol.align());
959         case TableColCh:              return jsString(tableCol.ch());
960         case TableColChOff:           return jsString(tableCol.chOff());
961         case TableColSpan:            return jsNumber(tableCol.span());
962         case TableColVAlign:          return jsString(tableCol.vAlign());
963         case TableColWidth:           return jsString(tableCol.width());
964     }
965     return jsUndefined();
966 }
967
968 JSValue *JSHTMLElement::tableSectionGetter(ExecState* exec, int token) const
969 {
970     HTMLTableSectionElement& tableSection = *static_cast<HTMLTableSectionElement*>(impl());
971     switch (token) {
972         case TableSectionAlign:           return jsString(tableSection.align());
973         case TableSectionCh:              return jsString(tableSection.ch());
974         case TableSectionChOff:           return jsString(tableSection.chOff());
975         case TableSectionVAlign:          return jsString(tableSection.vAlign());
976         case TableSectionRows:            return getHTMLCollection(exec, tableSection.rows().get()); // type JSHTMLCollection
977     }
978     return jsUndefined();
979 }
980
981 JSValue *JSHTMLElement::tableRowGetter(ExecState* exec, int token) const
982 {
983     HTMLTableRowElement& tableRow = *static_cast<HTMLTableRowElement*>(impl());
984     switch (token) {
985         case TableRowRowIndex:        return jsNumber(tableRow.rowIndex());
986         case TableRowSectionRowIndex: return jsNumber(tableRow.sectionRowIndex());
987         case TableRowCells:           return getHTMLCollection(exec, tableRow.cells().get()); // type JSHTMLCollection
988         case TableRowAlign:           return jsString(tableRow.align());
989         case TableRowBgColor:         return jsString(tableRow.bgColor());
990         case TableRowCh:              return jsString(tableRow.ch());
991         case TableRowChOff:           return jsString(tableRow.chOff());
992         case TableRowVAlign:          return jsString(tableRow.vAlign());
993     }
994     return jsUndefined();
995 }
996
997 JSValue *JSHTMLElement::tableCellGetter(ExecState* exec, int token) const
998 {
999     HTMLTableCellElement& tableCell = *static_cast<HTMLTableCellElement*>(impl());
1000     switch (token) {
1001         case TableCellCellIndex:       return jsNumber(tableCell.cellIndex());
1002         case TableCellAbbr:            return jsString(tableCell.abbr());
1003         case TableCellAlign:           return jsString(tableCell.align());
1004         case TableCellAxis:            return jsString(tableCell.axis());
1005         case TableCellBgColor:         return jsString(tableCell.bgColor());
1006         case TableCellCh:              return jsString(tableCell.ch());
1007         case TableCellChOff:           return jsString(tableCell.chOff());
1008         case TableCellColSpan:         return jsNumber(tableCell.colSpan());
1009         case TableCellHeaders:         return jsString(tableCell.headers());
1010         case TableCellHeight:          return jsString(tableCell.height());
1011         case TableCellNoWrap:          return jsBoolean(tableCell.noWrap());
1012         case TableCellRowSpan:         return jsNumber(tableCell.rowSpan());
1013         case TableCellScope:           return jsString(tableCell.scope());
1014         case TableCellVAlign:          return jsString(tableCell.vAlign());
1015         case TableCellWidth:           return jsString(tableCell.width());
1016     }
1017     return jsUndefined();
1018 }
1019
1020 JSValue *JSHTMLElement::frameSetGetter(ExecState* exec, int token) const
1021 {
1022     HTMLFrameSetElement& frameSet = *static_cast<HTMLFrameSetElement*>(impl());
1023     switch (token) {
1024         case FrameSetCols:            return jsString(frameSet.cols());
1025         case FrameSetRows:            return jsString(frameSet.rows());
1026     }
1027     return jsUndefined();
1028 }
1029
1030 JSValue *JSHTMLElement::frameGetter(ExecState* exec, int token) const
1031 {
1032     HTMLFrameElement& frameElement = *static_cast<HTMLFrameElement*>(impl());
1033     switch (token) {
1034         case FrameContentDocument: return checkNodeSecurity(exec,frameElement.contentDocument()) ? 
1035                                           toJS(exec, frameElement.contentDocument()) : jsUndefined();
1036         case FrameContentWindow:   return checkNodeSecurity(exec,frameElement.contentDocument())
1037                                         ? Window::retrieve(frameElement.contentFrame())
1038                                         : jsUndefined();
1039         case FrameFrameBorder:     return jsString(frameElement.frameBorder());
1040         case FrameLongDesc:        return jsString(frameElement.longDesc());
1041         case FrameMarginHeight:    return jsString(frameElement.marginHeight());
1042         case FrameMarginWidth:     return jsString(frameElement.marginWidth());
1043         case FrameName:            return jsString(frameElement.name());
1044         case FrameNoResize:        return jsBoolean(frameElement.noResize());
1045         case FrameWidth:           return jsNumber(frameElement.frameWidth());
1046         case FrameHeight:          return jsNumber(frameElement.frameHeight());
1047         case FrameScrolling:       return jsString(frameElement.scrolling());
1048         case FrameSrc:
1049         case FrameLocation:        return jsString(frameElement.src());
1050     }
1051     return jsUndefined();
1052 }
1053
1054 JSValue *JSHTMLElement::iFrameGetter(ExecState* exec, int token) const
1055 {
1056     HTMLIFrameElement& iFrame = *static_cast<HTMLIFrameElement*>(impl());
1057     switch (token) {
1058         case IFrameAlign:                return jsString(iFrame.align());
1059           // ### security check ?
1060         case IFrameDocument: // non-standard, mapped to contentDocument
1061         case IFrameContentDocument: return checkNodeSecurity(exec,iFrame.contentDocument()) ? 
1062                                       toJS(exec, iFrame.contentDocument()) : jsUndefined();
1063         case IFrameContentWindow:   return checkNodeSecurity(exec,iFrame.contentDocument()) 
1064                                         ? Window::retrieve(iFrame.contentFrame())
1065                                         : jsUndefined();
1066         case IFrameFrameBorder:     return jsString(iFrame.frameBorder());
1067         case IFrameHeight:          return jsString(iFrame.height());
1068         case IFrameLongDesc:        return jsString(iFrame.longDesc());
1069         case IFrameMarginHeight:    return jsString(iFrame.marginHeight());
1070         case IFrameMarginWidth:     return jsString(iFrame.marginWidth());
1071         case IFrameName:            return jsString(iFrame.name());
1072         case IFrameScrolling:       return jsString(iFrame.scrolling());
1073         case IFrameSrc:             return jsString(iFrame.src());
1074         case IFrameWidth:           return jsString(iFrame.width());
1075     }
1076     return jsUndefined();
1077 }
1078
1079 JSValue *JSHTMLElement::marqueeGetter(ExecState* exec, int token) const
1080 {
1081     // FIXME: Find out what WinIE exposes as properties and implement this.
1082     return jsUndefined();
1083 }
1084
1085 JSValue *JSHTMLElement::getValueProperty(ExecState* exec, int token) const
1086 {
1087     // Check our set of generic properties first.
1088     HTMLElement &element = *static_cast<HTMLElement*>(impl());
1089     switch (token) {
1090         case ElementId:
1091             // iht.com relies on this value being "" when no id is present. Other browsers do this as well.
1092             // So we use jsString() instead of jsStringOrNull() here.
1093             return jsString(element.id());
1094         case ElementLang:
1095             return jsString(element.lang());
1096         case ElementDir:
1097             return jsString(element.dir());
1098         case ElementClassName:
1099             return jsString(element.className());
1100         case ElementInnerHTML:
1101             return jsString(element.innerHTML());
1102         case ElementInnerText:
1103             impl()->document()->updateLayoutIgnorePendingStylesheets();
1104             return jsString(element.innerText());
1105         case ElementOuterHTML:
1106             return jsString(element.outerHTML());
1107         case ElementOuterText:
1108             return jsString(element.outerText());
1109         case ElementDocument:
1110             return toJS(exec,element.ownerDocument());
1111         case ElementChildren:
1112             return getHTMLCollection(exec, element.children().get());
1113         case ElementContentEditable:
1114             return jsString(element.contentEditable());
1115         case ElementIsContentEditable:
1116             return jsBoolean(element.isContentEditable());
1117     }
1118
1119     // Now check the properties specific to our element type.
1120     const Accessors* access = accessors();
1121     if (access && access->m_getter)
1122         return (this->*(access->m_getter))(exec, token);
1123     return jsUndefined();
1124 }
1125
1126 UString JSHTMLElement::toString(ExecState* exec) const
1127 {
1128     if (impl()->hasTagName(aTag))
1129         return UString(static_cast<const HTMLAnchorElement*>(impl())->href());
1130     else
1131         return JSElement::toString(exec);
1132 }
1133
1134 static HTMLFormElement* getForm(HTMLElement* element)
1135 {
1136     if (element->isGenericFormElement())
1137         return static_cast<HTMLGenericFormElement*>(element)->form();
1138     if (element->hasTagName(labelTag))
1139         return static_cast<HTMLLabelElement*>(element)->form();
1140     if (element->hasTagName(objectTag))
1141         return static_cast<HTMLObjectElement*>(element)->form();
1142
1143     return 0;
1144 }
1145
1146 void JSHTMLElement::pushEventHandlerScope(ExecState* exec, ScopeChain &scope) const
1147 {
1148   HTMLElement* element = static_cast<HTMLElement*>(impl());
1149
1150   // The document is put on first, fall back to searching it only after the element and form.
1151   scope.push(static_cast<JSObject*>(toJS(exec, element->ownerDocument())));
1152
1153   // The form is next, searched before the document, but after the element itself.
1154   
1155   // First try to obtain the form from the element itself.  We do this to deal with
1156   // the malformed case where <form>s aren't in our parent chain (e.g., when they were inside 
1157   // <table> or <tbody>.
1158   HTMLFormElement* form = getForm(element);
1159   if (form)
1160     scope.push(static_cast<JSObject*>(toJS(exec, form)));
1161   else {
1162     WebCore::Node* form = element->parentNode();
1163     while (form && !form->hasTagName(formTag))
1164       form = form->parentNode();
1165     
1166     if (form)
1167       scope.push(static_cast<JSObject*>(toJS(exec, form)));
1168   }
1169   
1170   // The element is on top, searched first.
1171   scope.push(static_cast<JSObject*>(toJS(exec, element)));
1172 }
1173
1174 HTMLElementFunction::HTMLElementFunction(ExecState* exec, int i, int len, const Identifier& name)
1175   : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
1176   , id(i)
1177 {
1178   put(exec,lengthPropertyName,jsNumber(len),DontDelete|ReadOnly|DontEnum);
1179 }
1180
1181 JSValue *HTMLElementFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
1182 {
1183     if (!thisObj->inherits(&JSHTMLElement::info))
1184         return throwError(exec, TypeError);
1185     DOMExceptionTranslator exception(exec);
1186     HTMLElement &element = *static_cast<HTMLElement*>(static_cast<JSHTMLElement*>(thisObj)->impl());
1187
1188     if (element.hasLocalName(selectTag)) {
1189         HTMLSelectElement &select = static_cast<HTMLSelectElement &>(element);
1190         if (id == JSHTMLElement::SelectAdd) {
1191             select.add(toHTMLElement(args[0]), toHTMLElement(args[1]), exception);
1192             return jsUndefined();
1193         }
1194         else if (id == JSHTMLElement::SelectRemove) {
1195             // we support both options index and options objects
1196             HTMLElement* element = toHTMLElement(args[0]);
1197             if (element && element->hasTagName(optionTag))
1198                 select.remove(((HTMLOptionElement*)element)->index());
1199             else
1200                 select.remove(int(args[0]->toNumber(exec)));
1201             return jsUndefined();
1202         }
1203         else if (id == JSHTMLElement::SelectBlur) {
1204             select.blur();
1205             return jsUndefined();
1206         }
1207         else if (id == JSHTMLElement::SelectFocus) {
1208             select.focus();
1209             return jsUndefined();
1210         }
1211         else if (id == JSHTMLElement::SelectNamedItem) {
1212             return toJS(exec, select.namedItem(Identifier(args[0]->toString(exec))));
1213         }
1214     }
1215     else if (element.hasLocalName(tableTag)) {
1216         HTMLTableElement &table = static_cast<HTMLTableElement &>(element);
1217         if (id == JSHTMLElement::TableCreateTHead)
1218             return toJS(exec,table.createTHead());
1219         else if (id == JSHTMLElement::TableDeleteTHead) {
1220             table.deleteTHead();
1221             return jsUndefined();
1222         }
1223         else if (id == JSHTMLElement::TableCreateTFoot)
1224             return toJS(exec,table.createTFoot());
1225         else if (id == JSHTMLElement::TableDeleteTFoot) {
1226             table.deleteTFoot();
1227             return jsUndefined();
1228         }
1229         else if (id == JSHTMLElement::TableCreateCaption)
1230             return toJS(exec,table.createCaption());
1231         else if (id == JSHTMLElement::TableDeleteCaption) {
1232             table.deleteCaption();
1233             return jsUndefined();
1234         }
1235         else if (id == JSHTMLElement::TableInsertRow)
1236             return toJS(exec,table.insertRow(args[0]->toInt32(exec), exception));
1237         else if (id == JSHTMLElement::TableDeleteRow) {
1238             table.deleteRow(args[0]->toInt32(exec), exception);
1239             return jsUndefined();
1240         }
1241     }
1242     else if (element.hasLocalName(theadTag) ||
1243              element.hasLocalName(tbodyTag) ||
1244              element.hasLocalName(tfootTag)) {
1245         HTMLTableSectionElement &tableSection = static_cast<HTMLTableSectionElement &>(element);
1246         if (id == JSHTMLElement::TableSectionInsertRow)
1247             return toJS(exec, tableSection.insertRow(args[0]->toInt32(exec), exception));
1248         else if (id == JSHTMLElement::TableSectionDeleteRow) {
1249             tableSection.deleteRow(args[0]->toInt32(exec), exception);
1250             return jsUndefined();
1251         }
1252     }
1253     else if (element.hasLocalName(trTag)) {
1254         HTMLTableRowElement &tableRow = static_cast<HTMLTableRowElement &>(element);
1255         if (id == JSHTMLElement::TableRowInsertCell)
1256             return toJS(exec,tableRow.insertCell(args[0]->toInt32(exec), exception));
1257         else if (id == JSHTMLElement::TableRowDeleteCell) {
1258             tableRow.deleteCell(args[0]->toInt32(exec), exception);
1259             return jsUndefined();
1260         }
1261     }
1262     else if (element.hasLocalName(marqueeTag)) {
1263         if (id == JSHTMLElement::MarqueeStart && element.renderer() && 
1264             element.renderer()->layer() &&
1265             element.renderer()->layer()->marquee()) {
1266             element.renderer()->layer()->marquee()->start();
1267             return jsUndefined();
1268         }
1269         if (id == JSHTMLElement::MarqueeStop && element.renderer() && 
1270             element.renderer()->layer() &&
1271             element.renderer()->layer()->marquee()) {
1272             element.renderer()->layer()->marquee()->stop();
1273             return jsUndefined();
1274         }
1275     }
1276 #if SVG_SUPPORT
1277   else if (element.hasLocalName(objectTag)) {
1278       HTMLObjectElement& object = static_cast<HTMLObjectElement&>(element);
1279       if (id == JSHTMLElement::ObjectGetSVGDocument)
1280           return checkNodeSecurity(exec, object.getSVGDocument(exception)) ? toJS(exec, object.getSVGDocument(exception)) : jsUndefined();
1281   } else if (element.hasLocalName(embedTag)) {
1282       HTMLEmbedElement& embed = static_cast<HTMLEmbedElement&>(element);
1283       if (id == JSHTMLElement::EmbedGetSVGDocument)
1284           return checkNodeSecurity(exec, embed.getSVGDocument(exception)) ? toJS(exec, embed.getSVGDocument(exception)) : jsUndefined();
1285   }
1286 #endif
1287
1288     return jsUndefined();
1289 }
1290
1291 void JSHTMLElement::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
1292 {
1293     HTMLElement &element = *static_cast<HTMLElement*>(impl());
1294     // First look at dynamic properties
1295     if (element.hasLocalName(selectTag)) {
1296         HTMLSelectElement &select = static_cast<HTMLSelectElement &>(element);
1297         bool ok;
1298         /*unsigned u =*/ propertyName.toUInt32(&ok);
1299         if (ok) {
1300             JSObject* coll = static_cast<JSObject*>(getHTMLOptionsCollection(exec, select.options().get()));
1301             coll->put(exec,propertyName,value);
1302             return;
1303         }
1304     }
1305     else if (element.hasLocalName(embedTag) || element.hasLocalName(objectTag) || element.hasLocalName(appletTag)) {
1306         if (JSValue *runtimeObject = getRuntimeObject(exec, &element)) {
1307             JSObject* imp = static_cast<JSObject*>(runtimeObject);
1308             if (imp->canPut(exec, propertyName))
1309                 return imp->put(exec, propertyName, value);
1310         }
1311     }
1312
1313     const HashTable* table = classInfo()->propHashTable; // get the right hashtable
1314     const HashEntry* entry = Lookup::findEntry(table, propertyName);
1315     if (entry) {
1316         if (entry->attr & Function) { // function: put as override property
1317             JSObject::put(exec, propertyName, value, attr);
1318             return;
1319         } else if (!(entry->attr & ReadOnly)) { // let lookupPut print the warning if read-only
1320             putValueProperty(exec, entry->value, value, attr);
1321             return;
1322         }
1323     }
1324
1325     lookupPut<JSHTMLElement, WebCore::JSHTMLElement>(exec, propertyName, value, attr, &HTMLElementTable, this);
1326 }
1327
1328 void JSHTMLElement::selectSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1329 {
1330     HTMLSelectElement& select = *static_cast<HTMLSelectElement*>(impl());
1331     switch (token) {
1332         // read-only: type
1333         case SelectSelectedIndex:   { select.setSelectedIndex(value->toInt32(exec)); return; }
1334         case SelectValue:           { select.setValue(str); return; }
1335         case SelectLength:          { // read-only according to the NS spec, but webpages need it writeable
1336                                         JSObject* coll = static_cast<JSObject*>(getHTMLOptionsCollection(exec, select.options().get()));
1337                                         coll->put(exec,lengthPropertyName,value);
1338                                         return;
1339                                     }
1340         // read-only: form
1341         // read-only: options
1342         case SelectDisabled:        { select.setDisabled(value->toBoolean(exec)); return; }
1343         case SelectMultiple:        { select.setMultiple(value->toBoolean(exec)); return; }
1344         case SelectName:            { select.setName(AtomicString(str)); return; }
1345         case SelectSize:            { select.setSize(value->toInt32(exec)); return; }
1346         case SelectTabIndex:        { select.setTabIndex(value->toInt32(exec)); return; }
1347     }
1348 }
1349
1350 void JSHTMLElement::objectSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1351 {
1352     HTMLObjectElement& object = *static_cast<HTMLObjectElement*>(impl());
1353     switch (token) {
1354         // read-only: form
1355         case ObjectCode:            { object.setCode(str); return; }
1356         case ObjectAlign:           { object.setAlign(str); return; }
1357         case ObjectArchive:         { object.setArchive(str); return; }
1358         case ObjectBorder:          { object.setBorder(str); return; }
1359         case ObjectCodeBase:        { object.setCodeBase(str); return; }
1360         case ObjectCodeType:        { object.setCodeType(str); return; }
1361         // read-only: ObjectContentDocument
1362         case ObjectData:            { object.setData(str); return; }
1363         case ObjectDeclare:         { object.setDeclare(value->toBoolean(exec)); return; }
1364         case ObjectHeight:          { object.setHeight(str); return; }
1365         case ObjectHspace:          { object.setHspace(value->toInt32(exec)); return; }
1366         case ObjectName:            { object.setName(str); return; }
1367         case ObjectStandby:         { object.setStandby(str); return; }
1368         case ObjectTabIndex:        { object.setTabIndex(value->toInt32(exec)); return; }
1369         case ObjectType:            { object.setType(str); return; }
1370         case ObjectUseMap:          { object.setUseMap(str); return; }
1371         case ObjectVspace:          { object.setVspace(value->toInt32(exec)); return; }
1372         case ObjectWidth:           { object.setWidth(str); return; }
1373     }
1374 }
1375
1376 void JSHTMLElement::embedSetter(ExecState*, int token, JSValue*, const WebCore::String& str)
1377 {
1378     HTMLEmbedElement& embed = *static_cast<HTMLEmbedElement*>(impl());
1379     switch (token) {
1380         case EmbedAlign:           { embed.setAlign(str); return; }
1381         case EmbedHeight:          { embed.setHeight(str); return; }
1382         case EmbedName:            { embed.setName(str); return; }
1383         case EmbedSrc:             { embed.setSrc(str); return; }
1384         case EmbedType:            { embed.setType(str); return; }
1385         case EmbedWidth:           { embed.setWidth(str); return; }
1386     }
1387 }
1388
1389 void JSHTMLElement::tableSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1390 {
1391     HTMLTableElement& table = *static_cast<HTMLTableElement*>(impl());
1392     switch (token) {
1393         case TableCaption:         { table.setCaption(toHTMLTableCaptionElement(value)); return; }
1394         case TableTHead:           { table.setTHead(toHTMLTableSectionElement(value)); return; }
1395         case TableTFoot:           { table.setTFoot(toHTMLTableSectionElement(value)); return; }
1396         // read-only: rows
1397         // read-only: tbodies
1398         case TableAlign:           { table.setAlign(str); return; }
1399         case TableBgColor:         { table.setBgColor(str); return; }
1400         case TableBorder:          { table.setBorder(str); return; }
1401         case TableCellPadding:     { table.setCellPadding(str); return; }
1402         case TableCellSpacing:     { table.setCellSpacing(str); return; }
1403         case TableFrame:           { table.setFrame(str); return; }
1404         case TableRules:           { table.setRules(str); return; }
1405         case TableSummary:         { table.setSummary(str); return; }
1406         case TableWidth:           { table.setWidth(str); return; }
1407     }
1408 }
1409
1410 void JSHTMLElement::tableCaptionSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1411 {
1412     HTMLTableCaptionElement& tableCaption = *static_cast<HTMLTableCaptionElement*>(impl());
1413     if (token == TableCaptionAlign)
1414         tableCaption.setAlign(str);
1415 }
1416
1417 void JSHTMLElement::tableColSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1418 {
1419     HTMLTableColElement& tableCol = *static_cast<HTMLTableColElement*>(impl());
1420     switch (token) {
1421         case TableColAlign:           { tableCol.setAlign(str); return; }
1422         case TableColCh:              { tableCol.setCh(str); return; }
1423         case TableColChOff:           { tableCol.setChOff(str); return; }
1424         case TableColSpan:            { tableCol.setSpan(value->toInt32(exec)); return; }
1425         case TableColVAlign:          { tableCol.setVAlign(str); return; }
1426         case TableColWidth:           { tableCol.setWidth(str); return; }
1427     }
1428 }
1429
1430 void JSHTMLElement::tableSectionSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1431 {
1432     HTMLTableSectionElement& tableSection = *static_cast<HTMLTableSectionElement*>(impl());
1433     switch (token) {
1434         case TableSectionAlign:           { tableSection.setAlign(str); return; }
1435         case TableSectionCh:              { tableSection.setCh(str); return; }
1436         case TableSectionChOff:           { tableSection.setChOff(str); return; }
1437         case TableSectionVAlign:          { tableSection.setVAlign(str); return; }
1438         // read-only: rows
1439     }
1440 }
1441
1442 void JSHTMLElement::tableRowSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1443 {
1444     HTMLTableRowElement& tableRow = *static_cast<HTMLTableRowElement*>(impl());
1445     switch (token) {
1446         // read-only: rowIndex
1447         // read-only: sectionRowIndex
1448         // read-only: cells
1449         case TableRowAlign:           { tableRow.setAlign(str); return; }
1450         case TableRowBgColor:         { tableRow.setBgColor(str); return; }
1451         case TableRowCh:              { tableRow.setCh(str); return; }
1452         case TableRowChOff:           { tableRow.setChOff(str); return; }
1453         case TableRowVAlign:          { tableRow.setVAlign(str); return; }
1454     }
1455 }
1456
1457 void JSHTMLElement::tableCellSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1458 {
1459     HTMLTableCellElement& tableCell = *static_cast<HTMLTableCellElement*>(impl());
1460     switch (token) {
1461         // read-only: cellIndex
1462         case TableCellAbbr:            { tableCell.setAbbr(str); return; }
1463         case TableCellAlign:           { tableCell.setAlign(str); return; }
1464         case TableCellAxis:            { tableCell.setAxis(str); return; }
1465         case TableCellBgColor:         { tableCell.setBgColor(str); return; }
1466         case TableCellCh:              { tableCell.setCh(str); return; }
1467         case TableCellChOff:           { tableCell.setChOff(str); return; }
1468         case TableCellColSpan:         { tableCell.setColSpan(value->toInt32(exec)); return; }
1469         case TableCellHeaders:         { tableCell.setHeaders(str); return; }
1470         case TableCellHeight:          { tableCell.setHeight(str); return; }
1471         case TableCellNoWrap:          { tableCell.setNoWrap(value->toBoolean(exec)); return; }
1472         case TableCellRowSpan:         { tableCell.setRowSpan(value->toInt32(exec)); return; }
1473         case TableCellScope:           { tableCell.setScope(str); return; }
1474         case TableCellVAlign:          { tableCell.setVAlign(str); return; }
1475         case TableCellWidth:           { tableCell.setWidth(str); return; }
1476     }
1477 }
1478
1479 void JSHTMLElement::frameSetSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1480 {
1481     HTMLFrameSetElement& frameSet = *static_cast<HTMLFrameSetElement*>(impl());
1482     switch (token) {
1483         case FrameSetCols:            { frameSet.setCols(str); return; }
1484         case FrameSetRows:            { frameSet.setRows(str); return; }
1485     }
1486 }
1487
1488 void JSHTMLElement::frameSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1489 {
1490     HTMLFrameElement& frameElement = *static_cast<HTMLFrameElement*>(impl());
1491     switch (token) {
1492         // read-only: FrameContentDocument:
1493         case FrameFrameBorder:     { frameElement.setFrameBorder(str); return; }
1494         case FrameLongDesc:        { frameElement.setLongDesc(str); return; }
1495         case FrameMarginHeight:    { frameElement.setMarginHeight(str); return; }
1496         case FrameMarginWidth:     { frameElement.setMarginWidth(str); return; }
1497         case FrameName:            { frameElement.setName(str); return; }
1498         case FrameNoResize:        { frameElement.setNoResize(value->toBoolean(exec)); return; }
1499         case FrameScrolling:       { frameElement.setScrolling(str); return; }
1500         case FrameSrc:             { frameElement.setSrc(str); return; }
1501         case FrameLocation:        { frameElement.setLocation(str); return; }
1502     }
1503 }
1504
1505 void JSHTMLElement::iFrameSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1506 {
1507     HTMLIFrameElement& iFrame = *static_cast<HTMLIFrameElement*>(impl());
1508     switch (token) {
1509         case IFrameAlign:           { iFrame.setAlign(str); return; }
1510         // read-only: IFrameContentDocument
1511         case IFrameFrameBorder:     { iFrame.setFrameBorder(str); return; }
1512         case IFrameHeight:          { iFrame.setHeight(str); return; }
1513         case IFrameLongDesc:        { iFrame.setLongDesc(str); return; }
1514         case IFrameMarginHeight:    { iFrame.setMarginHeight(str); return; }
1515         case IFrameMarginWidth:     { iFrame.setMarginWidth(str); return; }
1516         case IFrameName:            { iFrame.setName(str); return; }
1517         case IFrameScrolling:       { iFrame.setScrolling(str); return; }
1518         case IFrameSrc:             { iFrame.setSrc(str); return; }
1519         case IFrameWidth:           { iFrame.setWidth(str); return; }
1520     }
1521 }
1522
1523 void JSHTMLElement::marqueeSetter(ExecState* exec, int token, JSValue *value, const WebCore::String& str)
1524 {
1525     // FIXME: Find out what WinIE supports and implement it.
1526 }
1527
1528 void JSHTMLElement::putValueProperty(ExecState* exec, int token, JSValue *value, int)
1529 {
1530     DOMExceptionTranslator exception(exec);
1531     WebCore::String str = value->toString(exec);
1532  
1533     // Check our set of generic properties first.
1534     HTMLElement &element = *static_cast<HTMLElement*>(impl());
1535     switch (token) {
1536         case ElementId:
1537             element.setId(str);
1538             return;
1539         case ElementLang:
1540             element.setLang(str);
1541             return;
1542         case ElementDir:
1543             element.setDir(str);
1544             return;
1545         case ElementClassName:
1546             element.setClassName(str);
1547             return;
1548         case ElementInnerHTML:
1549             element.setInnerHTML(str, exception);
1550             return;
1551         case ElementInnerText:
1552             element.setInnerText(str, exception);
1553             return;
1554         case ElementOuterHTML:
1555             element.setOuterHTML(str, exception);
1556             return;
1557         case ElementOuterText:
1558             element.setOuterText(str, exception);
1559             return;
1560         case ElementContentEditable:
1561             element.setContentEditable(str);
1562             return;
1563     }
1564
1565     // Now check for properties that apply to a specific element type.
1566     const Accessors* access = accessors();
1567     if (access && access->m_setter)
1568         return (this->*(access->m_setter))(exec, token, value, str);  
1569 }
1570
1571 HTMLElement* toHTMLElement(JSValue *val)
1572 {
1573     if (!val || !val->isObject(&JSHTMLElement::info))
1574         return 0;
1575     return static_cast<HTMLElement*>(static_cast<JSHTMLElement*>(val)->impl());
1576 }
1577
1578 HTMLTableCaptionElement* toHTMLTableCaptionElement(JSValue *val)
1579 {
1580     HTMLElement* e = toHTMLElement(val);
1581     if (e && e->hasTagName(captionTag))
1582         return static_cast<HTMLTableCaptionElement*>(e);
1583     return 0;
1584 }
1585
1586 HTMLTableSectionElement* toHTMLTableSectionElement(JSValue *val)
1587 {
1588     HTMLElement* e = toHTMLElement(val);
1589     if (e && (e->hasTagName(theadTag) || e->hasTagName(tbodyTag) || e->hasTagName(tfootTag)))
1590         return static_cast<HTMLTableSectionElement*>(e);
1591     return 0;
1592 }
1593
1594 // -------------------------------------------------------------------------
1595 /* Source for JSHTMLCollectionProtoTable. Use "make hashtables" to regenerate.
1596 @begin JSHTMLCollectionProtoTable 3
1597   item          JSHTMLCollection::Item            DontDelete|Function 1
1598   namedItem     JSHTMLCollection::NamedItem       DontDelete|Function 1
1599   tags          JSHTMLCollection::Tags            DontDelete|Function 1
1600 @end
1601 */
1602 KJS_IMPLEMENT_PROTOFUNC(JSHTMLCollectionProtoFunc)
1603 KJS_IMPLEMENT_PROTOTYPE("HTMLCollection",JSHTMLCollectionProto,JSHTMLCollectionProtoFunc)
1604
1605 const ClassInfo JSHTMLCollection::info = { "Collection", 0, 0, 0 };
1606
1607 JSHTMLCollection::JSHTMLCollection(ExecState* exec, HTMLCollection* c)
1608   : m_impl(c) 
1609 {
1610   setPrototype(JSHTMLCollectionProto::self(exec));
1611 }
1612
1613 JSHTMLCollection::~JSHTMLCollection()
1614 {
1615   ScriptInterpreter::forgetDOMObject(m_impl.get());
1616 }
1617
1618 JSValue *JSHTMLCollection::lengthGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
1619 {
1620     JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase());
1621     return jsNumber(thisObj->m_impl->length());
1622 }
1623
1624 JSValue *JSHTMLCollection::indexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
1625 {
1626     JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase());
1627     return toJS(exec, thisObj->m_impl->item(slot.index()));
1628 }
1629
1630 JSValue *JSHTMLCollection::nameGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
1631 {
1632     JSHTMLCollection *thisObj = static_cast<JSHTMLCollection*>(slot.slotBase());
1633     return thisObj->getNamedItems(exec, propertyName);
1634 }
1635
1636 bool JSHTMLCollection::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
1637 {
1638   if (propertyName == lengthPropertyName) {
1639       slot.setCustom(this, lengthGetter);
1640       return true;
1641   } else {
1642     // Look in the prototype (for functions) before assuming it's an item's name
1643     JSValue *proto = prototype();
1644     if (proto->isObject() && static_cast<JSObject*>(proto)->hasProperty(exec, propertyName))
1645       return false;
1646
1647     // name or index ?
1648     bool ok;
1649     unsigned int u = propertyName.toUInt32(&ok);
1650     if (ok) {
1651       slot.setCustomIndex(this, u, indexGetter);
1652       return true;
1653     }
1654
1655     if (!getNamedItems(exec, propertyName)->isUndefined()) {
1656       slot.setCustom(this, nameGetter);
1657       return true;
1658     }
1659   }
1660
1661   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
1662 }
1663
1664 // HTMLCollections are strange objects, they support both get and call,
1665 // so that document.forms.item(0) and document.forms(0) both work.
1666 JSValue *JSHTMLCollection::callAsFunction(ExecState* exec, JSObject* , const List &args)
1667 {
1668   // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case.
1669   HTMLCollection &collection = *m_impl;
1670
1671   // Also, do we need the TypeError test here ?
1672
1673   if (args.size() == 1) {
1674     // support for document.all(<index>) etc.
1675     bool ok;
1676     UString s = args[0]->toString(exec);
1677     unsigned int u = s.toUInt32(&ok);
1678     if (ok)
1679       return toJS(exec, collection.item(u));
1680     // support for document.images('<name>') etc.
1681     return getNamedItems(exec, Identifier(s));
1682   }
1683   else if (args.size() >= 1) // the second arg, if set, is the index of the item we want
1684   {
1685     bool ok;
1686     UString s = args[0]->toString(exec);
1687     unsigned int u = args[1]->toString(exec).toUInt32(&ok);
1688     if (ok)
1689     {
1690       WebCore::String pstr = s;
1691       WebCore::Node *node = collection.namedItem(pstr);
1692       while (node) {
1693         if (!u)
1694           return toJS(exec,node);
1695         node = collection.nextNamedItem(pstr);
1696         --u;
1697       }
1698     }
1699   }
1700   return jsUndefined();
1701 }
1702
1703 JSValue *JSHTMLCollection::getNamedItems(ExecState* exec, const Identifier &propertyName) const
1704 {
1705     DeprecatedValueList< RefPtr<WebCore::Node> > namedItems = m_impl->namedItems(propertyName);
1706
1707     if (namedItems.isEmpty())
1708         return jsUndefined();
1709
1710     if (namedItems.count() == 1)
1711         return toJS(exec, namedItems[0].get());
1712
1713     return new DOMNamedNodesCollection(exec, namedItems);
1714 }
1715
1716 JSValue* JSHTMLCollectionProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
1717 {
1718   if (!thisObj->inherits(&JSHTMLCollection::info))
1719     return throwError(exec, TypeError);
1720   HTMLCollection &coll = *static_cast<JSHTMLCollection*>(thisObj)->impl();
1721
1722   switch (id) {
1723   case JSHTMLCollection::Item:
1724     return toJS(exec,coll.item(args[0]->toUInt32(exec)));
1725   case JSHTMLCollection::Tags:
1726     return toJS(exec, coll.base()->getElementsByTagName(args[0]->toString(exec)).get());
1727   case JSHTMLCollection::NamedItem:
1728     return static_cast<JSHTMLCollection*>(thisObj)->getNamedItems(exec, Identifier(args[0]->toString(exec)));
1729   default:
1730     return jsUndefined();
1731   }
1732 }
1733
1734 ////////////////////// Image Object ////////////////////////
1735
1736 ImageConstructorImp::ImageConstructorImp(ExecState* exec, Document* d)
1737     : m_doc(d)
1738 {
1739     setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
1740 }
1741
1742 bool ImageConstructorImp::implementsConstruct() const
1743 {
1744   return true;
1745 }
1746
1747 JSObject* ImageConstructorImp::construct(ExecState*  exec, const List & list)
1748 {
1749     bool widthSet = false, heightSet = false;
1750     int width = 0, height = 0;
1751     if (list.size() > 0) {
1752         widthSet = true;
1753         JSValue *w = list.at(0);
1754         width = w->toInt32(exec);
1755     }
1756     if (list.size() > 1) {
1757         heightSet = true;
1758         JSValue *h = list.at(1);
1759         height = h->toInt32(exec);
1760     }
1761         
1762     HTMLImageElement* result = new HTMLImageElement(m_doc.get());
1763     
1764     if (widthSet)
1765         result->setWidth(width);
1766     if (heightSet)
1767         result->setHeight(height);
1768     
1769     return static_cast<JSObject*>(toJS(exec, result));
1770 }
1771
1772 ////////////////////////////////////////////////////////////////
1773                      
1774 JSValue* getAllHTMLCollection(ExecState* exec, HTMLCollection* c)
1775 {
1776     return cacheDOMObject<HTMLCollection, HTMLAllCollection>(exec, c);
1777 }
1778
1779 JSValue* getHTMLCollection(ExecState* exec, HTMLCollection* c)
1780 {
1781     return cacheDOMObject<HTMLCollection, JSHTMLCollection>(exec, c);
1782 }
1783
1784 JSValue* getHTMLOptionsCollection(ExecState* exec, HTMLOptionsCollection* c)
1785 {
1786   DOMObject* ret;
1787   if (!c)
1788     return jsNull();
1789   ScriptInterpreter* interp = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter());
1790   if ((ret = interp->getDOMObject(c)))
1791     return ret;
1792   else {
1793     ret = new JSHTMLOptionsCollection(exec, c);
1794     interp->putDOMObject(c, ret);
1795     return ret;
1796   }
1797 }
1798
1799 } // namespace