Added support for callbacks (for embedded objects)
diff --git a/Mac/Modules/waste/wastemodule.c b/Mac/Modules/waste/wastemodule.c
index fb8f620..22fd22b 100644
--- a/Mac/Modules/waste/wastemodule.c
+++ b/Mac/Modules/waste/wastemodule.c
@@ -43,6 +43,7 @@
 extern PyObject *WinObj_WhichWindow(WindowPtr);
 
 #include <WASTE.h>
+#include <WEObjectHandlers.h>
 
 /* Exported by Qdmodule.c: */
 extern PyObject *QdRGB_New(RGBColor *);
@@ -50,6 +51,7 @@
 
 /* Forward declaration */
 staticforward PyObject *WEOObj_New(WEObjectReference);
+staticforward PyObject *ExistingwasteObj_New(WEReference);
 
 /*
 ** Parse/generate TextStyle records
@@ -115,6 +117,103 @@
 	return Py_BuildValue("(ll)", p->h, p->v);
 }
 
+/* Stuff for the callbacks: */
+static PyObject *callbackdict;
+UniversalProcPtr upp_new_handler, upp_dispose_handler, upp_draw_handler, upp_click_handler;
+
+static OSErr
+any_handler(WESelector what, WEObjectReference who, PyObject *args, PyObject **rv)
+{
+	FlavorType tp;
+	PyObject *key, *func;
+	
+	if ( args == NULL ) return errAECorruptData;
+	
+	tp = WEGetObjectType(who);
+	
+	if( (key=Py_BuildValue("O&O&", PyMac_BuildOSType, tp, PyMac_BuildOSType, what)) == NULL)
+		return errAECorruptData;
+	if( (func = PyDict_GetItem(callbackdict, key)) == NULL ) {
+		Py_DECREF(key);
+		return errAEHandlerNotFound;
+	}
+	Py_INCREF(func);
+	*rv = PyEval_CallObject(func, args);
+	Py_DECREF(func);
+	Py_DECREF(key);
+	if ( *rv == NULL ) {
+		fprintf(stderr, "--Exception in callback: ");
+		PyErr_Print();
+		return errAEReplyNotArrived;
+	}
+	return 0;
+}
+
+static pascal OSErr
+my_new_handler(Point *objectSize, WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	OSErr err;
+	
+	args=Py_BuildValue("(O&)", WEOObj_New, objref);
+	err = any_handler(weNewHandler, objref, args, &rv);
+	if (!err) {
+		if (!PyMac_GetPoint(rv, objectSize) )
+			err = errAECoercionFail;
+	}
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return err;
+}
+
+static pascal OSErr
+my_dispose_handler(WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	OSErr err;
+	
+	args=Py_BuildValue("(O&)", WEOObj_New, objref);
+	err = any_handler(weDisposeHandler, objref, args, &rv);
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return err;
+}
+
+static pascal OSErr
+my_draw_handler(Rect *destRect, WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	OSErr err;
+	
+	args=Py_BuildValue("O&O&", PyMac_BuildRect, destRect, WEOObj_New, objref);
+	err = any_handler(weDrawHandler, objref, args, &rv);
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return err;
+}
+
+static pascal Boolean
+my_click_handler(Point hitPt, EventModifiers modifiers,
+		unsigned long clickTime, WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	int retvalue;
+	OSErr err;
+	
+	args=Py_BuildValue("O&llO&", PyMac_BuildPoint, hitPt,
+			(long)modifiers, (long)clickTime, WEOObj_New, objref);
+	err = any_handler(weClickHandler, objref, args, &rv);
+	if (!err)
+		retvalue = PyInt_AsLong(rv);
+	else
+		retvalue = 0;
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return retvalue;
+}
+		
+
+
 static PyObject *waste_Error;
 
 /* ------------------------ Object type WEO ------------------------- */
@@ -203,6 +302,20 @@
 	return _res;
 }
 
+static PyObject *WEOObj_WEGetObjectOwner(_self, _args)
+	WEOObject *_self;
+	PyObject *_args;
+{
+	PyObject *_res = NULL;
+	WEReference _rv;
+	if (!PyArg_ParseTuple(_args, ""))
+		return NULL;
+	_rv = WEGetObjectOwner(_self->ob_itself);
+	_res = Py_BuildValue("O&",
+	                     ExistingwasteObj_New, _rv);
+	return _res;
+}
+
 static PyObject *WEOObj_WEGetObjectRefCon(_self, _args)
 	WEOObject *_self;
 	PyObject *_args;
@@ -240,6 +353,8 @@
 	 "() -> (Handle _rv)"},
 	{"WEGetObjectSize", (PyCFunction)WEOObj_WEGetObjectSize, 1,
 	 "() -> (Point _rv)"},
+	{"WEGetObjectOwner", (PyCFunction)WEOObj_WEGetObjectOwner, 1,
+	 "() -> (WEReference _rv)"},
 	{"WEGetObjectRefCon", (PyCFunction)WEOObj_WEGetObjectRefCon, 1,
 	 "() -> (long _rv)"},
 	{"WESetObjectRefCon", (PyCFunction)WEOObj_WESetObjectRefCon, 1,
@@ -296,6 +411,7 @@
 	it = PyObject_NEW(wasteObject, &waste_Type);
 	if (it == NULL) return NULL;
 	it->ob_itself = itself;
+	WESetInfo(weRefCon, (void *)&it, itself);
 	return (PyObject *)it;
 }
 wasteObj_Convert(v, p_itself)
@@ -1645,6 +1761,91 @@
 	return _res;
 }
 
+static PyObject *waste_STDObjectHandlers(_self, _args)
+	PyObject *_self;
+	PyObject *_args;
+{
+	PyObject *_res = NULL;
+
+		OSErr err;
+		// install the sample object handlers for pictures and sounds
+#define	kTypePicture			'PICT'
+#define	kTypeSound				'snd '
+		
+		if ( !PyArg_ParseTuple(_args, "") ) return NULL;
+		
+		if ((err = WEInstallObjectHandler(kTypePicture, weNewHandler,
+					(UniversalProcPtr) NewWENewObjectProc(HandleNewPicture), NULL)) != noErr)
+			goto cleanup;
+		
+		if ((err = WEInstallObjectHandler(kTypePicture, weDisposeHandler,
+					(UniversalProcPtr) NewWEDisposeObjectProc(HandleDisposePicture), NULL)) != noErr)
+			goto cleanup;
+		
+		if ((err = WEInstallObjectHandler(kTypePicture, weDrawHandler,
+					(UniversalProcPtr) NewWEDrawObjectProc(HandleDrawPicture), NULL)) != noErr)
+			goto cleanup;
+		
+		if ((err = WEInstallObjectHandler(kTypeSound, weNewHandler,
+					(UniversalProcPtr) NewWENewObjectProc(HandleNewSound), NULL)) != noErr)
+			goto cleanup;
+		
+		if ((err = WEInstallObjectHandler(kTypeSound, weDrawHandler,
+					(UniversalProcPtr) NewWEDrawObjectProc(HandleDrawSound), NULL)) != noErr)
+			goto cleanup;
+		
+		if ((err = WEInstallObjectHandler(kTypeSound, weClickHandler,
+					(UniversalProcPtr) NewWEClickObjectProc(HandleClickSound), NULL)) != noErr)
+			goto cleanup;
+		Py_INCREF(Py_None);
+		return Py_None;
+		
+	cleanup:
+		return PyMac_Error(err);
+
+}
+
+static PyObject *waste_WEInstallObjectHandler(_self, _args)
+	PyObject *_self;
+	PyObject *_args;
+{
+	PyObject *_res = NULL;
+
+		OSErr err;
+		FlavorType objectType;
+		WESelector selector;
+		PyObject *py_handler;
+		UniversalProcPtr handler;
+		WEReference we = NULL;
+		PyObject *key;
+		
+		
+		if ( !PyArg_ParseTuple(_args, "O&O&O|O&",
+				PyMac_GetOSType, &objectType,
+				PyMac_GetOSType, &selector,
+				&py_handler,
+				ExistingwasteObj_New, &we) ) return NULL;
+				
+		if ( selector == weNewHandler ) handler = upp_new_handler;
+		else if ( selector == weDisposeHandler ) handler = upp_dispose_handler;
+		else if ( selector == weDrawHandler ) handler = upp_draw_handler;
+		else if ( selector == weClickHandler ) handler = upp_click_handler;
+		else return PyMac_Error(weUndefinedSelectorErr);
+				
+		if ((key = Py_BuildValue("O&O&", 
+				PyMac_BuildOSType, objectType, 
+				PyMac_BuildOSType, selector)) == NULL )
+			return NULL;
+			
+		PyDict_SetItem(callbackdict, key, py_handler);
+		
+		err = WEInstallObjectHandler(objectType, selector, handler, we);
+		if ( err ) return PyMac_Error(err);
+		Py_INCREF(Py_None);
+		return Py_None;
+
+}
+
 static PyMethodDef waste_methods[] = {
 	{"WENew", (PyCFunction)waste_WENew, 1,
 	 "(LongRect destRect, LongRect viewRect, unsigned long flags) -> (WEReference we)"},
@@ -1666,11 +1867,33 @@
 	 "(long hOffset, long vOffset) -> (LongRect lr)"},
 	{"WELongPointInLongRect", (PyCFunction)waste_WELongPointInLongRect, 1,
 	 "(LongPt lp, LongRect lr) -> (Boolean _rv)"},
+	{"STDObjectHandlers", (PyCFunction)waste_STDObjectHandlers, 1,
+	 NULL},
+	{"WEInstallObjectHandler", (PyCFunction)waste_WEInstallObjectHandler, 1,
+	 NULL},
 	{NULL, NULL, 0}
 };
 
 
 
+/* Return the object corresponding to the window, or NULL */
+
+PyObject *
+ExistingwasteObj_New(w)
+	WEReference w;
+{
+	PyObject *it = NULL;
+	
+	if (w == NULL)
+		it = NULL;
+	else
+		WEGetInfo(weRefCon, (void *)&it, w);
+	if (it == NULL || ((wasteObject *)it)->ob_itself != w)
+		it = Py_None;
+	Py_INCREF(it);
+	return it;
+}
+
 
 void initwaste()
 {
@@ -1686,6 +1909,16 @@
 	if (waste_Error == NULL ||
 	    PyDict_SetItemString(d, "Error", waste_Error) != 0)
 		Py_FatalError("can't initialize waste.Error");
+
+		callbackdict = PyDict_New();
+		if (callbackdict == NULL || PyDict_SetItemString(d, "callbacks", callbackdict) != 0)
+			Py_FatalError("can't initialize Waste.callbackdict");
+		upp_new_handler = NewWENewObjectProc(my_new_handler);
+		upp_dispose_handler = NewWENewObjectProc(my_dispose_handler);
+		upp_draw_handler = NewWENewObjectProc(my_draw_handler);
+		upp_click_handler = NewWENewObjectProc(my_click_handler);
+
+
 }
 
 /* ======================== End module waste ======================== */
diff --git a/Mac/Modules/waste/wastescan.py b/Mac/Modules/waste/wastescan.py
index b501344..376ca4c 100644
--- a/Mac/Modules/waste/wastescan.py
+++ b/Mac/Modules/waste/wastescan.py
@@ -52,7 +52,6 @@
 			"WEDispose",
 			"WESetInfo", # Argument type unknown...
 			"WEGetInfo",
-			"WEGetObjectOwner", # Returns ref to existing WE
 			]
 
 	def makeblacklisttypes(self):
@@ -78,7 +77,12 @@
 			 
 			# WEInsert
 			([('StScrpHandle', 'hStyles', 'InMode'), ('WESoupHandle', 'hSoup', 'InMode')],
-    		 [('OptStScrpHandle', 'hStyles', 'InMode'), ('OptSoupHandle', 'hSoup', 'InMode')])
+    		 [('OptStScrpHandle', 'hStyles', 'InMode'), ('OptSoupHandle', 'hSoup', 'InMode')]),
+    		 
+    		# WEGetObjectOwner
+    		("WEGetObjectOwner",
+    		 [('WEReference', '*', 'ReturnMode')],
+    		 [('ExistingWEReference', '*', 'ReturnMode')])
 
 			]
 			
diff --git a/Mac/Modules/waste/wastesupport.py b/Mac/Modules/waste/wastesupport.py
index 605f083..ad18d26 100644
--- a/Mac/Modules/waste/wastesupport.py
+++ b/Mac/Modules/waste/wastesupport.py
@@ -23,6 +23,7 @@
 
 # Create the type objects
 WEReference = OpaqueByValueType("WEReference", "wasteObj")
+ExistingWEReference = OpaqueByValueType("WEReference", "ExistingwasteObj")
 WEObjectReference = OpaqueByValueType("WEObjectReference", "WEOObj")
 StScrpHandle = OpaqueByValueType("StScrpHandle", "ResObj")
 RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
@@ -49,6 +50,7 @@
 
 includestuff = includestuff + """
 #include <%s>""" % MACHEADERFILE + """
+#include <WEObjectHandlers.h>
 
 /* Exported by Qdmodule.c: */
 extern PyObject *QdRGB_New(RGBColor *);
@@ -56,6 +58,7 @@
 
 /* Forward declaration */
 staticforward PyObject *WEOObj_New(WEObjectReference);
+staticforward PyObject *ExistingwasteObj_New(WEReference);
 
 /*
 ** Parse/generate TextStyle records
@@ -120,6 +123,122 @@
 {
 	return Py_BuildValue("(ll)", p->h, p->v);
 }
+
+/* Stuff for the callbacks: */
+static PyObject *callbackdict;
+UniversalProcPtr upp_new_handler, upp_dispose_handler, upp_draw_handler, upp_click_handler;
+
+static OSErr
+any_handler(WESelector what, WEObjectReference who, PyObject *args, PyObject **rv)
+{
+	FlavorType tp;
+	PyObject *key, *func;
+	
+	if ( args == NULL ) return errAECorruptData;
+	
+	tp = WEGetObjectType(who);
+	
+	if( (key=Py_BuildValue("O&O&", PyMac_BuildOSType, tp, PyMac_BuildOSType, what)) == NULL)
+		return errAECorruptData;
+	if( (func = PyDict_GetItem(callbackdict, key)) == NULL ) {
+		Py_DECREF(key);
+		return errAEHandlerNotFound;
+	}
+	Py_INCREF(func);
+	*rv = PyEval_CallObject(func, args);
+	Py_DECREF(func);
+	Py_DECREF(key);
+	if ( *rv == NULL ) {
+		fprintf(stderr, "--Exception in callback: ");
+		PyErr_Print();
+		return errAEReplyNotArrived;
+	}
+	return 0;
+}
+
+static pascal OSErr
+my_new_handler(Point *objectSize, WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	OSErr err;
+	
+	args=Py_BuildValue("(O&)", WEOObj_New, objref);
+	err = any_handler(weNewHandler, objref, args, &rv);
+	if (!err) {
+		if (!PyMac_GetPoint(rv, objectSize) )
+			err = errAECoercionFail;
+	}
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return err;
+}
+
+static pascal OSErr
+my_dispose_handler(WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	OSErr err;
+	
+	args=Py_BuildValue("(O&)", WEOObj_New, objref);
+	err = any_handler(weDisposeHandler, objref, args, &rv);
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return err;
+}
+
+static pascal OSErr
+my_draw_handler(Rect *destRect, WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	OSErr err;
+	
+	args=Py_BuildValue("O&O&", PyMac_BuildRect, destRect, WEOObj_New, objref);
+	err = any_handler(weDrawHandler, objref, args, &rv);
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return err;
+}
+
+static pascal Boolean
+my_click_handler(Point hitPt, EventModifiers modifiers,
+		unsigned long clickTime, WEObjectReference objref)
+{
+	PyObject *args=NULL, *rv=NULL;
+	int retvalue;
+	OSErr err;
+	
+	args=Py_BuildValue("O&llO&", PyMac_BuildPoint, hitPt,
+			(long)modifiers, (long)clickTime, WEOObj_New, objref);
+	err = any_handler(weClickHandler, objref, args, &rv);
+	if (!err)
+		retvalue = PyInt_AsLong(rv);
+	else
+		retvalue = 0;
+	if ( args ) Py_DECREF(args);
+	if ( rv ) Py_DECREF(rv);
+	return retvalue;
+}
+		
+
+"""
+finalstuff = finalstuff + """
+/* Return the object corresponding to the window, or NULL */
+
+PyObject *
+ExistingwasteObj_New(w)
+	WEReference w;
+{
+	PyObject *it = NULL;
+	
+	if (w == NULL)
+		it = NULL;
+	else
+		WEGetInfo(weRefCon, (void *)&it, w);
+	if (it == NULL || ((wasteObject *)it)->ob_itself != w)
+		it = Py_None;
+	Py_INCREF(it);
+	return it;
+}
 """
 
 class WEMethodGenerator(OSErrMethodGenerator):
@@ -142,6 +261,9 @@
 					PyErr_SetString(waste_Error,"Cannot create null WE");
 					return NULL;
 				}""")
+	def outputInitStructMembers(self):
+		GlobalObjectDefinition.outputInitStructMembers(self)
+		Output("WESetInfo(weRefCon, (void *)&it, itself);")
 	def outputFreeIt(self, itselfname):
 		Output("WEDispose(%s);", itselfname)
 		
@@ -150,7 +272,18 @@
 		Output("""if (itself == NULL) {
 					Py_INCREF(Py_None);
 					return Py_None;
-				}""")		
+				}""")
+				
+variablestuff = """
+	callbackdict = PyDict_New();
+	if (callbackdict == NULL || PyDict_SetItemString(d, "callbacks", callbackdict) != 0)
+		Py_FatalError("can't initialize Waste.callbackdict");
+	upp_new_handler = NewWENewObjectProc(my_new_handler);
+	upp_dispose_handler = NewWENewObjectProc(my_dispose_handler);
+	upp_draw_handler = NewWENewObjectProc(my_draw_handler);
+	upp_click_handler = NewWENewObjectProc(my_click_handler);
+"""
+
 
 # From here on it's basically all boiler plate...
 
@@ -158,7 +291,7 @@
 ## execfile(TYPETESTFILE)
 
 # Create the generator groups and link them
-module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff)
+module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff, variablestuff)
 object = WEObjectDefinition(OBJECTNAME, OBJECTPREFIX, OBJECTTYPE)
 object2 = WEOObjectDefinition("WEO", "WEOObj", "WEObjectReference")
 module.addobject(object2)
@@ -175,9 +308,88 @@
 methods2 = []
 execfile(INPUTFILE)
 
+# A function written by hand:
+stdhandlers_body = """
+	OSErr err;
+	// install the sample object handlers for pictures and sounds
+#define	kTypePicture			'PICT'
+#define	kTypeSound				'snd '
+	
+	if ( !PyArg_ParseTuple(_args, "") ) return NULL;
+	
+	if ((err = WEInstallObjectHandler(kTypePicture, weNewHandler,
+				(UniversalProcPtr) NewWENewObjectProc(HandleNewPicture), NULL)) != noErr)
+		goto cleanup;
+	
+	if ((err = WEInstallObjectHandler(kTypePicture, weDisposeHandler,
+				(UniversalProcPtr) NewWEDisposeObjectProc(HandleDisposePicture), NULL)) != noErr)
+		goto cleanup;
+	
+	if ((err = WEInstallObjectHandler(kTypePicture, weDrawHandler,
+				(UniversalProcPtr) NewWEDrawObjectProc(HandleDrawPicture), NULL)) != noErr)
+		goto cleanup;
+	
+	if ((err = WEInstallObjectHandler(kTypeSound, weNewHandler,
+				(UniversalProcPtr) NewWENewObjectProc(HandleNewSound), NULL)) != noErr)
+		goto cleanup;
+	
+	if ((err = WEInstallObjectHandler(kTypeSound, weDrawHandler,
+				(UniversalProcPtr) NewWEDrawObjectProc(HandleDrawSound), NULL)) != noErr)
+		goto cleanup;
+	
+	if ((err = WEInstallObjectHandler(kTypeSound, weClickHandler,
+				(UniversalProcPtr) NewWEClickObjectProc(HandleClickSound), NULL)) != noErr)
+		goto cleanup;
+	Py_INCREF(Py_None);
+	return Py_None;
+	
+cleanup:
+	return PyMac_Error(err);
+"""
+
+inshandler_body = """
+	OSErr err;
+	FlavorType objectType;
+	WESelector selector;
+	PyObject *py_handler;
+	UniversalProcPtr handler;
+	WEReference we = NULL;
+	PyObject *key;
+	
+	
+	if ( !PyArg_ParseTuple(_args, "O&O&O|O&",
+			PyMac_GetOSType, &objectType,
+			PyMac_GetOSType, &selector,
+			&py_handler,
+			ExistingwasteObj_New, &we) ) return NULL;
+			
+	if ( selector == weNewHandler ) handler = upp_new_handler;
+	else if ( selector == weDisposeHandler ) handler = upp_dispose_handler;
+	else if ( selector == weDrawHandler ) handler = upp_draw_handler;
+	else if ( selector == weClickHandler ) handler = upp_click_handler;
+	else return PyMac_Error(weUndefinedSelectorErr);
+			
+	if ((key = Py_BuildValue("O&O&", 
+			PyMac_BuildOSType, objectType, 
+			PyMac_BuildOSType, selector)) == NULL )
+		return NULL;
+		
+	PyDict_SetItem(callbackdict, key, py_handler);
+	
+	err = WEInstallObjectHandler(objectType, selector, handler, we);
+	if ( err ) return PyMac_Error(err);
+	Py_INCREF(Py_None);
+	return Py_None;
+"""
+
+stdhand = ManualGenerator("STDObjectHandlers", stdhandlers_body)
+inshand = ManualGenerator("WEInstallObjectHandler", inshandler_body)
+
 # add the populated lists to the generator groups
 # (in a different wordl the scan program would generate this)
 for f in functions: module.add(f)
+module.add(stdhand)
+module.add(inshand)
 for f in methods: object.add(f)
 for f in methods2: object2.add(f)