39393958217dbc96bb36e8f4bf9d8c5fd6ba0237
[WebKit-https.git] / WebCore / khtml / ecma / kjs_events.cpp
1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003 Apple Computer, Inc.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "kjs_events.h"
23 #include "kjs_events.lut.h"
24
25 #include "khtml_part.h"
26 #include "kjs_window.h"
27 #include "kjs_views.h"
28 #include "kjs_proxy.h"
29 #include "xml/dom_nodeimpl.h"
30 #include "xml/dom_docimpl.h"
31 #include "xml/dom2_eventsimpl.h"
32 #include "xml/dom2_viewsimpl.h"
33 #include "xml/EventNames.h"
34 #include "rendering/render_object.h"
35 #include "misc/loader.h"
36
37 #include <kdebug.h>
38
39 using namespace DOM::EventNames;
40
41 using DOM::AtomicString;
42 using DOM::ClipboardEventImpl;
43 using DOM::DocumentImpl;
44 using DOM::DOMString;
45 using DOM::EventImpl;
46 using DOM::EventListenerEvent;
47 using DOM::KeyboardEventImpl;
48 using DOM::MouseEventImpl;
49 using DOM::UIEventImpl;
50 using DOM::MutationEventImpl;
51 using DOM::MouseRelatedEventImpl;
52 using DOM::NodeImpl;
53 using DOM::WheelEventImpl;
54
55 using khtml::RenderObject;
56
57 namespace KJS {
58
59 // -------------------------------------------------------------------------
60
61 JSAbstractEventListener::JSAbstractEventListener(bool _html)
62   : html(_html)
63 {
64 }
65
66 JSAbstractEventListener::~JSAbstractEventListener()
67 {
68 }
69
70 void JSAbstractEventListener::handleEvent(EventListenerEvent ele, bool isWindowEvent)
71 {
72 #ifdef KJS_DEBUGGER
73   if (KJSDebugWin::instance() && KJSDebugWin::instance()->inSession())
74     return;
75 #endif
76
77   EventImpl *evt = ele;
78
79   ObjectImp *listener = listenerObj();
80   ObjectImp *win = windowObj();
81
82   KHTMLPart *part = static_cast<Window*>(win)->part();
83   KJSProxy *proxy = 0;
84   if (part)
85       proxy = KJSProxy::proxy( part );
86   if (!proxy)
87     return;
88
89   JSLock lock;
90   
91   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(proxy->interpreter());
92   ExecState *exec = interpreter->globalExec();
93   
94   bool hasHandleEvent = false;
95   ValueImp *handleEventFuncValue = 0;
96   ObjectImp *handleEventFunc = 0;
97   
98   handleEventFuncValue = listener->get(exec, "handleEvent");
99   if (handleEventFuncValue->isObject()) {      
100       handleEventFunc = static_cast<ObjectImp *>(handleEventFuncValue);
101       
102       if (handleEventFunc->implementsCall())
103           hasHandleEvent = true;
104   }
105   
106   if (listener->implementsCall() || hasHandleEvent) {
107       ref();
108       
109       List args;
110       args.append(getDOMEvent(exec,evt));
111       
112       Window *window = static_cast<Window*>(win);
113       // Set the event we're handling in the Window object
114       window->setCurrentEvent(evt);
115       // ... and in the interpreter
116       interpreter->setCurrentEvent(evt);
117       
118       ObjectImp *thisObj;
119       if (isWindowEvent) {
120           thisObj = win;
121       } else {
122           thisObj = static_cast<ObjectImp *>(getDOMNode(exec, evt->currentTarget()));
123       }
124       
125       ValueImp *retval;
126       if (hasHandleEvent)
127           retval = handleEventFunc->call(exec, listener, args);
128       else
129           retval = listener->call(exec, thisObj, args);
130
131       window->setCurrentEvent( 0 );
132       interpreter->setCurrentEvent( 0 );
133       if ( exec->hadException() ) {
134           char *message = exec->exception()->toObject(exec)->get(exec, messagePropertyName)->toString(exec).ascii();
135           int lineNumber =  exec->exception()->toObject(exec)->get(exec, "line")->toInt32(exec);
136           QString sourceURL;
137           {
138               // put this in a block to make sure UString is deallocated inside the lock
139               UString uSourceURL = exec->exception()->toObject(exec)->get(exec, "sourceURL")->toString(exec);
140               sourceURL = uSourceURL.qstring();
141           }
142           if (Interpreter::shouldPrintExceptions()) {
143               printf("(event handler):%s\n", message);
144           }
145           KWQ(part)->addMessageToConsole(message, lineNumber, sourceURL);
146           
147           if (Interpreter::shouldPrintExceptions())
148               printf("(event handler):%s\n", message);
149           exec->clearException();
150       } else {
151             if (!retval->isUndefinedOrNull() && evt->storesResultAsString())
152                 evt->storeResult(retval->toString(exec).domString());
153             if (html) {
154                 QVariant ret = ValueToVariant(exec, retval);
155                 if (ret.type() == QVariant::Bool && ret.toBool() == false)
156                     evt->preventDefault();
157             }
158       }
159   
160       DOM::DocumentImpl::updateDocumentsRendering();
161       deref();
162   }
163 }
164
165 DOM::DOMString JSAbstractEventListener::eventListenerType()
166 {
167     if (html)
168         return "_khtml_HTMLEventListener";
169     else
170         return "_khtml_JSEventListener";
171 }
172
173 // -------------------------------------------------------------------------
174
175 JSUnprotectedEventListener::JSUnprotectedEventListener(ObjectImp *_listener, ObjectImp *_win, bool _html)
176   : JSAbstractEventListener(_html)
177   , listener(_listener)
178   , win(_win)
179 {
180     if (_listener) {
181       static_cast<Window*>(win)->jsUnprotectedEventListeners.insert(_listener, this);
182     }
183 }
184
185 JSUnprotectedEventListener::~JSUnprotectedEventListener()
186 {
187     if (listener) {
188         if (win) {
189             static_cast<Window*>(win)->jsUnprotectedEventListeners.remove(listener);
190         }
191     }
192 }
193
194 ObjectImp *JSUnprotectedEventListener::listenerObj() const
195
196     return listener; 
197 }
198
199 ObjectImp *JSUnprotectedEventListener::windowObj() const
200 {
201     return win;
202 }
203
204 void JSUnprotectedEventListener::clearWindowObj()
205 {
206     win = NULL;
207 }
208
209
210 void JSUnprotectedEventListener::mark()
211 {
212   ObjectImp *listenerImp = listener;
213   if (listenerImp && !listenerImp->marked())
214     listenerImp->mark();
215 }
216
217 // -------------------------------------------------------------------------
218
219 JSEventListener::JSEventListener(ObjectImp *_listener, ObjectImp *_win, bool _html)
220   : JSAbstractEventListener(_html)
221   , listener(_listener)
222   , win(_win)
223 {
224     if (_listener)
225       static_cast<Window*>(_win)->jsEventListeners.insert(_listener, this);
226 }
227
228 JSEventListener::~JSEventListener()
229 {
230     if (ObjectImp *l = listener) {
231         ObjectImp *w = win;
232         if (w) {
233             static_cast<Window *>(w)->jsEventListeners.remove(l);
234         }
235     }
236 }
237
238 ObjectImp *JSEventListener::listenerObj() const
239
240     return listener; 
241 }
242
243 ObjectImp *JSEventListener::windowObj() const
244 {
245     return win;
246 }
247
248 void JSEventListener::clearWindowObj()
249 {
250     win = NULL;
251 }
252
253 // -------------------------------------------------------------------------
254
255 JSLazyEventListener::JSLazyEventListener(QString _code, ObjectImp *_win, NodeImpl *_originalNode, int lineno)
256   : JSEventListener(NULL, _win, true),
257     code(_code),
258     parsed(false)
259 {
260     lineNumber = lineno;
261
262     // We don't retain the original node, because we assume it
263     // will stay alive as long as this handler object is around
264     // and we need to avoid a reference cycle. If JS transfers
265     // this handler to another node, parseCode will be called and
266     // then originalNode is no longer needed.
267     
268     originalNode = _originalNode;
269 }
270
271 void JSLazyEventListener::handleEvent(EventListenerEvent evt, bool isWindowEvent)
272 {
273     parseCode();
274     ObjectImp *listenerObj = listener;
275     if (listenerObj)
276         JSEventListener::handleEvent(evt, isWindowEvent);
277 }
278
279
280 ObjectImp *JSLazyEventListener::listenerObj() const
281 {
282   parseCode();
283   return listener;
284 }
285
286 void JSLazyEventListener::parseCode() const
287 {
288   if (!parsed) {
289     ObjectImp *w = win;
290     KHTMLPart *part = static_cast<Window *>(w)->part();
291     KJSProxy *proxy = 0L;
292     if (part)
293       proxy = KJSProxy::proxy( part );
294
295     if (proxy) {
296       ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(proxy->interpreter());
297       ExecState *exec = interpreter->globalExec();
298
299       JSLock lock;
300       ObjectImp *constr = interpreter->builtinFunction();
301       List args;
302
303       static ProtectedPtr<ValueImp> eventString = String("event");
304       UString sourceURL(part->m_url.url());
305       args.append(eventString);
306       args.append(String(code));
307       listener = constr->construct(exec, args, sourceURL, lineNumber); // ### is globalExec ok ?
308
309       if (exec->hadException()) {
310         exec->clearException();
311
312         // failed to parse, so let's just make this listener a no-op
313         listener = NULL;
314       } else if (originalNode) {
315         // Add the event's home element to the scope
316         // (and the document, and the form - see HTMLElement::eventHandlerScope)
317         ScopeChain scope = listener->scope();
318
319         ObjectImp *thisObj;
320         { // scope
321             JSLock lock;
322             thisObj = static_cast<ObjectImp *>(getDOMNode(exec, originalNode));
323         }
324
325         if (thisObj) {
326           static_cast<DOMNode*>(thisObj)->pushEventHandlerScope(exec, scope);
327           listener->setScope(scope);
328         }
329       }
330     }
331
332     // no more need to keep the unparsed code around
333     code = QString();
334     
335     if (ObjectImp *l = listener) {
336         ObjectImp *w = win;
337         static_cast<Window *>(w)->jsEventListeners.insert(l, const_cast<JSLazyEventListener *>(this));
338     }
339     
340     parsed = true;
341   }
342 }
343
344 ValueImp *getNodeEventListener(NodeImpl *n, const AtomicString &eventType)
345 {
346   JSAbstractEventListener *listener = static_cast<JSAbstractEventListener *>(n->getHTMLEventListener(eventType));
347   if (listener)
348     if (ValueImp *obj = listener->listenerObjImp())
349       return obj;
350   return jsNull();
351 }
352
353 // -------------------------------------------------------------------------
354
355 const ClassInfo EventConstructor::info = { "EventConstructor", 0, &EventConstructorTable, 0 };
356 /*
357 @begin EventConstructorTable 3
358   CAPTURING_PHASE       DOM::Event::CAPTURING_PHASE     DontDelete|ReadOnly
359   AT_TARGET             DOM::Event::AT_TARGET           DontDelete|ReadOnly
360   BUBBLING_PHASE        DOM::Event::BUBBLING_PHASE      DontDelete|ReadOnly
361 # Reverse-engineered from Netscape
362   MOUSEDOWN             1                               DontDelete|ReadOnly
363   MOUSEUP               2                               DontDelete|ReadOnly
364   MOUSEOVER             4                               DontDelete|ReadOnly
365   MOUSEOUT              8                               DontDelete|ReadOnly
366   MOUSEMOVE             16                              DontDelete|ReadOnly
367   MOUSEDRAG             32                              DontDelete|ReadOnly
368   CLICK                 64                              DontDelete|ReadOnly
369   DBLCLICK              128                             DontDelete|ReadOnly
370   KEYDOWN               256                             DontDelete|ReadOnly
371   KEYUP                 512                             DontDelete|ReadOnly
372   KEYPRESS              1024                            DontDelete|ReadOnly
373   DRAGDROP              2048                            DontDelete|ReadOnly
374   FOCUS                 4096                            DontDelete|ReadOnly
375   BLUR                  8192                            DontDelete|ReadOnly
376   SELECT                16384                           DontDelete|ReadOnly
377   CHANGE                32768                           DontDelete|ReadOnly
378 @end
379 */
380
381 bool EventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
382 {
383   return getStaticValueSlot<EventConstructor, DOMObject>(exec, &EventConstructorTable, this, propertyName, slot);
384 }
385
386 ValueImp *EventConstructor::getValueProperty(ExecState *, int token) const
387 {
388   // We use the token as the value to return directly
389   return Number(token);
390 }
391
392 ValueImp *getEventConstructor(ExecState *exec)
393 {
394   return cacheGlobalObject<EventConstructor>(exec, "[[event.constructor]]");
395 }
396
397 // -------------------------------------------------------------------------
398
399 const ClassInfo DOMEvent::info = { "Event", 0, &DOMEventTable, 0 };
400 /*
401 @begin DOMEventTable 12
402   type          DOMEvent::Type          DontDelete|ReadOnly
403   target        DOMEvent::Target        DontDelete|ReadOnly
404   currentTarget DOMEvent::CurrentTarget DontDelete|ReadOnly
405   srcElement    DOMEvent::SrcElement    DontDelete|ReadOnly
406   eventPhase    DOMEvent::EventPhase    DontDelete|ReadOnly
407   bubbles       DOMEvent::Bubbles       DontDelete|ReadOnly
408   cancelable    DOMEvent::Cancelable    DontDelete|ReadOnly
409   timeStamp     DOMEvent::TimeStamp     DontDelete|ReadOnly
410   returnValue   DOMEvent::ReturnValue   DontDelete
411   cancelBubble  DOMEvent::CancelBubble  DontDelete
412   dataTransfer  DOMEvent::DataTransfer  DontDelete|ReadOnly
413   clipboardData  DOMEvent::ClipboardData  DontDelete|ReadOnly
414 @end
415 @begin DOMEventProtoTable 3
416   stopPropagation       DOMEvent::StopPropagation       DontDelete|Function 0
417   preventDefault        DOMEvent::PreventDefault        DontDelete|Function 0
418   initEvent             DOMEvent::InitEvent             DontDelete|Function 3
419 @end
420 */
421 DEFINE_PROTOTYPE("DOMEvent", DOMEventProto)
422 IMPLEMENT_PROTOFUNC(DOMEventProtoFunc)
423 IMPLEMENT_PROTOTYPE(DOMEventProto, DOMEventProtoFunc)
424
425 DOMEvent::DOMEvent(ExecState *exec, EventImpl *e)
426   : m_impl(e), clipboard(0) 
427 {
428   setPrototype(DOMEventProto::self(exec));
429 }
430
431 DOMEvent::~DOMEvent()
432 {
433   ScriptInterpreter::forgetDOMObject(m_impl.get());
434 }
435
436 // pass marks through to JS objects we hold during garbage collection
437 void DOMMouseEvent::mark()
438 {
439     ObjectImp::mark();
440     if (clipboard && !clipboard->marked())
441         clipboard->mark();
442 }
443
444 bool DOMEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
445 {
446   return getStaticValueSlot<DOMEvent, DOMObject>(exec, &DOMEventTable, this, propertyName, slot);
447 }
448
449 ValueImp *DOMEvent::getValueProperty(ExecState *exec, int token) const
450 {
451   EventImpl &event = *m_impl;
452   switch (token) {
453   case Type:
454     return String(event.type().domString());
455   case Target:
456   case SrcElement: /*MSIE extension - "the object that fired the event"*/
457     return getDOMNode(exec, event.target());
458   case CurrentTarget:
459     return getDOMNode(exec, event.currentTarget());
460   case EventPhase:
461     return Number((unsigned int)event.eventPhase());
462   case Bubbles:
463     return Boolean(event.bubbles());
464   case CancelBubble:
465     return Boolean(event.getCancelBubble());
466   case ReturnValue:
467     return Boolean(!event.defaultPrevented());
468   case Cancelable:
469     return Boolean(event.cancelable());
470   case TimeStamp:
471     return Number(event.timeStamp());
472   case ClipboardData:
473   {
474     if (event.isClipboardEvent()) {
475       ClipboardEventImpl *impl = static_cast<ClipboardEventImpl *>(&event);
476       if (!clipboard) {
477         clipboard = new Clipboard(exec, impl->clipboard());
478       }
479       return clipboard;
480     } else {
481       return Undefined();
482     }
483   }
484   case DataTransfer:
485   {
486     if (event.isDragEvent()) {
487       MouseEventImpl *impl = static_cast<MouseEventImpl *>(&event);
488       if (!clipboard) {
489         clipboard = new Clipboard(exec, impl->clipboard());
490       }
491       return clipboard;
492     } else {
493       return Undefined();
494     }
495   }
496   default:
497     kdWarning() << "Unhandled token in DOMEvent::getValueProperty : " << token << endl;
498     return NULL;
499   }
500 }
501
502 void DOMEvent::put(ExecState *exec, const Identifier &propertyName,
503                       ValueImp *value, int attr)
504 {
505   lookupPut<DOMEvent, DOMObject>(exec, propertyName, value, attr,
506                                           &DOMEventTable, this);
507 }
508
509 void DOMEvent::putValueProperty(ExecState *exec, int token, ValueImp *value, int)
510 {
511   EventImpl &event = *m_impl;
512   switch (token) {
513   case ReturnValue:
514     event.setDefaultPrevented(!value->toBoolean(exec));
515     break;
516   case CancelBubble:
517     event.setCancelBubble(value->toBoolean(exec));
518     break;
519   default:
520     break;
521   }
522 }
523
524 ValueImp *DOMEventProtoFunc::callAsFunction(ExecState *exec, ObjectImp * thisObj, const List &args)
525 {
526   if (!thisObj->inherits(&DOMEvent::info))
527     return throwError(exec, TypeError);
528   EventImpl &event = *static_cast<DOMEvent *>( thisObj )->impl();
529   switch (id) {
530     case DOMEvent::StopPropagation:
531       event.stopPropagation();
532       return Undefined();
533     case DOMEvent::PreventDefault:
534       event.preventDefault();
535       return Undefined();
536     case DOMEvent::InitEvent:
537       event.initEvent(AtomicString(args[0]->toString(exec).domString()), args[1]->toBoolean(exec), args[2]->toBoolean(exec));
538       return Undefined();
539   };
540   return Undefined();
541 }
542
543 ValueImp *getDOMEvent(ExecState *exec, EventImpl *e)
544 {
545   if (!e)
546     return Null();
547   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
548
549   JSLock lock;
550
551   DOMObject *ret = interp->getDOMObject(e);
552   if (!ret) {
553     if (e->isKeyboardEvent())
554       ret = new DOMKeyboardEvent(exec, static_cast<KeyboardEventImpl *>(e));
555     else if (e->isMouseEvent())
556       ret = new DOMMouseEvent(exec, static_cast<MouseEventImpl *>(e));
557     else if (e->isWheelEvent())
558       ret = new DOMWheelEvent(exec, static_cast<WheelEventImpl *>(e));
559     else if (e->isUIEvent())
560       ret = new DOMUIEvent(exec, static_cast<UIEventImpl *>(e));
561     else if (e->isMutationEvent())
562       ret = new DOMMutationEvent(exec, static_cast<MutationEventImpl *>(e));
563     else
564       ret = new DOMEvent(exec, e);
565
566     interp->putDOMObject(e, ret);
567   }
568
569   return ret;
570 }
571
572 EventImpl *toEvent(ValueImp *val)
573 {
574     if (!val || !val->isObject(&DOMEvent::info))
575         return 0;
576     return static_cast<DOMEvent *>(val)->impl();
577 }
578
579 // -------------------------------------------------------------------------
580
581
582 const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor", 0, &EventExceptionConstructorTable, 0 };
583 /*
584 @begin EventExceptionConstructorTable 1
585   UNSPECIFIED_EVENT_TYPE_ERR    DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
586 @end
587 */
588 bool EventExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
589 {
590   return getStaticValueSlot<EventExceptionConstructor, DOMObject>(exec, &EventExceptionConstructorTable, this, propertyName, slot);
591 }
592
593 ValueImp *EventExceptionConstructor::getValueProperty(ExecState *, int token) const
594 {
595   // We use the token as the value to return directly
596   return Number(token);
597 }
598
599 ValueImp *getEventExceptionConstructor(ExecState *exec)
600 {
601   return cacheGlobalObject<EventExceptionConstructor>(exec, "[[eventException.constructor]]");
602 }
603
604 // -------------------------------------------------------------------------
605
606 const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTable, 0 };
607 /*
608 @begin DOMUIEventTable 8
609   view          DOMUIEvent::View        DontDelete|ReadOnly
610   detail        DOMUIEvent::Detail      DontDelete|ReadOnly
611   keyCode       DOMUIEvent::KeyCode     DontDelete|ReadOnly
612   charCode      DOMUIEvent::CharCode    DontDelete|ReadOnly
613   layerX        DOMUIEvent::LayerX      DontDelete|ReadOnly
614   layerY        DOMUIEvent::LayerY      DontDelete|ReadOnly
615   pageX         DOMUIEvent::PageX       DontDelete|ReadOnly
616   pageY         DOMUIEvent::PageY       DontDelete|ReadOnly
617   which         DOMUIEvent::Which       DontDelete|ReadOnly
618 @end
619 @begin DOMUIEventProtoTable 1
620   initUIEvent   DOMUIEvent::InitUIEvent DontDelete|Function 5
621 @end
622 */
623 DEFINE_PROTOTYPE("DOMUIEvent",DOMUIEventProto)
624 IMPLEMENT_PROTOFUNC(DOMUIEventProtoFunc)
625 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMUIEventProto,DOMUIEventProtoFunc,DOMEventProto)
626
627 DOMUIEvent::DOMUIEvent(ExecState *exec, UIEventImpl *e)
628   : DOMEvent(exec, e)
629 {
630   setPrototype(DOMUIEventProto::self(exec));
631 }
632
633 DOMUIEvent::~DOMUIEvent()
634 {
635 }
636
637 bool DOMUIEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
638 {
639   return getStaticValueSlot<DOMUIEvent, DOMEvent>(exec, &DOMUIEventTable, this, propertyName, slot);
640 }
641
642 ValueImp *DOMUIEvent::getValueProperty(ExecState *exec, int token) const
643 {
644   UIEventImpl &event = *static_cast<UIEventImpl *>(impl());
645   switch (token) {
646   case View:
647     return getDOMAbstractView(exec, event.view());
648   case Detail:
649     return Number(event.detail());
650   case KeyCode:
651     return Number(event.keyCode());
652   case CharCode:
653     return Number(event.charCode());
654   case LayerX:
655     return Number(event.layerX());
656   case LayerY:
657     return Number(event.layerY());
658   case PageX:
659     return Number(event.pageX());
660   case PageY:
661     return Number(event.pageY());
662   case Which:
663     return Number(event.which());
664   default:
665     kdWarning() << "Unhandled token in DOMUIEvent::getValueProperty : " << token << endl;
666     return Undefined();
667   }
668 }
669
670 ValueImp *DOMUIEventProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
671 {
672   if (!thisObj->inherits(&DOMUIEvent::info))
673     return throwError(exec, TypeError);
674   UIEventImpl &uiEvent = *static_cast<UIEventImpl *>(static_cast<DOMUIEvent *>(thisObj)->impl());
675   switch (id) {
676     case DOMUIEvent::InitUIEvent:
677       uiEvent.initUIEvent(AtomicString(args[0]->toString(exec).domString()),
678                           args[1]->toBoolean(exec),
679                           args[2]->toBoolean(exec),
680                           toAbstractView(args[3]),
681                           args[4]->toInt32(exec));
682       return Undefined();
683   }
684   return Undefined();
685 }
686
687 // -------------------------------------------------------------------------
688
689 const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMouseEventTable, 0 };
690
691 /*
692 @begin DOMMouseEventTable 16
693   screenX       DOMMouseEvent::ScreenX  DontDelete|ReadOnly
694   screenY       DOMMouseEvent::ScreenY  DontDelete|ReadOnly
695   clientX       DOMMouseEvent::ClientX  DontDelete|ReadOnly
696   x             DOMMouseEvent::X        DontDelete|ReadOnly
697   clientY       DOMMouseEvent::ClientY  DontDelete|ReadOnly
698   y             DOMMouseEvent::Y        DontDelete|ReadOnly
699   offsetX       DOMMouseEvent::OffsetX  DontDelete|ReadOnly
700   offsetY       DOMMouseEvent::OffsetY  DontDelete|ReadOnly
701   ctrlKey       DOMMouseEvent::CtrlKey  DontDelete|ReadOnly
702   shiftKey      DOMMouseEvent::ShiftKey DontDelete|ReadOnly
703   altKey        DOMMouseEvent::AltKey   DontDelete|ReadOnly
704   metaKey       DOMMouseEvent::MetaKey  DontDelete|ReadOnly
705   button        DOMMouseEvent::Button   DontDelete|ReadOnly
706   relatedTarget DOMMouseEvent::RelatedTarget DontDelete|ReadOnly
707   fromElement   DOMMouseEvent::FromElement DontDelete|ReadOnly
708   toElement     DOMMouseEvent::ToElement        DontDelete|ReadOnly
709 @end
710 @begin DOMMouseEventProtoTable 1
711   initMouseEvent        DOMMouseEvent::InitMouseEvent   DontDelete|Function 15
712 @end
713 */
714 DEFINE_PROTOTYPE("DOMMouseEvent",DOMMouseEventProto)
715 IMPLEMENT_PROTOFUNC(DOMMouseEventProtoFunc)
716 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMMouseEventProto,DOMMouseEventProtoFunc,DOMUIEventProto)
717
718 DOMMouseEvent::DOMMouseEvent(ExecState *exec, MouseEventImpl *e)
719   : DOMUIEvent(exec, e)
720 {
721   setPrototype(DOMMouseEventProto::self(exec));
722 }
723
724 DOMMouseEvent::~DOMMouseEvent()
725 {
726 }
727
728 bool DOMMouseEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
729 {
730   return getStaticValueSlot<DOMMouseEvent, DOMUIEvent>(exec, &DOMMouseEventTable, this, propertyName, slot);
731 }
732
733 static QPoint offsetFromTarget(const MouseRelatedEventImpl *e)
734 {
735     int x = e->clientX();
736     int y = e->clientY();
737
738     NodeImpl *n = e->target();
739     if (n) {
740         DocumentImpl *doc = n->getDocument();
741         if (doc) {
742             doc->updateRendering();
743             RenderObject *r = n->renderer();
744             if (r) {
745                 int rx, ry;
746                 if (r->absolutePosition(rx, ry)) {
747                     x -= rx;
748                     y -= ry;
749                 }
750             }
751         }
752     }
753     return QPoint(x, y);
754 }
755
756 ValueImp *DOMMouseEvent::getValueProperty(ExecState *exec, int token) const
757 {
758   MouseEventImpl &event = *static_cast<MouseEventImpl *>(impl());
759   switch (token) {
760   case ScreenX:
761     return Number(event.screenX());
762   case ScreenY:
763     return Number(event.screenY());
764   case ClientX:
765   case X:
766     return Number(event.clientX());
767   case ClientY:
768   case Y:
769     return Number(event.clientY());
770   case OffsetX: // MSIE extension
771     return Number(offsetFromTarget(&event).x());
772   case OffsetY: // MSIE extension
773     return Number(offsetFromTarget(&event).y());
774   case CtrlKey:
775     return Boolean(event.ctrlKey());
776   case ShiftKey:
777     return Boolean(event.shiftKey());
778   case AltKey:
779     return Boolean(event.altKey());
780   case MetaKey:
781     return Boolean(event.metaKey());
782   case Button:
783     // WinIE uses 1,4,2 for left/middle/right but not for click (just for mousedown/up, maybe others), but we will match the standard DOM.
784     return Number(event.button());
785   case ToElement:
786     // MSIE extension - "the object toward which the user is moving the mouse pointer"
787     return getDOMNode(exec, event.type() == mouseoutEvent ? event.relatedTarget() : event.target());
788   case FromElement:
789     // MSIE extension - "object from which activation or the mouse pointer is exiting during the event" (huh?)
790     return getDOMNode(exec, event.type() == mouseoutEvent ? event.target() : event.relatedTarget());
791   case RelatedTarget:
792     return getDOMNode(exec, event.relatedTarget());
793   default:
794     kdWarning() << "Unhandled token in DOMMouseEvent::getValueProperty : " << token << endl;
795     return NULL;
796   }
797 }
798
799 ValueImp *DOMMouseEventProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
800 {
801   if (!thisObj->inherits(&DOMMouseEvent::info))
802     return throwError(exec, TypeError);
803   MouseEventImpl &mouseEvent = *static_cast<MouseEventImpl *>(static_cast<DOMMouseEvent *>(thisObj)->impl());
804   switch (id) {
805     case DOMMouseEvent::InitMouseEvent:
806       mouseEvent.initMouseEvent(AtomicString(args[0]->toString(exec).domString()), // typeArg
807                                 args[1]->toBoolean(exec), // canBubbleArg
808                                 args[2]->toBoolean(exec), // cancelableArg
809                                 toAbstractView(args[3]), // viewArg
810                                 args[4]->toInt32(exec), // detailArg
811                                 args[5]->toInt32(exec), // screenXArg
812                                 args[6]->toInt32(exec), // screenYArg
813                                 args[7]->toInt32(exec), // clientXArg
814                                 args[8]->toInt32(exec), // clientYArg
815                                 args[9]->toBoolean(exec), // ctrlKeyArg
816                                 args[10]->toBoolean(exec), // altKeyArg
817                                 args[11]->toBoolean(exec), // shiftKeyArg
818                                 args[12]->toBoolean(exec), // metaKeyArg
819                                 args[13]->toInt32(exec), // buttonArg
820                                 toNode(args[14])); // relatedTargetArg
821       return Undefined();
822   }
823   return Undefined();
824 }
825
826 // -------------------------------------------------------------------------
827
828 const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMUIEvent::info, &DOMKeyboardEventTable, 0 };
829
830 /*
831 @begin DOMKeyboardEventTable 5
832   keyIdentifier DOMKeyboardEvent::KeyIdentifier DontDelete|ReadOnly
833   keyLocation   DOMKeyboardEvent::KeyLocation   DontDelete|ReadOnly
834   ctrlKey       DOMKeyboardEvent::CtrlKey       DontDelete|ReadOnly
835   shiftKey      DOMKeyboardEvent::ShiftKey      DontDelete|ReadOnly
836   altKey        DOMKeyboardEvent::AltKey        DontDelete|ReadOnly
837   metaKey       DOMKeyboardEvent::MetaKey       DontDelete|ReadOnly
838   altGraphKey   DOMKeyboardEvent::AltGraphKey   DontDelete|ReadOnly
839 @end
840 @begin DOMKeyboardEventProtoTable 1
841   initKeyboardEvent     DOMKeyboardEvent::InitKeyboardEvent     DontDelete|Function 11
842 @end
843 */
844 DEFINE_PROTOTYPE("DOMKeyboardEvent", DOMKeyboardEventProto)
845 IMPLEMENT_PROTOFUNC(DOMKeyboardEventProtoFunc)
846 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMKeyboardEventProto, DOMKeyboardEventProtoFunc, DOMUIEventProto)
847
848 DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, KeyboardEventImpl *e)
849   : DOMUIEvent(exec, e)
850 {
851   setPrototype(DOMKeyboardEventProto::self(exec));
852 }
853
854 DOMKeyboardEvent::~DOMKeyboardEvent()
855 {
856 }
857
858 const ClassInfo* DOMKeyboardEvent::classInfo() const
859 {
860     return &info;
861 }
862
863 bool DOMKeyboardEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
864 {
865   return getStaticValueSlot<DOMKeyboardEvent, DOMUIEvent>(exec, &DOMKeyboardEventTable, this, propertyName, slot);
866 }
867
868 ValueImp *DOMKeyboardEvent::getValueProperty(ExecState *exec, int token) const
869 {
870   KeyboardEventImpl &event = *static_cast<KeyboardEventImpl *>(impl());
871   switch (token) {
872   case KeyIdentifier:
873     return String(event.keyIdentifier());
874   case KeyLocation:
875     return Number(event.keyLocation());
876   case CtrlKey:
877     return Boolean(event.ctrlKey());
878   case ShiftKey:
879     return Boolean(event.shiftKey());
880   case AltKey:
881     return Boolean(event.altKey());
882   case MetaKey:
883     return Boolean(event.metaKey());
884   case AltGraphKey:
885     return Boolean(event.altGraphKey());
886   default:
887     kdWarning() << "Unhandled token in DOMKeyboardEvent::getValueProperty : " << token << endl;
888     return NULL;
889   }
890 }
891
892 ValueImp *DOMKeyboardEventProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
893 {
894   if (!thisObj->inherits(&DOMKeyboardEvent::info))
895     return throwError(exec, TypeError);
896   KeyboardEventImpl &event = *static_cast<KeyboardEventImpl *>(static_cast<DOMUIEvent *>(thisObj)->impl());
897   switch (id) {
898     case DOMKeyboardEvent::InitKeyboardEvent:
899       event.initKeyboardEvent(AtomicString(args[0]->toString(exec).domString()), // typeArg
900                               args[1]->toBoolean(exec), // canBubbleArg
901                               args[2]->toBoolean(exec), // cancelableArg
902                               toAbstractView(args[3]), // viewArg
903                               args[4]->toString(exec).domString(), // keyIdentifier
904                               args[5]->toInt32(exec), // keyLocationArg
905                               args[6]->toBoolean(exec), // ctrlKeyArg
906                               args[7]->toBoolean(exec), // altKeyArg
907                               args[8]->toBoolean(exec), // shiftKeyArg
908                               args[9]->toBoolean(exec), // metaKeyArg
909                               args[10]->toBoolean(exec)); // altGraphKeyArg
910       return Undefined();
911   }
912   return Undefined();
913 }
914
915 // -------------------------------------------------------------------------
916
917 const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", 0, &MutationEventConstructorTable, 0 };
918 /*
919 @begin MutationEventConstructorTable 3
920   MODIFICATION  DOM::MutationEvent::MODIFICATION        DontDelete|ReadOnly
921   ADDITION      DOM::MutationEvent::ADDITION            DontDelete|ReadOnly
922   REMOVAL       DOM::MutationEvent::REMOVAL             DontDelete|ReadOnly
923 @end
924 */
925 bool MutationEventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
926 {
927   return getStaticValueSlot<MutationEventConstructor, DOMObject>(exec, &MutationEventConstructorTable, this, propertyName, slot);
928 }
929
930 ValueImp *MutationEventConstructor::getValueProperty(ExecState *, int token) const
931 {
932   // We use the token as the value to return directly
933   return Number(token);
934 }
935
936 ValueImp *getMutationEventConstructor(ExecState *exec)
937 {
938   return cacheGlobalObject<MutationEventConstructor>(exec, "[[mutationEvent.constructor]]");
939 }
940
941 // -------------------------------------------------------------------------
942
943 const ClassInfo DOMMutationEvent::info = { "MutationEvent", &DOMEvent::info, &DOMMutationEventTable, 0 };
944 /*
945 @begin DOMMutationEventTable 5
946   relatedNode   DOMMutationEvent::RelatedNode   DontDelete|ReadOnly
947   prevValue     DOMMutationEvent::PrevValue     DontDelete|ReadOnly
948   newValue      DOMMutationEvent::NewValue      DontDelete|ReadOnly
949   attrName      DOMMutationEvent::AttrName      DontDelete|ReadOnly
950   attrChange    DOMMutationEvent::AttrChange    DontDelete|ReadOnly
951 @end
952 @begin DOMMutationEventProtoTable 1
953   initMutationEvent     DOMMutationEvent::InitMutationEvent     DontDelete|Function 8
954 @end
955 */
956 DEFINE_PROTOTYPE("DOMMutationEvent",DOMMutationEventProto)
957 IMPLEMENT_PROTOFUNC(DOMMutationEventProtoFunc)
958 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMMutationEventProto,DOMMutationEventProtoFunc,DOMEventProto)
959
960 DOMMutationEvent::DOMMutationEvent(ExecState *exec, MutationEventImpl *e)
961   : DOMEvent(exec, e)
962 {
963   setPrototype(DOMMutationEventProto::self(exec));
964 }
965
966 DOMMutationEvent::~DOMMutationEvent()
967 {
968 }
969
970 bool DOMMutationEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
971 {
972   return getStaticValueSlot<DOMMutationEvent, DOMEvent>(exec, &DOMMutationEventTable, this, propertyName, slot);
973 }
974
975 ValueImp *DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
976 {
977   MutationEventImpl &event = *static_cast<MutationEventImpl *>(impl());
978   switch (token) {
979   case RelatedNode:
980     return getDOMNode(exec, event.relatedNode());
981   case PrevValue:
982     return String(event.prevValue());
983   case NewValue:
984     return String(event.newValue());
985   case AttrName:
986     return String(event.attrName());
987   case AttrChange:
988     return Number(event.attrChange());
989   default:
990     kdWarning() << "Unhandled token in DOMMutationEvent::getValueProperty : " << token << endl;
991     return NULL;
992   }
993 }
994
995 ValueImp *DOMMutationEventProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
996 {
997   if (!thisObj->inherits(&DOMMutationEvent::info))
998     return throwError(exec, TypeError);
999   MutationEventImpl &mutationEvent = *static_cast<MutationEventImpl *>(static_cast<DOMEvent *>(thisObj)->impl());
1000   switch (id) {
1001     case DOMMutationEvent::InitMutationEvent:
1002       mutationEvent.initMutationEvent(AtomicString(args[0]->toString(exec).domString()), // typeArg,
1003                                       args[1]->toBoolean(exec), // canBubbleArg
1004                                       args[2]->toBoolean(exec), // cancelableArg
1005                                       toNode(args[3]), // relatedNodeArg
1006                                       args[4]->toString(exec).domString(), // prevValueArg
1007                                       args[5]->toString(exec).domString(), // newValueArg
1008                                       args[6]->toString(exec).domString(), // attrNameArg
1009                                       args[7]->toInt32(exec)); // attrChangeArg
1010       return Undefined();
1011   }
1012   return Undefined();
1013 }
1014
1015 // -------------------------------------------------------------------------
1016
1017 const ClassInfo DOMWheelEvent::info = { "WheelEvent", &DOMEvent::info, &DOMWheelEventTable, 0 };
1018 /*
1019 @begin DOMWheelEventTable 10
1020     altKey      DOMWheelEvent::AltKey       DontDelete|ReadOnly
1021     clientX     DOMWheelEvent::ClientX      DontDelete|ReadOnly
1022     clientY     DOMWheelEvent::ClientY      DontDelete|ReadOnly
1023     ctrlKey     DOMWheelEvent::CtrlKey      DontDelete|ReadOnly
1024     metaKey     DOMWheelEvent::MetaKey      DontDelete|ReadOnly
1025     offsetX     DOMWheelEvent::OffsetX      DontDelete|ReadOnly
1026     offsetY     DOMWheelEvent::OffsetY      DontDelete|ReadOnly
1027     screenX     DOMWheelEvent::ScreenX      DontDelete|ReadOnly
1028     screenY     DOMWheelEvent::ScreenY      DontDelete|ReadOnly
1029     shiftKey    DOMWheelEvent::ShiftKey     DontDelete|ReadOnly
1030     wheelDelta  DOMWheelEvent::WheelDelta   DontDelete|ReadOnly
1031     x           DOMWheelEvent::X            DontDelete|ReadOnly
1032     y           DOMWheelEvent::Y            DontDelete|ReadOnly
1033 @end
1034 @begin DOMWheelEventProtoTable 1
1035 @end
1036 */
1037 DEFINE_PROTOTYPE("DOMWheelEvent",DOMWheelEventProto)
1038 IMPLEMENT_PROTOFUNC(DOMWheelEventProtoFunc)
1039 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMWheelEventProto,DOMWheelEventProtoFunc,DOMEventProto)
1040
1041 DOMWheelEvent::DOMWheelEvent(ExecState *exec, DOM::WheelEventImpl *e)
1042     : DOMUIEvent(exec, e)
1043 {
1044 }
1045
1046 bool DOMWheelEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1047 {
1048     return getStaticValueSlot<DOMWheelEvent, DOMEvent>(exec, &DOMWheelEventTable, this, propertyName, slot);
1049 }
1050
1051 ValueImp *DOMWheelEvent::getValueProperty(ExecState *exec, int token) const
1052 {
1053     DOM::WheelEventImpl *e = static_cast<DOM::WheelEventImpl *>(impl());
1054     switch (token) {
1055         case AltKey:
1056             return Boolean(e->altKey());
1057         case ClientX:
1058         case X:
1059             return Number(e->clientX());
1060         case ClientY:
1061         case Y:
1062             return Number(e->clientY());
1063         case CtrlKey:
1064             return Number(e->ctrlKey());
1065         case MetaKey:
1066             return Number(e->metaKey());
1067         case OffsetX:
1068             return Number(offsetFromTarget(e).x());
1069         case OffsetY:
1070             return Number(offsetFromTarget(e).y());
1071         case ScreenX:
1072             return Number(e->screenX());
1073         case ScreenY:
1074             return Number(e->screenY());
1075         case ShiftKey:
1076             return Boolean(e->shiftKey());
1077         case WheelDelta:
1078             return Number(e->wheelDelta());
1079     }
1080     return Undefined();
1081 }
1082
1083 ValueImp *DOMWheelEventProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1084 {
1085     if (!thisObj->inherits(&DOMWheelEvent::info))
1086         return throwError(exec, TypeError);
1087     return Undefined();
1088 }
1089
1090 // -------------------------------------------------------------------------
1091
1092 const ClassInfo Clipboard::info = { "Clipboard", 0, &ClipboardTable, 0 };
1093
1094 /* Source for ClipboardTable. Use "make hashtables" to regenerate.
1095 @begin ClipboardTable 3
1096   dropEffect    Clipboard::DropEffect   DontDelete
1097   effectAllowed Clipboard::EffectAllowed        DontDelete
1098   types         Clipboard::Types        DontDelete|ReadOnly
1099 @end
1100 @begin ClipboardProtoTable 4
1101   clearData     Clipboard::ClearData    DontDelete|Function 0
1102   getData       Clipboard::GetData      DontDelete|Function 1
1103   setData       Clipboard::SetData      DontDelete|Function 2
1104   setDragImage  Clipboard::SetDragImage DontDelete|Function 3
1105 @end
1106 */
1107
1108 DEFINE_PROTOTYPE("Clipboard", ClipboardProto)
1109 IMPLEMENT_PROTOFUNC(ClipboardProtoFunc)
1110 IMPLEMENT_PROTOTYPE(ClipboardProto, ClipboardProtoFunc)
1111
1112 Clipboard::Clipboard(ExecState *exec, DOM::ClipboardImpl *cb)
1113   : clipboard(cb)
1114 {
1115     setPrototype(ClipboardProto::self(exec));
1116   
1117     if (clipboard)
1118         clipboard->ref();
1119 }
1120
1121 Clipboard::~Clipboard()
1122 {
1123     if (clipboard)
1124         clipboard->deref();
1125 }
1126
1127 static ValueImp *stringOrUndefined(const DOM::DOMString &str)
1128 {
1129     if (str.isNull()) {
1130         return Undefined();
1131     } else {
1132         return String(str);
1133     }
1134 }
1135
1136 bool Clipboard::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1137 {
1138     return getStaticValueSlot<Clipboard, DOMObject>(exec, &ClipboardTable, this, propertyName, slot);
1139 }
1140
1141 ValueImp *Clipboard::getValueProperty(ExecState *exec, int token) const
1142 {
1143     switch (token) {
1144         case DropEffect:
1145             assert(clipboard->isForDragging() || clipboard->dropEffect().isNull());
1146             return stringOrUndefined(clipboard->dropEffect());
1147         case EffectAllowed:
1148             assert(clipboard->isForDragging() || clipboard->effectAllowed().isNull());
1149             return stringOrUndefined(clipboard->effectAllowed());
1150         case Types:
1151         {
1152             QStringList qTypes = clipboard->types();
1153             if (qTypes.isEmpty()) {
1154                 return Null(); 
1155             } else {
1156                 List list;
1157                 for (QStringList::Iterator it = qTypes.begin(); it != qTypes.end(); ++it) {
1158                     list.append(String(UString(*it)));
1159                 }
1160                 return exec->lexicalInterpreter()->builtinArray()->construct(exec, list);
1161             }
1162         }
1163         default:
1164             kdWarning() << "Clipboard::getValueProperty unhandled token " << token << endl;
1165             return NULL;
1166     }
1167 }
1168
1169 void Clipboard::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
1170 {
1171     lookupPut<Clipboard,DOMObject>(exec, propertyName, value, attr, &ClipboardTable, this );
1172 }
1173
1174 void Clipboard::putValueProperty(ExecState *exec, int token, ValueImp *value, int /*attr*/)
1175 {
1176     switch (token) {
1177         case DropEffect:
1178             // can never set this when not for dragging, thus getting always returns NULL string
1179             if (clipboard->isForDragging())
1180                 clipboard->setDropEffect(value->toString(exec).domString());
1181             break;
1182         case EffectAllowed:
1183             // can never set this when not for dragging, thus getting always returns NULL string
1184             if (clipboard->isForDragging())
1185                 clipboard->setEffectAllowed(value->toString(exec).domString());
1186             break;
1187         default:
1188             kdWarning() << "Clipboard::putValueProperty unhandled token " << token << endl;
1189     }
1190 }
1191
1192 ValueImp *ClipboardProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1193 {
1194     if (!thisObj->inherits(&Clipboard::info))
1195         return throwError(exec, TypeError);
1196
1197     Clipboard *cb = static_cast<Clipboard *>(thisObj);
1198     switch (id) {
1199         case Clipboard::ClearData:
1200             if (args.size() == 0) {
1201                 cb->clipboard->clearAllData();
1202                 return Undefined();
1203             } else if (args.size() == 1) {
1204                 cb->clipboard->clearData(args[0]->toString(exec).domString());
1205                 return Undefined();
1206             } else {
1207                 return throwError(exec, SyntaxError, "clearData: Invalid number of arguments");
1208             }
1209         case Clipboard::GetData:
1210         {
1211             if (args.size() == 1) {
1212                 bool success;
1213                 DOM::DOMString result = cb->clipboard->getData(args[0]->toString(exec).domString(), success);
1214                 if (success) {
1215                     return String(result);
1216                 } else {
1217                     return Undefined();
1218                 }
1219             } else {
1220                 return throwError(exec, SyntaxError, "getData: Invalid number of arguments");
1221             }
1222         }
1223         case Clipboard::SetData:
1224             if (args.size() == 2) {
1225                 return Boolean(cb->clipboard->setData(args[0]->toString(exec).domString(), args[1]->toString(exec).domString()));
1226             } else {
1227                 return throwError(exec, SyntaxError, "setData: Invalid number of arguments");
1228             }
1229         case Clipboard::SetDragImage:
1230         {
1231             if (!cb->clipboard->isForDragging()) {
1232                 return Undefined();
1233             }
1234
1235             if (args.size() != 3)
1236                 return throwError(exec, SyntaxError, "setDragImage: Invalid number of arguments");
1237
1238             int x = (int)args[1]->toNumber(exec);
1239             int y = (int)args[2]->toNumber(exec);
1240
1241             // See if they passed us a node
1242             NodeImpl *node = toNode(args[0]);
1243             if (node) {
1244                 if (node->isElementNode()) {
1245                     cb->clipboard->setDragImageElement(node, QPoint(x,y));                    
1246                     return Undefined();
1247                 } else {
1248                     return throwError(exec, SyntaxError, "setDragImageFromElement: Invalid first argument");
1249                 }
1250             }
1251
1252             // See if they passed us an Image object
1253             ObjectImp *o = static_cast<ObjectImp*>(args[0]);
1254             if (o->isObject() && o->inherits(&Image::info)) {
1255                 Image *JSImage = static_cast<Image*>(o);
1256                 cb->clipboard->setDragImage(JSImage->image()->pixmap(), QPoint(x,y));                
1257                 return Undefined();
1258             } else {
1259                 return throwError(exec, TypeError);
1260             }
1261         }
1262     }
1263     return Undefined();
1264 }
1265
1266 }