3bc417958b0ef0ad5ade30bf69cd0352f8e876f3
[WebKit-https.git] / WebCore / khtml / ecma / kjs_html.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2004 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 "misc/loader.h"
23 #include "dom/html_block.h"
24 #include "dom/html_head.h"
25 #include "dom/html_image.h"
26 #include "dom/html_inline.h"
27 #include "dom/html_list.h"
28 #include "dom/html_table.h"
29 #include "dom/html_object.h"
30 #include "dom/dom_exception.h"
31 #include "xml/dom2_eventsimpl.h"
32
33 // ### HACK
34 #include "html/html_baseimpl.h"
35 #include "html/html_canvasimpl.h"
36 #include "html/html_documentimpl.h"
37 #include "html/html_imageimpl.h"
38 #include "html/html_objectimpl.h"
39
40 #include "khtml_part.h"
41 #include "khtmlview.h"
42
43 #include "ecma/kjs_css.h"
44 #include "ecma/kjs_html.h"
45 #include "ecma/kjs_window.h"
46 #include "ecma/kjs_html.lut.h"
47 #include "kjs_events.h"
48
49 #include "misc/htmltags.h"
50
51 #include "rendering/render_canvasimage.h"
52 #include "rendering/render_object.h"
53 #include "rendering/render_layer.h"
54
55 #include <kdebug.h>
56
57 #include "cssparser.h"
58 #include "css_stylesheetimpl.h"
59
60 #include "qcolor.h"
61 #include "qpixmap.h"
62 #include "qpainter.h"
63
64 #include <ApplicationServices/ApplicationServices.h>
65
66 using namespace KJS;
67
68 using DOM::DocumentImpl;
69 using DOM::DOMString;
70 using DOM::HTMLFrameElementImpl;
71 using DOM::HTMLIFrameElementImpl;
72
73 IMPLEMENT_PROTOFUNC(HTMLDocFunction)
74
75 Value KJS::HTMLDocFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
76 {
77   if (!thisObj.inherits(&HTMLDocument::info)) {
78     Object err = Error::create(exec,TypeError);
79     exec->setException(err);
80     return err;
81   }
82   DOM::HTMLDocument doc = static_cast<KJS::HTMLDocument *>(thisObj.imp())->toDocument();
83
84   switch (id) {
85   case HTMLDocument::Clear: // even IE doesn't support that one...
86     //doc.clear(); // TODO
87     return Undefined();
88   case HTMLDocument::Open:
89     // For compatibility with other browsers, pass open calls with more than 2 parameters to the window.
90     if (args.size() > 2) {
91       KHTMLPart *part = static_cast<DOM::DocumentImpl *>(doc.handle())->part();
92       if (part) {
93         Window *window = Window::retrieveWindow(part);
94         if (window) {
95           Object functionObject = Object::dynamicCast(window->get(exec, "open"));
96           if (functionObject.isNull() || !functionObject.implementsCall()) {
97             Object exception = Error::create(exec, TypeError);
98             exec->setException(exception);
99             return exception;
100           }
101           Object windowObject(window);
102           return functionObject.call(exec, windowObject, args);
103         }
104       }
105       return Undefined();
106     }
107     // In the case of two parameters or fewer, do a normal document open.
108     doc.open();
109     return Undefined();
110   case HTMLDocument::Close:
111     // see khtmltests/ecma/tokenizer-script-recursion.html
112     doc.close();
113     return Undefined();
114   case HTMLDocument::Write:
115   case HTMLDocument::WriteLn: {
116     // DOM only specifies single string argument, but NS & IE allow multiple
117     // or no arguments
118     UString str = "";
119     for (int i = 0; i < args.size(); i++)
120       str += args[i].toString(exec);
121     if (id == HTMLDocument::WriteLn)
122       str += "\n";
123     //kdDebug() << "document.write: " << str.ascii() << endl;
124     doc.write(str.string());
125     return Undefined();
126   }
127   case HTMLDocument::GetElementsByName:
128     return getDOMNodeList(exec,doc.getElementsByName(args[0].toString(exec).string()));
129   case HTMLDocument::CaptureEvents:
130   case HTMLDocument::ReleaseEvents:
131     // Do nothing for now. These are NS-specific legacy calls.
132     break;
133   }
134
135   return Undefined();
136 }
137
138 const ClassInfo KJS::HTMLDocument::info =
139   { "HTMLDocument", &DOMDocument::info, &HTMLDocumentTable, 0 };
140 /* Source for HTMLDocumentTable. Use "make hashtables" to regenerate.
141 @begin HTMLDocumentTable 30
142   title                 HTMLDocument::Title             DontDelete
143   referrer              HTMLDocument::Referrer          DontDelete|ReadOnly
144   domain                HTMLDocument::Domain            DontDelete
145   URL                   HTMLDocument::URL               DontDelete|ReadOnly
146   body                  HTMLDocument::Body              DontDelete
147   location              HTMLDocument::Location          DontDelete
148   cookie                HTMLDocument::Cookie            DontDelete
149   images                HTMLDocument::Images            DontDelete|ReadOnly
150   embeds                HTMLDocument::Embeds            DontDelete|ReadOnly
151   applets               HTMLDocument::Applets           DontDelete|ReadOnly
152   links                 HTMLDocument::Links             DontDelete|ReadOnly
153   forms                 HTMLDocument::Forms             DontDelete|ReadOnly
154   anchors               HTMLDocument::Anchors           DontDelete|ReadOnly
155   scripts               HTMLDocument::Scripts           DontDelete|ReadOnly
156 # We want no document.all at all, not just a function that returns undefined.
157 # That means we lose the "document.all when spoofing as IE" feature, but we don't spoof in Safari.
158 # And this makes sites that set document.all explicitly work when they otherwise wouldn't, 
159 # e.g. https://corporateexchange.airborne.com
160 # (Not in APPLE_CHANGES since we can't do #if in KJS identifier lists.)
161 #  all                  HTMLDocument::All               DontDelete|ReadOnly
162   clear                 HTMLDocument::Clear             DontDelete|Function 0
163   open                  HTMLDocument::Open              DontDelete|Function 0
164   close                 HTMLDocument::Close             DontDelete|Function 0
165   write                 HTMLDocument::Write             DontDelete|Function 1
166   writeln               HTMLDocument::WriteLn           DontDelete|Function 1
167   getElementsByName     HTMLDocument::GetElementsByName DontDelete|Function 1
168   captureEvents         HTMLDocument::CaptureEvents     DontDelete|Function 0
169   releaseEvents         HTMLDocument::ReleaseEvents     DontDelete|Function 0
170   bgColor               HTMLDocument::BgColor           DontDelete
171   fgColor               HTMLDocument::FgColor           DontDelete
172   alinkColor            HTMLDocument::AlinkColor        DontDelete
173   linkColor             HTMLDocument::LinkColor         DontDelete
174   vlinkColor            HTMLDocument::VlinkColor        DontDelete
175   lastModified          HTMLDocument::LastModified      DontDelete|ReadOnly
176   height                HTMLDocument::Height            DontDelete|ReadOnly
177   width                 HTMLDocument::Width             DontDelete|ReadOnly
178   dir                   HTMLDocument::Dir               DontDelete
179   designMode            HTMLDocument::DesignMode        DontDelete
180 #potentially obsolete array properties
181 # layers
182 # plugins
183 # tags
184 #potentially obsolete properties
185 # embeds
186 # ids
187 @end
188 */
189 bool KJS::HTMLDocument::hasProperty(ExecState *exec, const Identifier &p) const
190 {
191 #ifdef KJS_VERBOSE
192   //kdDebug(6070) << "KJS::HTMLDocument::hasProperty " << p.qstring() << endl;
193 #endif
194   DOM::HTMLDocumentImpl *docImpl = static_cast<DOM::HTMLDocumentImpl *>(node.handle());
195
196   return (DOMDocument::hasProperty(exec, p) ||  
197           docImpl->haveNamedImageOrForm(p.qstring()));
198 }
199
200 Value KJS::HTMLDocument::tryGet(ExecState *exec, const Identifier &propertyName) const
201 {
202 #ifdef KJS_VERBOSE
203   kdDebug(6070) << "KJS::HTMLDocument::tryGet " << propertyName.qstring() << endl;
204 #endif
205   DOM::HTMLDocument doc = static_cast<DOM::HTMLDocument>(node);
206   DOM::HTMLBodyElement body = doc.body();
207
208   KHTMLView *view = static_cast<DOM::DocumentImpl*>(doc.handle())->view();
209
210   const HashEntry* entry = Lookup::findEntry(&HTMLDocumentTable, propertyName);
211   if (entry) {
212     switch (entry->value) {
213     case Title:
214       return String(doc.title());
215     case Referrer:
216       return String(doc.referrer());
217     case Domain:
218       return String(doc.domain());
219     case URL:
220       return String(doc.URL());
221     case Body:
222       return getDOMNode(exec,doc.body());
223     case Location:
224       if ( view && view->part() )
225       {
226         Window* win = Window::retrieveWindow(view->part());
227         if (win)
228           return Value(win->location());
229         else
230           return Undefined();
231       }
232       else
233         return Undefined();
234     case Cookie:
235       return String(doc.cookie());
236     case Images:
237       return getHTMLCollection(exec,doc.images());
238     case Embeds:
239       return getHTMLCollection(exec,doc.embeds());
240     case Applets:
241       return getHTMLCollection(exec,doc.applets());
242     case Links:
243       return getHTMLCollection(exec,doc.links());
244     case Forms:
245       return getHTMLCollection(exec,doc.forms());
246     case Anchors:
247       return getHTMLCollection(exec,doc.anchors());
248     case Scripts: // TODO (IE-specific)
249     {
250       // To be implemented. Meanwhile, return an object with a length property set to 0
251       kdWarning() << "KJS::HTMLDocument document.scripts called - not implemented" << endl;
252       Object obj( new ObjectImp() );
253       obj.put( exec, lengthPropertyName, Number(0) );
254       return obj;
255     }
256     case All:
257       // Disable document.all when we try to be Netscape-compatible
258       if ( exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat )
259         return Undefined();
260       return getHTMLCollection(exec,doc.all());
261     case Clear:
262     case Open:
263     case Close:
264     case Write:
265     case WriteLn:
266     case GetElementsByName:
267     case CaptureEvents:
268     case ReleaseEvents:
269       return lookupOrCreateFunction<HTMLDocFunction>( exec, propertyName, this, entry->value, entry->params, entry->attr );
270     }
271   }
272   // Look for overrides
273   ValueImp * val = ObjectImp::getDirect(propertyName);
274   if (val)
275     return Value(val);
276
277   if (entry) {
278     switch (entry->value) {
279     case BgColor:
280       return String(body.bgColor());
281     case FgColor:
282       return String(body.text());
283     case AlinkColor:
284       return String(body.aLink());
285     case LinkColor:
286       return String(body.link());
287     case VlinkColor:
288       return String(body.vLink());
289     case LastModified:
290       return String(doc.lastModified());
291     case Height:
292       return Number(view ? view->contentsHeight() : 0);
293     case Width:
294       return Number(view ? view->contentsWidth() : 0);
295     case Dir:
296       return String(body.dir());
297     case DesignMode:
298     {
299       DocumentImpl *docimpl = static_cast<DocumentImpl *>(doc.handle());
300       if (!docimpl)
301         return Undefined();
302       return String(docimpl->inDesignMode() ? "on" : "off");  
303     }
304     }
305   }
306
307   if (DOMDocument::hasProperty(exec, propertyName))
308     return DOMDocument::tryGet(exec, propertyName);
309
310   //kdDebug(6070) << "KJS::HTMLDocument::tryGet " << propertyName.qstring() << " not found, returning element" << endl;
311   // image and form elements with the name p will be looked up last
312
313 #if APPLE_CHANGES
314     // Look for named applets.
315     // FIXME:  Factor code that creates RuntimeObjectImp for applet.  It's also
316     // located in applets[0]. 
317     DOM::HTMLCollection applets = doc.applets();
318     DOM::HTMLElement anApplet = applets.namedItem (propertyName.string());
319     if (!anApplet.isNull()) {
320         return getRuntimeObject(exec,anApplet);
321     }
322
323     DOM::HTMLCollection embeds = doc.embeds();
324     DOM::HTMLElement anEmbed = embeds.namedItem (propertyName.string());
325     if (!anEmbed.isNull()) {
326         return getRuntimeObject(exec,anEmbed);
327     }
328 #endif
329
330   DOM::HTMLDocumentImpl *docImpl = static_cast<DOM::HTMLDocumentImpl*>(node.handle());
331   if (!docImpl->haveNamedImageOrForm(propertyName.qstring())) {
332     return Undefined();
333   }
334
335   DOM::HTMLCollection collAll = doc.all();
336   KJS::HTMLCollection htmlcoll(exec,collAll);
337   return htmlcoll.getNamedItems(exec, propertyName); // Get all the items with the same name
338
339   return Undefined();
340 }
341
342 void KJS::HTMLDocument::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
343 {
344 #ifdef KJS_VERBOSE
345   kdDebug(6070) << "KJS::HTMLDocument::tryPut " << propertyName.qstring() << endl;
346 #endif
347   DOMObjectLookupPut<HTMLDocument, DOMDocument>( exec, propertyName, value, attr, &HTMLDocumentTable, this );
348 }
349
350 void KJS::HTMLDocument::putValue(ExecState *exec, int token, const Value& value, int /*attr*/)
351 {
352   DOM::HTMLDocument doc = static_cast<DOM::HTMLDocument>(node);
353   DOM::HTMLBodyElement body = doc.body();
354
355   switch (token) {
356   case Title:
357     doc.setTitle(value.toString(exec).string());
358     break;
359   case Body: {
360     DOMNode *node = new DOMNode(exec, KJS::toNode(value));
361     // This is required to avoid leaking the node.
362     Value nodeValue(node);
363     doc.setBody(node->toNode());
364     break;
365   }
366   case Domain: { // not part of the DOM
367     DOM::HTMLDocumentImpl* docimpl = static_cast<DOM::HTMLDocumentImpl*>(doc.handle());
368     if (docimpl)
369       docimpl->setDomain(value.toString(exec).string());
370     break;
371   }
372   case Cookie:
373     doc.setCookie(value.toString(exec).string());
374     break;
375   case Location: {
376     KHTMLPart *part = static_cast<DOM::DocumentImpl *>( doc.handle() )->part();
377     if (part)
378     {
379       QString str = value.toString(exec).qstring();
380
381       // When assigning location, IE and Mozilla both resolve the URL
382       // relative to the frame where the JavaScript is executing not
383       // the target frame.
384       KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
385       if (activePart)
386         str = activePart->htmlDocument().completeURL(str).string();
387
388 #if APPLE_CHANGES
389       // We want a new history item if this JS was called via a user gesture
390       bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
391       part->scheduleLocationChange(str, !userGesture);
392 #else
393       part->scheduleLocationChange(str, false/*don't lock history*/);
394 #endif
395     }
396     break;
397   }
398   case BgColor:
399     body.setBgColor(value.toString(exec).string());
400     break;
401   case FgColor:
402     body.setText(value.toString(exec).string());
403     break;
404   case AlinkColor:
405     // this check is a bit silly, but some benchmarks like to set the
406     // document's link colors over and over to the same value and we
407     // don't want to incur a style update each time.
408     {
409       DOM::DOMString newColor = value.toString(exec).string();
410       if (body.aLink() != newColor) {
411         body.setALink(newColor);
412       }
413     }
414     break;
415   case LinkColor:
416     // this check is a bit silly, but some benchmarks like to set the
417     // document's link colors over and over to the same value and we
418     // don't want to incur a style update each time.
419     {
420       DOM::DOMString newColor = value.toString(exec).string();
421       if (body.link() != newColor) {
422         body.setLink(newColor);
423       }
424     }
425     break;
426   case VlinkColor:
427     // this check is a bit silly, but some benchmarks like to set the
428     // document's link colors over and over to the same value and we
429     // don't want to incur a style update each time.
430     {
431       DOM::DOMString newColor = value.toString(exec).string();
432       if (body.vLink() != newColor) {
433         body.setVLink(newColor);
434       }
435     }
436     break;
437   case Dir:
438     body.setDir(value.toString(exec).string());
439     break;
440   case DesignMode:
441     {
442       DocumentImpl *docimpl = static_cast<DocumentImpl *>(doc.handle());
443       if (!docimpl)
444         break;
445       DOMString modeString = value.toString(exec).string();
446       DocumentImpl::InheritedBool mode;
447       if (!strcasecmp(modeString, "on"))
448         mode = DocumentImpl::on;
449       else if (!strcasecmp(modeString, "off"))
450         mode = DocumentImpl::off;
451       else
452         mode = DocumentImpl::inherit;
453       docimpl->setDesignMode(mode);
454      }
455     break;
456   default:
457     kdWarning() << "HTMLDocument::putValue unhandled token " << token << endl;
458   }
459 }
460
461 // -------------------------------------------------------------------------
462
463 const ClassInfo KJS::HTMLElement::info = { "HTMLElement", &DOMElement::info, &HTMLElementTable, 0 };
464 const ClassInfo KJS::HTMLElement::html_info = { "HTMLHtmlElement", &KJS::HTMLElement::info, &HTMLHtmlElementTable, 0 };
465 const ClassInfo KJS::HTMLElement::head_info = { "HTMLHeadElement", &KJS::HTMLElement::info, &HTMLHeadElementTable, 0 };
466 const ClassInfo KJS::HTMLElement::link_info = { "HTMLLinkElement", &KJS::HTMLElement::info, &HTMLLinkElementTable, 0 };
467 const ClassInfo KJS::HTMLElement::title_info = { "HTMLTitleElement", &KJS::HTMLElement::info, &HTMLTitleElementTable, 0 };
468 const ClassInfo KJS::HTMLElement::meta_info = { "HTMLMetaElement", &KJS::HTMLElement::info, &HTMLMetaElementTable, 0 };
469 const ClassInfo KJS::HTMLElement::base_info = { "HTMLBaseElement", &KJS::HTMLElement::info, &HTMLBaseElementTable, 0 };
470 const ClassInfo KJS::HTMLElement::isIndex_info = { "HTMLIsIndexElement", &KJS::HTMLElement::info, &HTMLIsIndexElementTable, 0 };
471 const ClassInfo KJS::HTMLElement::style_info = { "HTMLStyleElement", &KJS::HTMLElement::info, &HTMLStyleElementTable, 0 };
472 const ClassInfo KJS::HTMLElement::body_info = { "HTMLBodyElement", &KJS::HTMLElement::info, &HTMLBodyElementTable, 0 };
473 const ClassInfo KJS::HTMLElement::form_info = { "HTMLFormElement", &KJS::HTMLElement::info, &HTMLFormElementTable, 0 };
474 const ClassInfo KJS::HTMLElement::select_info = { "HTMLSelectElement", &KJS::HTMLElement::info, &HTMLSelectElementTable, 0 };
475 const ClassInfo KJS::HTMLElement::optGroup_info = { "HTMLOptGroupElement", &KJS::HTMLElement::info, &HTMLOptGroupElementTable, 0 };
476 const ClassInfo KJS::HTMLElement::option_info = { "HTMLOptionElement", &KJS::HTMLElement::info, &HTMLOptionElementTable, 0 };
477 const ClassInfo KJS::HTMLElement::input_info = { "HTMLInputElement", &KJS::HTMLElement::info, &HTMLInputElementTable, 0 };
478 const ClassInfo KJS::HTMLElement::textArea_info = { "HTMLTextAreaElement", &KJS::HTMLElement::info, &HTMLTextAreaElementTable, 0 };
479 const ClassInfo KJS::HTMLElement::button_info = { "HTMLButtonElement", &KJS::HTMLElement::info, &HTMLButtonElementTable, 0 };
480 const ClassInfo KJS::HTMLElement::label_info = { "HTMLLabelElement", &KJS::HTMLElement::info, &HTMLLabelElementTable, 0 };
481 const ClassInfo KJS::HTMLElement::fieldSet_info = { "HTMLFieldSetElement", &KJS::HTMLElement::info, &HTMLFieldSetElementTable, 0 };
482 const ClassInfo KJS::HTMLElement::legend_info = { "HTMLLegendElement", &KJS::HTMLElement::info, &HTMLLegendElementTable, 0 };
483 const ClassInfo KJS::HTMLElement::ul_info = { "HTMLUListElement", &KJS::HTMLElement::info, &HTMLUListElementTable, 0 };
484 const ClassInfo KJS::HTMLElement::ol_info = { "HTMLOListElement", &KJS::HTMLElement::info, &HTMLOListElementTable, 0 };
485 const ClassInfo KJS::HTMLElement::dl_info = { "HTMLDListElement", &KJS::HTMLElement::info, &HTMLDListElementTable, 0 };
486 const ClassInfo KJS::HTMLElement::dir_info = { "HTMLDirectoryElement", &KJS::HTMLElement::info, &HTMLDirectoryElementTable, 0 };
487 const ClassInfo KJS::HTMLElement::menu_info = { "HTMLMenuElement", &KJS::HTMLElement::info, &HTMLMenuElementTable, 0 };
488 const ClassInfo KJS::HTMLElement::li_info = { "HTMLLIElement", &KJS::HTMLElement::info, &HTMLLIElementTable, 0 };
489 const ClassInfo KJS::HTMLElement::div_info = { "HTMLDivElement", &KJS::HTMLElement::info, &HTMLDivElementTable, 0 };
490 const ClassInfo KJS::HTMLElement::p_info = { "HTMLParagraphElement", &KJS::HTMLElement::info, &HTMLParagraphElementTable, 0 };
491 const ClassInfo KJS::HTMLElement::heading_info = { "HTMLHeadingElement", &KJS::HTMLElement::info, &HTMLHeadingElementTable, 0 };
492 const ClassInfo KJS::HTMLElement::blockQuote_info = { "HTMLBlockQuoteElement", &KJS::HTMLElement::info, &HTMLBlockQuoteElementTable, 0 };
493 const ClassInfo KJS::HTMLElement::q_info = { "HTMLQuoteElement", &KJS::HTMLElement::info, &HTMLQuoteElementTable, 0 };
494 const ClassInfo KJS::HTMLElement::pre_info = { "HTMLPreElement", &KJS::HTMLElement::info, &HTMLPreElementTable, 0 };
495 const ClassInfo KJS::HTMLElement::br_info = { "HTMLBRElement", &KJS::HTMLElement::info, &HTMLBRElementTable, 0 };
496 const ClassInfo KJS::HTMLElement::baseFont_info = { "HTMLBaseFontElement", &KJS::HTMLElement::info, &HTMLBaseFontElementTable, 0 };
497 const ClassInfo KJS::HTMLElement::font_info = { "HTMLFontElement", &KJS::HTMLElement::info, &HTMLFontElementTable, 0 };
498 const ClassInfo KJS::HTMLElement::hr_info = { "HTMLHRElement", &KJS::HTMLElement::info, &HTMLHRElementTable, 0 };
499 const ClassInfo KJS::HTMLElement::mod_info = { "HTMLModElement", &KJS::HTMLElement::info, &HTMLModElementTable, 0 };
500 const ClassInfo KJS::HTMLElement::a_info = { "HTMLAnchorElement", &KJS::HTMLElement::info, &HTMLAnchorElementTable, 0 };
501 const ClassInfo KJS::HTMLElement::canvas_info = { "HTMLCanvasElement", &KJS::HTMLElement::info, &HTMLCanvasElementTable, 0 };
502 const ClassInfo KJS::HTMLElement::img_info = { "HTMLImageElement", &KJS::HTMLElement::info, &HTMLImageElementTable, 0 };
503 const ClassInfo KJS::HTMLElement::object_info = { "HTMLObjectElement", &KJS::HTMLElement::info, &HTMLObjectElementTable, 0 };
504 const ClassInfo KJS::HTMLElement::param_info = { "HTMLParamElement", &KJS::HTMLElement::info, &HTMLParamElementTable, 0 };
505 const ClassInfo KJS::HTMLElement::applet_info = { "HTMLAppletElement", &KJS::HTMLElement::info, &HTMLAppletElementTable, 0 };
506 const ClassInfo KJS::HTMLElement::map_info = { "HTMLMapElement", &KJS::HTMLElement::info, &HTMLMapElementTable, 0 };
507 const ClassInfo KJS::HTMLElement::area_info = { "HTMLAreaElement", &KJS::HTMLElement::info, &HTMLAreaElementTable, 0 };
508 const ClassInfo KJS::HTMLElement::script_info = { "HTMLScriptElement", &KJS::HTMLElement::info, &HTMLScriptElementTable, 0 };
509 const ClassInfo KJS::HTMLElement::table_info = { "HTMLTableElement", &KJS::HTMLElement::info, &HTMLTableElementTable, 0 };
510 const ClassInfo KJS::HTMLElement::caption_info = { "HTMLTableCaptionElement", &KJS::HTMLElement::info, &HTMLTableCaptionElementTable, 0 };
511 const ClassInfo KJS::HTMLElement::col_info = { "HTMLTableColElement", &KJS::HTMLElement::info, &HTMLTableColElementTable, 0 };
512 const ClassInfo KJS::HTMLElement::tablesection_info = { "HTMLTableSectionElement", &KJS::HTMLElement::info, &HTMLTableSectionElementTable, 0 };
513 const ClassInfo KJS::HTMLElement::tr_info = { "HTMLTableRowElement", &KJS::HTMLElement::info, &HTMLTableRowElementTable, 0 };
514 const ClassInfo KJS::HTMLElement::tablecell_info = { "HTMLTableCellElement", &KJS::HTMLElement::info, &HTMLTableCellElementTable, 0 };
515 const ClassInfo KJS::HTMLElement::frameSet_info = { "HTMLFrameSetElement", &KJS::HTMLElement::info, &HTMLFrameSetElementTable, 0 };
516 const ClassInfo KJS::HTMLElement::frame_info = { "HTMLFrameElement", &KJS::HTMLElement::info, &HTMLFrameElementTable, 0 };
517 const ClassInfo KJS::HTMLElement::iFrame_info = { "HTMLIFrameElement", &KJS::HTMLElement::info, &HTMLIFrameElementTable, 0 };
518 const ClassInfo KJS::HTMLElement::marquee_info = { "HTMLMarqueeElement", &KJS::HTMLElement::info, &HTMLMarqueeElementTable, 0 };
519
520 const ClassInfo* KJS::HTMLElement::classInfo() const
521 {
522   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
523   switch (element.elementId()) {
524   case ID_HTML:
525     return &html_info;
526   case ID_HEAD:
527     return &head_info;
528   case ID_LINK:
529     return &link_info;
530   case ID_TITLE:
531     return &title_info;
532   case ID_META:
533     return &meta_info;
534   case ID_BASE:
535     return &base_info;
536   case ID_ISINDEX:
537     return &isIndex_info;
538   case ID_STYLE:
539     return &style_info;
540   case ID_BODY:
541     return &body_info;
542   case ID_FORM:
543     return &form_info;
544   case ID_SELECT:
545     return &select_info;
546   case ID_OPTGROUP:
547     return &optGroup_info;
548   case ID_OPTION:
549     return &option_info;
550   case ID_INPUT:
551     return &input_info;
552   case ID_TEXTAREA:
553     return &textArea_info;
554   case ID_BUTTON:
555     return &button_info;
556   case ID_LABEL:
557     return &label_info;
558   case ID_FIELDSET:
559     return &fieldSet_info;
560   case ID_LEGEND:
561     return &legend_info;
562   case ID_UL:
563     return &ul_info;
564   case ID_OL:
565     return &ol_info;
566   case ID_DL:
567     return &dl_info;
568   case ID_DIR:
569     return &dir_info;
570   case ID_MENU:
571     return &menu_info;
572   case ID_LI:
573     return &li_info;
574   case ID_DIV:
575     return &div_info;
576   case ID_P:
577     return &p_info;
578   case ID_H1:
579   case ID_H2:
580   case ID_H3:
581   case ID_H4:
582   case ID_H5:
583   case ID_H6:
584     return &heading_info;
585   case ID_BLOCKQUOTE:
586     return &blockQuote_info;
587   case ID_Q:
588     return &q_info;
589   case ID_PRE:
590     return &pre_info;
591   case ID_BR:
592     return &br_info;
593   case ID_BASEFONT:
594     return &baseFont_info;
595   case ID_FONT:
596     return &font_info;
597   case ID_HR:
598     return &hr_info;
599   case ID_INS:
600   case ID_DEL:
601     return &mod_info;
602   case ID_A:
603     return &a_info;
604   case ID_CANVAS:
605     return &canvas_info;
606   case ID_IMG:
607     return &img_info;
608   case ID_OBJECT:
609     return &object_info;
610   case ID_PARAM:
611     return &param_info;
612   case ID_APPLET:
613     return &applet_info;
614   case ID_MAP:
615     return &map_info;
616   case ID_AREA:
617     return &area_info;
618   case ID_SCRIPT:
619     return &script_info;
620   case ID_TABLE:
621     return &table_info;
622   case ID_CAPTION:
623     return &caption_info;
624   case ID_COL:
625     return &col_info;
626   case ID_THEAD:
627     return &tablesection_info;
628   case ID_TBODY:
629     return &tablesection_info;
630   case ID_TFOOT:
631     return &tablesection_info;
632   case ID_TR:
633     return &tr_info;
634   case ID_TH:
635     return &tablecell_info;
636   case ID_TD:
637     return &tablecell_info;
638   case ID_FRAMESET:
639     return &frameSet_info;
640   case ID_FRAME:
641     return &frame_info;
642   case ID_IFRAME:
643     return &iFrame_info;
644   case ID_MARQUEE:
645     return &marquee_info;
646   default:
647     return &info;
648   }
649 }
650 /*
651 @begin HTMLElementTable 14
652   id            KJS::HTMLElement::ElementId     DontDelete
653   title         KJS::HTMLElement::ElementTitle  DontDelete
654   lang          KJS::HTMLElement::ElementLang   DontDelete
655   dir           KJS::HTMLElement::ElementDir    DontDelete
656 ### isn't this "class" in the HTML spec?
657   className     KJS::HTMLElement::ElementClassName DontDelete
658   innerHTML     KJS::HTMLElement::ElementInnerHTML DontDelete
659   innerText     KJS::HTMLElement::ElementInnerText DontDelete
660   outerHTML     KJS::HTMLElement::ElementOuterHTML DontDelete
661   outerText     KJS::HTMLElement::ElementOuterText DontDelete
662   document      KJS::HTMLElement::ElementDocument  DontDelete|ReadOnly
663 # IE extension
664   children      KJS::HTMLElement::ElementChildren  DontDelete|ReadOnly
665   contentEditable   KJS::HTMLElement::ElementContentEditable  DontDelete
666   isContentEditable KJS::HTMLElement::ElementIsContentEditable  DontDelete|ReadOnly
667 @end
668 @begin HTMLHtmlElementTable 1
669   version       KJS::HTMLElement::HtmlVersion   DontDelete
670 @end
671 @begin HTMLHeadElementTable 1
672   profile       KJS::HTMLElement::HeadProfile   DontDelete
673 @end
674 @begin HTMLLinkElementTable 11
675   disabled      KJS::HTMLElement::LinkDisabled  DontDelete
676   charset       KJS::HTMLElement::LinkCharset   DontDelete
677   href          KJS::HTMLElement::LinkHref      DontDelete
678   hreflang      KJS::HTMLElement::LinkHrefLang  DontDelete
679   media         KJS::HTMLElement::LinkMedia     DontDelete
680   rel           KJS::HTMLElement::LinkRel       DontDelete
681   rev           KJS::HTMLElement::LinkRev       DontDelete
682   target        KJS::HTMLElement::LinkTarget    DontDelete
683   type          KJS::HTMLElement::LinkType      DontDelete
684   sheet         KJS::HTMLElement::LinkSheet     DontDelete|ReadOnly
685 @end
686 @begin HTMLTitleElementTable 1
687   text          KJS::HTMLElement::TitleText     DontDelete
688 @end
689 @begin HTMLMetaElementTable 4
690   content       KJS::HTMLElement::MetaContent   DontDelete
691   httpEquiv     KJS::HTMLElement::MetaHttpEquiv DontDelete
692   name          KJS::HTMLElement::MetaName      DontDelete
693   scheme        KJS::HTMLElement::MetaScheme    DontDelete
694 @end
695 @begin HTMLBaseElementTable 2
696   href          KJS::HTMLElement::BaseHref      DontDelete
697   target        KJS::HTMLElement::BaseTarget    DontDelete
698 @end
699 @begin HTMLIsIndexElementTable 2
700   form          KJS::HTMLElement::IsIndexForm   DontDelete|ReadOnly
701   prompt        KJS::HTMLElement::IsIndexPrompt DontDelete
702 @end
703 @begin HTMLStyleElementTable 4
704   disabled      KJS::HTMLElement::StyleDisabled DontDelete
705   media         KJS::HTMLElement::StyleMedia    DontDelete
706   type          KJS::HTMLElement::StyleType     DontDelete
707   sheet         KJS::HTMLElement::StyleSheet    DontDelete|ReadOnly
708 @end
709 @begin HTMLBodyElementTable 10
710   aLink         KJS::HTMLElement::BodyALink     DontDelete
711   background    KJS::HTMLElement::BodyBackground        DontDelete
712   bgColor       KJS::HTMLElement::BodyBgColor   DontDelete
713   link          KJS::HTMLElement::BodyLink      DontDelete
714   text          KJS::HTMLElement::BodyText      DontDelete
715   vLink         KJS::HTMLElement::BodyVLink     DontDelete
716   scrollLeft    KJS::HTMLElement::BodyScrollLeft        DontDelete
717   scrollTop     KJS::HTMLElement::BodyScrollTop         DontDelete
718   scrollHeight  KJS::HTMLElement::BodyScrollHeight      DontDelete|ReadOnly
719   scrollWidth   KJS::HTMLElement::BodyScrollWidth       DontDelete|ReadOnly
720 @end
721 @begin HTMLFormElementTable 11
722 # Also supported, by name/index
723   elements      KJS::HTMLElement::FormElements  DontDelete|ReadOnly
724   length        KJS::HTMLElement::FormLength    DontDelete|ReadOnly
725   name          KJS::HTMLElement::FormName      DontDelete
726   acceptCharset KJS::HTMLElement::FormAcceptCharset     DontDelete
727   action        KJS::HTMLElement::FormAction    DontDelete
728   enctype       KJS::HTMLElement::FormEncType   DontDelete
729   method        KJS::HTMLElement::FormMethod    DontDelete
730   target        KJS::HTMLElement::FormTarget    DontDelete
731   submit        KJS::HTMLElement::FormSubmit    DontDelete|Function 0
732   reset         KJS::HTMLElement::FormReset     DontDelete|Function 0
733 @end
734 @begin HTMLSelectElementTable 11
735 # Also supported, by index
736   type          KJS::HTMLElement::SelectType    DontDelete|ReadOnly
737   selectedIndex KJS::HTMLElement::SelectSelectedIndex   DontDelete
738   value         KJS::HTMLElement::SelectValue   DontDelete
739   length        KJS::HTMLElement::SelectLength  DontDelete
740   form          KJS::HTMLElement::SelectForm    DontDelete|ReadOnly
741   options       KJS::HTMLElement::SelectOptions DontDelete|ReadOnly
742   disabled      KJS::HTMLElement::SelectDisabled        DontDelete
743   multiple      KJS::HTMLElement::SelectMultiple        DontDelete
744   name          KJS::HTMLElement::SelectName    DontDelete
745   size          KJS::HTMLElement::SelectSize    DontDelete
746   tabIndex      KJS::HTMLElement::SelectTabIndex        DontDelete
747   add           KJS::HTMLElement::SelectAdd     DontDelete|Function 2
748   remove        KJS::HTMLElement::SelectRemove  DontDelete|Function 1
749   blur          KJS::HTMLElement::SelectBlur    DontDelete|Function 0
750   focus         KJS::HTMLElement::SelectFocus   DontDelete|Function 0
751 @end
752 @begin HTMLOptGroupElementTable 2
753   disabled      KJS::HTMLElement::OptGroupDisabled      DontDelete
754   label         KJS::HTMLElement::OptGroupLabel         DontDelete
755 @end
756 @begin HTMLOptionElementTable 8
757   form          KJS::HTMLElement::OptionForm            DontDelete|ReadOnly
758   defaultSelected KJS::HTMLElement::OptionDefaultSelected       DontDelete
759   text          KJS::HTMLElement::OptionText            DontDelete
760   index         KJS::HTMLElement::OptionIndex           DontDelete|ReadOnly
761   disabled      KJS::HTMLElement::OptionDisabled        DontDelete
762   label         KJS::HTMLElement::OptionLabel           DontDelete
763   selected      KJS::HTMLElement::OptionSelected        DontDelete
764   value         KJS::HTMLElement::OptionValue           DontDelete
765 @end
766 @begin HTMLInputElementTable 23
767   defaultValue  KJS::HTMLElement::InputDefaultValue     DontDelete
768   defaultChecked KJS::HTMLElement::InputDefaultChecked  DontDelete
769   form          KJS::HTMLElement::InputForm             DontDelete|ReadOnly
770   accept        KJS::HTMLElement::InputAccept           DontDelete
771   accessKey     KJS::HTMLElement::InputAccessKey        DontDelete
772   align         KJS::HTMLElement::InputAlign            DontDelete
773   alt           KJS::HTMLElement::InputAlt              DontDelete
774   checked       KJS::HTMLElement::InputChecked          DontDelete
775   disabled      KJS::HTMLElement::InputDisabled         DontDelete
776   maxLength     KJS::HTMLElement::InputMaxLength        DontDelete
777   name          KJS::HTMLElement::InputName             DontDelete
778   readOnly      KJS::HTMLElement::InputReadOnly         DontDelete
779   size          KJS::HTMLElement::InputSize             DontDelete
780   src           KJS::HTMLElement::InputSrc              DontDelete
781   tabIndex      KJS::HTMLElement::InputTabIndex         DontDelete
782   type          KJS::HTMLElement::InputType             DontDelete
783   useMap        KJS::HTMLElement::InputUseMap           DontDelete
784   value         KJS::HTMLElement::InputValue            DontDelete
785   blur          KJS::HTMLElement::InputBlur             DontDelete|Function 0
786   focus         KJS::HTMLElement::InputFocus            DontDelete|Function 0
787   select        KJS::HTMLElement::InputSelect           DontDelete|Function 0
788   click         KJS::HTMLElement::InputClick            DontDelete|Function 0
789 @end
790 @begin HTMLTextAreaElementTable 13
791   defaultValue  KJS::HTMLElement::TextAreaDefaultValue  DontDelete
792   form          KJS::HTMLElement::TextAreaForm          DontDelete|ReadOnly
793   accessKey     KJS::HTMLElement::TextAreaAccessKey     DontDelete
794   cols          KJS::HTMLElement::TextAreaCols          DontDelete
795   disabled      KJS::HTMLElement::TextAreaDisabled      DontDelete
796   name          KJS::HTMLElement::TextAreaName          DontDelete
797   readOnly      KJS::HTMLElement::TextAreaReadOnly      DontDelete
798   rows          KJS::HTMLElement::TextAreaRows          DontDelete
799   tabIndex      KJS::HTMLElement::TextAreaTabIndex      DontDelete
800   type          KJS::HTMLElement::TextAreaType          DontDelete|ReadOnly
801   value         KJS::HTMLElement::TextAreaValue         DontDelete
802   blur          KJS::HTMLElement::TextAreaBlur          DontDelete|Function 0
803   focus         KJS::HTMLElement::TextAreaFocus         DontDelete|Function 0
804   select        KJS::HTMLElement::TextAreaSelect        DontDelete|Function 0
805 @end
806 @begin HTMLButtonElementTable 7
807   form          KJS::HTMLElement::ButtonForm            DontDelete|ReadOnly
808   accessKey     KJS::HTMLElement::ButtonAccessKey       DontDelete
809   disabled      KJS::HTMLElement::ButtonDisabled        DontDelete
810   name          KJS::HTMLElement::ButtonName            DontDelete
811   tabIndex      KJS::HTMLElement::ButtonTabIndex        DontDelete
812   type          KJS::HTMLElement::ButtonType            DontDelete|ReadOnly
813   value         KJS::HTMLElement::ButtonValue           DontDelete
814 @end
815 @begin HTMLLabelElementTable 3
816   form          KJS::HTMLElement::LabelForm             DontDelete|ReadOnly
817   accessKey     KJS::HTMLElement::LabelAccessKey        DontDelete
818   htmlFor       KJS::HTMLElement::LabelHtmlFor          DontDelete
819 @end
820 @begin HTMLFieldSetElementTable 1
821   form          KJS::HTMLElement::FieldSetForm          DontDelete|ReadOnly
822 @end
823 @begin HTMLLegendElementTable 3
824   form          KJS::HTMLElement::LegendForm            DontDelete|ReadOnly
825   accessKey     KJS::HTMLElement::LegendAccessKey       DontDelete
826   align         KJS::HTMLElement::LegendAlign           DontDelete
827 @end
828 @begin HTMLUListElementTable 2
829   compact       KJS::HTMLElement::UListCompact          DontDelete
830   type          KJS::HTMLElement::UListType             DontDelete
831 @end
832 @begin HTMLOListElementTable 3
833   compact       KJS::HTMLElement::OListCompact          DontDelete
834   start         KJS::HTMLElement::OListStart            DontDelete
835   type          KJS::HTMLElement::OListType             DontDelete
836 @end
837 @begin HTMLDListElementTable 1
838   compact       KJS::HTMLElement::DListCompact          DontDelete
839 @end
840 @begin HTMLDirectoryElementTable 1
841   compact       KJS::HTMLElement::DirectoryCompact      DontDelete
842 @end
843 @begin HTMLMenuElementTable 1
844   compact       KJS::HTMLElement::MenuCompact           DontDelete
845 @end
846 @begin HTMLLIElementTable 2
847   type          KJS::HTMLElement::LIType                DontDelete
848   value         KJS::HTMLElement::LIValue               DontDelete
849 @end
850 @begin HTMLDivElementTable 1
851   align         KJS::HTMLElement::DivAlign              DontDelete
852 @end
853 @begin HTMLParagraphElementTable 1
854   align         KJS::HTMLElement::ParagraphAlign        DontDelete
855 @end
856 @begin HTMLHeadingElementTable 1
857   align         KJS::HTMLElement::HeadingAlign          DontDelete
858 @end
859 @begin HTMLBlockQuoteElementTable 1
860   cite          KJS::HTMLElement::BlockQuoteCite        DontDelete
861 @end
862 @begin HTMLQuoteElementTable 1
863   cite          KJS::HTMLElement::QuoteCite             DontDelete
864 @end
865 @begin HTMLPreElementTable 1
866   width         KJS::HTMLElement::PreWidth              DontDelete
867 @end
868 @begin HTMLBRElementTable 1
869   clear         KJS::HTMLElement::BRClear               DontDelete
870 @end
871 @begin HTMLBaseFontElementTable 3
872   color         KJS::HTMLElement::BaseFontColor         DontDelete
873   face          KJS::HTMLElement::BaseFontFace          DontDelete
874   size          KJS::HTMLElement::BaseFontSize          DontDelete
875 @end
876 @begin HTMLFontElementTable 3
877   color         KJS::HTMLElement::FontColor             DontDelete
878   face          KJS::HTMLElement::FontFace              DontDelete
879   size          KJS::HTMLElement::FontSize              DontDelete
880 @end
881 @begin HTMLHRElementTable 4
882   align         KJS::HTMLElement::HRAlign               DontDelete
883   noShade       KJS::HTMLElement::HRNoShade             DontDelete
884   size          KJS::HTMLElement::HRSize                DontDelete
885   width         KJS::HTMLElement::HRWidth               DontDelete
886 @end
887 @begin HTMLModElementTable 2
888   cite          KJS::HTMLElement::ModCite               DontDelete
889   dateTime      KJS::HTMLElement::ModDateTime           DontDelete
890 @end
891 @begin HTMLAnchorElementTable 24
892   accessKey     KJS::HTMLElement::AnchorAccessKey       DontDelete
893   charset       KJS::HTMLElement::AnchorCharset         DontDelete
894   coords        KJS::HTMLElement::AnchorCoords          DontDelete
895   href          KJS::HTMLElement::AnchorHref            DontDelete
896   hreflang      KJS::HTMLElement::AnchorHrefLang        DontDelete
897   hash          KJS::HTMLElement::AnchorHash            DontDelete|ReadOnly
898   host          KJS::HTMLElement::AnchorHost            DontDelete|ReadOnly
899   hostname      KJS::HTMLElement::AnchorHostname        DontDelete|ReadOnly
900   name          KJS::HTMLElement::AnchorName            DontDelete
901   pathname      KJS::HTMLElement::AnchorPathName        DontDelete|ReadOnly
902   port          KJS::HTMLElement::AnchorPort            DontDelete|ReadOnly
903   protocol      KJS::HTMLElement::AnchorProtocol        DontDelete|ReadOnly
904   rel           KJS::HTMLElement::AnchorRel             DontDelete
905   rev           KJS::HTMLElement::AnchorRev             DontDelete
906   search        KJS::HTMLElement::AnchorSearch          DontDelete|ReadOnly
907   shape         KJS::HTMLElement::AnchorShape           DontDelete
908   tabIndex      KJS::HTMLElement::AnchorTabIndex        DontDelete
909   target        KJS::HTMLElement::AnchorTarget          DontDelete
910   text          KJS::HTMLElement::AnchorText            DontDelete|ReadOnly
911   type          KJS::HTMLElement::AnchorType            DontDelete
912   blur          KJS::HTMLElement::AnchorBlur            DontDelete|Function 0
913   focus         KJS::HTMLElement::AnchorFocus           DontDelete|Function 0
914   toString      KJS::HTMLElement::AnchorToString        DontDelete|Function 0
915 @end
916 @begin HTMLImageElementTable 14
917   name          KJS::HTMLElement::ImageName             DontDelete
918   align         KJS::HTMLElement::ImageAlign            DontDelete
919   alt           KJS::HTMLElement::ImageAlt              DontDelete
920   border        KJS::HTMLElement::ImageBorder           DontDelete
921   height        KJS::HTMLElement::ImageHeight           DontDelete
922   hspace        KJS::HTMLElement::ImageHspace           DontDelete
923   isMap         KJS::HTMLElement::ImageIsMap            DontDelete
924   longDesc      KJS::HTMLElement::ImageLongDesc         DontDelete
925   src           KJS::HTMLElement::ImageSrc              DontDelete
926   useMap        KJS::HTMLElement::ImageUseMap           DontDelete
927   vspace        KJS::HTMLElement::ImageVspace           DontDelete
928   width         KJS::HTMLElement::ImageWidth            DontDelete
929   x         KJS::HTMLElement::ImageX            DontDelete|ReadOnly
930   y         KJS::HTMLElement::ImageY            DontDelete|ReadOnly
931 @end
932 @begin HTMLObjectElementTable 20
933   form            KJS::HTMLElement::ObjectForm            DontDelete|ReadOnly
934   code            KJS::HTMLElement::ObjectCode            DontDelete
935   align           KJS::HTMLElement::ObjectAlign           DontDelete
936   archive         KJS::HTMLElement::ObjectArchive         DontDelete
937   border          KJS::HTMLElement::ObjectBorder          DontDelete
938   codeBase        KJS::HTMLElement::ObjectCodeBase        DontDelete
939   codeType        KJS::HTMLElement::ObjectCodeType        DontDelete
940   contentDocument KJS::HTMLElement::ObjectContentDocument DontDelete|ReadOnly
941   data            KJS::HTMLElement::ObjectData            DontDelete
942   declare         KJS::HTMLElement::ObjectDeclare         DontDelete
943   height          KJS::HTMLElement::ObjectHeight          DontDelete
944   hspace          KJS::HTMLElement::ObjectHspace          DontDelete
945   name            KJS::HTMLElement::ObjectName            DontDelete
946   standby         KJS::HTMLElement::ObjectStandby         DontDelete
947   tabIndex        KJS::HTMLElement::ObjectTabIndex        DontDelete
948   type            KJS::HTMLElement::ObjectType            DontDelete
949   useMap          KJS::HTMLElement::ObjectUseMap          DontDelete
950   vspace          KJS::HTMLElement::ObjectVspace          DontDelete
951   width           KJS::HTMLElement::ObjectWidth           DontDelete
952 @end
953 @begin HTMLParamElementTable 4
954   name          KJS::HTMLElement::ParamName             DontDelete
955   type          KJS::HTMLElement::ParamType             DontDelete
956   value         KJS::HTMLElement::ParamValue            DontDelete
957   valueType     KJS::HTMLElement::ParamValueType        DontDelete
958 @end
959 @begin HTMLAppletElementTable 11
960   align         KJS::HTMLElement::AppletAlign           DontDelete
961   alt           KJS::HTMLElement::AppletAlt             DontDelete
962   archive       KJS::HTMLElement::AppletArchive         DontDelete
963   code          KJS::HTMLElement::AppletCode            DontDelete
964   codeBase      KJS::HTMLElement::AppletCodeBase        DontDelete
965   height        KJS::HTMLElement::AppletHeight          DontDelete
966   hspace        KJS::HTMLElement::AppletHspace          DontDelete
967   name          KJS::HTMLElement::AppletName            DontDelete
968   object        KJS::HTMLElement::AppletObject          DontDelete
969   vspace        KJS::HTMLElement::AppletVspace          DontDelete
970   width         KJS::HTMLElement::AppletWidth           DontDelete
971 @end
972 @begin HTMLMapElementTable 2
973   areas         KJS::HTMLElement::MapAreas              DontDelete|ReadOnly
974   name          KJS::HTMLElement::MapName               DontDelete
975 @end
976 @begin HTMLAreaElementTable 15
977   accessKey     KJS::HTMLElement::AreaAccessKey         DontDelete
978   alt           KJS::HTMLElement::AreaAlt               DontDelete
979   coords        KJS::HTMLElement::AreaCoords            DontDelete
980   href          KJS::HTMLElement::AreaHref              DontDelete
981   hash          KJS::HTMLElement::AreaHash              DontDelete|ReadOnly
982   host          KJS::HTMLElement::AreaHost              DontDelete|ReadOnly
983   hostname      KJS::HTMLElement::AreaHostName          DontDelete|ReadOnly
984   pathname      KJS::HTMLElement::AreaPathName          DontDelete|ReadOnly
985   port          KJS::HTMLElement::AreaPort              DontDelete|ReadOnly
986   protocol      KJS::HTMLElement::AreaProtocol          DontDelete|ReadOnly
987   search        KJS::HTMLElement::AreaSearch            DontDelete|ReadOnly
988   noHref        KJS::HTMLElement::AreaNoHref            DontDelete
989   shape         KJS::HTMLElement::AreaShape             DontDelete
990   tabIndex      KJS::HTMLElement::AreaTabIndex          DontDelete
991   target        KJS::HTMLElement::AreaTarget            DontDelete
992 @end
993 @begin HTMLScriptElementTable 7
994   text          KJS::HTMLElement::ScriptText            DontDelete
995   htmlFor       KJS::HTMLElement::ScriptHtmlFor         DontDelete
996   event         KJS::HTMLElement::ScriptEvent           DontDelete
997   charset       KJS::HTMLElement::ScriptCharset         DontDelete
998   defer         KJS::HTMLElement::ScriptDefer           DontDelete
999   src           KJS::HTMLElement::ScriptSrc             DontDelete
1000   type          KJS::HTMLElement::ScriptType            DontDelete
1001 @end
1002 @begin HTMLTableElementTable 23
1003   caption       KJS::HTMLElement::TableCaption          DontDelete
1004   tHead         KJS::HTMLElement::TableTHead            DontDelete
1005   tFoot         KJS::HTMLElement::TableTFoot            DontDelete
1006   rows          KJS::HTMLElement::TableRows             DontDelete|ReadOnly
1007   tBodies       KJS::HTMLElement::TableTBodies          DontDelete|ReadOnly
1008   align         KJS::HTMLElement::TableAlign            DontDelete
1009   bgColor       KJS::HTMLElement::TableBgColor          DontDelete
1010   border        KJS::HTMLElement::TableBorder           DontDelete
1011   cellPadding   KJS::HTMLElement::TableCellPadding      DontDelete
1012   cellSpacing   KJS::HTMLElement::TableCellSpacing      DontDelete
1013   frame         KJS::HTMLElement::TableFrame            DontDelete
1014   rules         KJS::HTMLElement::TableRules            DontDelete
1015   summary       KJS::HTMLElement::TableSummary          DontDelete
1016   width         KJS::HTMLElement::TableWidth            DontDelete
1017   createTHead   KJS::HTMLElement::TableCreateTHead      DontDelete|Function 0
1018   deleteTHead   KJS::HTMLElement::TableDeleteTHead      DontDelete|Function 0
1019   createTFoot   KJS::HTMLElement::TableCreateTFoot      DontDelete|Function 0
1020   deleteTFoot   KJS::HTMLElement::TableDeleteTFoot      DontDelete|Function 0
1021   createCaption KJS::HTMLElement::TableCreateCaption    DontDelete|Function 0
1022   deleteCaption KJS::HTMLElement::TableDeleteCaption    DontDelete|Function 0
1023   insertRow     KJS::HTMLElement::TableInsertRow        DontDelete|Function 1
1024   deleteRow     KJS::HTMLElement::TableDeleteRow        DontDelete|Function 1
1025 @end
1026 @begin HTMLTableCaptionElementTable 1
1027   align         KJS::HTMLElement::TableCaptionAlign     DontDelete
1028 @end
1029 @begin HTMLTableColElementTable 7
1030   align         KJS::HTMLElement::TableColAlign         DontDelete
1031   ch            KJS::HTMLElement::TableColCh            DontDelete
1032   chOff         KJS::HTMLElement::TableColChOff         DontDelete
1033   span          KJS::HTMLElement::TableColSpan          DontDelete
1034   vAlign        KJS::HTMLElement::TableColVAlign        DontDelete
1035   width         KJS::HTMLElement::TableColWidth         DontDelete
1036 @end
1037 @begin HTMLTableSectionElementTable 7
1038   align         KJS::HTMLElement::TableSectionAlign             DontDelete
1039   ch            KJS::HTMLElement::TableSectionCh                DontDelete
1040   chOff         KJS::HTMLElement::TableSectionChOff             DontDelete
1041   vAlign        KJS::HTMLElement::TableSectionVAlign            DontDelete
1042   rows          KJS::HTMLElement::TableSectionRows              DontDelete|ReadOnly
1043   insertRow     KJS::HTMLElement::TableSectionInsertRow         DontDelete|Function 1
1044   deleteRow     KJS::HTMLElement::TableSectionDeleteRow         DontDelete|Function 1
1045 @end
1046 @begin HTMLTableRowElementTable 11
1047   rowIndex      KJS::HTMLElement::TableRowRowIndex              DontDelete|ReadOnly
1048   sectionRowIndex KJS::HTMLElement::TableRowSectionRowIndex     DontDelete|ReadOnly
1049   cells         KJS::HTMLElement::TableRowCells                 DontDelete|ReadOnly
1050   align         KJS::HTMLElement::TableRowAlign                 DontDelete
1051   bgColor       KJS::HTMLElement::TableRowBgColor               DontDelete
1052   ch            KJS::HTMLElement::TableRowCh                    DontDelete
1053   chOff         KJS::HTMLElement::TableRowChOff                 DontDelete
1054   vAlign        KJS::HTMLElement::TableRowVAlign                DontDelete
1055   insertCell    KJS::HTMLElement::TableRowInsertCell            DontDelete|Function 1
1056   deleteCell    KJS::HTMLElement::TableRowDeleteCell            DontDelete|Function 1
1057 @end
1058 @begin HTMLTableCellElementTable 15
1059   cellIndex     KJS::HTMLElement::TableCellCellIndex            DontDelete|ReadOnly
1060   abbr          KJS::HTMLElement::TableCellAbbr                 DontDelete
1061   align         KJS::HTMLElement::TableCellAlign                DontDelete
1062   axis          KJS::HTMLElement::TableCellAxis                 DontDelete
1063   bgColor       KJS::HTMLElement::TableCellBgColor              DontDelete
1064   ch            KJS::HTMLElement::TableCellCh                   DontDelete
1065   chOff         KJS::HTMLElement::TableCellChOff                DontDelete
1066   colSpan       KJS::HTMLElement::TableCellColSpan              DontDelete
1067   headers       KJS::HTMLElement::TableCellHeaders              DontDelete
1068   height        KJS::HTMLElement::TableCellHeight               DontDelete
1069   noWrap        KJS::HTMLElement::TableCellNoWrap               DontDelete
1070   rowSpan       KJS::HTMLElement::TableCellRowSpan              DontDelete
1071   scope         KJS::HTMLElement::TableCellScope                DontDelete
1072   vAlign        KJS::HTMLElement::TableCellVAlign               DontDelete
1073   width         KJS::HTMLElement::TableCellWidth                DontDelete
1074 @end
1075 @begin HTMLFrameSetElementTable 2
1076   cols          KJS::HTMLElement::FrameSetCols                  DontDelete
1077   rows          KJS::HTMLElement::FrameSetRows                  DontDelete
1078 @end
1079 @begin HTMLFrameElementTable 9
1080   contentDocument KJS::HTMLElement::FrameContentDocument        DontDelete|ReadOnly
1081   contentWindow   KJS::HTMLElement::FrameContentWindow          DontDelete|ReadOnly
1082   frameBorder     KJS::HTMLElement::FrameFrameBorder            DontDelete
1083   longDesc        KJS::HTMLElement::FrameLongDesc               DontDelete
1084   marginHeight    KJS::HTMLElement::FrameMarginHeight           DontDelete
1085   marginWidth     KJS::HTMLElement::FrameMarginWidth            DontDelete
1086   name            KJS::HTMLElement::FrameName                   DontDelete
1087   noResize        KJS::HTMLElement::FrameNoResize               DontDelete
1088   scrolling       KJS::HTMLElement::FrameScrolling              DontDelete
1089   src             KJS::HTMLElement::FrameSrc                    DontDelete
1090   location        KJS::HTMLElement::FrameLocation               DontDelete
1091 @end
1092 @begin HTMLIFrameElementTable 12
1093   align           KJS::HTMLElement::IFrameAlign                 DontDelete
1094   contentDocument KJS::HTMLElement::IFrameContentDocument       DontDelete|ReadOnly
1095   contentWindow   KJS::HTMLElement::IFrameContentWindow         DontDelete|ReadOnly
1096   document        KJS::HTMLElement::IFrameDocument              DontDelete|ReadOnly
1097   frameBorder     KJS::HTMLElement::IFrameFrameBorder           DontDelete
1098   height          KJS::HTMLElement::IFrameHeight                DontDelete
1099   longDesc        KJS::HTMLElement::IFrameLongDesc              DontDelete
1100   marginHeight    KJS::HTMLElement::IFrameMarginHeight          DontDelete
1101   marginWidth     KJS::HTMLElement::IFrameMarginWidth           DontDelete
1102   name            KJS::HTMLElement::IFrameName                  DontDelete
1103   scrolling       KJS::HTMLElement::IFrameScrolling             DontDelete
1104   src             KJS::HTMLElement::IFrameSrc                   DontDelete
1105   width           KJS::HTMLElement::IFrameWidth                 DontDelete
1106 @end
1107
1108 @begin HTMLMarqueeElementTable 2
1109   start           KJS::HTMLElement::MarqueeStart                DontDelete|Function 0
1110   stop            KJS::HTMLElement::MarqueeStop                 DontDelete|Function 0
1111 @end
1112
1113 @begin HTMLCanvasElementTable 1
1114   getContext      KJS::HTMLElement::GetContext                  DontDelete|Function 0
1115 @end
1116 */
1117
1118 Value KJS::HTMLElement::tryGet(ExecState *exec, const Identifier &propertyName) const
1119 {
1120   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
1121 #ifdef KJS_VERBOSE
1122   kdDebug(6070) << "KJS::HTMLElement::tryGet " << propertyName.qstring() << " thisTag=" << element.tagName().string() << endl;
1123 #endif
1124   // First look at dynamic properties
1125   switch (element.elementId()) {
1126     case ID_FORM: {
1127       DOM::HTMLFormElement form = element;
1128       // Check if we're retrieving an element (by index or by name)
1129       bool ok;
1130       uint u = propertyName.toULong(&ok);
1131       if (ok)
1132         return getDOMNode(exec,form.elements().item(u));
1133       KJS::HTMLCollection coll(exec,form.elements());
1134       Value namedItems = coll.getNamedItems(exec, propertyName);
1135       if (namedItems.type() != UndefinedType)
1136         return namedItems;
1137     }
1138       break;
1139     case ID_SELECT: {
1140       DOM::HTMLSelectElement select = element;
1141       bool ok;
1142       uint u = propertyName.toULong(&ok);
1143       if (ok)
1144         return getDOMNode(exec,select.options().item(u)); // not specified by DOM(?) but supported in netscape/IE
1145     }
1146       break;
1147     case ID_FRAME:
1148     case ID_IFRAME: {
1149         DOM::DocumentImpl* doc = static_cast<DOM::HTMLFrameElementImpl *>(element.handle())->contentDocument();
1150         if ( doc ) {
1151             KHTMLPart* part = doc->part();
1152             if ( part ) {
1153               Object globalObject = Object::dynamicCast( Window::retrieve( part ) );
1154               // Calling hasProperty on a Window object doesn't work, it always says true.
1155               // Hence we need to use getDirect instead.
1156               if ( !globalObject.isNull() && static_cast<ObjectImp *>(globalObject.imp())->getDirect( propertyName ) )
1157                 return globalObject.get( exec, propertyName );
1158             }
1159         }
1160     }
1161       break;
1162 #if APPLE_CHANGES
1163     case ID_EMBED:
1164     case ID_APPLET: {
1165         return getRuntimeObject(exec,element);
1166     }
1167       break;
1168 #endif
1169     default:
1170         break;
1171     }
1172
1173   const HashTable* table = classInfo()->propHashTable; // get the right hashtable
1174   const HashEntry* entry = Lookup::findEntry(table, propertyName);
1175   if (entry) {
1176     if (entry->attr & Function)
1177       return lookupOrCreateFunction<KJS::HTMLElementFunction>(exec, propertyName, this, entry->value, entry->params, entry->attr);
1178     return getValueProperty(exec, entry->value);
1179   }
1180
1181   // Base HTMLElement stuff or parent class forward, as usual
1182   return DOMObjectLookupGet<KJS::HTMLElementFunction, KJS::HTMLElement, DOMElement>(exec, propertyName, &KJS::HTMLElementTable, this);
1183 }
1184
1185 Value KJS::HTMLElement::getValueProperty(ExecState *exec, int token) const
1186 {
1187   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
1188   switch (element.elementId()) {
1189   case ID_HTML: {
1190     DOM::HTMLHtmlElement html = element;
1191     if      (token == HtmlVersion)         return String(html.version());
1192   }
1193   break;
1194   case ID_HEAD: {
1195     DOM::HTMLHeadElement head = element;
1196     if      (token == HeadProfile)         return String(head.profile());
1197   }
1198   break;
1199   case ID_LINK: {
1200     DOM::HTMLLinkElement link = element;
1201     switch (token) {
1202     case LinkDisabled:        return Boolean(link.disabled());
1203     case LinkCharset:         return String(link.charset());
1204     case LinkHref:            return String(link.href());
1205     case LinkHrefLang:        return String(link.hreflang());
1206     case LinkMedia:           return String(link.media());
1207     case LinkRel:             return String(link.rel());
1208     case LinkRev:             return String(link.rev());
1209     case LinkTarget:          return String(link.target());
1210     case LinkType:            return String(link.type());
1211     case LinkSheet:           return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
1212     }
1213   }
1214   break;
1215   case ID_TITLE: {
1216     DOM::HTMLTitleElement title = element;
1217     switch (token) {
1218     case TitleText:                 return String(title.text());
1219     }
1220   }
1221   break;
1222   case ID_META: {
1223     DOM::HTMLMetaElement meta = element;
1224     switch (token) {
1225     case MetaContent:         return String(meta.content());
1226     case MetaHttpEquiv:       return String(meta.httpEquiv());
1227     case MetaName:            return String(meta.name());
1228     case MetaScheme:          return String(meta.scheme());
1229     }
1230   }
1231   break;
1232   case ID_BASE: {
1233     DOM::HTMLBaseElement base = element;
1234     switch (token) {
1235     case BaseHref:            return String(base.href());
1236     case BaseTarget:          return String(base.target());
1237     }
1238   }
1239   break;
1240   case ID_ISINDEX: {
1241     DOM::HTMLIsIndexElement isindex = element;
1242     switch (token) {
1243     case IsIndexForm:            return getDOMNode(exec,isindex.form()); // type HTMLFormElement
1244     case IsIndexPrompt:          return String(isindex.prompt());
1245     }
1246   }
1247   break;
1248   case ID_STYLE: {
1249     DOM::HTMLStyleElement style = element;
1250     switch (token) {
1251     case StyleDisabled:        return Boolean(style.disabled());
1252     case StyleMedia:           return String(style.media());
1253     case StyleType:            return String(style.type());
1254     case StyleSheet:           return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
1255     }
1256   }
1257   break;
1258   case ID_BODY: {
1259     DOM::HTMLBodyElement body = element;
1260     switch (token) {
1261     case BodyALink:           return String(body.aLink());
1262     case BodyBackground:      return String(body.background());
1263     case BodyBgColor:         return String(body.bgColor());
1264     case BodyLink:            return String(body.link());
1265     case BodyText:            return String(body.text());
1266     case BodyVLink:           return String(body.vLink());
1267     default:
1268       // Update the document's layout before we compute these attributes.
1269       DOM::DocumentImpl* docimpl = node.handle()->getDocument();
1270       if (docimpl) {
1271         docimpl->updateLayoutIgnorePendingStylesheets();
1272       }
1273       switch (token) {
1274         case BodyScrollLeft:
1275             return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsX() : 0);
1276         case BodyScrollTop:
1277             return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsY() : 0);
1278         case BodyScrollHeight:   return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsHeight() : 0);
1279         case BodyScrollWidth:    return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsWidth() : 0);
1280       }
1281     }
1282   }
1283   break;
1284
1285   case ID_FORM: {
1286     DOM::HTMLFormElement form = element;
1287     switch (token) {
1288     case FormElements:        return getHTMLCollection(exec,form.elements());
1289     case FormLength:          return Number(form.length());
1290     case FormName:            return String(form.name());
1291     case FormAcceptCharset:   return String(form.acceptCharset());
1292     case FormAction:          return String(form.action());
1293     case FormEncType:         return String(form.enctype());
1294     case FormMethod:          return String(form.method());
1295     case FormTarget:          return String(form.target());
1296     }
1297   }
1298   break;
1299   case ID_SELECT: {
1300     DOM::HTMLSelectElement select = element;
1301     switch (token) {
1302     case SelectType:            return String(select.type());
1303     case SelectSelectedIndex:   return Number(select.selectedIndex());
1304     case SelectValue:           return String(select.value());
1305     case SelectLength:          return Number(select.length());
1306     case SelectForm:            return getDOMNode(exec,select.form()); // type HTMLFormElement
1307     case SelectOptions:         return getSelectHTMLCollection(exec, select.options(), select); // type HTMLCollection
1308     case SelectDisabled:        return Boolean(select.disabled());
1309     case SelectMultiple:        return Boolean(select.multiple());
1310     case SelectName:            return String(select.name());
1311     case SelectSize:            return Number(select.size());
1312     case SelectTabIndex:        return Number(select.tabIndex());
1313     }
1314   }
1315   break;
1316   case ID_OPTGROUP: {
1317     DOM::HTMLOptGroupElement optgroup = element;
1318     switch (token) {
1319     case OptGroupDisabled:        return Boolean(optgroup.disabled());
1320     case OptGroupLabel:           return String(optgroup.label());
1321     }
1322   }
1323   break;
1324   case ID_OPTION: {
1325     DOM::HTMLOptionElement option = element;
1326     switch (token) {
1327     case OptionForm:            return getDOMNode(exec,option.form()); // type HTMLFormElement
1328     case OptionDefaultSelected: return Boolean(option.defaultSelected());
1329     case OptionText:            return String(option.text());
1330     case OptionIndex:           return Number(option.index());
1331     case OptionDisabled:        return Boolean(option.disabled());
1332     case OptionLabel:           return String(option.label());
1333     case OptionSelected:        return Boolean(option.selected());
1334     case OptionValue:           return String(option.value());
1335     }
1336   }
1337   break;
1338   case ID_INPUT: {
1339     DOM::HTMLInputElement input = element;
1340     switch (token) {
1341     case InputDefaultValue:    return String(input.defaultValue());
1342     case InputDefaultChecked:  return Boolean(input.defaultChecked());
1343     case InputForm:            return getDOMNode(exec,input.form()); // type HTMLFormElement
1344     case InputAccept:          return String(input.accept());
1345     case InputAccessKey:       return String(input.accessKey());
1346     case InputAlign:           return String(input.align());
1347     case InputAlt:             return String(input.alt());
1348     case InputChecked:         return Boolean(input.checked());
1349     case InputDisabled:        return Boolean(input.disabled());
1350     case InputMaxLength:       return Number(input.maxLength());
1351     case InputName:            return String(input.name());
1352     case InputReadOnly:        return Boolean(input.readOnly());
1353     case InputSize:            return String(input.size());
1354     case InputSrc:             return String(input.src());
1355     case InputTabIndex:        return Number(input.tabIndex());
1356     case InputType:            return String(input.type());
1357     case InputUseMap:          return String(input.useMap());
1358     case InputValue:           return String(input.value());
1359     }
1360   }
1361   break;
1362   case ID_TEXTAREA: {
1363     DOM::HTMLTextAreaElement textarea = element;
1364     switch (token) {
1365     case TextAreaDefaultValue:    return String(textarea.defaultValue());
1366     case TextAreaForm:            return getDOMNode(exec,textarea.form()); // type HTMLFormElement
1367     case TextAreaAccessKey:       return String(textarea.accessKey());
1368     case TextAreaCols:            return Number(textarea.cols());
1369     case TextAreaDisabled:        return Boolean(textarea.disabled());
1370     case TextAreaName:            return String(textarea.name());
1371     case TextAreaReadOnly:        return Boolean(textarea.readOnly());
1372     case TextAreaRows:            return Number(textarea.rows());
1373     case TextAreaTabIndex:        return Number(textarea.tabIndex());
1374     case TextAreaType:            return String(textarea.type());
1375     case TextAreaValue:           return String(textarea.value());
1376     }
1377   }
1378   break;
1379   case ID_BUTTON: {
1380     DOM::HTMLButtonElement button = element;
1381     switch (token) {
1382     case ButtonForm:            return getDOMNode(exec,button.form()); // type HTMLFormElement
1383     case ButtonAccessKey:       return String(button.accessKey());
1384     case ButtonDisabled:        return Boolean(button.disabled());
1385     case ButtonName:            return String(button.name());
1386     case ButtonTabIndex:        return Number(button.tabIndex());
1387     case ButtonType:            return String(button.type());
1388     case ButtonValue:           return String(button.value());
1389     }
1390   }
1391   break;
1392   case ID_LABEL: {
1393     DOM::HTMLLabelElement label = element;
1394     switch (token) {
1395     case LabelForm:            return getDOMNode(exec,label.form()); // type HTMLFormElement
1396     case LabelAccessKey:       return String(label.accessKey());
1397     case LabelHtmlFor:         return String(label.htmlFor());
1398     }
1399   }
1400   break;
1401   case ID_FIELDSET: {
1402     DOM::HTMLFieldSetElement fieldSet = element;
1403     switch (token) {
1404     case FieldSetForm:            return getDOMNode(exec,fieldSet.form()); // type HTMLFormElement
1405     }
1406   }
1407   break;
1408   case ID_LEGEND: {
1409     DOM::HTMLLegendElement legend = element;
1410     switch (token) {
1411     case LegendForm:            return getDOMNode(exec,legend.form()); // type HTMLFormElement
1412     case LegendAccessKey:       return String(legend.accessKey());
1413     case LegendAlign:           return String(legend.align());
1414     }
1415   }
1416   break;
1417   case ID_UL: {
1418     DOM::HTMLUListElement uList = element;
1419     switch (token) {
1420     case UListCompact:         return Boolean(uList.compact());
1421     case UListType:            return String(uList.type());
1422     }
1423   }
1424   break;
1425   case ID_OL: {
1426     DOM::HTMLOListElement oList = element;
1427     switch (token) {
1428     case OListCompact:         return Boolean(oList.compact());
1429     case OListStart:           return Number(oList.start());
1430     case OListType:            return String(oList.type());
1431     }
1432   }
1433   break;
1434   case ID_DL: {
1435     DOM::HTMLDListElement dList = element;
1436     switch (token) {
1437     case DListCompact:         return Boolean(dList.compact());
1438     }
1439   }
1440   break;
1441   case ID_DIR: {
1442     DOM::HTMLDirectoryElement directory = element;
1443     switch (token) {
1444     case DirectoryCompact:         return Boolean(directory.compact());
1445     }
1446   }
1447   break;
1448   case ID_MENU: {
1449     DOM::HTMLMenuElement menu = element;
1450     switch (token) {
1451     case MenuCompact:         return Boolean(menu.compact());
1452     }
1453   }
1454   break;
1455   case ID_LI: {
1456     DOM::HTMLLIElement li = element;
1457     switch (token) {
1458     case LIType:            return String(li.type());
1459     case LIValue:           return Number(li.value());
1460     }
1461   }
1462   break;
1463   case ID_DIV: {
1464     DOM::HTMLDivElement div = element;
1465     switch (token) {
1466     case DivAlign:           return String(div.align());
1467     }
1468   }
1469   break;
1470   case ID_P: {
1471     DOM::HTMLParagraphElement paragraph = element;
1472     switch (token) {
1473     case ParagraphAlign:           return String(paragraph.align());
1474     }
1475   }
1476   break;
1477   case ID_H1:
1478   case ID_H2:
1479   case ID_H3:
1480   case ID_H4:
1481   case ID_H5:
1482   case ID_H6: {
1483     DOM::HTMLHeadingElement heading = element;
1484     switch (token) {
1485     case HeadingAlign:           return String(heading.align());
1486     }
1487   }
1488   break;
1489   case ID_BLOCKQUOTE: {
1490     DOM::HTMLBlockquoteElement blockquote = element;
1491     switch (token) {
1492     case BlockQuoteCite:            return String(blockquote.cite());
1493     }
1494   }
1495   case ID_Q: {
1496     DOM::HTMLQuoteElement quote = element;
1497     switch (token) {
1498     case QuoteCite:            return String(quote.cite());
1499     }
1500   }
1501   case ID_PRE: {
1502     DOM::HTMLPreElement pre = element;
1503     switch (token) {
1504     case PreWidth:           return Number(pre.width());
1505     }
1506   }
1507   break;
1508   case ID_BR: {
1509     DOM::HTMLBRElement br = element;
1510     switch (token) {
1511     case BRClear:           return String(br.clear());
1512     }
1513   }
1514   break;
1515   case ID_BASEFONT: {
1516     DOM::HTMLBaseFontElement baseFont = element;
1517     switch (token) {
1518     case BaseFontColor:           return String(baseFont.color());
1519     case BaseFontFace:            return String(baseFont.face());
1520     case BaseFontSize:            return String(baseFont.size());
1521     }
1522   }
1523   break;
1524   case ID_FONT: {
1525     DOM::HTMLFontElement font = element;
1526     switch (token) {
1527     case FontColor:           return String(font.color());
1528     case FontFace:            return String(font.face());
1529     case FontSize:            return String(font.size());
1530     }
1531   }
1532   break;
1533   case ID_HR: {
1534     DOM::HTMLHRElement hr = element;
1535     switch (token) {
1536     case HRAlign:           return String(hr.align());
1537     case HRNoShade:         return Boolean(hr.noShade());
1538     case HRSize:            return String(hr.size());
1539     case HRWidth:           return String(hr.width());
1540     }
1541   }
1542   break;
1543   case ID_INS:
1544   case ID_DEL: {
1545     DOM::HTMLModElement mod = element;
1546     switch (token) {
1547     case ModCite:            return String(mod.cite());
1548     case ModDateTime:        return String(mod.dateTime());
1549     }
1550   }
1551   break;
1552   case ID_A: {
1553     DOM::HTMLAnchorElement anchor = element;
1554     switch (token) {
1555     case AnchorAccessKey:       return String(anchor.accessKey());
1556     case AnchorCharset:         return String(anchor.charset());
1557     case AnchorCoords:          return String(anchor.coords());
1558     case AnchorHref:            return String(anchor.href());
1559     case AnchorHrefLang:        return String(anchor.hreflang());
1560     case AnchorHash:            return String('#'+KURL(anchor.href().string()).ref());
1561     case AnchorHost:            return String(KURL(anchor.href().string()).host());
1562     case AnchorHostname: {
1563       KURL url(anchor.href().string());
1564       kdDebug(6070) << "anchor::hostname uses:" <<url.url()<<endl;
1565       if (url.port()==0)
1566         return String(url.host());
1567       else
1568         return String(url.host() + ":" + QString::number(url.port()));
1569     }
1570     case AnchorPathName:        return String(KURL(anchor.href().string()).path());
1571     case AnchorPort:            return String(QString::number(KURL(anchor.href().string()).port()));
1572     case AnchorProtocol:        return String(KURL(anchor.href().string()).protocol()+":");
1573     case AnchorSearch:          return String(KURL(anchor.href().string()).query());
1574     case AnchorName:            return String(anchor.name());
1575     case AnchorRel:             return String(anchor.rel());
1576     case AnchorRev:             return String(anchor.rev());
1577     case AnchorShape:           return String(anchor.shape());
1578     case AnchorTabIndex:        return Number(anchor.tabIndex());
1579     case AnchorTarget:          return String(anchor.target());
1580     case AnchorType:            return String(anchor.type());
1581     case AnchorText: {
1582         DOM::DocumentImpl* docimpl = node.handle()->getDocument();
1583         if (docimpl) {
1584           docimpl->updateLayoutIgnorePendingStylesheets();
1585         }
1586       }
1587       return String(anchor.innerText());
1588     }
1589   }
1590   break;
1591   case ID_IMG: {
1592     DOM::HTMLImageElement image = element;
1593     switch (token) {
1594     case ImageName:            return String(image.name());
1595     case ImageAlign:           return String(image.align());
1596     case ImageAlt:             return String(image.alt());
1597     case ImageBorder:          return Number(image.border());
1598     case ImageHeight:          return Number(static_cast<DOM::HTMLImageElementImpl *>(image.handle())->height(true));
1599     case ImageHspace:          return Number(image.hspace());
1600     case ImageIsMap:           return Boolean(image.isMap());
1601     case ImageLongDesc:        return String(image.longDesc());
1602     case ImageSrc:             return String(image.src());
1603     case ImageUseMap:          return String(image.useMap());
1604     case ImageVspace:          return Number(image.vspace());
1605     case ImageWidth:           return Number(static_cast<DOM::HTMLImageElementImpl *>(image.handle())->width(true));
1606     case ImageX:               return Number(image.x());
1607     case ImageY:               return Number(image.y());
1608     }
1609   }
1610   break;
1611   case ID_OBJECT: {
1612     DOM::HTMLObjectElement object = element;
1613     switch (token) {
1614     case ObjectForm:            return getDOMNode(exec,object.form()); // type HTMLFormElement
1615     case ObjectCode:            return String(object.code());
1616     case ObjectAlign:           return String(object.align());
1617     case ObjectArchive:         return String(object.archive());
1618     case ObjectBorder:          return String(object.border());
1619     case ObjectCodeBase:        return String(object.codeBase());
1620     case ObjectCodeType:        return String(object.codeType());
1621     case ObjectContentDocument: return checkNodeSecurity(exec,object.contentDocument()) ? 
1622                                        getDOMNode(exec, object.contentDocument()) : Undefined();
1623     case ObjectData:            return String(object.data());
1624     case ObjectDeclare:         return Boolean(object.declare());
1625     case ObjectHeight:          return String(object.height());
1626     case ObjectHspace:          return String(object.hspace());
1627     case ObjectName:            return String(object.name());
1628     case ObjectStandby:         return String(object.standby());
1629     case ObjectTabIndex:        return Number(object.tabIndex());
1630     case ObjectType:            return String(object.type());
1631     case ObjectUseMap:          return String(object.useMap());
1632     case ObjectVspace:          return String(object.vspace());
1633     case ObjectWidth:           return String(object.width());
1634     }
1635   }
1636   break;
1637   case ID_PARAM: {
1638     DOM::HTMLParamElement param = element;
1639     switch (token) {
1640     case ParamName:            return String(param.name());
1641     case ParamType:            return String(param.type());
1642     case ParamValue:           return String(param.value());
1643     case ParamValueType:       return String(param.valueType());
1644     }
1645   }
1646   break;
1647   case ID_APPLET: {
1648     DOM::HTMLAppletElement applet = element;
1649     switch (token) {
1650     case AppletAlign:           return String(applet.align());
1651     case AppletAlt:             return String(applet.alt());
1652     case AppletArchive:         return String(applet.archive());
1653     case AppletCode:            return String(applet.code());
1654     case AppletCodeBase:        return String(applet.codeBase());
1655     case AppletHeight:          return String(applet.height());
1656     case AppletHspace:          return String(applet.hspace());
1657     case AppletName:            return String(applet.name());
1658     case AppletObject:          return String(applet.object());
1659     case AppletVspace:          return String(applet.vspace());
1660     case AppletWidth:           return String(applet.width());
1661     }
1662   }
1663   break;
1664   case ID_MAP: {
1665     DOM::HTMLMapElement map = element;
1666     switch (token) {
1667     case MapAreas:           return getHTMLCollection(exec, map.areas()); // type HTMLCollection
1668     case MapName:            return String(map.name());
1669     }
1670   }
1671   break;
1672   case ID_AREA: {
1673     DOM::HTMLAreaElement area = element;
1674     switch (token) {
1675     case AreaAccessKey:       return String(area.accessKey());
1676     case AreaAlt:             return String(area.alt());
1677     case AreaCoords:          return String(area.coords());
1678     case AreaHref:            return String(area.href());
1679     case AreaHash:            return String('#'+KURL(area.href().string()).ref());
1680     case AreaHost:            return String(KURL(area.href().string()).host());
1681     case AreaHostName: {
1682       KURL url(area.href().string());
1683       kdDebug(6070) << "link::hostname uses:" <<url.url()<<endl;
1684       if (url.port()==0)
1685         return String(url.host());
1686       else
1687         return String(url.host() + ":" + QString::number(url.port()));
1688     }
1689     case AreaPathName:        return String(KURL(area.href().string()).path());
1690     case AreaPort:            return String(QString::number(KURL(area.href().string()).port()));
1691     case AreaProtocol:        return String(KURL(area.href().string()).protocol()+":");
1692     case AreaSearch:          return String(KURL(area.href().string()).query());
1693     case AreaNoHref:          return Boolean(area.noHref());
1694     case AreaShape:           return String(area.shape());
1695     case AreaTabIndex:        return Number(area.tabIndex());
1696     case AreaTarget:          return String(area.target());
1697     }
1698   }
1699   break;
1700   case ID_SCRIPT: {
1701     DOM::HTMLScriptElement script = element;
1702     switch (token) {
1703     case ScriptText:            return String(script.text());
1704     case ScriptHtmlFor:         return String(script.htmlFor());
1705     case ScriptEvent:           return String(script.event());
1706     case ScriptCharset:         return String(script.charset());
1707     case ScriptDefer:           return Boolean(script.defer());
1708     case ScriptSrc:             return String(script.src());
1709     case ScriptType:            return String(script.type());
1710     }
1711   }
1712   break;
1713   case ID_TABLE: {
1714     DOM::HTMLTableElement table = element;
1715     switch (token) {
1716     case TableCaption:         return getDOMNode(exec,table.caption()); // type HTMLTableCaptionElement
1717     case TableTHead:           return getDOMNode(exec,table.tHead()); // type HTMLTableSectionElement
1718     case TableTFoot:           return getDOMNode(exec,table.tFoot()); // type HTMLTableSectionElement
1719     case TableRows:            return getHTMLCollection(exec,table.rows()); // type HTMLCollection
1720     case TableTBodies:         return getHTMLCollection(exec,table.tBodies()); // type HTMLCollection
1721     case TableAlign:           return String(table.align());
1722     case TableBgColor:         return String(table.bgColor());
1723     case TableBorder:          return String(table.border());
1724     case TableCellPadding:     return String(table.cellPadding());
1725     case TableCellSpacing:     return String(table.cellSpacing());
1726     case TableFrame:           return String(table.frame());
1727     case TableRules:           return String(table.rules());
1728     case TableSummary:         return String(table.summary());
1729     case TableWidth:           return String(table.width());
1730     }
1731   }
1732   break;
1733   case ID_CAPTION: {
1734     DOM::HTMLTableCaptionElement tableCaption;
1735     switch (token) {
1736     case TableCaptionAlign:       return String(tableCaption.align());
1737     }
1738   }
1739   break;
1740   case ID_COL: {
1741     DOM::HTMLTableColElement tableCol = element;
1742     switch (token) {
1743     case TableColAlign:           return String(tableCol.align());
1744     case TableColCh:              return String(tableCol.ch());
1745     case TableColChOff:           return String(tableCol.chOff());
1746     case TableColSpan:            return Number(tableCol.span());
1747     case TableColVAlign:          return String(tableCol.vAlign());
1748     case TableColWidth:           return String(tableCol.width());
1749     }
1750   }
1751   break;
1752   case ID_THEAD:
1753   case ID_TBODY:
1754   case ID_TFOOT: {
1755     DOM::HTMLTableSectionElement tableSection = element;
1756     switch (token) {
1757     case TableSectionAlign:           return String(tableSection.align());
1758     case TableSectionCh:              return String(tableSection.ch());
1759     case TableSectionChOff:           return String(tableSection.chOff());
1760     case TableSectionVAlign:          return String(tableSection.vAlign());
1761     case TableSectionRows:            return getHTMLCollection(exec,tableSection.rows()); // type HTMLCollection
1762     }
1763   }
1764   break;
1765   case ID_TR: {
1766    DOM::HTMLTableRowElement tableRow = element;
1767    switch (token) {
1768    case TableRowRowIndex:        return Number(tableRow.rowIndex());
1769    case TableRowSectionRowIndex: return Number(tableRow.sectionRowIndex());
1770    case TableRowCells:           return getHTMLCollection(exec,tableRow.cells()); // type HTMLCollection
1771    case TableRowAlign:           return String(tableRow.align());
1772    case TableRowBgColor:         return String(tableRow.bgColor());
1773    case TableRowCh:              return String(tableRow.ch());
1774    case TableRowChOff:           return String(tableRow.chOff());
1775    case TableRowVAlign:          return String(tableRow.vAlign());
1776    }
1777   }
1778   break;
1779   case ID_TH:
1780   case ID_TD: {
1781     DOM::HTMLTableCellElement tableCell = element;
1782     switch (token) {
1783     case TableCellCellIndex:       return Number(tableCell.cellIndex());
1784     case TableCellAbbr:            return String(tableCell.abbr());
1785     case TableCellAlign:           return String(tableCell.align());
1786     case TableCellAxis:            return String(tableCell.axis());
1787     case TableCellBgColor:         return String(tableCell.bgColor());
1788     case TableCellCh:              return String(tableCell.ch());
1789     case TableCellChOff:           return String(tableCell.chOff());
1790     case TableCellColSpan:         return Number(tableCell.colSpan());
1791     case TableCellHeaders:         return String(tableCell.headers());
1792     case TableCellHeight:          return String(tableCell.height());
1793     case TableCellNoWrap:          return Boolean(tableCell.noWrap());
1794     case TableCellRowSpan:         return Number(tableCell.rowSpan());
1795     case TableCellScope:           return String(tableCell.scope());
1796     case TableCellVAlign:          return String(tableCell.vAlign());
1797     case TableCellWidth:           return String(tableCell.width());
1798     }
1799   }
1800   break;
1801   case ID_FRAMESET: {
1802     DOM::HTMLFrameSetElement frameSet = element;
1803     switch (token) {
1804     case FrameSetCols:            return String(frameSet.cols());
1805     case FrameSetRows:            return String(frameSet.rows());
1806     }
1807   }
1808   break;
1809   case ID_FRAME: {
1810     DOM::HTMLFrameElement frameElement = element;
1811     switch (token) {
1812     case FrameContentDocument: return checkNodeSecurity(exec,frameElement.contentDocument()) ? 
1813                                       getDOMNode(exec, frameElement.contentDocument()) : Undefined();
1814     case FrameContentWindow:   return checkNodeSecurity(exec,frameElement.contentDocument())
1815                                     ? Window::retrieve(static_cast<HTMLFrameElementImpl *>(frameElement.handle())->contentPart())
1816                                     : Undefined();
1817     case FrameFrameBorder:     return String(frameElement.frameBorder());
1818     case FrameLongDesc:        return String(frameElement.longDesc());
1819     case FrameMarginHeight:    return String(frameElement.marginHeight());
1820     case FrameMarginWidth:     return String(frameElement.marginWidth());
1821     case FrameName:            return String(frameElement.name());
1822     case FrameNoResize:        return Boolean(frameElement.noResize());
1823     case FrameScrolling:       return String(frameElement.scrolling());
1824     case FrameSrc:
1825     case FrameLocation:        return String(frameElement.src());
1826     }
1827   }
1828   break;
1829   case ID_IFRAME: {
1830     DOM::HTMLIFrameElement iFrame = element;
1831     switch (token) {
1832     case IFrameAlign:                return String(iFrame.align());
1833       // ### security check ?
1834     case IFrameDocument: // non-standard, mapped to contentDocument
1835     case IFrameContentDocument: return checkNodeSecurity(exec,iFrame.contentDocument()) ? 
1836                                   getDOMNode(exec, iFrame.contentDocument()) : Undefined();
1837     case IFrameContentWindow:   return checkNodeSecurity(exec,iFrame.contentDocument()) 
1838                                     ? Window::retrieve(static_cast<HTMLIFrameElementImpl *>(iFrame.handle())->contentPart())
1839                                     : Undefined();
1840     case IFrameFrameBorder:     return String(iFrame.frameBorder());
1841     case IFrameHeight:          return String(iFrame.height());
1842     case IFrameLongDesc:        return String(iFrame.longDesc());
1843     case IFrameMarginHeight:    return String(iFrame.marginHeight());
1844     case IFrameMarginWidth:     return String(iFrame.marginWidth());
1845     case IFrameName:            return String(iFrame.name());
1846     case IFrameScrolling:       return String(iFrame.scrolling());
1847     case IFrameSrc:             return String(iFrame.src());
1848     case IFrameWidth:           return String(iFrame.width());
1849     }
1850     break;
1851   }
1852   } // xemacs (or arnt) could be a bit smarter when it comes to indenting switch()es ;)
1853   // its not arnt to blame - its the original Stroustrup style we like :) (Dirk)
1854
1855   // generic properties
1856   switch (token) {
1857   case ElementId:
1858       // iht.com relies on this value being "" when no id is present.  Other browsers do this as well.
1859       // So we use String() instead of String() here.
1860     return String(element.id());
1861   case ElementTitle:
1862     return String(element.title());
1863   case ElementLang:
1864     return String(element.lang());
1865   case ElementDir:
1866     return String(element.dir());
1867   case ElementClassName:
1868     return String(element.className());
1869   case ElementInnerHTML:
1870     return String(element.innerHTML());
1871   case ElementInnerText:
1872     {
1873       DOM::DocumentImpl* docimpl = node.handle()->getDocument();
1874       if (docimpl) {
1875         docimpl->updateLayoutIgnorePendingStylesheets();
1876       }
1877     }
1878     return String(element.innerText());
1879   case ElementOuterHTML:
1880     return String(element.outerHTML());
1881   case ElementOuterText:
1882     return String(element.outerText());
1883   case ElementDocument:
1884     return getDOMNode(exec,element.ownerDocument());
1885   case ElementChildren:
1886     return getHTMLCollection(exec,element.children());
1887   case ElementContentEditable:
1888     return String(element.contentEditable());
1889   case ElementIsContentEditable:
1890     return Boolean(element.isContentEditable());
1891   // ### what about style? or is this used instead for DOM2 stylesheets?
1892   }
1893   kdWarning() << "HTMLElement::getValueProperty unhandled token " << token << endl;
1894   return Undefined();
1895 }
1896
1897 bool KJS::HTMLElement::hasProperty(ExecState *exec, const Identifier &propertyName) const
1898 {
1899 #ifdef KJS_VERBOSE
1900   //kdDebug(6070) << "HTMLElement::hasProperty " << propertyName.qstring() << endl;
1901 #endif
1902   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
1903   // First look at dynamic properties - keep this in sync with tryGet
1904   switch (element.elementId()) {
1905     case ID_FORM: {
1906       DOM::HTMLFormElement form = element;
1907       // Check if we're retrieving an element (by index or by name)
1908       bool ok;
1909       uint u = propertyName.toULong(&ok);
1910       if (ok && !(form.elements().item(u).isNull()))
1911         return true;
1912       DOM::Node testnode = form.elements().namedItem(propertyName.string());
1913       if (!testnode.isNull())
1914         return true;
1915     }
1916     case ID_SELECT: {
1917       DOM::HTMLSelectElement select = element;
1918       bool ok;
1919       uint u = propertyName.toULong(&ok);
1920       if (ok && !(select.options().item(u).isNull()))
1921         return true;
1922     }
1923     default:
1924       break;
1925   }
1926
1927   return DOMElement::hasProperty(exec, propertyName);
1928 }
1929
1930 UString KJS::HTMLElement::toString(ExecState *exec) const
1931 {
1932   if (node.elementId() == ID_A)
1933     return UString(static_cast<const DOM::HTMLAnchorElement&>(node).href());
1934   else
1935     return DOMElement::toString(exec);
1936 }
1937
1938 static void getForm(DOM::HTMLFormElement* form, const DOM::HTMLElement& element)
1939 {
1940     switch (element.elementId()) {
1941         case ID_ISINDEX: {
1942             DOM::HTMLIsIndexElement isindex = element;
1943             *form = isindex.form();
1944             break;
1945         }
1946         case ID_SELECT: {
1947             DOM::HTMLSelectElement select = element;
1948             *form = select.form();
1949             break;
1950         }
1951         case ID_OPTION: {
1952             DOM::HTMLOptionElement option = element;
1953             *form = option.form();
1954             break;
1955         }
1956         case ID_INPUT: {
1957             DOM::HTMLInputElement input = element;
1958             *form = input.form();
1959             break;
1960         }
1961         case ID_TEXTAREA: {
1962             DOM::HTMLTextAreaElement textarea = element;
1963             *form = textarea.form();
1964             break;
1965         }
1966         case ID_LABEL: {
1967             DOM::HTMLLabelElement label = element;
1968             *form = label.form();
1969             break;
1970         }
1971         case ID_FIELDSET: {
1972             DOM::HTMLFieldSetElement fieldset = element;
1973             *form = fieldset.form();
1974             break;
1975         }
1976         case ID_LEGEND: {
1977             DOM::HTMLLegendElement legend = element;
1978             *form = legend.form();
1979             break;
1980         }
1981         case ID_OBJECT: {
1982             DOM::HTMLObjectElement object = element;
1983             *form = object.form();
1984             break;
1985         }
1986         default:
1987             break;
1988     }
1989 }
1990
1991 void KJS::HTMLElement::pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const
1992 {
1993   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
1994
1995   // The document is put on first, fall back to searching it only after the element and form.
1996   scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element.ownerDocument()).imp()));
1997
1998   // The form is next, searched before the document, but after the element itself.
1999   DOM::HTMLFormElement formElt;
2000   
2001   // First try to obtain the form from the element itself.  We do this to deal with
2002   // the malformed case where <form>s aren't in our parent chain (e.g., when they were inside 
2003   // <table> or <tbody>.
2004   getForm(&formElt, element);
2005   if (!formElt.isNull())
2006     scope.push(static_cast<ObjectImp *>(getDOMNode(exec, formElt).imp()));
2007   else {
2008     DOM::Node form = element.parentNode();
2009     while (!form.isNull() && form.elementId() != ID_FORM)
2010         form = form.parentNode();
2011     
2012     if (!form.isNull())
2013         scope.push(static_cast<ObjectImp *>(getDOMNode(exec, form).imp()));
2014   }
2015   
2016   // The element is on top, searched first.
2017   scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element).imp()));
2018 }
2019
2020 HTMLElementFunction::HTMLElementFunction(ExecState *exec, int i, int len)
2021   : DOMFunction(), id(i)
2022 {
2023   Value protect(this);
2024   put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum);
2025 }
2026
2027 Value KJS::HTMLElementFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
2028 {
2029   if (!thisObj.inherits(&KJS::HTMLElement::info)) {
2030     Object err = Error::create(exec,TypeError);
2031     exec->setException(err);
2032     return err;
2033   }
2034   kdDebug() << "KJS::HTMLElementFunction::tryCall " << endl;
2035   DOM::HTMLElement element = static_cast<KJS::HTMLElement *>(thisObj.imp())->toElement();
2036
2037   switch (element.elementId()) {
2038     case ID_FORM: {
2039       DOM::HTMLFormElement form = element;
2040       if (id == KJS::HTMLElement::FormSubmit) {
2041         form.submit();
2042         return Undefined();
2043       }
2044       else if (id == KJS::HTMLElement::FormReset) {
2045         form.reset();
2046         return Undefined();
2047       }
2048     }
2049     break;
2050     case ID_SELECT: {
2051       DOM::HTMLSelectElement select = element;
2052       if (id == KJS::HTMLElement::SelectAdd) {
2053         select.add(KJS::toNode(args[0]),KJS::toNode(args[1]));
2054         return Undefined();
2055       }
2056       else if (id == KJS::HTMLElement::SelectRemove) {
2057         select.remove(int(args[0].toNumber(exec)));
2058         return Undefined();
2059       }
2060       else if (id == KJS::HTMLElement::SelectBlur) {
2061         select.blur();
2062         return Undefined();
2063       }
2064       else if (id == KJS::HTMLElement::SelectFocus) {
2065         select.focus();
2066         return Undefined();
2067       }
2068     }
2069     break;
2070     case ID_INPUT: {
2071       DOM::HTMLInputElement input = element;
2072       if (id == KJS::HTMLElement::InputBlur) {
2073         input.blur();
2074         return Undefined();
2075       }
2076       else if (id == KJS::HTMLElement::InputFocus) {
2077         input.focus();
2078         return Undefined();
2079       }
2080       else if (id == KJS::HTMLElement::InputSelect) {
2081         input.select();
2082         return Undefined();
2083       }
2084       else if (id == KJS::HTMLElement::InputClick) {
2085         input.click();
2086         return Undefined();
2087       }
2088     }
2089     break;
2090     case ID_TEXTAREA: {
2091       DOM::HTMLTextAreaElement textarea = element;
2092       if (id == KJS::HTMLElement::TextAreaBlur) {
2093         textarea.blur();
2094         return Undefined();
2095       }
2096       else if (id == KJS::HTMLElement::TextAreaFocus) {
2097         textarea.focus();
2098         return Undefined();
2099       }
2100       else if (id == KJS::HTMLElement::TextAreaSelect) {
2101         textarea.select();
2102         return Undefined();
2103       }
2104     }
2105     break;
2106     case ID_A: {
2107       DOM::HTMLAnchorElement anchor = element;
2108       if (id == KJS::HTMLElement::AnchorBlur) {
2109         anchor.blur();
2110         return Undefined();
2111       }
2112       else if (id == KJS::HTMLElement::AnchorFocus) {
2113         anchor.focus();
2114         return Undefined();
2115       } 
2116       else if (id == KJS::HTMLElement::AnchorToString) {
2117         return String(thisObj.toString(exec));
2118       }
2119     }
2120     break;
2121     case ID_TABLE: {
2122       DOM::HTMLTableElement table = element;
2123       if (id == KJS::HTMLElement::TableCreateTHead)
2124         return getDOMNode(exec,table.createTHead());
2125       else if (id == KJS::HTMLElement::TableDeleteTHead) {
2126         table.deleteTHead();
2127         return Undefined();
2128       }
2129       else if (id == KJS::HTMLElement::TableCreateTFoot)
2130         return getDOMNode(exec,table.createTFoot());
2131       else if (id == KJS::HTMLElement::TableDeleteTFoot) {
2132         table.deleteTFoot();
2133         return Undefined();
2134       }
2135       else if (id == KJS::HTMLElement::TableCreateCaption)
2136         return getDOMNode(exec,table.createCaption());
2137       else if (id == KJS::HTMLElement::TableDeleteCaption) {
2138         table.deleteCaption();
2139         return Undefined();
2140       }
2141       else if (id == KJS::HTMLElement::TableInsertRow)
2142         return getDOMNode(exec,table.insertRow(args[0].toInt32(exec)));
2143       else if (id == KJS::HTMLElement::TableDeleteRow) {
2144         table.deleteRow(args[0].toInt32(exec));
2145         return Undefined();
2146       }
2147     }
2148     break;
2149     case ID_THEAD:
2150     case ID_TBODY:
2151     case ID_TFOOT: {
2152       DOM::HTMLTableSectionElement tableSection = element;
2153       if (id == KJS::HTMLElement::TableSectionInsertRow)
2154         return getDOMNode(exec,tableSection.insertRow(args[0].toInt32(exec)));
2155       else if (id == KJS::HTMLElement::TableSectionDeleteRow) {
2156         tableSection.deleteRow(args[0].toInt32(exec));
2157         return Undefined();
2158       }
2159     }
2160     break;
2161     case ID_TR: {
2162       DOM::HTMLTableRowElement tableRow = element;
2163       if (id == KJS::HTMLElement::TableRowInsertCell)
2164         return getDOMNode(exec,tableRow.insertCell(args[0].toInt32(exec)));
2165       else if (id == KJS::HTMLElement::TableRowDeleteCell) {
2166         tableRow.deleteCell(args[0].toInt32(exec));
2167         return Undefined();
2168       }
2169     }
2170     case ID_MARQUEE: {
2171         if (id == KJS::HTMLElement::MarqueeStart && element.handle()->renderer() && 
2172             element.handle()->renderer()->layer() &&
2173             element.handle()->renderer()->layer()->marquee()) {
2174             element.handle()->renderer()->layer()->marquee()->start();
2175             return Undefined();
2176         }
2177         else if (id == KJS::HTMLElement::MarqueeStop && element.handle()->renderer() && 
2178                  element.handle()->renderer()->layer() &&
2179                  element.handle()->renderer()->layer()->marquee()) {
2180             element.handle()->renderer()->layer()->marquee()->stop();
2181             return Undefined();
2182         }
2183         break;
2184     }
2185     case ID_CANVAS: {
2186         if (id == KJS::HTMLElement::GetContext) {
2187             if (args.size() == 0 || (args.size() == 1 && args[0].toString(exec).qstring().lower() == "2d")) {
2188                 return Object(new Context2D(element));
2189             }
2190             return Undefined();
2191         }
2192     }
2193     
2194     break;
2195   }
2196
2197   return Undefined();
2198 }
2199
2200 void KJS::HTMLElement::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
2201 {
2202 #ifdef KJS_VERBOSE
2203   DOM::DOMString str = value.isA(NullType) ? DOM::DOMString() : value.toString(exec).string();
2204 #endif
2205   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
2206 #ifdef KJS_VERBOSE
2207   kdDebug(6070) << "KJS::HTMLElement::tryPut " << propertyName.qstring()
2208                 << " thisTag=" << element.tagName().string()
2209                 << " str=" << str.string() << endl;
2210 #endif
2211   // First look at dynamic properties
2212   switch (element.elementId()) {
2213     case ID_SELECT: {
2214       DOM::HTMLSelectElement select = element;
2215       bool ok;
2216       /*uint u =*/ propertyName.toULong(&ok);
2217       if (ok) {
2218         Object coll = Object::dynamicCast( getSelectHTMLCollection(exec, select.options(), select) );
2219         if ( !coll.isNull() )
2220           coll.put(exec,propertyName,value);
2221         return;
2222       }
2223     }
2224     break;
2225   default:
2226       break;
2227   }
2228
2229   const HashTable* table = classInfo()->propHashTable; // get the right hashtable
2230   const HashEntry* entry = Lookup::findEntry(table, propertyName);
2231   if (entry) {
2232     if (entry->attr & Function) // function: put as override property
2233     {
2234       ObjectImp::put(exec, propertyName, value, attr);
2235       return;
2236     }
2237     else if ((entry->attr & ReadOnly) == 0) // let DOMObjectLookupPut print the warning if not
2238     {
2239       putValue(exec, entry->value, value, attr);
2240       return;
2241     }
2242   }
2243   DOMObjectLookupPut<KJS::HTMLElement, DOMElement>(exec, propertyName, value, attr, &KJS::HTMLElementTable, this);
2244 }
2245
2246 void KJS::HTMLElement::putValue(ExecState *exec, int token, const Value& value, int)
2247 {
2248   DOM::DOMString str = value.isA(NullType) ? DOM::DOMString() : value.toString(exec).string();
2249   DOMNode *kjsNode = new DOMNode(exec, KJS::toNode(value));
2250   // Need to create a Value wrapper to avoid leaking the KJS::DOMNode
2251   Value nodeValue(kjsNode);
2252   DOM::Node n = kjsNode->toNode();
2253   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
2254 #ifdef KJS_VERBOSE
2255   kdDebug(6070) << "KJS::HTMLElement::putValue "
2256                 << " thisTag=" << element.tagName().string()
2257                 << " token=" << token << endl;
2258 #endif
2259
2260   switch (element.elementId()) {
2261   case ID_HTML: {
2262       DOM::HTMLHtmlElement html = element;
2263       switch (token) {
2264       case HtmlVersion:         { html.setVersion(str); return; }
2265       }
2266   }
2267   break;
2268   case ID_HEAD: {
2269     DOM::HTMLHeadElement head = element;
2270     switch (token) {
2271     case HeadProfile:         { head.setProfile(str); return; }
2272     }
2273   }
2274   break;
2275   case ID_LINK: {
2276     DOM::HTMLLinkElement link = element;
2277     switch (token) {
2278       case LinkDisabled:        { link.setDisabled(value.toBoolean(exec)); return; }
2279       case LinkCharset:         { link.setCharset(str); return; }
2280       case LinkHref:            { link.setHref(str); return; }
2281       case LinkHrefLang:        { link.setHreflang(str); return; }
2282       case LinkMedia:           { link.setMedia(str); return; }
2283       case LinkRel:             { link.setRel(str); return; }
2284       case LinkRev:             { link.setRev(str); return; }
2285       case LinkTarget:          { link.setTarget(str); return; }
2286       case LinkType:            { link.setType(str); return; }
2287       }
2288     }
2289     break;
2290     case ID_TITLE: {
2291       DOM::HTMLTitleElement title = element;
2292       switch (token) {
2293       case TitleText:                 { title.setText(str); return; }
2294       }
2295     }
2296     break;
2297     case ID_META: {
2298       DOM::HTMLMetaElement meta = element;
2299       switch (token) {
2300       case MetaContent:         { meta.setContent(str); return; }
2301       case MetaHttpEquiv:       { meta.setHttpEquiv(str); return; }
2302       case MetaName:            { meta.setName(str); return; }
2303       case MetaScheme:          { meta.setScheme(str); return; }
2304       }
2305     }
2306     break;
2307     case ID_BASE: {
2308       DOM::HTMLBaseElement base = element;
2309       switch (token) {
2310       case BaseHref:            { base.setHref(str); return; }
2311       case BaseTarget:          { base.setTarget(str); return; }
2312       }
2313     }
2314     break;
2315     case ID_ISINDEX: {
2316       DOM::HTMLIsIndexElement isindex = element;
2317       switch (token) {
2318       // read-only: form
2319       case IsIndexPrompt:               { isindex.setPrompt(str); return; }
2320       }
2321     }
2322     break;
2323     case ID_STYLE: {
2324       DOM::HTMLStyleElement style = element;
2325       switch (token) {
2326       case StyleDisabled:        { style.setDisabled(value.toBoolean(exec)); return; }
2327       case StyleMedia:           { style.setMedia(str); return; }
2328       case StyleType:            { style.setType(str); return; }
2329       }
2330     }
2331     break;
2332     case ID_BODY: {
2333       DOM::HTMLBodyElement body = element;
2334       switch (token) {
2335       case BodyALink:           { body.setALink(str); return; }
2336       case BodyBackground:      { body.setBackground(str); return; }
2337       case BodyBgColor:         { body.setBgColor(str); return; }
2338       case BodyLink:            { body.setLink(str); return; }
2339       case BodyText:            { body.setText(str); return; }
2340       case BodyVLink:           { body.setVLink(str); return; }
2341       case BodyScrollLeft:
2342       case BodyScrollTop: {
2343           QScrollView* sview = body.ownerDocument().view();
2344           if (sview) {
2345               // Update the document's layout before we compute these attributes.
2346               DOM::DocumentImpl* docimpl = body.handle()->getDocument();
2347               if (docimpl)
2348                   docimpl->updateLayoutIgnorePendingStylesheets();
2349               if (token == BodyScrollLeft)
2350                   sview->setContentsPos(value.toInt32(exec), sview->contentsY());
2351               else
2352                   sview->setContentsPos(sview->contentsX(), value.toInt32(exec));
2353           }
2354           return;
2355         }
2356       }
2357     }
2358     break;
2359     case ID_FORM: {
2360       DOM::HTMLFormElement form = element;
2361       switch (token) {
2362       // read-only: elements
2363       // read-only: length
2364       case FormName:            { form.setName(str); return; }
2365       case FormAcceptCharset:   { form.setAcceptCharset(str); return; }
2366       case FormAction:          { form.setAction(str.string()); return; }
2367       case FormEncType:         { form.setEnctype(str); return; }
2368       case FormMethod:          { form.setMethod(str); return; }
2369       case FormTarget:          { form.setTarget(str); return; }
2370       }
2371     }
2372     break;
2373     case ID_SELECT: {
2374       DOM::HTMLSelectElement select = element;
2375       switch (token) {
2376       // read-only: type
2377       case SelectSelectedIndex:   { select.setSelectedIndex(value.toInt32(exec)); return; }
2378       case SelectValue:           { select.setValue(str); return; }
2379       case SelectLength:          { // read-only according to the NS spec, but webpages need it writeable
2380                                          Object coll = Object::dynamicCast( getSelectHTMLCollection(exec, select.options(), select) );
2381                                          if ( !coll.isNull() )
2382                                            coll.put(exec,lengthPropertyName,value);
2383                                          return;
2384                                        }
2385       // read-only: form
2386       // read-only: options
2387       case SelectDisabled:        { select.setDisabled(value.toBoolean(exec)); return; }
2388       case SelectMultiple:        { select.setMultiple(value.toBoolean(exec)); return; }
2389       case SelectName:            { select.setName(str); return; }
2390       case SelectSize:            { select.setSize(value.toInt32(exec)); return; }
2391       case SelectTabIndex:        { select.setTabIndex(value.toInt32(exec)); return; }
2392       }
2393     }
2394     break;
2395     case ID_OPTGROUP: {
2396       DOM::HTMLOptGroupElement optgroup = element;
2397       switch (token) {
2398       case OptGroupDisabled:        { optgroup.setDisabled(value.toBoolean(exec)); return; }
2399       case OptGroupLabel:           { optgroup.setLabel(str); return; }
2400       }
2401     }
2402     break;
2403     case ID_OPTION: {
2404       DOM::HTMLOptionElement option = element;
2405       switch (token) {
2406       // read-only: form
2407       case OptionDefaultSelected: { option.setDefaultSelected(value.toBoolean(exec)); return; }
2408       // read-only: text  <--- According to the DOM, but JavaScript and JScript both allow changes.
2409       // So, we'll do it here and not add it to our DOM headers.
2410       case OptionText:            { DOM::NodeList nl(option.childNodes());
2411                                     for (unsigned int i = 0; i < nl.length(); i++) {
2412                                         if (nl.item(i).nodeType() == DOM::Node::TEXT_NODE) {
2413                                             static_cast<DOM::Text>(nl.item(i)).setData(str);
2414                                             return;
2415                                         }
2416                                   }
2417                                   // No child text node found, creating one
2418                                   DOM::Text t = option.ownerDocument().createTextNode(str);
2419                                   try { option.appendChild(t); }
2420                                   catch(DOM::DOMException& e) {
2421                                     // #### exec->setException ?
2422                                   }
2423
2424                                   return;
2425       }
2426       // read-only: index
2427       case OptionDisabled:        { option.setDisabled(value.toBoolean(exec)); return; }
2428       case OptionLabel:           { option.setLabel(str); return; }
2429       case OptionSelected:        { option.setSelected(value.toBoolean(exec)); return; }
2430       case OptionValue:           { option.setValue(str); return; }
2431       }
2432     }
2433     break;
2434     case ID_INPUT: {
2435       DOM::HTMLInputElement input = element;
2436       switch (token) {
2437       case InputDefaultValue:    { input.setDefaultValue(str); return; }
2438       case InputDefaultChecked:  { input.setDefaultChecked(value.toBoolean(exec)); return; }
2439       // read-only: form
2440       case InputAccept:          { input.setAccept(str); return; }
2441       case InputAccessKey:       { input.setAccessKey(str); return; }
2442       case InputAlign:           { input.setAlign(str); return; }
2443       case InputAlt:             { input.setAlt(str); return; }
2444       case InputChecked:         { input.setChecked(value.toBoolean(exec)); return; }
2445       case InputDisabled:        { input.setDisabled(value.toBoolean(exec)); return; }
2446       case InputMaxLength:       { input.setMaxLength(value.toInt32(exec)); return; }
2447       case InputName:            { input.setName(str); return; }
2448       case InputReadOnly:        { input.setReadOnly(value.toBoolean(exec)); return; }
2449       case InputSize:            { input.setSize(str); return; }
2450       case InputSrc:             { input.setSrc(str); return; }
2451       case InputTabIndex:        { input.setTabIndex(value.toInt32(exec)); return; }
2452       case InputType:            { input.setType(str); return; }
2453       case InputUseMap:          { input.setUseMap(str); return; }
2454       case InputValue:           { input.setValue(str); return; }
2455       }
2456     }
2457     break;
2458     case ID_TEXTAREA: {
2459       DOM::HTMLTextAreaElement textarea = element;
2460       switch (token) {
2461       case TextAreaDefaultValue:    { textarea.setDefaultValue(str); return; }
2462       // read-only: form
2463       case TextAreaAccessKey:       { textarea.setAccessKey(str); return; }
2464       case TextAreaCols:            { textarea.setCols(value.toInt32(exec)); return; }
2465       case TextAreaDisabled:        { textarea.setDisabled(value.toBoolean(exec)); return; }
2466       case TextAreaName:            { textarea.setName(str); return; }
2467       case TextAreaReadOnly:        { textarea.setReadOnly(value.toBoolean(exec)); return; }
2468       case TextAreaRows:            { textarea.setRows(value.toInt32(exec)); return; }
2469       case TextAreaTabIndex:        { textarea.setTabIndex(value.toInt32(exec)); return; }
2470       // read-only: type
2471       case TextAreaValue:           { textarea.setValue(str); return; }
2472       }
2473     }
2474     break;
2475     case ID_BUTTON: {
2476       DOM::HTMLButtonElement button = element;
2477       switch (token) {
2478       // read-only: form
2479       case ButtonAccessKey:       { button.setAccessKey(str); return; }
2480       case ButtonDisabled:        { button.setDisabled(value.toBoolean(exec)); return; }
2481       case ButtonName:            { button.setName(str); return; }
2482       case ButtonTabIndex:        { button.setTabIndex(value.toInt32(exec)); return; }
2483       // read-only: type
2484       case ButtonValue:           { button.setValue(str); return; }
2485       }
2486     }
2487     break;
2488     case ID_LABEL: {
2489       DOM::HTMLLabelElement label = element;
2490       switch (token) {
2491       // read-only: form
2492       case LabelAccessKey:       { label.setAccessKey(str); return; }
2493       case LabelHtmlFor:         { label.setHtmlFor(str); return; }
2494       }
2495     }
2496     break;
2497 //    case ID_FIELDSET: {
2498 //      DOM::HTMLFieldSetElement fieldSet = element;
2499 //      // read-only: form
2500 //    }
2501 //    break;
2502     case ID_LEGEND: {
2503       DOM::HTMLLegendElement legend = element;
2504       switch (token) {
2505       // read-only: form
2506       case LegendAccessKey:       { legend.setAccessKey(str); return; }
2507       case LegendAlign:           { legend.setAlign(str); return; }
2508       }
2509     }
2510     break;
2511     case ID_UL: {
2512       DOM::HTMLUListElement uList = element;
2513       switch (token) {
2514       case UListCompact:         { uList.setCompact(value.toBoolean(exec)); return; }
2515       case UListType:            { uList.setType(str); return; }
2516       }
2517     }
2518     break;
2519     case ID_OL: {
2520       DOM::HTMLOListElement oList = element;
2521       switch (token) {
2522       case OListCompact:         { oList.setCompact(value.toBoolean(exec)); return; }
2523       case OListStart:           { oList.setStart(value.toInt32(exec)); return; }
2524       case OListType:            { oList.setType(str); return; }
2525       }
2526     }
2527     break;
2528     case ID_DL: {
2529       DOM::HTMLDListElement dList = element;
2530       switch (token) {
2531       case DListCompact:         { dList.setCompact(value.toBoolean(exec)); return; }
2532       }
2533     }
2534     break;
2535     case ID_DIR: {
2536       DOM::HTMLDirectoryElement directory = element;
2537       switch (token) {
2538       case DirectoryCompact:     { directory.setCompact(value.toBoolean(exec)); return; }
2539       }
2540     }
2541     break;
2542     case ID_MENU: {
2543       DOM::HTMLMenuElement menu = element;
2544       switch (token) {
2545       case MenuCompact:         { menu.setCompact(value.toBoolean(exec)); return; }
2546       }
2547     }
2548     break;
2549     case ID_LI: {
2550       DOM::HTMLLIElement li = element;
2551       switch (token) {
2552       case LIType:            { li.setType(str); return; }
2553       case LIValue:           { li.setValue(value.toInt32(exec)); return; }
2554       }
2555     }
2556     break;
2557     case ID_DIV: {
2558       DOM::HTMLDivElement div = element;
2559       switch (token) {
2560       case DivAlign:           { div.setAlign(str); return; }
2561       }
2562     }
2563     break;
2564     case ID_P: {
2565       DOM::HTMLParagraphElement paragraph = element;
2566       switch (token) {
2567       case ParagraphAlign:     { paragraph.setAlign(str); return; }
2568       }
2569     }
2570     break;
2571     case ID_H1:
2572     case ID_H2:
2573     case ID_H3:
2574     case ID_H4:
2575     case ID_H5:
2576     case ID_H6: {
2577       DOM::HTMLHeadingElement heading = element;
2578       switch (token) {
2579       case HeadingAlign:         { heading.setAlign(str); return; }
2580       }
2581     }
2582     break;
2583     case ID_BLOCKQUOTE: {
2584       DOM::HTMLBlockquoteElement blockquote = element;
2585       switch (token) {
2586       case BlockQuoteCite:       { blockquote.setCite(str); return; }
2587       }
2588     }
2589     break;
2590     case ID_Q: {
2591       DOM::HTMLQuoteElement quote = element;
2592       switch (token) {
2593       case QuoteCite:            { quote.setCite(str); return; }
2594       }
2595     }
2596     break;
2597     case ID_PRE: {
2598       DOM::HTMLPreElement pre = element;
2599       switch (token) {
2600       case PreWidth:           { pre.setWidth(value.toInt32(exec)); return; }
2601       }
2602     }
2603     break;
2604     case ID_BR: {
2605       DOM::HTMLBRElement br = element;
2606       switch (token) {
2607       case BRClear:           { br.setClear(str); return; }
2608       }
2609     }
2610     break;
2611     case ID_BASEFONT: {
2612       DOM::HTMLBaseFontElement baseFont = element;
2613       switch (token) {
2614       case BaseFontColor:           { baseFont.setColor(str); return; }
2615       case BaseFontFace:            { baseFont.setFace(str); return; }
2616       case BaseFontSize:            { baseFont.setSize(str); return; }
2617       }
2618     }
2619     break;
2620     case ID_FONT: {
2621       DOM::HTMLFontElement font = element;
2622       switch (token) {
2623       case FontColor:           { font.setColor(str); return; }
2624       case FontFace:            { font.setFace(str); return; }
2625       case FontSize:            { font.setSize(str); return; }
2626       }
2627     }
2628     break;
2629     case ID_HR: {
2630       DOM::HTMLHRElement hr = element;
2631       switch (token) {
2632       case HRAlign:           { hr.setAlign(str); return; }
2633       case HRNoShade:         { hr.setNoShade(value.toBoolean(exec)); return; }
2634       case HRSize:            { hr.setSize(str); return; }
2635       case HRWidth:           { hr.setWidth(str); return; }
2636       }
2637     }
2638     break;
2639     case ID_INS:
2640     case ID_DEL: {
2641       DOM::HTMLModElement mod = element;
2642       switch (token) {
2643       case ModCite:            { mod.setCite(str); return; }
2644       case ModDateTime:        { mod.setDateTime(str); return; }
2645       }
2646     }
2647     break;
2648     case ID_A: {
2649       DOM::HTMLAnchorElement anchor = element;
2650       switch (token) {
2651       case AnchorAccessKey:       { anchor.setAccessKey(str); return; }
2652       case AnchorCharset:         { anchor.setCharset(str); return; }
2653       case AnchorCoords:          { anchor.setCoords(str); return; }
2654       case AnchorHref:            { anchor.setHref(str); return; }
2655       case AnchorHrefLang:        { anchor.setHreflang(str); return; }
2656       case AnchorName:            { anchor.setName(str); return; }
2657       case AnchorRel:             { anchor.setRel(str); return; }
2658       case AnchorRev:             { anchor.setRev(str); return; }
2659       case AnchorShape:           { anchor.setShape(str); return; }
2660       case AnchorTabIndex:        { anchor.setTabIndex(value.toInt32(exec)); return; }
2661       case AnchorTarget:          { anchor.setTarget(str); return; }
2662       case AnchorType:            { anchor.setType(str); return; }
2663       }
2664     }
2665     break;
2666     case ID_IMG: {
2667       DOM::HTMLImageElement image = element;
2668       switch (token) {
2669       case ImageName:            { image.setName(str); return; }
2670       case ImageAlign:           { image.setAlign(str); return; }
2671       case ImageAlt:             { image.setAlt(str); return; }
2672       case ImageBorder:          { image.setBorder(value.toInt32(exec)); return; }
2673       case ImageHeight:          { image.setHeight(value.toInt32(exec)); return; }
2674       case ImageHspace:          { image.setHspace(value.toInt32(exec)); return; }
2675       case ImageIsMap:           { image.setIsMap(value.toBoolean(exec)); return; }
2676       case ImageLongDesc:        { image.setLongDesc(str); return; }
2677       case ImageSrc:             { image.setSrc(str); return; }
2678       case ImageUseMap:          { image.setUseMap(str); return; }
2679       case ImageVspace:          { image.setVspace(value.toInt32(exec)); return; }
2680       case ImageWidth:           { image.setWidth(value.toInt32(exec)); return; }
2681       }
2682     }
2683     break;
2684     case ID_OBJECT: {
2685       DOM::HTMLObjectElement object = element;
2686       switch (token) {
2687       // read-only: form
2688       case ObjectCode:                 { object.setCode(str); return; }
2689       case ObjectAlign:           { object.setAlign(str); return; }
2690       case ObjectArchive:         { object.setArchive(str); return; }
2691       case ObjectBorder:          { object.setBorder(str); return; }
2692       case ObjectCodeBase:        { object.setCodeBase(str); return; }
2693       case ObjectCodeType:        { object.setCodeType(str); return; }
2694       // read-only: ObjectContentDocument
2695       case ObjectData:            { object.setData(str); return; }
2696       case ObjectDeclare:         { object.setDeclare(value.toBoolean(exec)); return; }
2697       case ObjectHeight:          { object.setHeight(str); return; }
2698       case ObjectHspace:          { object.setHspace(str); return; }
2699       case ObjectName:            { object.setName(str); return; }
2700       case ObjectStandby:         { object.setStandby(str); return; }
2701       case ObjectTabIndex:        { object.setTabIndex(value.toInt32(exec)); return; }
2702       case ObjectType:            { object.setType(str); return; }
2703       case ObjectUseMap:          { object.setUseMap(str); return; }
2704       case ObjectVspace:          { object.setVspace(str); return; }
2705       case ObjectWidth:           { object.setWidth(str); return; }
2706       }
2707     }
2708     break;
2709     case ID_PARAM: {
2710       DOM::HTMLParamElement param = element;
2711       switch (token) {
2712       case ParamName:            { param.setName(str); return; }
2713       case ParamType:            { param.setType(str); return; }
2714       case ParamValue:           { param.setValue(str); return; }
2715       case ParamValueType:       { param.setValueType(str); return; }
2716       }
2717     }
2718     break;
2719     case ID_APPLET: {
2720       DOM::HTMLAppletElement applet = element;
2721       switch (token) {
2722       case AppletAlign:           { applet.setAlign(str); return; }
2723       case AppletAlt:             { applet.setAlt(str); return; }
2724       case AppletArchive:         { applet.setArchive(str); return; }
2725       case AppletCode:            { applet.setCode(str); return; }
2726       case AppletCodeBase:        { applet.setCodeBase(str); return; }
2727       case AppletHeight:          { applet.setHeight(str); return; }
2728       case AppletHspace:          { applet.setHspace(str); return; }
2729       case AppletName:            { applet.setName(str); return; }
2730       case AppletObject:          { applet.setObject(str); return; }
2731       case AppletVspace:          { applet.setVspace(str); return; }
2732       case AppletWidth:           { applet.setWidth(str); return; }
2733       }
2734     }
2735     break;
2736     case ID_MAP: {
2737       DOM::HTMLMapElement map = element;
2738       switch (token) {
2739       // read-only: areas
2740       case MapName:                 { map.setName(str); return; }
2741      }
2742     }
2743     break;
2744     case ID_AREA: {
2745       DOM::HTMLAreaElement area = element;
2746       switch (token) {
2747       case AreaAccessKey:       { area.setAccessKey(str); return; }
2748       case AreaAlt:             { area.setAlt(str); return; }
2749       case AreaCoords:          { area.setCoords(str); return; }
2750       case AreaHref:            { area.setHref(str); return; }
2751       case AreaNoHref:          { area.setNoHref(value.toBoolean(exec)); return; }
2752       case AreaShape:           { area.setShape(str); return; }
2753       case AreaTabIndex:        { area.setTabIndex(value.toInt32(exec)); return; }
2754       case AreaTarget:          { area.setTarget(str); return; }
2755       }
2756     }
2757     break;
2758     case ID_SCRIPT: {
2759       DOM::HTMLScriptElement script = element;
2760       switch (token) {
2761       case ScriptText:            { script.setText(str); return; }
2762       case ScriptHtmlFor:         { script.setHtmlFor(str); return; }
2763       case ScriptEvent:           { script.setEvent(str); return; }
2764       case ScriptCharset:         { script.setCharset(str); return; }
2765       case ScriptDefer:           { script.setDefer(value.toBoolean(exec)); return; }
2766       case ScriptSrc:             { script.setSrc(str); return; }
2767       case ScriptType:            { script.setType(str); return; }
2768       }
2769     }
2770     break;
2771     case ID_TABLE: {
2772       DOM::HTMLTableElement table = element;
2773       switch (token) {
2774       case TableCaption:         { table.setCaption(n); return; } // type HTMLTableCaptionElement
2775       case TableTHead:           { table.setTHead(n); return; } // type HTMLTableSectionElement
2776       case TableTFoot:           { table.setTFoot(n); return; } // type HTMLTableSectionElement
2777       // read-only: rows
2778       // read-only: tbodies
2779       case TableAlign:           { table.setAlign(str); return; }
2780       case TableBgColor:         { table.setBgColor(str); return; }
2781       case TableBorder:          { table.setBorder(str); return; }
2782       case TableCellPadding:     { table.setCellPadding(str); return; }
2783       case TableCellSpacing:     { table.setCellSpacing(str); return; }
2784       case TableFrame:           { table.setFrame(str); return; }
2785       case TableRules:           { table.setRules(str); return; }
2786       case TableSummary:         { table.setSummary(str); return; }
2787       case TableWidth:           { table.setWidth(str); return; }
2788       }
2789     }
2790     break;
2791     case ID_CAPTION: {
2792       DOM::HTMLTableCaptionElement tableCaption;
2793       switch (token) {
2794       case TableAlign:           { tableCaption.setAlign(str); return; }
2795       }
2796     }
2797     break;
2798     case ID_COL: {
2799       DOM::HTMLTableColElement tableCol = element;
2800       switch (token) {
2801       case TableColAlign:           { tableCol.setAlign(str); return; }
2802       case TableColCh:              { tableCol.setCh(str); return; }
2803       case TableColChOff:           { tableCol.setChOff(str); return; }
2804       case TableColSpan:            { tableCol.setSpan(value.toInt32(exec)); return; }
2805       case TableColVAlign:          { tableCol.setVAlign(str); return; }
2806       case TableColWidth:           { tableCol.setWidth(str); return; }
2807       }
2808     }
2809     break;
2810     case ID_THEAD:
2811     case ID_TBODY:
2812     case ID_TFOOT: {
2813       DOM::HTMLTableSectionElement tableSection = element;
2814       switch (token) {
2815       case TableSectionAlign:           { tableSection.setAlign(str); return; }
2816       case TableSectionCh:              { tableSection.setCh(str); return; }
2817       case TableSectionChOff:           { tableSection.setChOff(str); return; }
2818       case TableSectionVAlign:          { tableSection.setVAlign(str); return; }
2819       // read-only: rows
2820       }
2821     }
2822     break;
2823     case ID_TR: {
2824       DOM::HTMLTableRowElement tableRow = element;
2825       switch (token) {
2826       // read-only: rowIndex
2827       // read-only: sectionRowIndex
2828       // read-only: cells
2829       case TableRowAlign:           { tableRow.setAlign(str); return; }
2830       case TableRowBgColor:         { tableRow.setBgColor(str); return; }
2831       case TableRowCh:              { tableRow.setCh(str); return; }
2832       case TableRowChOff:           { tableRow.setChOff(str); return; }
2833       case TableRowVAlign:          { tableRow.setVAlign(str); return; }
2834       }
2835     }
2836     break;
2837     case ID_TH:
2838     case ID_TD: {
2839       DOM::HTMLTableCellElement tableCell = element;
2840       switch (token) {
2841       // read-only: cellIndex
2842       case TableCellAbbr:            { tableCell.setAbbr(str); return; }
2843       case TableCellAlign:           { tableCell.setAlign(str); return; }
2844       case TableCellAxis:            { tableCell.setAxis(str); return; }
2845       case TableCellBgColor:         { tableCell.setBgColor(str); return; }
2846       case TableCellCh:              { tableCell.setCh(str); return; }
2847       case TableCellChOff:           { tableCell.setChOff(str); return; }
2848       case TableCellColSpan:         { tableCell.setColSpan(value.toInt32(exec)); return; }
2849       case TableCellHeaders:         { tableCell.setHeaders(str); return; }
2850       case TableCellHeight:          { tableCell.setHeight(str); return; }
2851       case TableCellNoWrap:          { tableCell.setNoWrap(value.toBoolean(exec)); return; }
2852       case TableCellRowSpan:         { tableCell.setRowSpan(value.toInt32(exec)); return; }
2853       case TableCellScope:           { tableCell.setScope(str); return; }
2854       case TableCellVAlign:          { tableCell.setVAlign(str); return; }
2855       case TableCellWidth:           { tableCell.setWidth(str); return; }
2856       }
2857     }
2858     break;
2859     case ID_FRAMESET: {
2860       DOM::HTMLFrameSetElement frameSet = element;
2861       switch (token) {
2862       case FrameSetCols:            { frameSet.setCols(str); return; }
2863       case FrameSetRows:            { frameSet.setRows(str); return; }
2864       }
2865     }
2866     break;
2867     case ID_FRAME: {
2868       DOM::HTMLFrameElement frameElement = element;
2869       switch (token) {
2870        // read-only: FrameContentDocument:
2871       case FrameFrameBorder:     { frameElement.setFrameBorder(str); return; }
2872       case FrameLongDesc:        { frameElement.setLongDesc(str); return; }
2873       case FrameMarginHeight:    { frameElement.setMarginHeight(str); return; }
2874       case FrameMarginWidth:     { frameElement.setMarginWidth(str); return; }
2875       case FrameName:            { frameElement.setName(str); return; }
2876       case FrameNoResize:        { frameElement.setNoResize(value.toBoolean(exec)); return; }
2877       case FrameScrolling:       { frameElement.setScrolling(str); return; }
2878       case FrameSrc:             { frameElement.setSrc(str); return; }
2879       case FrameLocation:        {
2880                                    static_cast<DOM::HTMLFrameElementImpl *>(frameElement.handle())->setLocation(str);
2881                                    return;
2882                                  }
2883       }
2884     }
2885     break;
2886     case ID_IFRAME: {
2887       DOM::HTMLIFrameElement iFrame = element;
2888       switch (token) {
2889       case IFrameAlign:           { iFrame.setAlign(str); return; }
2890       // read-only: IFrameContentDocument
2891       case IFrameFrameBorder:     { iFrame.setFrameBorder(str); return; }
2892       case IFrameHeight:          { iFrame.setHeight(str); return; }
2893       case IFrameLongDesc:        { iFrame.setLongDesc(str); return; }
2894       case IFrameMarginHeight:    { iFrame.setMarginHeight(str); return; }
2895       case IFrameMarginWidth:     { iFrame.setMarginWidth(str); return; }
2896       case IFrameName:            { iFrame.setName(str); return; }
2897       case IFrameScrolling:       { iFrame.setScrolling(str); return; }
2898       case IFrameSrc:             { iFrame.setSrc(str); return; }
2899       case IFrameWidth:           { iFrame.setWidth(str); return; }
2900       }
2901       break;
2902     }
2903   }
2904
2905   // generic properties
2906   switch (token) {
2907   case ElementId:
2908     element.setId(str);
2909     return;
2910   case ElementTitle:
2911     element.setTitle(str);
2912     return;
2913   case ElementLang:
2914     element.setLang(str);
2915     return;
2916   case ElementDir:
2917     element.setDir(str);
2918     return;
2919   case ElementClassName:
2920     element.setClassName(str);
2921     return;
2922   case ElementInnerHTML:
2923     element.setInnerHTML(str);
2924     return;
2925   case ElementInnerText:
2926     element.setInnerText(str);
2927     return;
2928   case ElementOuterHTML:
2929     element.setOuterHTML(str);
2930     return;
2931   case ElementOuterText:
2932     element.setOuterText(str);
2933     return;
2934   case ElementContentEditable:
2935     element.setContentEditable(str);
2936     return;
2937   default:
2938     kdWarning() << "KJS::HTMLElement::putValue unhandled token " << token << " thisTag=" << element.tagName().string() << " str=" << str.string() << endl;
2939   }
2940 }
2941
2942 // -------------------------------------------------------------------------
2943 /* Source for HTMLCollectionProtoTable. Use "make hashtables" to regenerate.
2944 @begin HTMLCollectionProtoTable 3
2945   item          HTMLCollection::Item            DontDelete|Function 1
2946   namedItem     HTMLCollection::NamedItem       DontDelete|Function 1
2947   tags          HTMLCollection::Tags            DontDelete|Function 1
2948 @end
2949 */
2950 DEFINE_PROTOTYPE("HTMLCollection", HTMLCollectionProto)
2951 IMPLEMENT_PROTOFUNC(HTMLCollectionProtoFunc)
2952 IMPLEMENT_PROTOTYPE(HTMLCollectionProto,HTMLCollectionProtoFunc)
2953
2954 const ClassInfo HTMLCollection::info = { "HTMLCollection", 0, 0, 0 };
2955
2956 HTMLCollection::HTMLCollection(ExecState *exec, const DOM::HTMLCollection &c)
2957   : DOMObject(HTMLCollectionProto::self(exec)), collection(c) {}
2958
2959 HTMLCollection::~HTMLCollection()
2960 {
2961   ScriptInterpreter::forgetDOMObject(collection.handle());
2962 }
2963
2964 // We have to implement hasProperty since we don't use a hashtable for 'selectedIndex' and 'length'
2965 // ## this breaks "for (..in..)" though.
2966 bool KJS::HTMLCollection::hasProperty(ExecState *exec, const Identifier &p) const
2967 {
2968   if (p == "selectedIndex" || p == lengthPropertyName)
2969     return true;
2970   return DOMObject::hasProperty(exec, p);
2971 }
2972
2973 Value KJS::HTMLCollection::tryGet(ExecState *exec, const Identifier &propertyName) const
2974 {
2975 #ifdef KJS_VERBOSE
2976   kdDebug() << "KJS::HTMLCollection::tryGet " << propertyName.ascii() << endl;
2977 #endif
2978   if (propertyName == lengthPropertyName)
2979     return Number(collection.length());
2980   else if (propertyName == "selectedIndex" &&
2981            collection.item(0).elementId() == ID_OPTION) {
2982     // NON-STANDARD options.selectedIndex
2983     DOM::Node node = collection.item(0).parentNode();
2984     while(!node.isNull()) {
2985       if(node.elementId() == ID_SELECT) {
2986         DOM::HTMLSelectElement sel = static_cast<DOM::HTMLSelectElement>(node);
2987         return Number(sel.selectedIndex());
2988       }
2989       node = node.parentNode();
2990     }
2991     return Undefined();
2992   } else {
2993     // Look in the prototype (for functions) before assuming it's an item's name
2994     Object proto = Object::dynamicCast(prototype());
2995     if (!proto.isNull() && proto.hasProperty(exec,propertyName))
2996       return proto.get(exec,propertyName);
2997
2998     // name or index ?
2999     bool ok;
3000     unsigned int u = propertyName.toULong(&ok);
3001     if (ok) {
3002       DOM::Node node = collection.item(u);
3003
3004 #if APPLE_CHANGES
3005         if (!node.isNull() && (node.handle()->id() == ID_APPLET || node.handle()->id() == ID_EMBED)) {
3006             return getRuntimeObject(exec,node);
3007         }
3008 #endif
3009       return getDOMNode(exec,node);
3010     }
3011     else
3012       return getNamedItems(exec,propertyName);
3013   }
3014 }
3015
3016 // HTMLCollections are strange objects, they support both get and call,
3017 // so that document.forms.item(0) and document.forms(0) both work.
3018 Value KJS::HTMLCollection::call(ExecState *exec, Object &thisObj, const List &args)
3019 {
3020   // This code duplication is necessary, HTMLCollection isn't a DOMFunction
3021   Value val;
3022   try {
3023     val = tryCall(exec, thisObj, args);
3024   }
3025   // pity there's no way to distinguish between these in JS code
3026   catch (...) {
3027     Object err = Error::create(exec, GeneralError, "Exception from HTMLCollection");
3028     exec->setException(err);
3029   }
3030   return val;
3031 }
3032
3033 Value KJS::HTMLCollection::tryCall(ExecState *exec, Object &, const List &args)
3034 {
3035   // Do not use thisObj here. It can be the HTMLDocument, in the document.forms(i) case.
3036   /*if( thisObj.imp() != this )
3037   {
3038     kdWarning() << "thisObj.imp() != this in HTMLCollection::tryCall" << endl;
3039     KJS::printInfo(exec,"KJS::HTMLCollection::tryCall thisObj",thisObj,-1);
3040     KJS::printInfo(exec,"KJS::HTMLCollection::tryCall this",Value(this),-1);
3041   }*/
3042   // Also, do we need the TypeError test here ?
3043
3044   if (args.size() == 1) {
3045     // support for document.all(<index>) etc.
3046     bool ok;
3047     UString s = args[0].toString(exec);
3048     unsigned int u = s.toULong(&ok);
3049     if (ok) {
3050       DOM::Element element = collection.item(u);
3051       return getDOMNode(exec,element);
3052     }
3053     // support for document.images('<name>') etc.
3054     return getNamedItems(exec, Identifier(s));
3055   }
3056   else if (args.size() >= 1) // the second arg, if set, is the index of the item we want
3057   {
3058     bool ok;
3059     UString s = args[0].toString(exec);
3060     unsigned int u = args[1].toString(exec).toULong(&ok);
3061     if (ok)
3062     {
3063       DOM::DOMString pstr = s.string();
3064       DOM::Node node = collection.namedItem(pstr);
3065       while (!node.isNull()) {
3066         if (!u)
3067           return getDOMNode(exec,node);
3068         node = collection.nextNamedItem(pstr);
3069         --u;
3070       }
3071     }
3072   }
3073   return Undefined();
3074 }
3075
3076 Value KJS::HTMLCollection::getNamedItems(ExecState *exec, const Identifier &propertyName) const
3077 {
3078 #ifdef KJS_VERBOSE
3079   kdDebug(6070) << "KJS::HTMLCollection::getNamedItems " << propertyName.ascii() << endl;
3080 #endif
3081   DOM::DOMString pstr = propertyName.string();
3082
3083   QValueList<DOM::Node> namedItems = collection.namedItems(pstr);
3084
3085   if (namedItems.isEmpty()) {
3086 #ifdef KJS_VERBOSE
3087     kdDebug(6070) << "not found" << endl;
3088 #endif
3089     return Undefined();
3090   }
3091
3092   if (namedItems.count() == 1) {
3093     DOM::Node node = namedItems[0];
3094 #if APPLE_CHANGES
3095     if (!node.isNull() && (node.handle()->id() == ID_APPLET || node.handle()->id() == ID_EMBED)) {
3096       return getRuntimeObject(exec, node);
3097     }
3098 #endif
3099
3100     return getDOMNode(exec,node);
3101   }
3102   
3103   return Value(new DOMNamedNodesCollection(exec,namedItems));
3104 }
3105
3106 Value KJS::HTMLCollectionProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
3107 {
3108   if (!thisObj.inherits(&KJS::HTMLCollection::info)) {
3109     Object err = Error::create(exec,TypeError);
3110     exec->setException(err);
3111     return err;
3112   }
3113   DOM::HTMLCollection coll = static_cast<KJS::HTMLCollection *>(thisObj.imp())->toCollection();
3114
3115   switch (id) {
3116   case KJS::HTMLCollection::Item:
3117     return getDOMNode(exec,coll.item(args[0].toUInt32(exec)));
3118   case KJS::HTMLCollection::Tags:
3119   {
3120     DOM::DOMString tagName = args[0].toString(exec).string();
3121     DOM::NodeList list;
3122     // getElementsByTagName exists in Document and in Element, pick up the right one
3123     if ( coll.base().nodeType() == DOM::Node::DOCUMENT_NODE )
3124     {
3125       DOM::Document doc = coll.base();
3126       list = doc.getElementsByTagName(tagName);
3127 #ifdef KJS_VERBOSE
3128       kdDebug() << "KJS::HTMLCollectionProtoFunc::tryCall document.tags(" << tagName.string() << ") -> " << list.length() << " items in node list" << endl;
3129 #endif
3130     } else
3131     {
3132       DOM::Element e = coll.base();
3133       list = e.getElementsByTagName(tagName);
3134 #ifdef KJS_VERBOSE
3135       kdDebug() << "KJS::HTMLCollectionProtoFunc::tryCall element.tags(" << tagName.string() << ") -> " << list.length() << " items in node list" << endl;
3136 #endif
3137     }
3138     return getDOMNodeList(exec, list);
3139   }
3140   case KJS::HTMLCollection::NamedItem:
3141     return static_cast<HTMLCollection *>(thisObj.imp())->getNamedItems(exec, Identifier(args[0].toString(exec)));
3142   default:
3143     return Undefined();
3144   }
3145 }
3146
3147 Value KJS::HTMLSelectCollection::tryGet(ExecState *exec, const Identifier &p) const
3148 {
3149   if (p == "selectedIndex")
3150     return Number(element.selectedIndex());
3151
3152   return  HTMLCollection::tryGet(exec, p);
3153 }
3154
3155 void KJS::HTMLSelectCollection::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int)
3156 {
3157 #ifdef KJS_VERBOSE
3158   kdDebug(6070) << "KJS::HTMLSelectCollection::tryPut " << propertyName.qstring() << endl;
3159 #endif
3160   if ( propertyName == "selectedIndex" ) {
3161     element.setSelectedIndex( value.toInt32( exec ) );
3162     return;
3163   }
3164   // resize ?
3165   else if (propertyName == lengthPropertyName) {
3166     unsigned newLen;
3167     bool converted = value.toUInt32(newLen);
3168
3169     if (!converted) {
3170       return;
3171     }
3172
3173     long diff = element.length() - newLen;
3174
3175     if (diff < 0) { // add dummy elements
3176       do {
3177         element.add(element.ownerDocument().createElement("OPTION"), DOM::HTMLElement());
3178       } while (++diff);
3179     }
3180     else // remove elements
3181       while (diff-- > 0)
3182         element.remove(newLen);
3183
3184     return;
3185   }
3186   // an index ?
3187   bool ok;
3188   unsigned int u = propertyName.toULong(&ok);
3189   if (!ok)
3190     return;
3191
3192   if (value.isA(NullType) || value.isA(UndefinedType)) {
3193     // null and undefined delete. others, too ?
3194     element.remove(u);
3195     return;
3196   }
3197
3198   // is v an option element ?
3199   DOM::Node node = KJS::toNode(value);
3200   if (node.isNull() || node.elementId() != ID_OPTION)
3201     return;
3202
3203   DOM::HTMLOptionElement option = static_cast<DOM::HTMLOptionElement>(node);
3204   long diff = long(u) - element.length();
3205   DOM::HTMLElement before;
3206   // out of array bounds ? first insert empty dummies
3207   if (diff > 0) {
3208     while (diff--) {
3209       element.add(element.ownerDocument().createElement("OPTION"), before);
3210     }
3211     // replace an existing entry ?
3212   } else if (diff < 0) {
3213     before = element.options().item(u+1);
3214     element.remove(u);
3215   }
3216   // finally add the new element
3217   element.add(option, before);
3218 }
3219
3220 ////////////////////// Option Object ////////////////////////
3221
3222 OptionConstructorImp::OptionConstructorImp(ExecState *exec, const DOM::Document &d)
3223     : ObjectImp(), doc(d)
3224 {
3225   // ## isn't there some redundancy between ObjectImp::_proto and the "prototype" property ?
3226   //put(exec,"prototype", ...,DontEnum|DontDelete|ReadOnly);
3227
3228   // no. of arguments for constructor
3229   // ## is 4 correct ? 0 to 4, it seems to be
3230   put(exec,lengthPropertyName, Number(4), ReadOnly|DontDelete|DontEnum);
3231 }
3232
3233 bool OptionConstructorImp::implementsConstruct() const
3234 {
3235   return true;
3236 }
3237
3238 Object OptionConstructorImp::construct(ExecState *exec, const List &args)
3239 {
3240   DOM::Element el = doc.createElement("OPTION");
3241   DOM::HTMLOptionElement opt = static_cast<DOM::HTMLOptionElement>(el);
3242   int sz = args.size();
3243   DOM::Text t = doc.createTextNode("");
3244   try { opt.appendChild(t); }
3245   catch(DOM::DOMException& e) {
3246     // #### exec->setException ?
3247   }
3248   if (sz > 0)
3249     t.setData(args[0].toString(exec).string()); // set the text
3250   if (sz > 1)
3251     opt.setValue(args[1].toString(exec).string());
3252   if (sz > 2)
3253     opt.setDefaultSelected(args[2].toBoolean(exec));
3254   if (sz > 3)
3255     opt.setSelected(args[3].toBoolean(exec));
3256
3257   return Object::dynamicCast(getDOMNode(exec,opt));
3258 }
3259
3260 ////////////////////// Image Object ////////////////////////
3261
3262 ImageConstructorImp::ImageConstructorImp(ExecState *, const DOM::Document &d)
3263     : ObjectImp(), doc(d)
3264 {
3265 }
3266
3267 bool ImageConstructorImp::implementsConstruct() const
3268 {
3269   return true;
3270 }
3271
3272 Object ImageConstructorImp::construct(ExecState *, const List &)
3273 {
3274   /* TODO: fetch optional height & width from arguments */
3275
3276   Object result(new Image(doc));
3277   /* TODO: do we need a prototype ? */
3278
3279   return result;
3280 }
3281
3282 const ClassInfo KJS::Image::info = { "Image", 0, &ImageTable, 0 };
3283
3284 /* Source for ImageTable. Use "make hashtables" to regenerate.
3285 @begin ImageTable 6
3286   src           Image::Src              DontDelete
3287   complete      Image::Complete         DontDelete|ReadOnly
3288   onload        Image::OnLoad           DontDelete
3289   width         Image::Width            DontDelete|ReadOnly
3290   height        Image::Height           DontDelete|ReadOnly
3291 @end
3292 */
3293
3294 Value Image::tryGet(ExecState *exec, const Identifier &propertyName) const
3295 {
3296   return DOMObjectLookupGetValue<Image,DOMObject>(exec, propertyName, &ImageTable, this);
3297 }
3298
3299 Value Image::getValueProperty(ExecState *, int token) const
3300 {
3301   switch (token) {
3302   case Src:
3303     return String(src);
3304   case Complete:
3305     return Boolean(!img || img->status() >= khtml::CachedObject::Persistent);
3306   case OnLoad:
3307     if (onLoadListener && onLoadListener->listenerObjImp()) {
3308       return onLoadListener->listenerObj();
3309     } else {
3310       return Null();
3311     }
3312   case Width: {
3313     int width = 0;
3314     if (img) {
3315       QSize size = img->pixmap_size();
3316       if (size.isValid())
3317         width = size.width();
3318     }
3319     return Number(width);
3320   }
3321   case Height: {
3322     int height = 0;
3323     if (img) {
3324       QSize size = img->pixmap_size();
3325       if (size.isValid())
3326         height = size.height();
3327     }
3328     return Number(height);
3329   }
3330   default:
3331     kdWarning() << "Image::getValueProperty unhandled token " << token << endl;
3332     return Value();
3333   }
3334 }
3335
3336 void Image::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
3337 {
3338   DOMObjectLookupPut<Image,DOMObject>(exec, propertyName, value, attr, &ImageTable, this );
3339 }
3340
3341 void Image::putValue(ExecState *exec, int token, const Value& value, int /*attr*/)
3342 {
3343   switch(token) {
3344   case Src:
3345   {
3346     String str = value.toString(exec);
3347     src = str.value();
3348     if ( img ) img->deref(this);
3349     img = doc ? doc->docLoader()->requestImage( src.string() ) : 0;
3350     if ( img ) img->ref(this);
3351     break;
3352   }
3353   case OnLoad:
3354     onLoadListener = Window::retrieveActive(exec)->getJSEventListener(value, true);
3355     if (onLoadListener) onLoadListener->ref();
3356     break;
3357   default:
3358     kdWarning() << "HTMLDocument::putValue unhandled token " << token << endl;
3359   }
3360 }
3361
3362 void Image::notifyFinished(khtml::CachedObject *)
3363 {
3364   if (onLoadListener && doc->part()) {
3365     DOM::Event ev = doc->part()->document().createEvent("HTMLEvents");
3366     ev.initEvent("load", true, true);
3367     onLoadListener->handleEvent(ev, true);
3368   }
3369 }
3370
3371 Image::Image(const DOM::Document &d)
3372   : doc(static_cast<DOM::DocumentImpl*>(d.handle())), img(0), onLoadListener(0)
3373 {
3374 }
3375
3376 Image::~Image()
3377 {
3378   if ( img ) img->deref(this);
3379   if ( onLoadListener ) onLoadListener->deref();
3380 }
3381
3382
3383 ////////////////////// Context2D Object ////////////////////////
3384
3385 IMPLEMENT_PROTOFUNC(Context2DFunction)
3386
3387 static bool isGradient(const Value &value)
3388 {
3389     ObjectImp *o = static_cast<ObjectImp*>(value.imp());
3390     if (o->type() == ObjectType && o->inherits(&Gradient::info))
3391         return true;
3392     return false;
3393 }
3394
3395 static bool isImagePattern(const Value &value)
3396 {
3397     ObjectImp *o = static_cast<ObjectImp*>(value.imp());
3398     if (o->type() == ObjectType && o->inherits(&ImagePattern::info))
3399         return true;
3400     return false;
3401 }
3402
3403 #define BITS_PER_COMPONENT 8
3404 #define BYTES_PER_ROW(width,bitsPerComponent,numComponents) ((width * bitsPerComponent * numComponents + 7)/8)
3405
3406 Value KJS::Context2DFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
3407 {
3408     if (!thisObj.inherits(&Context2D::info)) {
3409         Object err = Error::create(exec,TypeError);
3410         exec->setException(err);
3411         return err;
3412     }
3413
3414     Context2D *contextObject = static_cast<KJS::Context2D *>(thisObj.imp());
3415     khtml::RenderCanvasImage *renderer = static_cast<khtml::RenderCanvasImage*>(contextObject->_element->renderer());
3416     if (!renderer)
3417         return Undefined();
3418
3419     CGContextRef drawingContext = renderer->drawingContext();
3420     if (!drawingContext)
3421         return Undefined();
3422     
3423     switch (id) {
3424         case Context2D::Save: {
3425             if (args.size() != 0) {
3426                 Object err = Error::create(exec,SyntaxError);
3427                 exec->setException(err);
3428                 return err;
3429             }
3430             CGContextSaveGState(drawingContext);
3431             
3432             contextObject->save();
3433             
3434             break;
3435         }
3436         case Context2D::Restore: {
3437             if (args.size() != 0) {
3438                 Object err = Error::create(exec,SyntaxError);
3439                 exec->setException(err);
3440                 return err;
3441             }
3442             CGContextRestoreGState(drawingContext);
3443             
3444             contextObject->restore();
3445             
3446             break;
3447         }
3448         case Context2D::BeginPath: {
3449             if (args.size() != 0) {
3450                 Object err = Error::create(exec,SyntaxError);
3451                 exec->setException(err);
3452                 return err;
3453             }
3454             CGContextBeginPath(drawingContext);
3455             break;
3456         }
3457         case Context2D::ClosePath: {
3458             if (args.size() != 0) {
3459                 Object err = Error::create(exec,SyntaxError);
3460                 exec->setException(err);
3461                 return err;
3462             }
3463             CGContextClosePath(drawingContext);
3464             break;
3465         }
3466         case Context2D::SetStrokeColor: {
3467             // string arg = named color
3468             // string arg, number arg = named color, alpha
3469             // number arg = gray color
3470             // number arg, number arg = gray color, alpha
3471             // 4 args (string or number) = r, g, b, a
3472             // 5 args (string or number) = c, m, y, k, a
3473             int numArgs = args.size();
3474             switch (numArgs) {
3475                 case 1: {
3476                     if (args[0].type() == StringType) {                    
3477                         QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
3478                         QColor qc(color);
3479                         CGContextSetRGBStrokeColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., qc.alpha()/255.);
3480
3481                     }
3482                     else {
3483                         float g = (float)args[0].toNumber(exec);
3484                         CGContextSetGrayStrokeColor(drawingContext, g, 1.);
3485                     }
3486                 }
3487                 break;
3488                 case 2: {
3489                     float a = args[1].toNumber(exec);
3490                     if (args[0].type() == StringType) {
3491                         QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
3492                         QColor qc(color);
3493                         CGContextSetRGBStrokeColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., a);
3494                     }
3495                     else {
3496                         float g = (float)args[0].toNumber(exec);
3497                         CGContextSetGrayStrokeColor(drawingContext, g, a);
3498                     }
3499                 }
3500                 break;
3501                 case 4: {
3502                     float r = (float)args[0].toNumber(exec);
3503                     float g = (float)args[1].toNumber(exec);
3504                     float b = (float)args[2].toNumber(exec);
3505                     float a = (float)args[3].toNumber(exec);
3506                     CGContextSetRGBStrokeColor(drawingContext, r, g, b, a);
3507                 }
3508                 break;
3509                 case 5: {
3510                     float c = (float)args[0].toNumber(exec);
3511                     float m = (float)args[1].toNumber(exec);
3512                     float y = (float)args[2].toNumber(exec);
3513                     float k = (float)args[3].toNumber(exec);
3514                     float a = (float)args[4].toNumber(exec);
3515                     CGContextSetCMYKStrokeColor(drawingContext, c, m, y, k, a);
3516                 }
3517                 break;
3518                 default: {
3519                     Object err = Error::create(exec,SyntaxError);
3520                     exec->setException(err);
3521                     return err;
3522                 }
3523             }
3524             break;
3525         }
3526         case Context2D::SetFillColor: {
3527             // string arg = named color
3528             // string arg, number arg = named color, alpha
3529             // number arg = gray color
3530             // number arg, number arg = gray color, alpha
3531             // 4 args (string or number) = r, g, b, a
3532             // 5 args (string or number) = c, m, y, k, a
3533             int numArgs = args.size();
3534             switch (numArgs) {
3535                 case 1: {
3536                     if (args[0].type() == StringType) {
3537                         QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
3538                         QColor qc(color);
3539                         CGContextSetRGBFillColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., qc.alpha()/255.);
3540                     }
3541                     else {
3542                         float g = (float)args[0].toNumber(exec);
3543                         CGContextSetGrayFillColor(drawingContext, g, 1.);
3544                     }
3545                 }
3546                 break;
3547                 case 2: {
3548                     float a = args[1].toNumber(exec);
3549                     if (args[0].type() == StringType) {
3550                         QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
3551                         QColor qc(color);
3552                         CGContextSetRGBFillColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., a);
3553                     }
3554                     else {
3555                         float g = (float)args[0].toNumber(exec);
3556                         CGContextSetGrayFillColor(drawingContext, g, a);
3557                     }
3558                 }
3559                 break;
3560                 case 4: {
3561                     float r = (float)args[0].toNumber(exec);
3562                     float g = (float)args[1].toNumber(exec);
3563                     float b = (float)args[2].toNumber(exec);
3564                     float a = (float)args[3].toNumber(exec);
3565                     CGContextSetRGBFillColor(drawingContext, r, g, b, a);
3566                 }
3567                 break;
3568                 case 5: {
3569                     float c = (float)args[0].toNumber(exec);
3570                     float m = (float)args[1].toNumber(exec);
3571                     float y = (float)args[2].toNumber(exec);
3572                     float k = (float)args[3].toNumber(exec);
3573                     float a = (float)args[4].toNumber(exec);
3574                     CGContextSetCMYKStrokeColor(drawingContext, c, m, y, k, a);
3575                 }
3576                 break;
3577                 default: {
3578                     Object err = Error::create(exec,SyntaxError);
3579                     exec->setException(err);
3580                     return err;
3581                 }
3582             }
3583             break;
3584         }
3585         case Context2D::SetLineWidth: {
3586             if (args.size() != 1) {
3587                 Object err = Error::create(exec,SyntaxError);
3588                 exec->setException(err);
3589                 return err;
3590             }
3591             float w = (float)args[0].toNumber(exec);
3592             CGContextSetLineWidth (drawingContext, w);
3593             break;
3594         }
3595         case Context2D::SetLineCap: {
3596             if (args.size() != 1) {
3597                 Object err = Error::create(exec,SyntaxError);
3598                 exec->setException(err);
3599                 return err;
3600             }
3601             CGLineCap cap = kCGLineCapButt;
3602             QString capString = args[0].toString(exec).qstring().lower();
3603             if (capString == "round")
3604                 cap = kCGLineCapRound;
3605             else if (capString == "square")
3606                 cap = kCGLineCapSquare;
3607             CGContextSetLineCap (drawingContext, cap);
3608             break;
3609         }
3610         case Context2D::SetLineJoin: {
3611             if (args.size() != 1) {
3612                 Object err = Error::create(exec,SyntaxError);
3613                 exec->setException(err);
3614                 return err;
3615             }
3616             CGLineJoin join = kCGLineJoinMiter;
3617             QString joinString = args[0].toString(exec).qstring().lower();
3618             if (joinString == "round")
3619                 join = kCGLineJoinRound;
3620             else if (joinString == "bevel")
3621                 join = kCGLineJoinBevel;
3622             CGContextSetLineJoin (drawingContext, join);
3623             break;
3624         }
3625         case Context2D::SetMiterLimit: {
3626             if (args.size() != 1) {
3627                 Object err = Error::create(exec,SyntaxError);
3628                 exec->setException(err);
3629                 return err;
3630             }
3631             float l = (float)args[0].toNumber(exec);
3632             CGContextSetMiterLimit (drawingContext, l);
3633             break;
3634         }
3635         case Context2D::Fill: {
3636             if (args.size() != 0) {
3637                 Object err = Error::create(exec,SyntaxError);
3638                 exec->setException(err);
3639                 return err;
3640             }
3641             
3642             if (isGradient(contextObject->_fillStyle)) {
3643                 CGContextSaveGState(drawingContext);
3644                 
3645                 // Set the clip from the current path because shading only
3646                 // operates on clippin regions!  Odd, but true.
3647                 CGContextClip(drawingContext);
3648
3649                 ObjectImp *o = static_cast<ObjectImp*>(contextObject->_fillStyle.imp());
3650                 Gradient *gradient = static_cast<Gradient*>(o);
3651                 CGShadingRef shading = gradient->getShading();
3652                 CGContextDrawShading(drawingContext, shading);
3653                 
3654                 CGContextRestoreGState(drawingContext);
3655             }
3656             else
3657                 CGContextFillPath (drawingContext);
3658                 
3659             renderer->setNeedsImageUpdate();
3660             break;
3661         }
3662         case Context2D::Stroke: {
3663             if (args.size() != 0) {
3664                 Object err = Error::create(exec,SyntaxError);
3665                 exec->setException(err);
3666                 return err;
3667             }
3668             if (isGradient(contextObject->_strokeStyle)) {
3669                 CGContextSaveGState(drawingContext);
3670                 
3671                 // Convert the stroke normally performed on the path
3672                 // into a path.  Then set the clip from that path 
3673                 // because shading only operates on clipping regions!  Odd, 
3674                 // but true.
3675                 CGContextReplacePathWithStrokedPath(drawingContext);
3676                 CGContextClip(drawingContext);
3677
3678                 ObjectImp *o = static_cast<ObjectImp*>(contextObject->_strokeStyle.imp());
3679                 Gradient *gradient = static_cast<Gradient*>(o);
3680                 
3681                 CGShadingRef shading = gradient->getShading();
3682                 CGContextDrawShading(drawingContext, shading);
3683                 
3684                 CGContextRestoreGState(drawingContext);
3685             }
3686             else
3687                 CGContextStrokePath (drawingContext);
3688             renderer->setNeedsImageUpdate();
3689             break;
3690         }
3691         case Context2D::Scale: {
3692             if (args.size() != 2) {
3693                 Object err = Error::create(exec,SyntaxError);
3694                 exec->setException(err);
3695                 return err;
3696             }
3697             float sx = (float)args[0].toNumber(exec);
3698             float sy = (float)args[1].toNumber(exec);
3699             CGContextScaleCTM (drawingContext, sx, sy);
3700             contextObject->_needsFlushRasterCache = true;
3701             break;
3702         }
3703         case Context2D::Rotate: {
3704             if (args.size() != 1) {
3705                 Object err = Error::create(exec,SyntaxError);
3706                 exec->setException(err);
3707                 return err;
3708             }
3709             float angle = (float)args[0].toNumber(exec);
3710             CGContextRotateCTM (drawingContext, angle);
3711             contextObject->_needsFlushRasterCache = true;
3712             break;
3713         }
3714         case Context2D::Translate: {
3715             if (args.size() != 2) {
3716                 Object err = Error::create(exec,SyntaxError);
3717                 exec->setException(err);
3718                 return err;
3719             }
3720             float tx = (float)args[0].toNumber(exec);
3721             float ty = (float)args[1].toNumber(exec);
3722             CGContextTranslateCTM (drawingContext, tx, ty);
3723             break;
3724         }
3725         case Context2D::MoveTo: {
3726             if (args.size() != 2) {
3727                 Object err = Error::create(exec,SyntaxError);
3728                 exec->setException(err);
3729                 return err;
3730             }
3731             float x = (float)args[0].toNumber(exec);
3732             float y = (float)args[1].toNumber(exec);
3733             CGContextMoveToPoint (drawingContext, x, y);
3734             renderer->setNeedsImageUpdate();
3735             break;
3736         }
3737         case Context2D::LineTo: {
3738             if (args.size() != 2) {
3739                 Object err = Error::create(exec,SyntaxError);
3740                 exec->setException(err);
3741                 return err;
3742             }
3743             float x = (float)args[0].toNumber(exec);
3744             float y = (float)args[1].toNumber(exec);
3745             CGContextAddLineToPoint (drawingContext, x, y);
3746             renderer->setNeedsImageUpdate();
3747             break;
3748         }
3749         case Context2D::QuadraticCurveTo: {
3750             if (args.size() != 4) {
3751                 Object err = Error::create(exec,SyntaxError);
3752                 exec->setException(err);
3753                 return err;
3754             }
3755             float cpx = (float)args[0].toNumber(exec);
3756             float cpy = (float)args[1].toNumber(exec);
3757             float x = (float)args[2].toNumber(exec);
3758             float y = (float)args[3].toNumber(exec);
3759             CGContextAddQuadCurveToPoint (drawingContext, cpx, cpy, x, y);
3760             renderer->setNeedsImageUpdate();
3761             break;
3762         }
3763         case Context2D::BezierCurveTo: {
3764             if (args.size() != 6) {
3765                 Object err = Error::create(exec,SyntaxError);
3766                 exec->setException(err);
3767                 return err;
3768             }
3769             float cp1x = (float)args[0].toNumber(exec);
3770             float cp1y = (float)args[1].toNumber(exec);
3771             float cp2x = (float)args[2].toNumber(exec);
3772             float cp2y = (float)args[3].toNumber(exec);
3773             float x = (float)args[2].toNumber(exec);
3774             float y = (float)args[3].toNumber(exec);
3775             CGContextAddCurveToPoint (drawingContext, cp1x, cp1y, cp2x, cp2y, x, y);
3776             renderer->setNeedsImageUpdate();
3777             break;
3778         }
3779         case Context2D::ArcTo: {
3780             if (args.size() != 5) {
3781                 Object err = Error::create(exec,SyntaxError);
3782                 exec->setException(err);
3783                 return err;
3784             }
3785             float x1 = (float)args[0].toNumber(exec);
3786             float y1 = (float)args[1].toNumber(exec);
3787             float x2 = (float)args[2].toNumber(exec);
3788             float y2 = (float)args[3].toNumber(exec);
3789             float r = (float)args[4].toNumber(exec);
3790             CGContextAddArcToPoint (drawingContext, x1, y1, x2, y2, r);
3791             break;
3792         }
3793         case Context2D::Arc: {
3794             if (args.size() != 6) {
3795                 Object err = Error::create(exec,SyntaxError);
3796                 exec->setException(err);
3797                 return err;
3798             }
3799             float x = (float)args[0].toNumber(exec);
3800             float y = (float)args[1].toNumber(exec);
3801             float r = (float)args[2].toNumber(exec);
3802             float sa = (float)args[3].toNumber(exec);
3803             float ea = (float)args[4].toNumber(exec);
3804             bool clockwise = args[5].toBoolean(exec);
3805             CGContextAddArc (drawingContext, x, y, r, sa, ea, clockwise);
3806             break;
3807         }
3808         case Context2D::Rect: {
3809             if (args.size() != 4) {
3810                 Object err = Error::create(exec,SyntaxError);
3811                 exec->setException(err);
3812                 return err;
3813             }
3814             float x = (float)args[0].toNumber(exec);
3815             float y = (float)args[1].toNumber(exec);
3816             float w = (float)args[2].toNumber(exec);
3817             float h = (float)args[3].toNumber(exec);
3818             CGContextAddRect (drawingContext, CGRectMake(x,y,w,h));
3819             break;
3820         }
3821         case Context2D::Clip: {
3822             if (args.size() != 0) {
3823                 Object err = Error::create(exec,SyntaxError);
3824                 exec->setException(err);
3825                 return err;
3826             }
3827             CGContextClip (drawingContext);
3828             break;
3829         }
3830
3831         case Context2D::ClearRect: {
3832             if (args.size() != 4) {
3833                 Object err = Error::create(exec,SyntaxError);
3834                 exec->setException(err);
3835                 return err;
3836             }
3837             float x = (float)args[0].toNumber(exec);
3838             float y = (float)args[1].toNumber(exec);
3839             float w = (float)args[2].toNumber(exec);
3840             float h = (float)args[3].toNumber(exec);
3841             CGContextClearRect (drawingContext, CGRectMake(x,y,w,h));
3842             renderer->setNeedsImageUpdate();
3843             break;
3844         }
3845         case Context2D::FillRect: {
3846             if (args.size() != 4) {
3847                 Object err = Error::create(exec,SyntaxError);
3848                 exec->setException(err);
3849                 return err;
3850             }
3851             float x = (float)args[0].toNumber(exec);
3852             float y = (float)args[1].toNumber(exec);
3853             float w = (float)args[2].toNumber(exec);
3854             float h = (float)args[3].toNumber(exec);
3855             CGContextFillRect&n