diff --git a/mozilla/dom/public/coreEvents/MANIFEST b/mozilla/dom/public/coreEvents/MANIFEST index e1da60f8127..b5f3053c0e2 100644 --- a/mozilla/dom/public/coreEvents/MANIFEST +++ b/mozilla/dom/public/coreEvents/MANIFEST @@ -15,4 +15,5 @@ nsIDOMMouseListener.h nsIDOMMouseMotionListener.h nsIDOMDragListener.h nsIDOMPaintListener.h +nsIDOMEventTarget.h nsIDOMTextListener.h diff --git a/mozilla/dom/public/coreEvents/Makefile.in b/mozilla/dom/public/coreEvents/Makefile.in index 303c71fe4d9..d88a4497c98 100644 --- a/mozilla/dom/public/coreEvents/Makefile.in +++ b/mozilla/dom/public/coreEvents/Makefile.in @@ -39,6 +39,7 @@ EXPORTS = \ nsIDOMPaintListener.h \ nsIDOMDragListener.h \ nsIDOMNSEvent.h \ + nsIDOMEventTarget.h \ nsIDOMTextListener.h \ $(NULL) diff --git a/mozilla/dom/public/coreEvents/makefile.win b/mozilla/dom/public/coreEvents/makefile.win index db2c12f5748..14db8e0b1b3 100644 --- a/mozilla/dom/public/coreEvents/makefile.win +++ b/mozilla/dom/public/coreEvents/makefile.win @@ -34,6 +34,7 @@ EXPORTS = \ nsIDOMPaintListener.h \ nsIDOMDragListener.h \ nsIDOMNSEvent.h \ + nsIDOMEventTarget.h \ nsIDOMTextListener.h \ $(NULL) diff --git a/mozilla/dom/public/coreEvents/nsIDOMEvent.h b/mozilla/dom/public/coreEvents/nsIDOMEvent.h index a2702307caa..59c7d2b2163 100644 --- a/mozilla/dom/public/coreEvents/nsIDOMEvent.h +++ b/mozilla/dom/public/coreEvents/nsIDOMEvent.h @@ -39,6 +39,7 @@ public: VK_TAB = 9, VK_CLEAR = 12, VK_RETURN = 13, + VK_ENTER = 14, VK_SHIFT = 16, VK_CONTROL = 17, VK_ALT = 18, diff --git a/mozilla/dom/public/coreEvents/nsIDOMEventListener.h b/mozilla/dom/public/coreEvents/nsIDOMEventListener.h index 8f88943e251..d1694355b84 100644 --- a/mozilla/dom/public/coreEvents/nsIDOMEventListener.h +++ b/mozilla/dom/public/coreEvents/nsIDOMEventListener.h @@ -42,7 +42,7 @@ public: * @param anEvent the event to process. @see nsIDOMEvent.h for event types. */ - virtual nsresult ProcessEvent(nsIDOMEvent* aEvent) = 0; + virtual nsresult HandleEvent(nsIDOMEvent* aEvent) = 0; }; diff --git a/mozilla/dom/public/coreEvents/nsIDOMEventReceiver.h b/mozilla/dom/public/coreEvents/nsIDOMEventReceiver.h index 94306d6b921..e8e9933165e 100644 --- a/mozilla/dom/public/coreEvents/nsIDOMEventReceiver.h +++ b/mozilla/dom/public/coreEvents/nsIDOMEventReceiver.h @@ -19,6 +19,8 @@ #ifndef nsIDOMEventReceiver_h__ #define nsIDOMEventReceiver_h__ +#include "nsIDOMEventTarget.h" + class nsIDOMEventListener; class nsIDOMMouseListener; class nsIDOMMouseMotionListener; @@ -37,13 +39,13 @@ class nsIEventListenerManager; 0xe1dbcba0, 0xfb38, 0x11d1, \ {0xbd, 0x87, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4} } -class nsIDOMEventReceiver : public nsISupports { +class nsIDOMEventReceiver : public nsIDOMEventTarget { public: static const nsIID& GetIID() { static nsIID iid = NS_IDOMEVENTRECEIVER_IID; return iid; } - NS_IMETHOD AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID) = 0; - NS_IMETHOD RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID) = 0; + NS_IMETHOD AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID) = 0; + NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID) = 0; NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult) = 0; NS_IMETHOD GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult) = 0; diff --git a/mozilla/dom/public/idl/base/Window.idl b/mozilla/dom/public/idl/base/Window.idl index 823fd7ac70f..f5b529ef8b9 100644 --- a/mozilla/dom/public/idl/base/Window.idl +++ b/mozilla/dom/public/idl/base/Window.idl @@ -50,10 +50,18 @@ Window open(/* ... */); }; - interface EventCapturer : EventReceiver { + interface EventCapturer : EventReceiver { /* IID: { 0xa6cf906c, 0x15b3, 0x11d2, \ { 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } } */ - void captureEvent(in wstring type); - void releaseEvent(in wstring type); - }; + void captureEvent(in wstring type); + void releaseEvent(in wstring type); + }; + + interface EventTarget { + /* IID: { 0x1c773b30, 0xd1cf, 0x11d2, \ + { 0xbd, 0x95, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4 } } */ + + void addEventListener(in DOMString type, in function EventListener listener, in boolean postProcess, in boolean useCapture); + void removeEventListener(in DOMString type, in function EventListener listener, in boolean postProcess, in boolean useCapture); + }; diff --git a/mozilla/dom/public/idl/base/makefile.win b/mozilla/dom/public/idl/base/makefile.win index 0ec795966ca..c792a2f9049 100644 --- a/mozilla/dom/public/idl/base/makefile.win +++ b/mozilla/dom/public/idl/base/makefile.win @@ -51,6 +51,8 @@ export:: $(GENXDIR) $(GENJSDIR) install:: $(MAKE_INSTALL:/=\) $(GENXDIR)\nsIDOMEventCapturer.h $(XPCOM_DESTDIR)\..\coreEvents $(RM) $(GENXDIR)\nsIDOMEventCapturer.h + $(MAKE_INSTALL:/=\) $(GENXDIR)\nsIDOMEventTarget.h $(XPCOM_DESTDIR)\..\coreEvents + $(RM) $(GENXDIR)\nsIDOMEventTarget.h $(MAKE_INSTALL:/=\) $(GENXDIR)\nsIDOM*.h $(XPCOM_DESTDIR) $(MAKE_INSTALL:/=\) $(GENXDIR)\nsIDOM$(GLOBAL_IDLSRC:.idl=.h) $(XPCOM_DESTDIR) $(MAKE_INSTALL:/=\) $(GENJSDIR)\nsJS*.cpp $(JSSTUB_DESTDIR) diff --git a/mozilla/dom/public/idl/coreDom/Node.idl b/mozilla/dom/public/idl/coreDom/Node.idl index 39c5a3b1b06..6ffd7609028 100644 --- a/mozilla/dom/public/idl/coreDom/Node.idl +++ b/mozilla/dom/public/idl/coreDom/Node.idl @@ -42,4 +42,10 @@ Node cloneNode(in boolean deep); }; + interface EventTarget { + /* IID: { 0x1c773b30, 0xd1cf, 0x11d2, \ + { 0xbd, 0x95, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4 } } */ + void addEventListener(in DOMString type, in function EventListener listener, in boolean postProcess, in boolean useCapture); + void removeEventListener(in DOMString type, in function EventListener listener, in boolean postProcess, in boolean useCapture); + }; \ No newline at end of file diff --git a/mozilla/dom/public/idl/coreDom/makefile.win b/mozilla/dom/public/idl/coreDom/makefile.win index 4b995b7f869..f3f82157110 100644 --- a/mozilla/dom/public/idl/coreDom/makefile.win +++ b/mozilla/dom/public/idl/coreDom/makefile.win @@ -68,5 +68,7 @@ export:: $(GENXDIR) $(GENJSDIR) $(IDLSRCS) install:: $(MAKE_INSTALL:/=\) $(GENXDIR)\nsIDOMEventCapturer.h $(XPCOM_DESTDIR)\..\coreEvents $(RM) $(GENXDIR)\nsIDOMEventCapturer.h + $(MAKE_INSTALL:/=\) $(GENXDIR)\nsIDOMEventTarget.h $(XPCOM_DESTDIR)\..\coreEvents + $(RM) $(GENXDIR)\nsIDOMEventTarget.h $(MAKE_INSTALL:/=\) $(GENXDIR)\nsIDOM*.h $(XPCOM_DESTDIR) $(MAKE_INSTALL:/=\) $(GENJSDIR)\nsJS*.cpp $(JSSTUB_DESTDIR) diff --git a/mozilla/dom/public/idl/events/Event.idl b/mozilla/dom/public/idl/events/Event.idl index d3c80ebe38e..372c0b7d568 100644 --- a/mozilla/dom/public/idl/events/Event.idl +++ b/mozilla/dom/public/idl/events/Event.idl @@ -7,6 +7,7 @@ const int VK_TAB = 0x09; const int VK_CLEAR = 0x0C; const int VK_RETURN = 0x0D; + const int VK_ENTER = 0x0E; const int VK_SHIFT = 0x10; const int VK_CONTROL = 0x11; const int VK_ALT = 0x12; diff --git a/mozilla/dom/public/nsIScriptEventListener.h b/mozilla/dom/public/nsIScriptEventListener.h index 4e8687916ff..7444b444f38 100644 --- a/mozilla/dom/public/nsIScriptEventListener.h +++ b/mozilla/dom/public/nsIScriptEventListener.h @@ -37,14 +37,14 @@ class nsIScriptEventListener : public nsISupports { public: /** - * Processes all events excepting mouse and key events. - * @param anEvent the event to process. @see nsIDOMEvent.h for event types. + * Checks equality of internal script function pointer with the one passed in. */ - //virtual nsresult nsAddJSEventHandler(nsIDOMEvent* aEvent) = 0; + virtual nsresult CheckIfEqual(nsIScriptEventListener *aListener) = 0; }; -extern "C" NS_DOM nsresult NS_NewScriptEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void *aObj); +extern "C" NS_DOM nsresult NS_NewScriptEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void* aObj, void *aFun); +extern "C" NS_DOM nsresult NS_NewJSEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void *aObj); #endif // nsIScriptEventListener_h__ diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 9e6c736cb8c..0e01e27cb78 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -76,6 +76,7 @@ static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID); static NS_DEFINE_IID(kIPrivateDOMEventIID, NS_IPRIVATEDOMEVENT_IID); static NS_DEFINE_IID(kIDOMEventCapturerIID, NS_IDOMEVENTCAPTURER_IID); static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID); +static NS_DEFINE_IID(kIDOMEventTargetIID, NS_IDOMEVENTTARGET_IID); static NS_DEFINE_IID(kIBrowserWindowIID, NS_IBROWSER_WINDOW_IID); static NS_DEFINE_IID(kIScriptContextOwnerIID, NS_ISCRIPTCONTEXTOWNER_IID); static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID); @@ -167,6 +168,11 @@ GlobalWindowImpl::QueryInterface(const nsIID& aIID, AddRef(); return NS_OK; } + if (aIID.Equals(kIDOMEventTargetIID)) { + *aInstancePtrResult = (void*)(nsISupports*)(nsIDOMEventTarget*)this; + AddRef(); + return NS_OK; + } return NS_NOINTERFACE; } @@ -1817,7 +1823,7 @@ GlobalWindowImpl::HandleDOMEvent(nsIPresContext& aPresContext, nsresult mRet = NS_OK; nsIDOMEvent* mDOMEvent = nsnull; - if (DOM_EVENT_INIT == aFlags) { + if (NS_EVENT_FLAG_INIT == aFlags) { aDOMEvent = &mDOMEvent; } @@ -1828,13 +1834,13 @@ GlobalWindowImpl::HandleDOMEvent(nsIPresContext& aPresContext, //Local handling stage if (nsnull != mListenerManager) { - mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, aEventStatus); + mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } //Bubbling stage /*Up to frames?*/ - if (DOM_EVENT_INIT == aFlags) { + if (NS_EVENT_FLAG_INIT == aFlags) { // We're leaving the DOM event loop so if we created a DOM event, release here. if (nsnull != *aDOMEvent) { nsrefcnt rc; @@ -1856,12 +1862,12 @@ GlobalWindowImpl::HandleDOMEvent(nsIPresContext& aPresContext, } nsresult -GlobalWindowImpl::AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID) +GlobalWindowImpl::AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID) { nsIEventListenerManager *mManager; if (NS_OK == GetListenerManager(&mManager)) { - mManager->AddEventListener(aListener, aIID); + mManager->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); NS_RELEASE(mManager); return NS_OK; } @@ -1869,10 +1875,41 @@ GlobalWindowImpl::AddEventListener(nsIDOMEventListener *aListener, const nsIID& } nsresult -GlobalWindowImpl::RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID) +GlobalWindowImpl::RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID) { if (nsnull != mListenerManager) { - mListenerManager->RemoveEventListener(aListener, aIID); + mListenerManager->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +nsresult +GlobalWindowImpl::AddEventListener(const nsString& aType, nsIDOMEventListener* aListener, + PRBool aPostProcess, PRBool aUseCapture) +{ + nsIEventListenerManager *manager; + + if (NS_OK == GetListenerManager(&manager)) { + PRInt32 flags = (aPostProcess ? NS_EVENT_FLAG_POST_PROCESS : NS_EVENT_FLAG_NONE) | + (aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE); + + manager->AddEventListenerByType(aListener, aType, flags); + NS_RELEASE(manager); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +nsresult +GlobalWindowImpl::RemoveEventListener(const nsString& aType, nsIDOMEventListener* aListener, + PRBool aPostProcess, PRBool aUseCapture) +{ + if (nsnull != mListenerManager) { + PRInt32 flags = (aPostProcess ? NS_EVENT_FLAG_POST_PROCESS : NS_EVENT_FLAG_NONE) | + (aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE); + + mListenerManager->RemoveEventListenerByType(aListener, aType, flags); return NS_OK; } return NS_ERROR_FAILURE; diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index 5ac0bcd7ef2..a586bcaa771 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -33,6 +33,7 @@ #include "nsIDOMEventCapturer.h" #include "nsGUIEvent.h" #include "nsDOMWindowList.h" +#include "nsIDOMEventTarget.h" class nsIEventListenerManager; class nsIDOMDocument; @@ -147,11 +148,19 @@ public: NS_IMETHOD ReleaseEvent(const nsString& aType); // nsIDOMEventReceiver interface - NS_IMETHOD AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID); - NS_IMETHOD RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID); + NS_IMETHOD AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID); + NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID); NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult); NS_IMETHOD GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult); + // nsIDOMEventTarget interface + NS_IMETHOD AddEventListener(const nsString& aType, nsIDOMEventListener* aListener, + PRBool aPostProcess, PRBool aUseCapture); + NS_IMETHOD RemoveEventListener(const nsString& aType, nsIDOMEventListener* aListener, + PRBool aPostProcess, PRBool aUseCapture); + + + NS_IMETHOD HandleDOMEvent(nsIPresContext& aPresContext, nsEvent* aEvent, nsIDOMEvent** aDOMEvent, diff --git a/mozilla/dom/src/base/nsJSUtils.cpp b/mozilla/dom/src/base/nsJSUtils.cpp index 07d6973ae08..c151e1cb133 100644 --- a/mozilla/dom/src/base/nsJSUtils.cpp +++ b/mozilla/dom/src/base/nsJSUtils.cpp @@ -33,6 +33,7 @@ #include "nsString.h" #include "nsIScriptNameSpaceManager.h" #include "nsIComponentManager.h" +#include "nsIScriptEventListener.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIJSScriptObjectIID, NS_IJSSCRIPTOBJECT_IID); @@ -221,6 +222,41 @@ nsJSUtils::nsConvertJSValToBool(PRBool* aProp, return JS_TRUE; } +NS_EXPORT PRBool +nsJSUtils::nsConvertJSValToFunc(nsIDOMEventListener** aListener, + JSContext* aContext, + JSObject* aObj, + jsval aValue) +{ + if (JSVAL_IS_NULL(aValue)) { + *aListener = nsnull; + } + else if (JSVAL_IS_OBJECT(aValue)) { + JSFunction* jsfun = JS_ValueToFunction(aContext, aValue); + if (jsfun){ + nsIScriptContext* scriptContext = (nsIScriptContext*)JS_GetContextPrivate(aContext); + + if (NS_OK == NS_NewScriptEventListener(aListener, scriptContext, (void*)aObj, (void*)jsfun)) { + return JS_TRUE; + } + else { + JS_ReportError(aContext, "Out of memory"); + return JS_FALSE; + } + } + else { + JS_ReportError(aContext, "Parameter isn't a object"); + return JS_FALSE; + } + } + else { + JS_ReportError(aContext, "Parameter must be an object"); + return JS_FALSE; + } + + return JS_TRUE; +} + NS_EXPORT void nsJSUtils::nsGenericFinalize(JSContext* aContext, JSObject* aObj) diff --git a/mozilla/dom/src/base/nsJSUtils.h b/mozilla/dom/src/base/nsJSUtils.h index 884f3237420..e97fc46a0fd 100644 --- a/mozilla/dom/src/base/nsJSUtils.h +++ b/mozilla/dom/src/base/nsJSUtils.h @@ -30,6 +30,8 @@ #include "jsapi.h" #include "nsString.h" +class nsIDOMEventListener; + class nsJSUtils { public: static NS_EXPORT PRBool nsCallJSScriptObjectGetProperty(nsISupports* aSupports, @@ -69,6 +71,11 @@ public: JSContext* aContext, jsval aValue); + static NS_EXPORT PRBool nsConvertJSValToFunc(nsIDOMEventListener** aListener, + JSContext* aContext, + JSObject* aObj, + jsval aValue); + static NS_EXPORT void nsGenericFinalize(JSContext* aContext, JSObject* aObj); diff --git a/mozilla/dom/src/base/nsJSWindow.cpp b/mozilla/dom/src/base/nsJSWindow.cpp index 7a49ba2b882..c104e9b7835 100644 --- a/mozilla/dom/src/base/nsJSWindow.cpp +++ b/mozilla/dom/src/base/nsJSWindow.cpp @@ -30,7 +30,9 @@ #include "nsIDOMDocument.h" #include "nsIDOMScreen.h" #include "nsIDOMHistory.h" +#include "nsIDOMEventListener.h" #include "nsIDOMWindowCollection.h" +#include "nsIDOMEventTarget.h" #include "nsIDOMEventCapturer.h" #include "nsIDOMWindow.h" @@ -42,7 +44,9 @@ static NS_DEFINE_IID(kINavigatorIID, NS_IDOMNAVIGATOR_IID); static NS_DEFINE_IID(kIDocumentIID, NS_IDOMDOCUMENT_IID); static NS_DEFINE_IID(kIScreenIID, NS_IDOMSCREEN_IID); static NS_DEFINE_IID(kIHistoryIID, NS_IDOMHISTORY_IID); +static NS_DEFINE_IID(kIEventListenerIID, NS_IDOMEVENTLISTENER_IID); static NS_DEFINE_IID(kIWindowCollectionIID, NS_IDOMWINDOWCOLLECTION_IID); +static NS_DEFINE_IID(kIEventTargetIID, NS_IDOMEVENTTARGET_IID); static NS_DEFINE_IID(kIEventCapturerIID, NS_IDOMEVENTCAPTURER_IID); static NS_DEFINE_IID(kIWindowIID, NS_IDOMWINDOW_IID); @@ -50,7 +54,9 @@ NS_DEF_PTR(nsIDOMNavigator); NS_DEF_PTR(nsIDOMDocument); NS_DEF_PTR(nsIDOMScreen); NS_DEF_PTR(nsIDOMHistory); +NS_DEF_PTR(nsIDOMEventListener); NS_DEF_PTR(nsIDOMWindowCollection); +NS_DEF_PTR(nsIDOMEventTarget); NS_DEF_PTR(nsIDOMEventCapturer); NS_DEF_PTR(nsIDOMWindow); @@ -1456,6 +1462,126 @@ EventCapturerReleaseEvent(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, } +// +// Native method AddEventListener +// +PR_STATIC_CALLBACK(JSBool) +EventTargetAddEventListener(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + nsIDOMWindow *privateThis = (nsIDOMWindow*)JS_GetPrivate(cx, obj); + nsIDOMEventTarget *nativeThis = nsnull; + if (NS_OK != privateThis->QueryInterface(kIEventTargetIID, (void **)&nativeThis)) { + JS_ReportError(cx, "Object must be of type EventTarget"); + return JS_FALSE; + } + + JSBool rBool = JS_FALSE; + nsAutoString b0; + nsIDOMEventListener* b1; + PRBool b2; + PRBool b3; + + *rval = JSVAL_NULL; + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == nativeThis) { + return JS_TRUE; + } + + if (argc >= 4) { + + nsJSUtils::nsConvertJSValToString(b0, cx, argv[0]); + + if (!nsJSUtils::nsConvertJSValToFunc(&b1, + cx, + obj, + argv[1])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b2, cx, argv[2])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b3, cx, argv[3])) { + return JS_FALSE; + } + + if (NS_OK != nativeThis->AddEventListener(b0, b1, b2, b3)) { + return JS_FALSE; + } + + *rval = JSVAL_VOID; + } + else { + JS_ReportError(cx, "Function addEventListener requires 4 parameters"); + return JS_FALSE; + } + + return JS_TRUE; +} + + +// +// Native method RemoveEventListener +// +PR_STATIC_CALLBACK(JSBool) +EventTargetRemoveEventListener(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + nsIDOMWindow *privateThis = (nsIDOMWindow*)JS_GetPrivate(cx, obj); + nsIDOMEventTarget *nativeThis = nsnull; + if (NS_OK != privateThis->QueryInterface(kIEventTargetIID, (void **)&nativeThis)) { + JS_ReportError(cx, "Object must be of type EventTarget"); + return JS_FALSE; + } + + JSBool rBool = JS_FALSE; + nsAutoString b0; + nsIDOMEventListener* b1; + PRBool b2; + PRBool b3; + + *rval = JSVAL_NULL; + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == nativeThis) { + return JS_TRUE; + } + + if (argc >= 4) { + + nsJSUtils::nsConvertJSValToString(b0, cx, argv[0]); + + if (!nsJSUtils::nsConvertJSValToFunc(&b1, + cx, + obj, + argv[1])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b2, cx, argv[2])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b3, cx, argv[3])) { + return JS_FALSE; + } + + if (NS_OK != nativeThis->RemoveEventListener(b0, b1, b2, b3)) { + return JS_FALSE; + } + + *rval = JSVAL_VOID; + } + else { + JS_ReportError(cx, "Function removeEventListener requires 4 parameters"); + return JS_FALSE; + } + + return JS_TRUE; +} + + /***********************************************************************/ // // class for Window @@ -1533,6 +1659,8 @@ static JSFunctionSpec WindowMethods[] = {"open", WindowOpen, 0}, {"captureEvent", EventCapturerCaptureEvent, 1}, {"releaseEvent", EventCapturerReleaseEvent, 1}, + {"addEventListener", EventTargetAddEventListener, 4}, + {"removeEventListener", EventTargetRemoveEventListener, 4}, {0} }; diff --git a/mozilla/dom/src/build/nsDOMFactory.cpp b/mozilla/dom/src/build/nsDOMFactory.cpp index 4a29b561063..ba00ad3578b 100644 --- a/mozilla/dom/src/build/nsDOMFactory.cpp +++ b/mozilla/dom/src/build/nsDOMFactory.cpp @@ -705,7 +705,8 @@ void XXXDomNeverCalled() NS_NewScriptGlobalObject(0); NS_NewScriptNavigator(0, 0, 0, 0); NS_NewScriptLocation(0, 0, 0, 0); - NS_NewScriptEventListener(0, 0, 0); + NS_NewScriptEventListener(0, 0, 0, 0); + NS_NewJSEventListener(0, 0, 0); NS_NewScriptCSS2Properties(0, 0, 0, 0); NS_NewScriptCSSStyleSheet(0, 0, 0, 0); NS_NewScriptStyleSheetCollection(0, 0, 0, 0); diff --git a/mozilla/dom/src/coreDOM/nsJSNode.cpp b/mozilla/dom/src/coreDOM/nsJSNode.cpp index 9085640610f..d3af0c3c9b3 100644 --- a/mozilla/dom/src/coreDOM/nsJSNode.cpp +++ b/mozilla/dom/src/coreDOM/nsJSNode.cpp @@ -29,6 +29,8 @@ #include "nsIDOMDocument.h" #include "nsIDOMNamedNodeMap.h" #include "nsIDOMNode.h" +#include "nsIDOMEventListener.h" +#include "nsIDOMEventTarget.h" #include "nsIDOMNodeList.h" @@ -38,11 +40,15 @@ static NS_DEFINE_IID(kIScriptGlobalObjectIID, NS_ISCRIPTGLOBALOBJECT_IID); static NS_DEFINE_IID(kIDocumentIID, NS_IDOMDOCUMENT_IID); static NS_DEFINE_IID(kINamedNodeMapIID, NS_IDOMNAMEDNODEMAP_IID); static NS_DEFINE_IID(kINodeIID, NS_IDOMNODE_IID); +static NS_DEFINE_IID(kIEventListenerIID, NS_IDOMEVENTLISTENER_IID); +static NS_DEFINE_IID(kIEventTargetIID, NS_IDOMEVENTTARGET_IID); static NS_DEFINE_IID(kINodeListIID, NS_IDOMNODELIST_IID); NS_DEF_PTR(nsIDOMDocument); NS_DEF_PTR(nsIDOMNamedNodeMap); NS_DEF_PTR(nsIDOMNode); +NS_DEF_PTR(nsIDOMEventListener); +NS_DEF_PTR(nsIDOMEventTarget); NS_DEF_PTR(nsIDOMNodeList); // @@ -548,6 +554,126 @@ NodeCloneNode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval } +// +// Native method AddEventListener +// +PR_STATIC_CALLBACK(JSBool) +EventTargetAddEventListener(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + nsIDOMNode *privateThis = (nsIDOMNode*)JS_GetPrivate(cx, obj); + nsIDOMEventTarget *nativeThis = nsnull; + if (NS_OK != privateThis->QueryInterface(kIEventTargetIID, (void **)&nativeThis)) { + JS_ReportError(cx, "Object must be of type EventTarget"); + return JS_FALSE; + } + + JSBool rBool = JS_FALSE; + nsAutoString b0; + nsIDOMEventListener* b1; + PRBool b2; + PRBool b3; + + *rval = JSVAL_NULL; + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == nativeThis) { + return JS_TRUE; + } + + if (argc >= 4) { + + nsJSUtils::nsConvertJSValToString(b0, cx, argv[0]); + + if (!nsJSUtils::nsConvertJSValToFunc(&b1, + cx, + obj, + argv[1])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b2, cx, argv[2])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b3, cx, argv[3])) { + return JS_FALSE; + } + + if (NS_OK != nativeThis->AddEventListener(b0, b1, b2, b3)) { + return JS_FALSE; + } + + *rval = JSVAL_VOID; + } + else { + JS_ReportError(cx, "Function addEventListener requires 4 parameters"); + return JS_FALSE; + } + + return JS_TRUE; +} + + +// +// Native method RemoveEventListener +// +PR_STATIC_CALLBACK(JSBool) +EventTargetRemoveEventListener(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + nsIDOMNode *privateThis = (nsIDOMNode*)JS_GetPrivate(cx, obj); + nsIDOMEventTarget *nativeThis = nsnull; + if (NS_OK != privateThis->QueryInterface(kIEventTargetIID, (void **)&nativeThis)) { + JS_ReportError(cx, "Object must be of type EventTarget"); + return JS_FALSE; + } + + JSBool rBool = JS_FALSE; + nsAutoString b0; + nsIDOMEventListener* b1; + PRBool b2; + PRBool b3; + + *rval = JSVAL_NULL; + + // If there's no private data, this must be the prototype, so ignore + if (nsnull == nativeThis) { + return JS_TRUE; + } + + if (argc >= 4) { + + nsJSUtils::nsConvertJSValToString(b0, cx, argv[0]); + + if (!nsJSUtils::nsConvertJSValToFunc(&b1, + cx, + obj, + argv[1])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b2, cx, argv[2])) { + return JS_FALSE; + } + + if (!nsJSUtils::nsConvertJSValToBool(&b3, cx, argv[3])) { + return JS_FALSE; + } + + if (NS_OK != nativeThis->RemoveEventListener(b0, b1, b2, b3)) { + return JS_FALSE; + } + + *rval = JSVAL_VOID; + } + else { + JS_ReportError(cx, "Function removeEventListener requires 4 parameters"); + return JS_FALSE; + } + + return JS_TRUE; +} + + /***********************************************************************/ // // class for Node @@ -597,6 +723,8 @@ static JSFunctionSpec NodeMethods[] = {"appendChild", NodeAppendChild, 1}, {"hasChildNodes", NodeHasChildNodes, 0}, {"cloneNode", NodeCloneNode, 1}, + {"addEventListener", EventTargetAddEventListener, 4}, + {"removeEventListener", EventTargetRemoveEventListener, 4}, {0} }; diff --git a/mozilla/dom/src/events/Makefile.in b/mozilla/dom/src/events/Makefile.in index 317689bcc55..448ffe27f5f 100644 --- a/mozilla/dom/src/events/Makefile.in +++ b/mozilla/dom/src/events/Makefile.in @@ -28,6 +28,7 @@ DEFINES += -D_IMPL_NS_DOM CPPSRCS = \ nsJSEventListener.cpp \ + nsJSDOMEventListener.cpp \ nsJSEvent.cpp \ $(NULL) diff --git a/mozilla/dom/src/events/makefile.win b/mozilla/dom/src/events/makefile.win index 53d42dc9da3..4d3347fb97e 100644 --- a/mozilla/dom/src/events/makefile.win +++ b/mozilla/dom/src/events/makefile.win @@ -26,11 +26,12 @@ DEFINES=-D_IMPL_NS_DOM -DWIN32_LEAN_AND_MEAN CPPSRCS = \ nsJSEventListener.cpp \ + nsJSDOMEventListener.cpp \ nsJSEvent.cpp \ $(NULL) CPP_OBJS= \ - .\$(OBJDIR)\nsJSEventListener.obj .\$(OBJDIR)\nsJSEvent.obj + .\$(OBJDIR)\nsJSEventListener.obj .\$(OBJDIR)\nsJSDOMEventListener.obj .\$(OBJDIR)\nsJSEvent.obj LINCS=-I$(XPDIST)\public\xpcom -I$(XPDIST)\public\raptor -I$(XPDIST)\public\dom -I$(XPDIST)\public\js diff --git a/mozilla/dom/src/events/nsJSEvent.cpp b/mozilla/dom/src/events/nsJSEvent.cpp index d4ba864ac80..c723f2fa5ec 100644 --- a/mozilla/dom/src/events/nsJSEvent.cpp +++ b/mozilla/dom/src/events/nsJSEvent.cpp @@ -899,6 +899,9 @@ extern "C" NS_DOM nsresult NS_InitEventClass(nsIScriptContext *aContext, void ** vp = INT_TO_JSVAL(nsIDOMEvent::VK_RETURN); JS_SetProperty(jscontext, constructor, "VK_RETURN", &vp); + vp = INT_TO_JSVAL(nsIDOMEvent::VK_ENTER); + JS_SetProperty(jscontext, constructor, "VK_ENTER", &vp); + vp = INT_TO_JSVAL(nsIDOMEvent::VK_SHIFT); JS_SetProperty(jscontext, constructor, "VK_SHIFT", &vp); diff --git a/mozilla/dom/src/events/nsJSEventListener.cpp b/mozilla/dom/src/events/nsJSEventListener.cpp index f6002ab9e7a..8e1e4d29ccc 100644 --- a/mozilla/dom/src/events/nsJSEventListener.cpp +++ b/mozilla/dom/src/events/nsJSEventListener.cpp @@ -17,6 +17,10 @@ */ #include "nsJSEventListener.h" #include "nsString.h" +#include "nsIScriptEventListener.h" + +static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); /* * nsJSEventListener implementation @@ -37,19 +41,11 @@ nsresult nsJSEventListener::QueryInterface(REFNSIID aIID, void** aInstancePtr) if (NULL == aInstancePtr) { return NS_ERROR_NULL_POINTER; } - static NS_DEFINE_IID(kIScriptEventListenerIID, NS_ISCRIPTEVENTLISTENER_IID); - static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID); - static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); if (aIID.Equals(kIDOMEventListenerIID)) { *aInstancePtr = (void*)(nsIDOMEventListener*)this; AddRef(); return NS_OK; } - if (aIID.Equals(kIScriptEventListenerIID)) { - *aInstancePtr = (void*)(nsIScriptEventListener*)this; - AddRef(); - return NS_OK; - } if (aIID.Equals(kISupportsIID)) { *aInstancePtr = (void*)(nsISupports*)(nsIDOMEventListener*)this; AddRef(); @@ -62,7 +58,7 @@ NS_IMPL_ADDREF(nsJSEventListener) NS_IMPL_RELEASE(nsJSEventListener) -nsresult nsJSEventListener::ProcessEvent(nsIDOMEvent* aEvent) +nsresult nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent) { jsval funval, result; jsval argv[1]; @@ -110,7 +106,7 @@ nsresult nsJSEventListener::ProcessEvent(nsIDOMEvent* aEvent) * Factory functions */ -extern "C" NS_DOM nsresult NS_NewScriptEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void *aObj) +extern "C" NS_DOM nsresult NS_NewJSEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void *aObj) { JSContext *mCX = (JSContext*)aContext->GetNativeContext(); @@ -119,8 +115,6 @@ extern "C" NS_DOM nsresult NS_NewScriptEventListener(nsIDOMEventListener ** aIns return NS_ERROR_OUT_OF_MEMORY; } - static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID); - return it->QueryInterface(kIDOMEventListenerIID, (void **) aInstancePtrResult); } diff --git a/mozilla/dom/src/events/nsJSEventListener.h b/mozilla/dom/src/events/nsJSEventListener.h index 4ab19f6d957..6d02f9e1799 100644 --- a/mozilla/dom/src/events/nsJSEventListener.h +++ b/mozilla/dom/src/events/nsJSEventListener.h @@ -25,7 +25,7 @@ #include "jsapi.h" //nsIDOMMouseListener interface -class nsJSEventListener : public nsIDOMEventListener, public nsIScriptEventListener { +class nsJSEventListener : public nsIDOMEventListener { public: nsJSEventListener(JSContext *aContext, JSObject *aObj); virtual ~nsJSEventListener(); @@ -33,7 +33,7 @@ public: NS_DECL_ISUPPORTS //nsIDOMEventListener interface - virtual nsresult ProcessEvent(nsIDOMEvent* aEvent); + virtual nsresult HandleEvent(nsIDOMEvent* aEvent); //nsIJSEventListener interface protected: @@ -42,4 +42,5 @@ protected: }; + #endif //nsJSEventListener_h__ diff --git a/mozilla/dom/tools/FileGen.cpp b/mozilla/dom/tools/FileGen.cpp index 161fccd28ac..ac79e818647 100644 --- a/mozilla/dom/tools/FileGen.cpp +++ b/mozilla/dom/tools/FileGen.cpp @@ -138,6 +138,10 @@ FileGen::GetVariableTypeForMethodLocal(char *aBuffer, IdlVariable &aVariable) break; case TYPE_XPIDL_OBJECT: sprintf(aBuffer, kXPIDLObjTypePtrStr, aVariable.GetTypeName()); + break; + case TYPE_FUNC: + sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName()); + break; default: // XXX Fail for other cases break; @@ -181,6 +185,9 @@ FileGen::GetVariableTypeForLocal(char *aBuffer, IdlVariable &aVariable) case TYPE_XPIDL_OBJECT: sprintf(aBuffer, kXPIDLObjTypeStr, aVariable.GetTypeName()); break; + case TYPE_FUNC: + sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName()); + break; default: // XXX Fail for other cases break; @@ -224,6 +231,9 @@ FileGen::GetVariableTypeForParameter(char *aBuffer, IdlVariable &aVariable) case TYPE_XPIDL_OBJECT: sprintf(aBuffer, kXPIDLObjTypeStr, aVariable.GetTypeName()); break; + case TYPE_FUNC: + sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName()); + break; default: // XXX Fail for other cases break; @@ -338,8 +348,8 @@ FileGen::CollectAllInInterface(IdlInterface &aInterface, for (p = 0; p < pcount; p++) { IdlParameter *param = func->GetParameterAt(p); - if (((param->GetType() == TYPE_OBJECT) || (param->GetType() == TYPE_XPIDL_OBJECT)) && - !PL_HashTableLookup(aTable, param->GetTypeName())) { + if (((param->GetType() == TYPE_OBJECT) || (param->GetType() == TYPE_XPIDL_OBJECT) + || (param->GetType() == TYPE_FUNC)) && !PL_HashTableLookup(aTable, param->GetTypeName())) { PL_HashTableAdd(aTable, param->GetTypeName(), (void *)(param->GetType())); } } diff --git a/mozilla/dom/tools/IdlParser.cpp b/mozilla/dom/tools/IdlParser.cpp index c224a4e8abd..5878c3f77af 100644 --- a/mozilla/dom/tools/IdlParser.cpp +++ b/mozilla/dom/tools/IdlParser.cpp @@ -932,6 +932,13 @@ IdlParameter* IdlParser::ParseFunctionParameter(IdlSpecification &aSpecification argObj->SetTypeName(token->stringID); break; } + case FUNC_TOKEN: + token = mScanner->NextToken(); + if (IDENTIFIER_TOKEN == token->id) { + argObj->SetType(TYPE_FUNC); + argObj->SetTypeName(token->stringID); + break; + } default: delete argObj; throw ParameterParsingException("Unknow type in parameters list."); diff --git a/mozilla/dom/tools/IdlScanner.cpp b/mozilla/dom/tools/IdlScanner.cpp index 4fe0241e8ee..4b89d5cdeb9 100644 --- a/mozilla/dom/tools/IdlScanner.cpp +++ b/mozilla/dom/tools/IdlScanner.cpp @@ -559,6 +559,31 @@ void IdlScanner::FKeywords(char *aCurrentPos, Token *aToken) aToken->SetToken(FLOAT_TOKEN); } } + else if (c != EOF && c == 'u' && (*aCurrentPos++ = c) && (c = mInputFile->get()) && + c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) && + c != EOF && c == 'c' && (*aCurrentPos++ = c) && (c = mInputFile->get()) && + c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) && + c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) && + c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) && + c != EOF && c == 'n' && (*aCurrentPos++ = c)) { + // if terminated is a keyword + c = mInputFile->get(); + if (c != EOF) { + if (isalpha(c) || isdigit(c) || c == '_') { + // more characters, it must be an identifier + *aCurrentPos++ = c; + Identifier(aCurrentPos, aToken); + } + else { + // it is a keyword + aToken->SetToken(FUNC_TOKEN); + mInputFile->putback(c); + } + } + else { + aToken->SetToken(FUNC_TOKEN); + } + } else { // it must be an identifier KeywordMismatch(c, aCurrentPos, aToken); diff --git a/mozilla/dom/tools/IdlScanner.h b/mozilla/dom/tools/IdlScanner.h index a212f73e6fe..5de4cf7c3de 100644 --- a/mozilla/dom/tools/IdlScanner.h +++ b/mozilla/dom/tools/IdlScanner.h @@ -43,6 +43,7 @@ enum EIDLTokenType { READONLY_TOKEN, OPTIONAL_TOKEN, XPIDL_TOKEN, + FUNC_TOKEN, ELLIPSIS_TOKEN, IID_TOKEN, ATTRIBUTE_TOKEN, diff --git a/mozilla/dom/tools/IdlVariable.h b/mozilla/dom/tools/IdlVariable.h index 9cfb99b5fd3..f820e996d45 100644 --- a/mozilla/dom/tools/IdlVariable.h +++ b/mozilla/dom/tools/IdlVariable.h @@ -39,6 +39,7 @@ enum Type { TYPE_STRING, TYPE_OBJECT, TYPE_XPIDL_OBJECT, + TYPE_FUNC, TYPE_VOID }; diff --git a/mozilla/dom/tools/JSStubGen.cpp b/mozilla/dom/tools/JSStubGen.cpp index 326c15c66de..f0b6a7278ba 100644 --- a/mozilla/dom/tools/JSStubGen.cpp +++ b/mozilla/dom/tools/JSStubGen.cpp @@ -100,7 +100,7 @@ static const char *kIncludeStr = "#include \"nsIDOM%s.h\"\n"; static const char *kXPIDLIncludeStr = "#include \"%s.h\"\n"; static const char *kIncludeConstructorStr = "#include \"nsIScriptNameSpaceManager.h\"\n" -"#include \"nsComponentManager.h\"\n" +"#include \"nsIComponentManager.h\"\n" "#include \"nsDOMCID.h\"\n"; static PRIntn @@ -110,6 +110,7 @@ IncludeEnumerator(PLHashEntry *he, PRIntn i, void *arg) switch ((Type)(int)(he->value)) { case TYPE_OBJECT: + case TYPE_FUNC: sprintf(buf, kIncludeStr, (char *)he->key); break; @@ -158,6 +159,7 @@ JSStubGen_IIDEnumerator(PLHashEntry *he, PRIntn i, void *arg) switch ((Type)(int)(he->value)) { case TYPE_OBJECT: + case TYPE_FUNC: me->GetInterfaceIID(iid_buf, (char *)he->key); sprintf(buf, kIIDStr, (char *)he->key, iid_buf); break; @@ -205,6 +207,7 @@ JSStubGen_DefPtrEnumerator(PLHashEntry *he, PRIntn i, void *arg) switch ((Type)(int)(he->value)) { case TYPE_OBJECT: + case TYPE_FUNC: sprintf(buf, kDefPtrStr, (char *)he->key); break; @@ -961,6 +964,17 @@ static const char *kMethodIntParamStr = "\n" #define JSGEN_GENERATE_INTPARAM(buffer, paramNum) \ sprintf(buffer, kMethodIntParamStr, paramNum, paramNum) +static const char *kMethodFuncParamStr = "\n" +" if (!nsJSUtils::nsConvertJSValToFunc(&b%d,\n" +" cx,\n" +" obj,\n" +" argv[%d])) {\n" +" return JS_FALSE;\n" +" }\n"; + +#define JSGEN_GENERATE_FUNCPARAM(buffer, paramNum, paramType) \ + sprintf(buffer, kMethodFuncParamStr, paramNum, paramNum) + static const char *kMethodParamListStr = "b%d"; static const char *kMethodParamListDelimiterStr = ", "; static const char *kMethodParamEllipsisStr = "cx, argv+%d, argc-%d"; @@ -1087,6 +1101,9 @@ JSStubGen::GenerateMethods(IdlSpecification &aSpec) case TYPE_XPIDL_OBJECT: JSGEN_GENERATE_XPIDL_OBJECTPARAM(buf, p, param->GetTypeName()); break; + case TYPE_FUNC: + JSGEN_GENERATE_FUNCPARAM(buf, p, param->GetTypeName()); + break; default: // XXX Fail for other cases break; diff --git a/mozilla/dom/tools/XPCOMGen.cpp b/mozilla/dom/tools/XPCOMGen.cpp index a0c490584b4..53f7493ba2d 100644 --- a/mozilla/dom/tools/XPCOMGen.cpp +++ b/mozilla/dom/tools/XPCOMGen.cpp @@ -194,6 +194,7 @@ ForwardDeclEnumerator(PLHashEntry *he, PRIntn i, void *arg) ofstream *file = (ofstream *)arg; switch ((Type)(int)(he->value)) { case TYPE_OBJECT: + case TYPE_FUNC: sprintf(buf, kForwardClassStr, (char *)he->key); break;