Fixed 3922875. Fall back to DOM object is EMBED element
[WebKit-https.git] / WebCore / khtml / ecma / kjs_dom.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 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 <khtmlview.h>
23 #include "xml/dom2_eventsimpl.h"
24 #include "rendering/render_canvas.h"
25 #include "xml/dom_nodeimpl.h"
26 #include "xml/dom_docimpl.h"
27 #include <kdebug.h>
28 #include <khtml_part.h>
29
30 #include "kjs_dom.h"
31 #include "kjs_html.h"
32 #include "kjs_css.h"
33 #include "kjs_range.h"
34 #include "kjs_traversal.h"
35 #include "kjs_events.h"
36 #include "kjs_views.h"
37 #include "kjs_window.h"
38 #include "dom/dom_exception.h"
39 #include "kjs_dom.lut.h"
40 #include "khtmlpart_p.h"
41
42 #include "html_objectimpl.h"
43
44 #include "misc/htmltags.h"
45
46 #if APPLE_CHANGES
47 #include <JavaScriptCore/runtime_object.h>
48 #endif
49
50 using namespace KJS;
51
52 using DOM::DOMException;
53 using DOM::DOMString;
54 using DOM::NodeFilter;
55
56 // -------------------------------------------------------------------------
57 /* Source for DOMNodeProtoTable. Use "make hashtables" to regenerate.
58 @begin DOMNodeProtoTable 13
59   insertBefore  DOMNode::InsertBefore   DontDelete|Function 2
60   replaceChild  DOMNode::ReplaceChild   DontDelete|Function 2
61   removeChild   DOMNode::RemoveChild    DontDelete|Function 1
62   appendChild   DOMNode::AppendChild    DontDelete|Function 1
63   hasAttributes DOMNode::HasAttributes  DontDelete|Function 0
64   hasChildNodes DOMNode::HasChildNodes  DontDelete|Function 0
65   cloneNode     DOMNode::CloneNode      DontDelete|Function 1
66 # DOM2
67   normalize     DOMNode::Normalize      DontDelete|Function 0
68   isSupported   DOMNode::IsSupported    DontDelete|Function 2
69 # from the EventTarget interface
70   addEventListener      DOMNode::AddEventListener       DontDelete|Function 3
71   removeEventListener   DOMNode::RemoveEventListener    DontDelete|Function 3
72   dispatchEvent         DOMNode::DispatchEvent  DontDelete|Function 1
73   contains      DOMNode::Contains               DontDelete|Function 1
74 # "DOM level 0" (from Gecko DOM reference; also in WinIE)
75   item          DOMNode::Item           DontDelete|Function 1
76 @end
77 */
78 DEFINE_PROTOTYPE("DOMNode",DOMNodeProto)
79 IMPLEMENT_PROTOFUNC(DOMNodeProtoFunc)
80 IMPLEMENT_PROTOTYPE(DOMNodeProto,DOMNodeProtoFunc)
81
82 const ClassInfo DOMNode::info = { "Node", 0, &DOMNodeTable, 0 };
83
84 DOMNode::DOMNode(ExecState *exec, const DOM::Node &n)
85   : DOMObject(DOMNodeProto::self(exec)), node(n)
86 {
87 }
88
89 DOMNode::DOMNode(const Object &proto, const DOM::Node &n)
90   : DOMObject(proto), node(n)
91 {
92 }
93
94 bool DOMNode::toBoolean(ExecState *) const
95 {
96     return !node.isNull();
97 }
98
99 /* Source for DOMNodeTable. Use "make hashtables" to regenerate.
100 @begin DOMNodeTable 67
101   nodeName      DOMNode::NodeName       DontDelete|ReadOnly
102   nodeValue     DOMNode::NodeValue      DontDelete
103   nodeType      DOMNode::NodeType       DontDelete|ReadOnly
104   parentNode    DOMNode::ParentNode     DontDelete|ReadOnly
105   parentElement DOMNode::ParentElement  DontDelete|ReadOnly
106   childNodes    DOMNode::ChildNodes     DontDelete|ReadOnly
107   firstChild    DOMNode::FirstChild     DontDelete|ReadOnly
108   lastChild     DOMNode::LastChild      DontDelete|ReadOnly
109   previousSibling  DOMNode::PreviousSibling DontDelete|ReadOnly
110   nextSibling   DOMNode::NextSibling    DontDelete|ReadOnly
111   attributes    DOMNode::Attributes     DontDelete|ReadOnly
112   namespaceURI  DOMNode::NamespaceURI   DontDelete|ReadOnly
113 # DOM2
114   prefix        DOMNode::Prefix         DontDelete
115   localName     DOMNode::LocalName      DontDelete|ReadOnly
116   ownerDocument DOMNode::OwnerDocument  DontDelete|ReadOnly
117 #
118   onabort       DOMNode::OnAbort                DontDelete
119   onblur        DOMNode::OnBlur                 DontDelete
120   onchange      DOMNode::OnChange               DontDelete
121   onclick       DOMNode::OnClick                DontDelete
122   oncontextmenu DOMNode::OnContextMenu          DontDelete
123   ondblclick    DOMNode::OnDblClick             DontDelete
124   onbeforecut   DOMNode::OnBeforeCut            DontDelete
125   oncut         DOMNode::OnCut                  DontDelete
126   onbeforecopy  DOMNode::OnBeforeCopy           DontDelete
127   oncopy        DOMNode::OnCopy                 DontDelete
128   onbeforepaste DOMNode::OnBeforePaste          DontDelete
129   onpaste       DOMNode::OnPaste                DontDelete
130   ondrag        DOMNode::OnDrag                 DontDelete
131   ondragdrop    DOMNode::OnDragDrop             DontDelete
132   ondragend     DOMNode::OnDragEnd              DontDelete
133   ondragenter   DOMNode::OnDragEnter            DontDelete
134   ondragleave   DOMNode::OnDragLeave            DontDelete
135   ondragover    DOMNode::OnDragOver             DontDelete
136   ondragstart   DOMNode::OnDragStart            DontDelete
137   ondrop        DOMNode::OnDrop                 DontDelete
138   onerror       DOMNode::OnError                DontDelete
139   onfocus       DOMNode::OnFocus                DontDelete
140   oninput       DOMNode::OnInput                DontDelete
141   onkeydown     DOMNode::OnKeyDown              DontDelete
142   onkeypress    DOMNode::OnKeyPress             DontDelete
143   onkeyup       DOMNode::OnKeyUp                DontDelete
144   onload        DOMNode::OnLoad                 DontDelete
145   onmousedown   DOMNode::OnMouseDown            DontDelete
146   onmousemove   DOMNode::OnMouseMove            DontDelete
147   onmouseout    DOMNode::OnMouseOut             DontDelete
148   onmouseover   DOMNode::OnMouseOver            DontDelete
149   onmouseup     DOMNode::OnMouseUp              DontDelete
150   onmove        DOMNode::OnMove                 DontDelete
151   onreset       DOMNode::OnReset                DontDelete
152   onresize      DOMNode::OnResize               DontDelete
153   onscroll      DOMNode::OnScroll               DontDelete
154   onsearch      DOMNode::OnSearch               DontDelete
155   onselect      DOMNode::OnSelect               DontDelete
156   onselectstart DOMNode::OnSelectStart          DontDelete
157   onsubmit      DOMNode::OnSubmit               DontDelete
158   onunload      DOMNode::OnUnload               DontDelete
159 # IE extensions
160   offsetLeft    DOMNode::OffsetLeft             DontDelete|ReadOnly
161   offsetTop     DOMNode::OffsetTop              DontDelete|ReadOnly
162   offsetWidth   DOMNode::OffsetWidth            DontDelete|ReadOnly
163   offsetHeight  DOMNode::OffsetHeight           DontDelete|ReadOnly
164   offsetParent  DOMNode::OffsetParent           DontDelete|ReadOnly
165   clientWidth   DOMNode::ClientWidth            DontDelete|ReadOnly
166   clientHeight  DOMNode::ClientHeight           DontDelete|ReadOnly
167   scrollLeft    DOMNode::ScrollLeft             DontDelete
168   scrollTop     DOMNode::ScrollTop              DontDelete
169   scrollWidth   DOMNode::ScrollWidth            DontDelete|ReadOnly
170   scrollHeight  DOMNode::ScrollHeight           DontDelete|ReadOnly
171 @end
172 */
173 Value DOMNode::tryGet(ExecState *exec, const Identifier &propertyName) const
174 {
175 #ifdef KJS_VERBOSE
176   kdDebug(6070) << "DOMNode::tryGet " << propertyName.qstring() << endl;
177 #endif
178   return DOMObjectLookupGetValue<DOMNode, DOMObject>(exec, propertyName, &DOMNodeTable, this);
179 }
180
181 Value DOMNode::getValueProperty(ExecState *exec, int token) const
182 {
183   switch (token) {
184   case NodeName:
185     return getStringOrNull(node.nodeName());
186   case NodeValue:
187     return getStringOrNull(node.nodeValue());
188   case NodeType:
189     return Number((unsigned int)node.nodeType());
190   case ParentNode:
191     return getDOMNode(exec,node.parentNode());
192   case ParentElement: // IE only apparently
193     return getDOMNode(exec,node.parentNode());
194   case ChildNodes:
195     return getDOMNodeList(exec,node.childNodes());
196   case FirstChild:
197     return getDOMNode(exec,node.firstChild());
198   case LastChild:
199     return getDOMNode(exec,node.lastChild());
200   case PreviousSibling:
201     return getDOMNode(exec,node.previousSibling());
202   case NextSibling:
203     return getDOMNode(exec,node.nextSibling());
204   case Attributes:
205     return getDOMNamedNodeMap(exec,node.attributes());
206   case NamespaceURI:
207     return getStringOrNull(node.namespaceURI());
208   case Prefix:
209     return getStringOrNull(node.prefix());
210   case LocalName:
211     return getStringOrNull(node.localName());
212   case OwnerDocument:
213     return getDOMNode(exec,node.ownerDocument());
214   case OnAbort:
215     return getListener(DOM::EventImpl::ABORT_EVENT);
216   case OnBlur:
217     return getListener(DOM::EventImpl::BLUR_EVENT);
218   case OnChange:
219     return getListener(DOM::EventImpl::CHANGE_EVENT);
220   case OnClick:
221     return getListener(DOM::EventImpl::KHTML_CLICK_EVENT);
222   case OnContextMenu:
223     return getListener(DOM::EventImpl::CONTEXTMENU_EVENT);
224   case OnDblClick:
225     return getListener(DOM::EventImpl::KHTML_DBLCLICK_EVENT);
226   case OnDragDrop:
227     return getListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT);
228   case OnError:
229     return getListener(DOM::EventImpl::KHTML_ERROR_EVENT);
230   case OnFocus:
231     return getListener(DOM::EventImpl::FOCUS_EVENT);
232   case OnInput:
233     return getListener(DOM::EventImpl::INPUT_EVENT);
234   case OnKeyDown:
235     return getListener(DOM::EventImpl::KEYDOWN_EVENT);
236   case OnKeyPress:
237     return getListener(DOM::EventImpl::KEYPRESS_EVENT);
238   case OnKeyUp:
239     return getListener(DOM::EventImpl::KEYUP_EVENT);
240   case OnLoad:
241     return getListener(DOM::EventImpl::LOAD_EVENT);
242   case OnMouseDown:
243     return getListener(DOM::EventImpl::MOUSEDOWN_EVENT);
244   case OnMouseMove:
245     return getListener(DOM::EventImpl::MOUSEMOVE_EVENT);
246   case OnMouseOut:
247     return getListener(DOM::EventImpl::MOUSEOUT_EVENT);
248   case OnMouseOver:
249     return getListener(DOM::EventImpl::MOUSEOVER_EVENT);
250   case OnMouseUp:
251     return getListener(DOM::EventImpl::MOUSEUP_EVENT);      
252   case OnBeforeCut:
253     return getListener(DOM::EventImpl::BEFORECUT_EVENT);
254   case OnCut:
255     return getListener(DOM::EventImpl::CUT_EVENT);
256   case OnBeforeCopy:
257     return getListener(DOM::EventImpl::BEFORECOPY_EVENT);
258   case OnCopy:
259     return getListener(DOM::EventImpl::COPY_EVENT);
260   case OnBeforePaste:
261     return getListener(DOM::EventImpl::BEFOREPASTE_EVENT);
262   case OnPaste:
263     return getListener(DOM::EventImpl::PASTE_EVENT);
264   case OnDragEnter:
265     return getListener(DOM::EventImpl::DRAGENTER_EVENT);
266   case OnDragOver:
267     return getListener(DOM::EventImpl::DRAGOVER_EVENT);
268   case OnDragLeave:
269     return getListener(DOM::EventImpl::DRAGLEAVE_EVENT);
270   case OnDrop:
271     return getListener(DOM::EventImpl::DROP_EVENT);
272   case OnDragStart:
273     return getListener(DOM::EventImpl::DRAGSTART_EVENT);
274   case OnDrag:
275     return getListener(DOM::EventImpl::DRAG_EVENT);
276   case OnDragEnd:
277     return getListener(DOM::EventImpl::DRAGEND_EVENT);
278   case OnMove:
279     return getListener(DOM::EventImpl::KHTML_MOVE_EVENT);
280   case OnReset:
281     return getListener(DOM::EventImpl::RESET_EVENT);
282   case OnResize:
283     return getListener(DOM::EventImpl::RESIZE_EVENT);
284   case OnScroll:
285     return getListener(DOM::EventImpl::SCROLL_EVENT);
286 #if APPLE_CHANGES
287   case OnSearch:
288     return getListener(DOM::EventImpl::SEARCH_EVENT);
289 #endif
290   case OnSelect:
291     return getListener(DOM::EventImpl::SELECT_EVENT);
292   case OnSelectStart:
293     return getListener(DOM::EventImpl::SELECTSTART_EVENT);
294   case OnSubmit:
295     return getListener(DOM::EventImpl::SUBMIT_EVENT);
296   case OnUnload:
297     return getListener(DOM::EventImpl::UNLOAD_EVENT);
298   default:
299     // no DOM standard, found in IE only
300
301     // Make sure our layout is up to date before we allow a query on these attributes.
302     DOM::DocumentImpl* docimpl = node.handle()->getDocument();
303     if (docimpl) {
304       docimpl->updateLayoutIgnorePendingStylesheets();
305     }
306
307     khtml::RenderObject *rend = node.handle()->renderer();
308
309     switch (token) {
310     case OffsetLeft:
311       return rend ? static_cast<Value>(Number(rend->offsetLeft())) : Value(Undefined());
312     case OffsetTop:
313       return rend ? static_cast<Value>(Number(rend->offsetTop())) : Value(Undefined());
314     case OffsetWidth:
315       return rend ? static_cast<Value>(Number(rend->offsetWidth()) ) : Value(Undefined());
316     case OffsetHeight:
317       return rend ? static_cast<Value>(Number(rend->offsetHeight() ) ) : Value(Undefined());
318     case OffsetParent: {
319       khtml::RenderObject* par = rend ? rend->offsetParent() : 0;
320       return getDOMNode(exec, par ? par->element() : 0);
321     }
322     case ClientWidth:
323       return rend ? static_cast<Value>(Number(rend->clientWidth()) ) : Value(Undefined());
324     case ClientHeight:
325       return rend ? static_cast<Value>(Number(rend->clientHeight()) ) : Value(Undefined());
326     case ScrollWidth:
327         return rend ? static_cast<Value>(Number(rend->scrollWidth()) ) : Value(Undefined());
328     case ScrollHeight:
329         return rend ? static_cast<Value>(Number(rend->scrollHeight()) ) : Value(Undefined());
330     case ScrollLeft:
331       return Number(rend && rend->layer() ? rend->layer()->scrollXOffset() : 0);
332     case ScrollTop:
333       return Number(rend && rend->layer() ? rend->layer()->scrollYOffset() : 0);
334     default:
335       kdWarning() << "Unhandled token in DOMNode::getValueProperty : " << token << endl;
336       break;
337     }
338   }
339
340   return Value();
341 }
342
343 void DOMNode::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
344 {
345 #ifdef KJS_VERBOSE
346   kdDebug(6070) << "DOMNode::tryPut " << propertyName.qstring() << endl;
347 #endif
348   DOMObjectLookupPut<DOMNode,DOMObject>(exec, propertyName, value, attr,
349                                         &DOMNodeTable, this );
350 }
351
352 void DOMNode::putValue(ExecState *exec, int token, const Value& value, int /*attr*/)
353 {
354   switch (token) {
355   case NodeValue:
356     node.setNodeValue(value.toString(exec).string());
357     break;
358   case Prefix:
359     node.setPrefix(value.toString(exec).string());
360     break;
361   case OnAbort:
362     setListener(exec,DOM::EventImpl::ABORT_EVENT,value);
363     break;
364   case OnBlur:
365     setListener(exec,DOM::EventImpl::BLUR_EVENT,value);
366     break;
367   case OnChange:
368     setListener(exec,DOM::EventImpl::CHANGE_EVENT,value);
369     break;
370   case OnClick:
371     setListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT,value);
372     break;
373   case OnContextMenu:
374     setListener(exec,DOM::EventImpl::CONTEXTMENU_EVENT,value);
375     break;
376   case OnDblClick:
377     setListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT,value);
378     break;
379   case OnDragDrop:
380     setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
381     break;
382   case OnError:
383     setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
384     break;
385   case OnFocus:
386     setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
387     break;
388   case OnInput:
389     setListener(exec,DOM::EventImpl::INPUT_EVENT,value);
390     break;
391   case OnKeyDown:
392     setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
393     break;
394   case OnKeyPress:
395     setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
396     break;
397   case OnKeyUp:
398     setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
399     break;
400   case OnLoad:
401     setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
402     break;
403   case OnMouseDown:
404     setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
405     break;
406   case OnMouseMove:
407     setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
408     break;
409   case OnMouseOut:
410     setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
411     break;
412   case OnMouseOver:
413     setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
414     break;
415   case OnMouseUp:
416     setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
417     break;
418   case OnBeforeCut:
419     setListener(exec,DOM::EventImpl::BEFORECUT_EVENT,value);
420     break;
421   case OnCut:
422     setListener(exec,DOM::EventImpl::CUT_EVENT,value);
423     break;
424   case OnBeforeCopy:
425     setListener(exec,DOM::EventImpl::BEFORECOPY_EVENT,value);
426     break;
427   case OnCopy:
428     setListener(exec,DOM::EventImpl::COPY_EVENT,value);
429     break;
430   case OnBeforePaste:
431     setListener(exec,DOM::EventImpl::BEFOREPASTE_EVENT,value);
432     break;
433   case OnPaste:
434     setListener(exec,DOM::EventImpl::PASTE_EVENT,value);
435     break;
436   case OnDragEnter:
437     setListener(exec,DOM::EventImpl::DRAGENTER_EVENT,value);
438     break;
439   case OnDragOver:
440     setListener(exec,DOM::EventImpl::DRAGOVER_EVENT,value);
441     break;
442   case OnDragLeave:
443     setListener(exec,DOM::EventImpl::DRAGLEAVE_EVENT,value);
444     break;
445   case OnDrop:
446     setListener(exec,DOM::EventImpl::DROP_EVENT,value);
447     break;
448   case OnDragStart:
449     setListener(exec,DOM::EventImpl::DRAGSTART_EVENT,value);
450     break;
451   case OnDrag:
452     setListener(exec,DOM::EventImpl::DRAG_EVENT,value);
453     break;
454   case OnDragEnd:
455     setListener(exec,DOM::EventImpl::DRAGEND_EVENT,value);
456     break;
457   case OnMove:
458     setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
459     break;
460   case OnReset:
461     setListener(exec,DOM::EventImpl::RESET_EVENT,value);
462     break;
463   case OnResize:
464     setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
465     break;
466   case OnScroll:
467     setListener(exec,DOM::EventImpl::SCROLL_EVENT,value);
468 #if APPLE_CHANGES
469   case OnSearch:
470     setListener(exec,DOM::EventImpl::SEARCH_EVENT,value);
471     break;
472 #endif
473   case OnSelect:
474     setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
475     break;
476   case OnSelectStart:
477     setListener(exec,DOM::EventImpl::SELECTSTART_EVENT,value);
478     break;
479   case OnSubmit:
480     setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
481     break;
482   case OnUnload:
483     setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
484     break;
485   case ScrollTop: {
486     khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
487     if (rend && rend->hasOverflowClip())
488         rend->layer()->scrollToYOffset(value.toInt32(exec));
489     break;
490   }
491   case ScrollLeft: {
492     khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
493     if (rend && rend->hasOverflowClip())
494       rend->layer()->scrollToXOffset(value.toInt32(exec));
495     break;
496   }
497   default:
498     kdWarning() << "DOMNode::putValue unhandled token " << token << endl;
499   }
500 }
501
502 Value DOMNode::toPrimitive(ExecState *exec, Type /*preferred*/) const
503 {
504   if (node.isNull())
505     return Null();
506
507   return String(toString(exec));
508 }
509
510 UString DOMNode::toString(ExecState *) const
511 {
512   if (node.isNull())
513     return "null";
514   UString s;
515
516   DOM::Element e = node;
517   if ( !e.isNull() ) {
518     s = UString(e.nodeName().string());
519   } else
520     s = className(); // fallback
521
522   return "[object " + s + "]";
523 }
524
525 void DOMNode::setListener(ExecState *exec, int eventId, Value func) const
526 {
527   node.handle()->setHTMLEventListener(eventId,Window::retrieveActive(exec)->getJSEventListener(func,true));
528 }
529
530 Value DOMNode::getListener(int eventId) const
531 {
532     DOM::EventListener *listener = node.handle()->getHTMLEventListener(eventId);
533     JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
534     if ( jsListener && jsListener->listenerObjImp() )
535         return jsListener->listenerObj();
536     else
537         return Null();
538 }
539
540 void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
541 {
542 }
543
544 Value DOMNodeProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
545 {
546   if (!thisObj.inherits(&DOMNode::info)) {
547     Object err = Error::create(exec,TypeError);
548     exec->setException(err);
549     return err;
550   }
551   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
552   switch (id) {
553     case DOMNode::HasAttributes:
554       return Boolean(node.hasAttributes());
555     case DOMNode::HasChildNodes:
556       return Boolean(node.hasChildNodes());
557     case DOMNode::CloneNode:
558       return getDOMNode(exec,node.cloneNode(args[0].toBoolean(exec)));
559     case DOMNode::Normalize:
560       node.normalize();
561       return Undefined();
562     case DOMNode::IsSupported:
563         return Boolean(node.isSupported(args[0].toString(exec).string(),
564             (args[1].type() != UndefinedType && args[1].type() != NullType) ? args[1].toString(exec).string() : DOMString()));
565     case DOMNode::AddEventListener: {
566         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
567         if (listener)
568             node.addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
569         return Undefined();
570     }
571     case DOMNode::RemoveEventListener: {
572         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
573         if (listener)
574             node.removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
575         return Undefined();
576     }
577     case DOMNode::DispatchEvent:
578       return Boolean(node.dispatchEvent(toEvent(args[0])));
579     case DOMNode::AppendChild:
580       return getDOMNode(exec,node.appendChild(toNode(args[0])));
581     case DOMNode::RemoveChild:
582       return getDOMNode(exec,node.removeChild(toNode(args[0])));
583     case DOMNode::InsertBefore:
584       return getDOMNode(exec,node.insertBefore(toNode(args[0]), toNode(args[1])));
585     case DOMNode::ReplaceChild:
586       return getDOMNode(exec,node.replaceChild(toNode(args[0]), toNode(args[1])));
587     case DOMNode::Contains:
588     {
589         int exceptioncode=0;
590         DOM::Node other = toNode(args[0]);
591         if (!other.isNull() && node.nodeType()==DOM::Node::ELEMENT_NODE)
592         {
593             DOM::NodeBaseImpl *impl = static_cast<DOM::NodeBaseImpl *>(node.handle());
594             bool retval = !impl->checkNoOwner(other.handle(),exceptioncode);
595             return Boolean(retval && exceptioncode == 0);
596         }
597         return Undefined();
598     }
599     case DOMNode::Item:
600       return getDOMNode(exec, node.childNodes().item(static_cast<unsigned long>(args[0].toNumber(exec))));
601   }
602
603   return Undefined();
604 }
605
606 // -------------------------------------------------------------------------
607
608 const ClassInfo DOMNodeList::info = { "NodeList", 0, 0, 0 };
609
610 DOMNodeList::~DOMNodeList()
611 {
612   ScriptInterpreter::forgetDOMObject(list.handle());
613 }
614
615 Value DOMNodeList::toPrimitive(ExecState *exec, Type /*preferred*/) const
616 {
617   if (list.isNull())
618     return Null();
619
620   return String(toString(exec));
621 }
622
623
624
625 // We have to implement hasProperty since we don't use a hashtable for 'length' and 'item'
626 // ## this breaks "for (..in..)" though.
627 bool DOMNodeList::hasProperty(ExecState *exec, const Identifier &p) const
628 {
629   if (p == lengthPropertyName || p == "item")
630     return true;
631   return ObjectImp::hasProperty(exec, p);
632 }
633
634 Value DOMNodeList::tryGet(ExecState *exec, const Identifier &p) const
635 {
636 #ifdef KJS_VERBOSE
637   kdDebug(6070) << "DOMNodeList::tryGet " << p.ascii() << endl;
638 #endif
639   Value result;
640
641   if (p == lengthPropertyName)
642     result = Number(list.length());
643   else if (p == "item") {
644     // No need for a complete hashtable for a single func, but we still want
645     // to use the caching feature of lookupOrCreateFunction.
646     result = lookupOrCreateFunction<DOMNodeListFunc>(exec, p, this, DOMNodeListFunc::Item, 1, DontDelete|Function);
647     //result = new DOMNodeListFunc(exec, DOMNodeListFunc::Item, 1);
648   }
649   else {
650     // array index ?
651     bool ok;
652     long unsigned int idx = p.toULong(&ok);
653     if (ok) {
654       result = getDOMNode(exec,list.item(idx));
655     } else {
656       DOM::Node node = list.itemById(p.string());
657
658       if (!node.isNull()) {
659         result = getDOMNode(exec, node);
660       } else {
661         result = ObjectImp::get(exec, p);
662       }
663     }
664   }
665
666   return result;
667 }
668
669 // Need to support both get and call, so that list[0] and list(0) work.
670 Value DOMNodeList::call(ExecState *exec, Object &thisObj, const List &args)
671 {
672   // This code duplication is necessary, DOMNodeList isn't a DOMFunction
673   Value val;
674   try {
675     val = tryCall(exec, thisObj, args);
676   }
677   // pity there's no way to distinguish between these in JS code
678   catch (...) {
679     Object err = Error::create(exec, GeneralError, "Exception from DOMNodeList");
680     exec->setException(err);
681   }
682   return val;
683 }
684
685 Value DOMNodeList::tryCall(ExecState *exec, Object &, const List &args)
686 {
687   // Do not use thisObj here. See HTMLCollection.
688   UString s = args[0].toString(exec);
689   bool ok;
690   unsigned int u = s.toULong(&ok);
691   if (ok)
692     return getDOMNode(exec,list.item(u));
693
694   kdWarning() << "KJS::DOMNodeList::tryCall " << s.qstring() << " not implemented" << endl;
695   return Undefined();
696 }
697
698 DOMNodeListFunc::DOMNodeListFunc(ExecState *exec, int i, int len)
699   : DOMFunction(), id(i)
700 {
701   Value protect(this);
702   put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum);
703 }
704
705 // Not a prototype class currently, but should probably be converted to one
706 Value DOMNodeListFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
707 {
708   if (!thisObj.inherits(&KJS::DOMNodeList::info)) {
709     Object err = Error::create(exec,TypeError);
710     exec->setException(err);
711     return err;
712   }
713   DOM::NodeList list = static_cast<DOMNodeList *>(thisObj.imp())->nodeList();
714   Value result;
715
716   if (id == Item)
717     result = getDOMNode(exec, list.item(args[0].toInt32(exec)));
718   return result;
719 }
720
721 // -------------------------------------------------------------------------
722
723 const ClassInfo DOMAttr::info = { "Attr", &DOMNode::info, &DOMAttrTable, 0 };
724
725 /* Source for DOMAttrTable. Use "make hashtables" to regenerate.
726 @begin DOMAttrTable 5
727   name          DOMAttr::Name           DontDelete|ReadOnly
728   specified     DOMAttr::Specified      DontDelete|ReadOnly
729   value         DOMAttr::ValueProperty  DontDelete|ReadOnly
730   ownerElement  DOMAttr::OwnerElement   DontDelete|ReadOnly
731 @end
732 */
733 Value DOMAttr::tryGet(ExecState *exec, const Identifier &propertyName) const
734 {
735 #ifdef KJS_VERBOSE
736   kdDebug(6070) << "DOMAttr::tryPut " << propertyName.qstring() << endl;
737 #endif
738   return DOMObjectLookupGetValue<DOMAttr,DOMNode>(exec, propertyName,
739                                                   &DOMAttrTable, this );
740 }
741
742 Value DOMAttr::getValueProperty(ExecState *exec, int token) const
743 {
744   switch (token) {
745   case Name:
746     return getStringOrNull(static_cast<DOM::Attr>(node).name());
747   case Specified:
748     return Boolean(static_cast<DOM::Attr>(node).specified());
749   case ValueProperty:
750     return getStringOrNull(static_cast<DOM::Attr>(node).value());
751   case OwnerElement: // DOM2
752     return getDOMNode(exec,static_cast<DOM::Attr>(node).ownerElement());
753   }
754   return Value(); // not reached
755 }
756
757 void DOMAttr::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
758 {
759 #ifdef KJS_VERBOSE
760   kdDebug(6070) << "DOMAttr::tryPut " << propertyName.qstring() << endl;
761 #endif
762   DOMObjectLookupPut<DOMAttr,DOMNode>(exec, propertyName, value, attr,
763                                       &DOMAttrTable, this );
764 }
765
766 void DOMAttr::putValue(ExecState *exec, int token, const Value& value, int /*attr*/)
767 {
768   switch (token) {
769   case ValueProperty:
770     static_cast<DOM::Attr>(node).setValue(value.toString(exec).string());
771     return;
772   default:
773     kdWarning() << "DOMAttr::putValue unhandled token " << token << endl;
774   }
775 }
776
777 // -------------------------------------------------------------------------
778
779 /* Source for DOMDocumentProtoTable. Use "make hashtables" to regenerate.
780 @begin DOMDocumentProtoTable 29
781   createElement   DOMDocument::CreateElement                   DontDelete|Function 1
782   createDocumentFragment DOMDocument::CreateDocumentFragment   DontDelete|Function 1
783   createTextNode  DOMDocument::CreateTextNode                  DontDelete|Function 1
784   createComment   DOMDocument::CreateComment                   DontDelete|Function 1
785   createCDATASection DOMDocument::CreateCDATASection           DontDelete|Function 1
786   createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1
787   createAttribute DOMDocument::CreateAttribute                 DontDelete|Function 1
788   createEntityReference DOMDocument::CreateEntityReference     DontDelete|Function 1
789   getElementsByTagName  DOMDocument::GetElementsByTagName      DontDelete|Function 1
790   importNode           DOMDocument::ImportNode                 DontDelete|Function 2
791   createElementNS      DOMDocument::CreateElementNS            DontDelete|Function 2
792   createAttributeNS    DOMDocument::CreateAttributeNS          DontDelete|Function 2
793   getElementsByTagNameNS  DOMDocument::GetElementsByTagNameNS  DontDelete|Function 2
794   getElementById     DOMDocument::GetElementById               DontDelete|Function 1
795   createRange        DOMDocument::CreateRange                  DontDelete|Function 0
796   createNodeIterator DOMDocument::CreateNodeIterator           DontDelete|Function 3
797   createTreeWalker   DOMDocument::CreateTreeWalker             DontDelete|Function 4
798   createEvent        DOMDocument::CreateEvent                  DontDelete|Function 1
799   getOverrideStyle   DOMDocument::GetOverrideStyle             DontDelete|Function 2
800   execCommand        DOMDocument::ExecCommand                  DontDelete|Function 3
801   queryCommandEnabled DOMDocument::QueryCommandEnabled         DontDelete|Function 1
802   queryCommandIndeterm DOMDocument::QueryCommandIndeterm       DontDelete|Function 1
803   queryCommandState DOMDocument::QueryCommandState             DontDelete|Function 1
804   queryCommandSupported DOMDocument::QueryCommandSupported     DontDelete|Function 1
805   queryCommandValue DOMDocument::QueryCommandValue             DontDelete|Function 1
806 @end
807 */
808 DEFINE_PROTOTYPE("DOMDocument", DOMDocumentProto)
809 IMPLEMENT_PROTOFUNC(DOMDocumentProtoFunc)
810 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMDocumentProto, DOMDocumentProtoFunc, DOMNodeProto)
811
812 const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 };
813
814 /* Source for DOMDocumentTable. Use "make hashtables" to regenerate.
815 @begin DOMDocumentTable 4
816   doctype         DOMDocument::DocType                         DontDelete|ReadOnly
817   implementation  DOMDocument::Implementation                  DontDelete|ReadOnly
818   documentElement DOMDocument::DocumentElement                 DontDelete|ReadOnly
819   styleSheets     DOMDocument::StyleSheets                     DontDelete|ReadOnly
820   preferredStylesheetSet  DOMDocument::PreferredStylesheetSet  DontDelete|ReadOnly
821   selectedStylesheetSet  DOMDocument::SelectedStylesheetSet    DontDelete
822   readyState      DOMDocument::ReadyState                      DontDelete|ReadOnly
823   defaultView        DOMDocument::DefaultView                  DontDelete|ReadOnly
824 @end
825 */
826
827 DOMDocument::DOMDocument(ExecState *exec, const DOM::Document &d)
828   : DOMNode(DOMDocumentProto::self(exec), d) { }
829
830 DOMDocument::DOMDocument(const Object &proto, const DOM::Document &d)
831   : DOMNode(proto, d) { }
832
833 DOMDocument::~DOMDocument()
834 {
835   ScriptInterpreter::forgetDOMObject(node.handle());
836 }
837
838 Value DOMDocument::tryGet(ExecState *exec, const Identifier &propertyName) const
839 {
840 #ifdef KJS_VERBOSE
841   kdDebug(6070) << "DOMDocument::tryGet " << propertyName.qstring() << endl;
842 #endif
843   return DOMObjectLookupGetValue<DOMDocument, DOMNode>(
844     exec, propertyName, &DOMDocumentTable, this);
845 }
846
847 Value DOMDocument::getValueProperty(ExecState *exec, int token) const
848 {
849   DOM::Document doc = static_cast<DOM::Document>(node);
850
851   switch(token) {
852   case DocType:
853     return getDOMNode(exec,doc.doctype());
854   case Implementation:
855     return getDOMDOMImplementation(exec,doc.implementation());
856   case DocumentElement:
857     return getDOMNode(exec,doc.documentElement());
858   case StyleSheets:
859     //kdDebug() << "DOMDocument::StyleSheets, returning " << doc.styleSheets().length() << " stylesheets" << endl;
860     return getDOMStyleSheetList(exec, doc.styleSheets(), doc);
861   case PreferredStylesheetSet:
862     return getStringOrNull(doc.preferredStylesheetSet());
863   case SelectedStylesheetSet:
864     return getStringOrNull(doc.selectedStylesheetSet());
865   case ReadyState:
866     {
867     DOM::DocumentImpl* docimpl = node.handle()->getDocument();
868     if ( docimpl )
869     {
870       KHTMLPart* part = docimpl->part();
871       if ( part ) {
872         if (part->d->m_bComplete) return String("complete");
873         if (docimpl->parsing()) return String("loading");
874         return String("loaded");
875         // What does the interactive value mean ?
876         // Missing support for "uninitialized"
877       }
878     }
879     return Undefined();
880     }
881   case DOMDocument::DefaultView: // DOM2
882     return getDOMAbstractView(exec,doc.defaultView());
883   default:
884     kdWarning() << "DOMDocument::getValueProperty unhandled token " << token << endl;
885     return Value();
886   }
887 }
888
889 void DOMDocument::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
890 {
891 #ifdef KJS_VERBOSE
892   kdDebug(6070) << "DOMDocument::tryPut " << propertyName.qstring() << endl;
893 #endif
894   DOMObjectLookupPut<DOMDocument,DOMNode>(exec, propertyName, value, attr, &DOMDocumentTable, this );
895 }
896
897 void DOMDocument::putValue(ExecState *exec, int token, const Value& value, int /*attr*/)
898 {
899   DOM::Document doc = static_cast<DOM::Document>(node);
900   switch (token) {
901     case SelectedStylesheetSet: {
902       doc.setSelectedStylesheetSet(value.toString(exec).string());
903       break;
904     }
905   }
906 }
907
908 Value DOMDocumentProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
909 {
910   if (!thisObj.inherits(&KJS::DOMNode::info)) {
911     Object err = Error::create(exec,TypeError);
912     exec->setException(err);
913     return err;
914   }
915   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
916   DOM::Document doc = static_cast<DOM::Document>(node);
917   String str = args[0].toString(exec);
918   DOM::DOMString s = str.value().string();
919
920   switch(id) {
921   case DOMDocument::CreateElement:
922     return getDOMNode(exec,doc.createElement(s));
923   case DOMDocument::CreateDocumentFragment:
924     return getDOMNode(exec,doc.createDocumentFragment());
925   case DOMDocument::CreateTextNode:
926     return getDOMNode(exec,doc.createTextNode(s));
927   case DOMDocument::CreateComment:
928     return getDOMNode(exec,doc.createComment(s));
929   case DOMDocument::CreateCDATASection:
930     return getDOMNode(exec,doc.createCDATASection(s));  /* TODO: okay ? */
931   case DOMDocument::CreateProcessingInstruction:
932     return getDOMNode(exec,doc.createProcessingInstruction(args[0].toString(exec).string(),
933                                                                  args[1].toString(exec).string()));
934   case DOMDocument::CreateAttribute:
935     return getDOMNode(exec,doc.createAttribute(s));
936   case DOMDocument::CreateEntityReference:
937     return getDOMNode(exec,doc.createEntityReference(args[0].toString(exec).string()));
938   case DOMDocument::GetElementsByTagName:
939     return getDOMNodeList(exec,doc.getElementsByTagName(s));
940   case DOMDocument::ImportNode: // DOM2
941     return getDOMNode(exec,doc.importNode(toNode(args[0]), args[1].toBoolean(exec)));
942   case DOMDocument::CreateElementNS: // DOM2
943     return getDOMNode(exec,doc.createElementNS(args[0].toString(exec).string(), args[1].toString(exec).string()));
944   case DOMDocument::CreateAttributeNS: // DOM2
945     return getDOMNode(exec,doc.createAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
946   case DOMDocument::GetElementsByTagNameNS: // DOM2
947     return getDOMNodeList(exec,doc.getElementsByTagNameNS(args[0].toString(exec).string(),
948                                                           args[1].toString(exec).string()));
949   case DOMDocument::GetElementById:
950     return getDOMNode(exec,doc.getElementById(args[0].toString(exec).string()));
951   case DOMDocument::CreateRange:
952     return getDOMRange(exec,doc.createRange());
953   case DOMDocument::CreateNodeIterator: {
954     NodeFilter filter;
955     if (!args[2].isA(NullType)) {
956         Object obj = Object::dynamicCast(args[2]);
957         if (!obj.isNull())
958             filter = NodeFilter(new JSNodeFilterCondition(obj));
959     }
960     return getDOMNodeIterator(exec, doc.createNodeIterator(toNode(args[0]), (long unsigned int)(args[1].toNumber(exec)), filter, args[3].toBoolean(exec)));
961   }
962   case DOMDocument::CreateTreeWalker: {
963     NodeFilter filter;
964     if (!args[2].isA(NullType)) {
965         Object obj = Object::dynamicCast(args[2]);
966         if (!obj.isNull())
967             filter = NodeFilter(new JSNodeFilterCondition(obj));
968     }
969     return getDOMTreeWalker(exec, doc.createTreeWalker(toNode(args[0]), (long unsigned int)(args[1].toNumber(exec)), filter, args[3].toBoolean(exec)));
970   }
971   case DOMDocument::CreateEvent:
972     return getDOMEvent(exec,doc.createEvent(s));
973   case DOMDocument::GetOverrideStyle: {
974     DOM::Node arg0 = toNode(args[0]);
975     if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
976       return Undefined(); // throw exception?
977     else
978       return getDOMCSSStyleDeclaration(exec,doc.getOverrideStyle(static_cast<DOM::Element>(arg0),args[1].toString(exec).string()));
979   }
980   case DOMDocument::ExecCommand: {
981     return Boolean(doc.execCommand(args[0].toString(exec).string(), args[1].toBoolean(exec), args[2].toString(exec).string()));
982   }
983   case DOMDocument::QueryCommandEnabled: {
984     return Boolean(doc.queryCommandEnabled(args[0].toString(exec).string()));
985   }
986   case DOMDocument::QueryCommandIndeterm: {
987     return Boolean(doc.queryCommandIndeterm(args[0].toString(exec).string()));
988   }
989   case DOMDocument::QueryCommandState: {
990     return Boolean(doc.queryCommandState(args[0].toString(exec).string()));
991   }
992   case DOMDocument::QueryCommandSupported: {
993     return Boolean(doc.queryCommandSupported(args[0].toString(exec).string()));
994   }
995   case DOMDocument::QueryCommandValue: {
996     DOM::DOMString commandValue(doc.queryCommandValue(args[0].toString(exec).string()));
997     // Method returns null DOMString to signal command is unsupported.
998     // Micorsoft documentation for this method says:
999     // "If not supported [for a command identifier], this method returns a Boolean set to false."
1000     if (commandValue.isNull())
1001         return Boolean(false);
1002     else 
1003         return String(commandValue);
1004   }
1005   default:
1006     break;
1007   }
1008
1009   return Undefined();
1010 }
1011
1012 // -------------------------------------------------------------------------
1013
1014 /* Source for DOMElementProtoTable. Use "make hashtables" to regenerate.
1015 @begin DOMElementProtoTable 17
1016   getAttribute          DOMElement::GetAttribute        DontDelete|Function 1
1017   setAttribute          DOMElement::SetAttribute        DontDelete|Function 2
1018   removeAttribute       DOMElement::RemoveAttribute     DontDelete|Function 1
1019   getAttributeNode      DOMElement::GetAttributeNode    DontDelete|Function 1
1020   setAttributeNode      DOMElement::SetAttributeNode    DontDelete|Function 2
1021   removeAttributeNode   DOMElement::RemoveAttributeNode DontDelete|Function 1
1022   getElementsByTagName  DOMElement::GetElementsByTagName        DontDelete|Function 1
1023   hasAttribute          DOMElement::HasAttribute        DontDelete|Function 1
1024   getAttributeNS        DOMElement::GetAttributeNS      DontDelete|Function 2
1025   setAttributeNS        DOMElement::SetAttributeNS      DontDelete|Function 3
1026   removeAttributeNS     DOMElement::RemoveAttributeNS   DontDelete|Function 2
1027   getAttributeNodeNS    DOMElement::GetAttributeNodeNS  DontDelete|Function 2
1028   setAttributeNodeNS    DOMElement::SetAttributeNodeNS  DontDelete|Function 1
1029   getElementsByTagNameNS DOMElement::GetElementsByTagNameNS     DontDelete|Function 2
1030   hasAttributeNS        DOMElement::HasAttributeNS      DontDelete|Function 2
1031 # extension for Safari RSS
1032   scrollByLines         DOMElement::ScrollByLines       DontDelete|Function 1
1033   scrollByPages         DOMElement::ScrollByPages       DontDelete|Function 1
1034
1035 @end
1036 */
1037 DEFINE_PROTOTYPE("DOMElement",DOMElementProto)
1038 IMPLEMENT_PROTOFUNC(DOMElementProtoFunc)
1039 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMElementProto,DOMElementProtoFunc,DOMNodeProto)
1040
1041 const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 };
1042 /* Source for DOMElementTable. Use "make hashtables" to regenerate.
1043 @begin DOMElementTable 3
1044   tagName       DOMElement::TagName                         DontDelete|ReadOnly
1045   style         DOMElement::Style                           DontDelete|ReadOnly
1046 @end
1047 */
1048 DOMElement::DOMElement(ExecState *exec, const DOM::Element &e)
1049   : DOMNode(DOMElementProto::self(exec), e) { }
1050
1051 DOMElement::DOMElement(const Object &proto, const DOM::Element &e)
1052   : DOMNode(proto, e) { }
1053
1054 Value DOMElement::tryGet(ExecState *exec, const Identifier &propertyName) const
1055 {
1056 #ifdef KJS_VERBOSE
1057   kdDebug(6070) << "DOMElement::tryGet " << propertyName.qstring() << endl;
1058 #endif
1059   DOM::Element element = static_cast<DOM::Element>(node);
1060
1061   const HashEntry* entry = Lookup::findEntry(&DOMElementTable, propertyName);
1062   if (entry)
1063   {
1064     switch( entry->value ) {
1065     case TagName:
1066       return getStringOrNull(element.tagName());
1067     case Style:
1068       return getDOMCSSStyleDeclaration(exec,element.style());
1069     default:
1070       kdWarning() << "Unhandled token in DOMElement::tryGet : " << entry->value << endl;
1071       break;
1072     }
1073   }
1074   // We have to check in DOMNode before giving access to attributes, otherwise
1075   // onload="..." would make onload return the string (attribute value) instead of
1076   // the listener object (function).
1077   if (DOMNode::hasProperty(exec, propertyName))
1078     return DOMNode::tryGet(exec, propertyName);
1079
1080   DOM::DOMString attr = element.getAttribute( propertyName.string() );
1081   // Give access to attributes
1082   if ( !attr.isNull() )
1083     return getStringOrNull( attr );
1084
1085   return Undefined();
1086 }
1087
1088 Value DOMElementProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1089 {
1090   if (!thisObj.inherits(&KJS::DOMNode::info)) { // node should be enough here, given the cast
1091     Object err = Error::create(exec,TypeError);
1092     exec->setException(err);
1093     return err;
1094   }
1095   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
1096   DOM::Element element = static_cast<DOM::Element>(node);
1097
1098   switch(id) {
1099     case DOMElement::GetAttribute:
1100       // getString should be used here, since if the attribute isn't present at all, you should
1101       // return null and not "".
1102       return getStringOrNull(element.getAttribute(args[0].toString(exec).string()));
1103     case DOMElement::SetAttribute:
1104       element.setAttribute(args[0].toString(exec).string(),args[1].toString(exec).string());
1105       return Undefined();
1106     case DOMElement::RemoveAttribute:
1107       element.removeAttribute(args[0].toString(exec).string());
1108       return Undefined();
1109     case DOMElement::GetAttributeNode:
1110       return getDOMNode(exec,element.getAttributeNode(args[0].toString(exec).string()));
1111     case DOMElement::SetAttributeNode:
1112       return getDOMNode(exec,element.setAttributeNode((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
1113     case DOMElement::RemoveAttributeNode:
1114       return getDOMNode(exec,element.removeAttributeNode((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
1115     case DOMElement::GetElementsByTagName:
1116       return getDOMNodeList(exec,element.getElementsByTagName(args[0].toString(exec).string()));
1117     case DOMElement::HasAttribute: // DOM2
1118       return Boolean(element.hasAttribute(args[0].toString(exec).string()));
1119     case DOMElement::GetAttributeNS: // DOM2
1120       return String(element.getAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
1121     case DOMElement::SetAttributeNS: // DOM2
1122       element.setAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string());
1123       return Undefined();
1124     case DOMElement::RemoveAttributeNS: // DOM2
1125       element.removeAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string());
1126       return Undefined();
1127     case DOMElement::GetAttributeNodeNS: // DOM2
1128       return getDOMNode(exec,element.getAttributeNodeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
1129     case DOMElement::SetAttributeNodeNS: // DOM2
1130       return getDOMNode(exec,element.setAttributeNodeNS((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
1131     case DOMElement::GetElementsByTagNameNS: // DOM2
1132       return getDOMNodeList(exec,element.getElementsByTagNameNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
1133     case DOMElement::HasAttributeNS: // DOM2
1134       return Boolean(element.hasAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
1135     case DOMElement::ScrollByLines:
1136     case DOMElement::ScrollByPages:
1137     {
1138         DOM::DocumentImpl* docimpl = node.handle()->getDocument();
1139         if (docimpl) {
1140             docimpl->updateLayoutIgnorePendingStylesheets();
1141         }            
1142         khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
1143         if (rend && rend->hasOverflowClip()) {
1144             KWQScrollDirection direction = KWQScrollDown;
1145             int multiplier = args[0].toInt32(exec);
1146             if (multiplier < 0) {
1147                 direction = KWQScrollUp;
1148                 multiplier = -multiplier;
1149             }
1150             KWQScrollGranularity granularity = id == DOMElement::ScrollByLines ? KWQScrollLine : KWQScrollPage;
1151             rend->layer()->scroll(direction, granularity, multiplier);
1152         }
1153         return Undefined();
1154         
1155     }
1156   default:
1157     return Undefined();
1158   }
1159 }
1160
1161 // -------------------------------------------------------------------------
1162
1163 /* Source for DOMDOMImplementationProtoTable. Use "make hashtables" to regenerate.
1164 @begin DOMDOMImplementationProtoTable 5
1165   hasFeature            DOMDOMImplementation::HasFeature                DontDelete|Function 2
1166 # DOM2
1167   createCSSStyleSheet   DOMDOMImplementation::CreateCSSStyleSheet       DontDelete|Function 2
1168   createDocumentType    DOMDOMImplementation::CreateDocumentType        DontDelete|Function 3
1169   createDocument        DOMDOMImplementation::CreateDocument            DontDelete|Function 3
1170   createHTMLDocument    DOMDOMImplementation::CreateHTMLDocument        DontDelete|Function 1
1171 @end
1172 */
1173 DEFINE_PROTOTYPE("DOMImplementation",DOMDOMImplementationProto)
1174 IMPLEMENT_PROTOFUNC(DOMDOMImplementationProtoFunc)
1175 IMPLEMENT_PROTOTYPE(DOMDOMImplementationProto,DOMDOMImplementationProtoFunc)
1176
1177 const ClassInfo DOMDOMImplementation::info = { "DOMImplementation", 0, 0, 0 };
1178
1179 DOMDOMImplementation::DOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation &i)
1180   : DOMObject(DOMDOMImplementationProto::self(exec)), implementation(i) { }
1181
1182 DOMDOMImplementation::~DOMDOMImplementation()
1183 {
1184   ScriptInterpreter::forgetDOMObject(implementation.handle());
1185 }
1186
1187 Value DOMDOMImplementationProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1188 {
1189   if (!thisObj.inherits(&KJS::DOMDOMImplementation::info)) {
1190     Object err = Error::create(exec,TypeError);
1191     exec->setException(err);
1192     return err;
1193   }
1194   DOM::DOMImplementation implementation = static_cast<DOMDOMImplementation *>( thisObj.imp() )->toImplementation();
1195
1196   switch(id) {
1197   case DOMDOMImplementation::HasFeature:
1198     return Boolean(implementation.hasFeature(args[0].toString(exec).string(),
1199         (args[1].type() != UndefinedType && args[1].type() != NullType) ? args[1].toString(exec).string() : DOMString()));
1200   case DOMDOMImplementation::CreateDocumentType: // DOM2
1201     return getDOMNode(exec,implementation.createDocumentType(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string()));
1202   case DOMDOMImplementation::CreateDocument: // DOM2
1203     return getDOMNode(exec,implementation.createDocument(args[0].toString(exec).string(),args[1].toString(exec).string(),toNode(args[2])));
1204   case DOMDOMImplementation::CreateCSSStyleSheet: // DOM2
1205     return getDOMStyleSheet(exec,implementation.createCSSStyleSheet(args[0].toString(exec).string(),args[1].toString(exec).string()));
1206   case DOMDOMImplementation::CreateHTMLDocument: // DOM2-HTML
1207     return getDOMNode(exec, implementation.createHTMLDocument(args[0].toString(exec).string()));
1208   default:
1209     break;
1210   }
1211   return Undefined();
1212 }
1213
1214 // -------------------------------------------------------------------------
1215
1216 const ClassInfo DOMDocumentType::info = { "DocumentType", &DOMNode::info, &DOMDocumentTypeTable, 0 };
1217
1218 /* Source for DOMDocumentTypeTable. Use "make hashtables" to regenerate.
1219 @begin DOMDocumentTypeTable 6
1220   name                  DOMDocumentType::Name           DontDelete|ReadOnly
1221   entities              DOMDocumentType::Entities       DontDelete|ReadOnly
1222   notations             DOMDocumentType::Notations      DontDelete|ReadOnly
1223 # DOM2
1224   publicId              DOMDocumentType::PublicId       DontDelete|ReadOnly
1225   systemId              DOMDocumentType::SystemId       DontDelete|ReadOnly
1226   internalSubset        DOMDocumentType::InternalSubset DontDelete|ReadOnly
1227 @end
1228 */
1229 DOMDocumentType::DOMDocumentType(ExecState *exec, const DOM::DocumentType &dt)
1230   : DOMNode( /*### no proto yet*/exec, dt ) { }
1231
1232 Value DOMDocumentType::tryGet(ExecState *exec, const Identifier &propertyName) const
1233 {
1234   return DOMObjectLookupGetValue<DOMDocumentType, DOMNode>(exec, propertyName, &DOMDocumentTypeTable, this);
1235 }
1236
1237 Value DOMDocumentType::getValueProperty(ExecState *exec, int token) const
1238 {
1239   DOM::DocumentType type = static_cast<DOM::DocumentType>(node);
1240   switch (token) {
1241   case Name:
1242     return getStringOrNull(type.name());
1243   case Entities:
1244     return getDOMNamedNodeMap(exec,type.entities());
1245   case Notations:
1246     return getDOMNamedNodeMap(exec,type.notations());
1247   case PublicId: // DOM2
1248     return getStringOrNull(type.publicId());
1249   case SystemId: // DOM2
1250     return getStringOrNull(type.systemId());
1251   case InternalSubset: // DOM2
1252     return getStringOrNull(type.internalSubset());
1253   default:
1254     kdWarning() << "DOMDocumentType::getValueProperty unhandled token " << token << endl;
1255     return Value();
1256   }
1257 }
1258
1259 // -------------------------------------------------------------------------
1260
1261 /* Source for DOMNamedNodeMapProtoTable. Use "make hashtables" to regenerate.
1262 @begin DOMNamedNodeMapProtoTable 7
1263   getNamedItem          DOMNamedNodeMap::GetNamedItem           DontDelete|Function 1
1264   setNamedItem          DOMNamedNodeMap::SetNamedItem           DontDelete|Function 1
1265   removeNamedItem       DOMNamedNodeMap::RemoveNamedItem        DontDelete|Function 1
1266   item                  DOMNamedNodeMap::Item                   DontDelete|Function 1
1267 # DOM2
1268   getNamedItemNS        DOMNamedNodeMap::GetNamedItemNS         DontDelete|Function 2
1269   setNamedItemNS        DOMNamedNodeMap::SetNamedItemNS         DontDelete|Function 1
1270   removeNamedItemNS     DOMNamedNodeMap::RemoveNamedItemNS      DontDelete|Function 2
1271 @end
1272 */
1273 DEFINE_PROTOTYPE("NamedNodeMap", DOMNamedNodeMapProto)
1274 IMPLEMENT_PROTOFUNC(DOMNamedNodeMapProtoFunc)
1275 IMPLEMENT_PROTOTYPE(DOMNamedNodeMapProto,DOMNamedNodeMapProtoFunc)
1276
1277 const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", 0, 0, 0 };
1278
1279 DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap &m)
1280   : DOMObject(DOMNamedNodeMapProto::self(exec)), map(m) { }
1281
1282 DOMNamedNodeMap::~DOMNamedNodeMap()
1283 {
1284   ScriptInterpreter::forgetDOMObject(map.handle());
1285 }
1286
1287 // We have to implement hasProperty since we don't use a hashtable for 'length'
1288 // ## this breaks "for (..in..)" though.
1289 bool DOMNamedNodeMap::hasProperty(ExecState *exec, const Identifier &p) const
1290 {
1291   if (p == lengthPropertyName)
1292     return true;
1293   return DOMObject::hasProperty(exec, p);
1294 }
1295
1296 Value DOMNamedNodeMap::tryGet(ExecState* exec, const Identifier &p) const
1297 {
1298   if (p == lengthPropertyName)
1299     return Number(map.length());
1300
1301   // array index ?
1302   bool ok;
1303   long unsigned int idx = p.toULong(&ok);
1304   if (ok)
1305     return getDOMNode(exec,map.item(idx));
1306
1307   // Anything else (including functions, defined in the prototype)
1308   return DOMObject::tryGet(exec, p);
1309 }
1310
1311 Value DOMNamedNodeMapProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1312 {
1313   if (!thisObj.inherits(&KJS::DOMNamedNodeMap::info)) {
1314     Object err = Error::create(exec,TypeError);
1315     exec->setException(err);
1316     return err;
1317   }
1318   DOM::NamedNodeMap map = static_cast<DOMNamedNodeMap *>(thisObj.imp())->toMap();
1319
1320   switch(id) {
1321     case DOMNamedNodeMap::GetNamedItem:
1322       return getDOMNode(exec, map.getNamedItem(args[0].toString(exec).string()));
1323     case DOMNamedNodeMap::SetNamedItem:
1324       return getDOMNode(exec, map.setNamedItem((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
1325     case DOMNamedNodeMap::RemoveNamedItem:
1326       return getDOMNode(exec, map.removeNamedItem(args[0].toString(exec).string()));
1327     case DOMNamedNodeMap::Item:
1328       return getDOMNode(exec, map.item(args[0].toInt32(exec)));
1329     case DOMNamedNodeMap::GetNamedItemNS: // DOM2
1330       return getDOMNode(exec, map.getNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
1331     case DOMNamedNodeMap::SetNamedItemNS: // DOM2
1332       return getDOMNode(exec, map.setNamedItemNS(toNode(args[0])));
1333     case DOMNamedNodeMap::RemoveNamedItemNS: // DOM2
1334       return getDOMNode(exec, map.removeNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
1335     default:
1336       break;
1337   }
1338
1339   return Undefined();
1340 }
1341
1342 // -------------------------------------------------------------------------
1343
1344 const ClassInfo DOMProcessingInstruction::info = { "ProcessingInstruction", &DOMNode::info, &DOMProcessingInstructionTable, 0 };
1345
1346 /* Source for DOMProcessingInstructionTable. Use "make hashtables" to regenerate.
1347 @begin DOMProcessingInstructionTable 3
1348   target        DOMProcessingInstruction::Target        DontDelete|ReadOnly
1349   data          DOMProcessingInstruction::Data          DontDelete
1350   sheet         DOMProcessingInstruction::Sheet         DontDelete|ReadOnly
1351 @end
1352 */
1353 Value DOMProcessingInstruction::tryGet(ExecState *exec, const Identifier &propertyName) const
1354 {
1355   return DOMObjectLookupGetValue<DOMProcessingInstruction, DOMNode>(exec, propertyName, &DOMProcessingInstructionTable, this);
1356 }
1357
1358 Value DOMProcessingInstruction::getValueProperty(ExecState *exec, int token) const
1359 {
1360   switch (token) {
1361   case Target:
1362     return getStringOrNull(static_cast<DOM::ProcessingInstruction>(node).target());
1363   case Data:
1364     return getStringOrNull(static_cast<DOM::ProcessingInstruction>(node).data());
1365   case Sheet:
1366     return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
1367   default:
1368     kdWarning() << "DOMProcessingInstruction::getValueProperty unhandled token " << token << endl;
1369     return Value();
1370   }
1371 }
1372
1373 void DOMProcessingInstruction::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
1374 {
1375   // Not worth using the hashtable for this one ;)
1376   if (propertyName == "data")
1377     static_cast<DOM::ProcessingInstruction>(node).setData(value.toString(exec).string());
1378   else
1379     DOMNode::tryPut(exec, propertyName,value,attr);
1380 }
1381
1382 // -------------------------------------------------------------------------
1383
1384 const ClassInfo DOMNotation::info = { "Notation", &DOMNode::info, &DOMNotationTable, 0 };
1385
1386 /* Source for DOMNotationTable. Use "make hashtables" to regenerate.
1387 @begin DOMNotationTable 2
1388   publicId              DOMNotation::PublicId   DontDelete|ReadOnly
1389   systemId              DOMNotation::SystemId   DontDelete|ReadOnly
1390 @end
1391 */
1392 Value DOMNotation::tryGet(ExecState *exec, const Identifier &propertyName) const
1393 {
1394   return DOMObjectLookupGetValue<DOMNotation, DOMNode>(exec, propertyName, &DOMNotationTable, this);
1395 }
1396
1397 Value DOMNotation::getValueProperty(ExecState *, int token) const
1398 {
1399   switch (token) {
1400   case PublicId:
1401     return getStringOrNull(static_cast<DOM::Notation>(node).publicId());
1402   case SystemId:
1403     return getStringOrNull(static_cast<DOM::Notation>(node).systemId());
1404   default:
1405     kdWarning() << "DOMNotation::getValueProperty unhandled token " << token << endl;
1406     return Value();
1407   }
1408 }
1409
1410 // -------------------------------------------------------------------------
1411
1412 const ClassInfo DOMEntity::info = { "Entity", &DOMNode::info, 0, 0 };
1413
1414 /* Source for DOMEntityTable. Use "make hashtables" to regenerate.
1415 @begin DOMEntityTable 2
1416   publicId              DOMEntity::PublicId             DontDelete|ReadOnly
1417   systemId              DOMEntity::SystemId             DontDelete|ReadOnly
1418   notationName          DOMEntity::NotationName DontDelete|ReadOnly
1419 @end
1420 */
1421 Value DOMEntity::tryGet(ExecState *exec, const Identifier &propertyName) const
1422 {
1423   return DOMObjectLookupGetValue<DOMEntity, DOMNode>(exec, propertyName, &DOMEntityTable, this);
1424 }
1425
1426 Value DOMEntity::getValueProperty(ExecState *, int token) const
1427 {
1428   switch (token) {
1429   case PublicId:
1430     return getStringOrNull(static_cast<DOM::Entity>(node).publicId());
1431   case SystemId:
1432     return getStringOrNull(static_cast<DOM::Entity>(node).systemId());
1433   case NotationName:
1434     return getStringOrNull(static_cast<DOM::Entity>(node).notationName());
1435   default:
1436     kdWarning() << "DOMEntity::getValueProperty unhandled token " << token << endl;
1437     return Value();
1438   }
1439 }
1440
1441 // -------------------------------------------------------------------------
1442
1443 Value KJS::getDOMDocumentNode(ExecState *exec, const DOM::Document &n)
1444 {
1445   DOMDocument *ret = 0;
1446   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1447
1448   if ((ret = static_cast<DOMDocument *>(interp->getDOMObject(n.handle()))))
1449     return Value(ret);
1450
1451   if (n.isHTMLDocument())
1452     ret = new HTMLDocument(exec, static_cast<DOM::HTMLDocument>(n));
1453   else
1454     ret = new DOMDocument(exec, n);
1455
1456   Value val(ret);
1457   
1458   // Make sure the document is kept around by the window object, and works right with the
1459   // back/forward cache.
1460   if (n.view()) {
1461     static Identifier documentIdentifier("document");
1462     Window::retrieveWindow(n.view()->part())->putDirect(documentIdentifier, ret, DontDelete|ReadOnly);
1463   }
1464
1465   interp->putDOMObject(n.handle(), ret);
1466
1467   return val;
1468 }
1469
1470 bool KJS::checkNodeSecurity(ExecState *exec, const DOM::Node& n)
1471 {
1472   if (!n.handle()) 
1473     return false;
1474
1475   // Check to see if the currently executing interpreter is allowed to access the specified node
1476   KHTMLPart *part = n.handle()->getDocument()->part();
1477   Window* win = part ? Window::retrieveWindow(part) : 0L;
1478   if ( !win || !win->isSafeScript(exec) )
1479     return false;
1480   return true;
1481 }
1482
1483
1484 Value KJS::getDOMNode(ExecState *exec, const DOM::Node &n)
1485 {
1486   DOMObject *ret = 0;
1487   if (n.isNull())
1488     return Null();
1489   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1490   DOM::NodeImpl *doc = n.ownerDocument().handle();
1491
1492   if ((ret = interp->getDOMObjectForDocument(static_cast<DOM::DocumentImpl *>(doc), n.handle())))
1493     return Value(ret);
1494
1495   switch (n.nodeType()) {
1496     case DOM::Node::ELEMENT_NODE:
1497       if (static_cast<DOM::Element>(n).isHTMLElement())
1498         ret = new HTMLElement(exec, static_cast<DOM::HTMLElement>(n));
1499       else
1500         ret = new DOMElement(exec, static_cast<DOM::Element>(n));
1501       break;
1502     case DOM::Node::ATTRIBUTE_NODE:
1503       ret = new DOMAttr(exec, static_cast<DOM::Attr>(n));
1504       break;
1505     case DOM::Node::TEXT_NODE:
1506     case DOM::Node::CDATA_SECTION_NODE:
1507       ret = new DOMText(exec, static_cast<DOM::Text>(n));
1508       break;
1509     case DOM::Node::ENTITY_REFERENCE_NODE:
1510       ret = new DOMNode(exec, n);
1511       break;
1512     case DOM::Node::ENTITY_NODE:
1513       ret = new DOMEntity(exec, static_cast<DOM::Entity>(n));
1514       break;
1515     case DOM::Node::PROCESSING_INSTRUCTION_NODE:
1516       ret = new DOMProcessingInstruction(exec, static_cast<DOM::ProcessingInstruction>(n));
1517       break;
1518     case DOM::Node::COMMENT_NODE:
1519       ret = new DOMCharacterData(exec, static_cast<DOM::CharacterData>(n));
1520       break;
1521     case DOM::Node::DOCUMENT_NODE:
1522       // we don't want to cache the document itself in the per-document dictionary
1523       return getDOMDocumentNode(exec, static_cast<DOM::Document>(n));
1524     case DOM::Node::DOCUMENT_TYPE_NODE:
1525       ret = new DOMDocumentType(exec, static_cast<DOM::DocumentType>(n));
1526       break;
1527     case DOM::Node::DOCUMENT_FRAGMENT_NODE:
1528       ret = new DOMNode(exec, n);
1529       break;
1530     case DOM::Node::NOTATION_NODE:
1531       ret = new DOMNotation(exec, static_cast<DOM::Notation>(n));
1532       break;
1533     default:
1534       ret = new DOMNode(exec, n);
1535   }
1536
1537   interp->putDOMObjectForDocument(static_cast<DOM::DocumentImpl *>(doc), n.handle(), ret);
1538
1539   return Value(ret);
1540 }
1541
1542 Value KJS::getDOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap &m)
1543 {
1544   return Value(cacheDOMObject<DOM::NamedNodeMap, KJS::DOMNamedNodeMap>(exec, m));
1545 }
1546
1547 Value KJS::getRuntimeObject(ExecState *exec, const DOM::Node &node)
1548 {
1549     DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
1550
1551     if (!node.isNull()) {
1552         if (node.handle()->id() == ID_APPLET) {
1553             DOM::HTMLAppletElementImpl *appletElement = static_cast<DOM::HTMLAppletElementImpl *>(element.handle());
1554             
1555             if (appletElement->getAppletInstance()) {
1556                 // The instance is owned by the applet element.
1557                 RuntimeObjectImp *appletImp = new RuntimeObjectImp(appletElement->getAppletInstance(), false);
1558                 return Value(appletImp);
1559             }
1560         }
1561         else if (node.handle()->id() == ID_EMBED) {
1562             DOM::HTMLEmbedElementImpl *embedElement = static_cast<DOM::HTMLEmbedElementImpl *>(element.handle());
1563             
1564             if (embedElement->getEmbedInstance()) {
1565                 RuntimeObjectImp *runtimeImp = new RuntimeObjectImp(embedElement->getEmbedInstance(), false);
1566                 return Value(runtimeImp);
1567             }
1568         }
1569     }
1570     
1571     // If we don't have a runtime object return the a Value that reports isNull() == true.
1572     return Value();
1573 }
1574
1575 Value KJS::getDOMNodeList(ExecState *exec, const DOM::NodeList &l)
1576 {
1577   return Value(cacheDOMObject<DOM::NodeList, KJS::DOMNodeList>(exec, l));
1578 }
1579
1580 Value KJS::getDOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation &i)
1581 {
1582   return Value(cacheDOMObject<DOM::DOMImplementation, KJS::DOMDOMImplementation>(exec, i));
1583 }
1584
1585 // -------------------------------------------------------------------------
1586
1587 const ClassInfo NodeConstructor::info = { "NodeConstructor", 0, &NodeConstructorTable, 0 };
1588 /* Source for NodeConstructorTable. Use "make hashtables" to regenerate.
1589 @begin NodeConstructorTable 11
1590   ELEMENT_NODE          DOM::Node::ELEMENT_NODE         DontDelete|ReadOnly
1591   ATTRIBUTE_NODE        DOM::Node::ATTRIBUTE_NODE               DontDelete|ReadOnly
1592   TEXT_NODE             DOM::Node::TEXT_NODE            DontDelete|ReadOnly
1593   CDATA_SECTION_NODE    DOM::Node::CDATA_SECTION_NODE   DontDelete|ReadOnly
1594   ENTITY_REFERENCE_NODE DOM::Node::ENTITY_REFERENCE_NODE        DontDelete|ReadOnly
1595   ENTITY_NODE           DOM::Node::ENTITY_NODE          DontDelete|ReadOnly
1596   PROCESSING_INSTRUCTION_NODE DOM::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
1597   COMMENT_NODE          DOM::Node::COMMENT_NODE         DontDelete|ReadOnly
1598   DOCUMENT_NODE         DOM::Node::DOCUMENT_NODE                DontDelete|ReadOnly
1599   DOCUMENT_TYPE_NODE    DOM::Node::DOCUMENT_TYPE_NODE   DontDelete|ReadOnly
1600   DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE      DontDelete|ReadOnly
1601   NOTATION_NODE         DOM::Node::NOTATION_NODE                DontDelete|ReadOnly
1602 @end
1603 */
1604 Value NodeConstructor::tryGet(ExecState *exec, const Identifier &propertyName) const
1605 {
1606   return DOMObjectLookupGetValue<NodeConstructor, DOMObject>(exec, propertyName, &NodeConstructorTable, this);
1607 }
1608
1609 Value NodeConstructor::getValueProperty(ExecState *, int token) const
1610 {
1611   // We use the token as the value to return directly
1612   return Number((unsigned int)token);
1613 #if 0
1614   switch (token) {
1615   case ELEMENT_NODE:
1616     return Number((unsigned int)DOM::Node::ELEMENT_NODE);
1617   case ATTRIBUTE_NODE:
1618     return Number((unsigned int)DOM::Node::ATTRIBUTE_NODE);
1619   case TEXT_NODE:
1620     return Number((unsigned int)DOM::Node::TEXT_NODE);
1621   case CDATA_SECTION_NODE:
1622     return Number((unsigned int)DOM::Node::CDATA_SECTION_NODE);
1623   case ENTITY_REFERENCE_NODE:
1624     return Number((unsigned int)DOM::Node::ENTITY_REFERENCE_NODE);
1625   case ENTITY_NODE:
1626     return Number((unsigned int)DOM::Node::ENTITY_NODE);
1627   case PROCESSING_INSTRUCTION_NODE:
1628     return Number((unsigned int)DOM::Node::PROCESSING_INSTRUCTION_NODE);
1629   case COMMENT_NODE:
1630     return Number((unsigned int)DOM::Node::COMMENT_NODE);
1631   case DOCUMENT_NODE:
1632     return Number((unsigned int)DOM::Node::DOCUMENT_NODE);
1633   case DOCUMENT_TYPE_NODE:
1634     return Number((unsigned int)DOM::Node::DOCUMENT_TYPE_NODE);
1635   case DOCUMENT_FRAGMENT_NODE:
1636     return Number((unsigned int)DOM::Node::DOCUMENT_FRAGMENT_NODE);
1637   case NOTATION_NODE:
1638     return Number((unsigned int)DOM::Node::NOTATION_NODE);
1639   default:
1640     kdWarning() << "NodeConstructor::getValueProperty unhandled token " << token << endl;
1641     return Value();
1642   }
1643 #endif
1644 }
1645
1646 Object KJS::getNodeConstructor(ExecState *exec)
1647 {
1648   return Object(cacheGlobalObject<NodeConstructor>(exec, "[[node.constructor]]"));
1649 }
1650
1651 // -------------------------------------------------------------------------
1652
1653 const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0, 0, 0 };
1654
1655 /* Source for DOMExceptionConstructorTable. Use "make hashtables" to regenerate.
1656 @begin DOMExceptionConstructorTable 15
1657   INDEX_SIZE_ERR                DOM::DOMException::INDEX_SIZE_ERR               DontDelete|ReadOnly
1658   DOMSTRING_SIZE_ERR            DOM::DOMException::DOMSTRING_SIZE_ERR   DontDelete|ReadOnly
1659   HIERARCHY_REQUEST_ERR         DOM::DOMException::HIERARCHY_REQUEST_ERR        DontDelete|ReadOnly
1660   WRONG_DOCUMENT_ERR            DOM::DOMException::WRONG_DOCUMENT_ERR   DontDelete|ReadOnly
1661   INVALID_CHARACTER_ERR         DOM::DOMException::INVALID_CHARACTER_ERR        DontDelete|ReadOnly
1662   NO_DATA_ALLOWED_ERR           DOM::DOMException::NO_DATA_ALLOWED_ERR  DontDelete|ReadOnly
1663   NO_MODIFICATION_ALLOWED_ERR   DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR  DontDelete|ReadOnly
1664   NOT_FOUND_ERR                 DOM::DOMException::NOT_FOUND_ERR                DontDelete|ReadOnly
1665   NOT_SUPPORTED_ERR             DOM::DOMException::NOT_SUPPORTED_ERR    DontDelete|ReadOnly
1666   INUSE_ATTRIBUTE_ERR           DOM::DOMException::INUSE_ATTRIBUTE_ERR  DontDelete|ReadOnly
1667   INVALID_STATE_ERR             DOM::DOMException::INVALID_STATE_ERR    DontDelete|ReadOnly
1668   SYNTAX_ERR                    DOM::DOMException::SYNTAX_ERR           DontDelete|ReadOnly
1669   INVALID_MODIFICATION_ERR      DOM::DOMException::INVALID_MODIFICATION_ERR     DontDelete|ReadOnly
1670   NAMESPACE_ERR                 DOM::DOMException::NAMESPACE_ERR                DontDelete|ReadOnly
1671   INVALID_ACCESS_ERR            DOM::DOMException::INVALID_ACCESS_ERR   DontDelete|ReadOnly
1672 @end
1673 */
1674
1675 Value DOMExceptionConstructor::tryGet(ExecState *exec, const Identifier &propertyName) const
1676 {
1677   return DOMObjectLookupGetValue<DOMExceptionConstructor, DOMObject>(exec, propertyName, &DOMExceptionConstructorTable, this);
1678 }
1679
1680 Value DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
1681 {
1682   // We use the token as the value to return directly
1683   return Number((unsigned int)token);
1684 #if 0
1685   switch (token) {
1686   case INDEX_SIZE_ERR:
1687     return Number((unsigned int)DOM::DOMException::INDEX_SIZE_ERR);
1688   case DOMSTRING_SIZE_ERR:
1689     return Number((unsigned int)DOM::DOMException::DOMSTRING_SIZE_ERR);
1690   case HIERARCHY_REQUEST_ERR:
1691     return Number((unsigned int)DOM::DOMException::HIERARCHY_REQUEST_ERR);
1692   case WRONG_DOCUMENT_ERR:
1693     return Number((unsigned int)DOM::DOMException::WRONG_DOCUMENT_ERR);
1694   case INVALID_CHARACTER_ERR:
1695     return Number((unsigned int)DOM::DOMException::INVALID_CHARACTER_ERR);
1696   case NO_DATA_ALLOWED_ERR:
1697     return Number((unsigned int)DOM::DOMException::NO_DATA_ALLOWED_ERR);
1698   case NO_MODIFICATION_ALLOWED_ERR:
1699     return Number((unsigned int)DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR);
1700   case NOT_FOUND_ERR:
1701     return Number((unsigned int)DOM::DOMException::NOT_FOUND_ERR);
1702   case NOT_SUPPORTED_ERR:
1703     return Number((unsigned int)DOM::DOMException::NOT_SUPPORTED_ERR);
1704   case INUSE_ATTRIBUTE_ERR:
1705     return Number((unsigned int)DOM::DOMException::INUSE_ATTRIBUTE_ERR);
1706   case INVALID_STATE_ERR:
1707     return Number((unsigned int)DOM::DOMException::INVALID_STATE_ERR);
1708   case SYNTAX_ERR:
1709     return Number((unsigned int)DOM::DOMException::SYNTAX_ERR);
1710   case INVALID_MODIFICATION_ERR:
1711     return Number((unsigned int)DOM::DOMException::INVALID_MODIFICATION_ERR);
1712   case NAMESPACE_ERR:
1713     return Number((unsigned int)DOM::DOMException::NAMESPACE_ERR);
1714   case INVALID_ACCESS_ERR:
1715     return Number((unsigned int)DOM::DOMException::INVALID_ACCESS_ERR);
1716   default:
1717     kdWarning() << "DOMExceptionConstructor::getValueProperty unhandled token " << token << endl;
1718     return Value();
1719   }
1720 #endif
1721 }
1722
1723 Object KJS::getDOMExceptionConstructor(ExecState *exec)
1724 {
1725   return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
1726 }
1727
1728 // -------------------------------------------------------------------------
1729
1730 // Such a collection is usually very short-lived, it only exists
1731 // for constructs like document.forms.<name>[1],
1732 // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
1733 DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *, const QValueList<DOM::Node>& nodes )
1734   : DOMObject(), m_nodes(nodes)
1735 {
1736   // Maybe we should ref (and deref in the dtor) the nodes, though ?
1737 }
1738
1739 Value DOMNamedNodesCollection::tryGet(ExecState *exec, const Identifier &propertyName) const
1740 {
1741   if (propertyName == lengthPropertyName)
1742     return Number(m_nodes.count());
1743   // index?
1744   bool ok;
1745   unsigned int u = propertyName.toULong(&ok);
1746   if (ok && u < m_nodes.count()) {
1747     DOM::Node node = m_nodes[u];
1748     return getDOMNode(exec,node);
1749   }
1750   // For IE compatibility, we need to be able to look up elements in a
1751   // document.formName.name result by id as well as be index.
1752
1753   if (!ok) {
1754     for (QValueListConstIterator<DOM::Node> it = m_nodes.begin(); it != m_nodes.end(); it++) {
1755       DOM::Node node = *it;
1756       DOM::NamedNodeMap attributes = node.attributes();
1757       if (attributes.isNull()) {
1758         continue;
1759       }
1760
1761       DOM::Node idAttr = attributes.getNamedItem("id");
1762       if (idAttr.isNull()) {
1763         continue;
1764       }
1765
1766       if (idAttr.nodeValue() == propertyName.string()) {
1767         return getDOMNode(exec,node);
1768       }
1769     }
1770   }
1771
1772   return DOMObject::tryGet(exec,propertyName);
1773 }
1774
1775 // -------------------------------------------------------------------------
1776
1777 const ClassInfo DOMCharacterData::info = { "CharacterImp",
1778                                           &DOMNode::info, &DOMCharacterDataTable, 0 };
1779 /*
1780 @begin DOMCharacterDataTable 2
1781   data          DOMCharacterData::Data          DontDelete
1782   length        DOMCharacterData::Length        DontDelete|ReadOnly
1783 @end
1784 @begin DOMCharacterDataProtoTable 7
1785   substringData DOMCharacterData::SubstringData DontDelete|Function 2
1786   appendData    DOMCharacterData::AppendData    DontDelete|Function 1
1787   insertData    DOMCharacterData::InsertData    DontDelete|Function 2
1788   deleteData    DOMCharacterData::DeleteData    DontDelete|Function 2
1789   replaceData   DOMCharacterData::ReplaceData   DontDelete|Function 2
1790 @end
1791 */
1792 DEFINE_PROTOTYPE("DOMCharacterData",DOMCharacterDataProto)
1793 IMPLEMENT_PROTOFUNC(DOMCharacterDataProtoFunc)
1794 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMCharacterDataProto,DOMCharacterDataProtoFunc, DOMNodeProto)
1795
1796 DOMCharacterData::DOMCharacterData(ExecState *exec, const DOM::CharacterData &d)
1797  : DOMNode(DOMCharacterDataProto::self(exec), d) {}
1798
1799 DOMCharacterData::DOMCharacterData(const Object &proto, const DOM::CharacterData &d)
1800  : DOMNode(proto, d) {}
1801
1802 Value DOMCharacterData::tryGet(ExecState *exec, const Identifier &p) const
1803 {
1804 #ifdef KJS_VERBOSE
1805   kdDebug(6070)<<"DOMCharacterData::tryGet "<<p.string().string()<<endl;
1806 #endif
1807   return DOMObjectLookupGetValue<DOMCharacterData,DOMNode>(exec,p,&DOMCharacterDataTable,this);
1808 }
1809
1810 Value DOMCharacterData::getValueProperty(ExecState *, int token) const
1811 {
1812   DOM::CharacterData data = static_cast<DOM::CharacterData>(node);
1813   switch (token) {
1814   case Data:
1815     return String(data.data());
1816   case Length:
1817     return Number(data.length());
1818  default:
1819    kdWarning() << "Unhandled token in DOMCharacterData::getValueProperty : " << token << endl;
1820    return Value();
1821   }
1822 }
1823
1824 void DOMCharacterData::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
1825 {
1826   if (propertyName == "data")
1827     static_cast<DOM::CharacterData>(node).setData(value.toString(exec).string());
1828   else
1829     DOMNode::tryPut(exec, propertyName,value,attr);
1830 }
1831
1832 Value DOMCharacterDataProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1833 {
1834   if (!thisObj.inherits(&KJS::DOMCharacterData::info)) {
1835     Object err = Error::create(exec,TypeError);
1836     exec->setException(err);
1837     return err;
1838   }
1839   DOM::CharacterData data = static_cast<DOMCharacterData *>(thisObj.imp())->toData();
1840   switch(id) {
1841     case DOMCharacterData::SubstringData: {
1842       const int count = args[1].toInt32(exec);
1843       if (count < 0)
1844         throw DOMException(DOMException::INDEX_SIZE_ERR);
1845       return getStringOrNull(data.substringData(args[0].toInt32(exec), count));
1846     }
1847     case DOMCharacterData::AppendData:
1848       data.appendData(args[0].toString(exec).string());
1849       return Undefined();
1850     case DOMCharacterData::InsertData:
1851       data.insertData(args[0].toInt32(exec), args[1].toString(exec).string());
1852       return Undefined();
1853     case DOMCharacterData::DeleteData: {
1854       const int count = args[1].toInt32(exec);
1855       if (count < 0)
1856         throw DOMException(DOMException::INDEX_SIZE_ERR);
1857       data.deleteData(args[0].toInt32(exec), count);
1858       return Undefined();
1859     }
1860     case DOMCharacterData::ReplaceData: {
1861       const int count = args[1].toInt32(exec);
1862       if (count < 0)
1863         throw DOMException(DOMException::INDEX_SIZE_ERR);
1864       data.replaceData(args[0].toInt32(exec), count, args[2].toString(exec).string());
1865       return Undefined();
1866     }
1867     default:
1868       return Undefined();
1869   }
1870 }
1871
1872 // -------------------------------------------------------------------------
1873
1874 const ClassInfo DOMText::info = { "Text",
1875                                  &DOMCharacterData::info, 0, 0 };
1876 /*
1877 @begin DOMTextProtoTable 1
1878   splitText     DOMText::SplitText      DontDelete|Function 1
1879 @end
1880 */
1881 DEFINE_PROTOTYPE("DOMText",DOMTextProto)
1882 IMPLEMENT_PROTOFUNC(DOMTextProtoFunc)
1883 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMTextProto,DOMTextProtoFunc,DOMCharacterDataProto)
1884
1885 DOMText::DOMText(ExecState *exec, const DOM::Text &t)
1886   : DOMCharacterData(DOMTextProto::self(exec), t) { }
1887
1888 Value DOMText::tryGet(ExecState *exec, const Identifier &p) const
1889 {
1890   if (p == "")
1891     return Undefined(); // ### TODO
1892   else
1893     return DOMCharacterData::tryGet(exec, p);
1894 }
1895
1896 Value DOMTextProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1897 {
1898   if (!thisObj.inherits(&KJS::DOMText::info)) {
1899     Object err = Error::create(exec,TypeError);
1900     exec->setException(err);
1901     return err;
1902   }
1903   DOM::Text text = static_cast<DOMText *>(thisObj.imp())->toText();
1904   switch(id) {
1905     case DOMText::SplitText:
1906       return getDOMNode(exec,text.splitText(args[0].toInt32(exec)));
1907       break;
1908     default:
1909       return Undefined();
1910   }
1911 }
1912