| /* tkintermodule.c -- Interface to libtk.a and libtcl.a. | 
 |    Copyright (C) 1994 Steen Lumholt */ | 
 |  | 
 | #if 0 | 
 | #include <Py/Python.h> | 
 | #else | 
 |  | 
 | #include "allobjects.h" | 
 | #include "pythonrun.h" | 
 | #include "intrcheck.h" | 
 | #include "modsupport.h" | 
 | #include "sysmodule.h" | 
 |  | 
 | #define PyObject object | 
 | typedef struct methodlist PyMethodDef; | 
 | #define PyInit_tkinter inittkinter | 
 |  | 
 | #undef Py_True | 
 | #define Py_True ((object *) &TrueObject) | 
 | #undef True | 
 |  | 
 | #undef Py_False | 
 | #define Py_False ((object *) &FalseObject) | 
 | #undef False | 
 |  | 
 | #undef Py_None | 
 | #define Py_None (&NoObject) | 
 | #undef None | 
 |  | 
 | #endif /* 0 */ | 
 |  | 
 | #include <tcl.h> | 
 | #include <tk.h> | 
 |  | 
 | extern char *getprogramname (); | 
 | extern int tk_NumMainWindows; | 
 |  | 
 | /**** Tkapp Object Declaration ****/ | 
 |  | 
 | staticforward PyTypeObject Tkapp_Type; | 
 |  | 
 | typedef struct | 
 |   { | 
 |     PyObject_HEAD | 
 |     Tcl_Interp *interp; | 
 |     Tk_Window tkwin; | 
 |   } | 
 | TkappObject; | 
 |  | 
 | #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type) | 
 | #define Tkapp_Tkwin(v)  (((TkappObject *) (v))->tkwin) | 
 | #define Tkapp_Interp(v) (((TkappObject *) (v))->interp) | 
 | #define Tkapp_Result(v) (((TkappObject *) (v))->interp->result) | 
 |  | 
 | #define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \ | 
 | 				 (void *) v, ((PyObject *) v)->ob_refcnt)) | 
 |  | 
 | /**** Error Handling ****/ | 
 |  | 
 | static PyObject *Tkinter_TclError; | 
 | static int errorInCmd = 0; | 
 | static PyObject *excInCmd; | 
 | static PyObject *valInCmd; | 
 |  | 
 | static PyObject * | 
 | Tkinter_Error (v) | 
 |      PyObject *v; | 
 | { | 
 |   if (Tkapp_Check (v)) | 
 |     PyErr_BadInternalCall (); | 
 |   PyErr_SetString (Tkinter_TclError, Tkapp_Result (v)); | 
 |   return NULL; | 
 | } | 
 |  | 
 | int | 
 | PythonCmd_Error (interp) | 
 |      Tcl_Interp *interp; | 
 | { | 
 |   errorInCmd = 1; | 
 |   PyErr_GetAndClear (&excInCmd, &valInCmd); | 
 |   return TCL_ERROR; | 
 | } | 
 |  | 
 | /**** Utils ****/ | 
 |  | 
 | static char * | 
 | AsString (value, tmp) | 
 |      PyObject *value; | 
 |      PyObject *tmp; | 
 | { | 
 |   if (PyString_Check (value)) | 
 |     return PyString_AsString (value); | 
 |   else | 
 |     { | 
 |       PyObject *v; | 
 |  | 
 |       v = strobject (value); | 
 |       PyList_Append (tmp, v); | 
 |       Py_DECREF (v); | 
 |       return PyString_AsString (v); | 
 |     } | 
 | } | 
 |  | 
 | #define ARGSZ 64 | 
 |  | 
 | static char * | 
 | Merge (args) | 
 |      PyObject *args; | 
 | { | 
 |   PyObject *tmp; | 
 |   char *argvStore[ARGSZ]; | 
 |   char **argv; | 
 |   int fvStore[ARGSZ]; | 
 |   int *fv; | 
 |   int argc; | 
 |   char *res; | 
 |   int i; | 
 |  | 
 |   tmp = PyList_New (0); | 
 |   argv = argvStore; | 
 |   fv = fvStore; | 
 |  | 
 |   if (!PyTuple_Check (args)) | 
 |     { | 
 |       argc = 1; | 
 |       fv[0] = 0; | 
 |       argv[0] = AsString (args, tmp); | 
 |     } | 
 |   else | 
 |     { | 
 |       PyObject *v; | 
 |  | 
 |       if (PyTuple_Size (args) > ARGSZ) | 
 | 	{ | 
 | 	  argv = malloc (PyTuple_Size (args) * sizeof (char *)); | 
 | 	  fv = malloc (PyTuple_Size (args) * sizeof (int)); | 
 | 	  if (argv == NULL || fv == NULL) | 
 | 	    PyErr_NoMemory (); | 
 | 	} | 
 |  | 
 |       argc = PyTuple_Size (args); | 
 |       for (i = 0; i < argc; i++) | 
 | 	{ | 
 | 	  v = PyTuple_GetItem (args, i); | 
 | 	  if (PyTuple_Check (v)) | 
 | 	    { | 
 | 	      fv[i] = 1; | 
 | 	      argv[i] = Merge (v); | 
 | 	    } | 
 | 	  else if (v == Py_None) | 
 | 	    { | 
 | 	      argc = i; | 
 | 	      break; | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      fv[i] = 0; | 
 | 	      argv[i] = AsString (v, tmp); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   res = Tcl_Merge (argc, argv); | 
 |  | 
 |   Py_DECREF (tmp); | 
 |   for (i = 0; i < argc; i++) | 
 |     if (fv[i]) free (argv[i]); | 
 |   if (argv != argvStore) | 
 |     free (argv); | 
 |   if (fv != fvStore) | 
 |     free (fv); | 
 |  | 
 |   return res; | 
 | } | 
 |  | 
 | static PyObject * | 
 | Split (self, list) | 
 |      PyObject *self; | 
 |      char *list; | 
 | { | 
 |   int argc; | 
 |   char **argv; | 
 |   PyObject *v; | 
 |  | 
 |   if (list == NULL) | 
 |     { | 
 |       Py_INCREF (Py_None); | 
 |       return Py_None; | 
 |     } | 
 |  | 
 |   if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   if (argc == 0) | 
 |     v = PyString_FromString (""); | 
 |   else if (argc == 1) | 
 |     v = PyString_FromString (argv[0]); | 
 |   else | 
 |     { | 
 |       int i; | 
 |  | 
 |       v = PyTuple_New (argc); | 
 |       for (i = 0; i < argc; i++) | 
 | 	PyTuple_SetItem (v, i, Split (self, argv[i])); | 
 |     } | 
 |  | 
 |   free (argv); | 
 |   return v; | 
 | } | 
 |  | 
 | /**** Tkapp Object ****/ | 
 |  | 
 | #ifndef WITH_APPINIT | 
 | int | 
 | Tcl_AppInit (interp) | 
 |      Tcl_Interp *interp; | 
 | { | 
 |   if (Tcl_Init (interp) == TCL_ERROR) | 
 |     return TCL_ERROR; | 
 |   if (Tk_Init (interp) == TCL_ERROR) | 
 |     return TCL_ERROR; | 
 |   return TCL_OK; | 
 | } | 
 | #endif /* !WITH_APPINIT */ | 
 |  | 
 | /* Initialize the Tk application; see the `main' function in | 
 |    `tkMain.c'.  */ | 
 | static TkappObject * | 
 | Tkapp_New (screenName, baseName, className, interactive) | 
 |      char *screenName; | 
 |      char *baseName; | 
 |      char *className; | 
 |      int interactive; | 
 | { | 
 |   TkappObject *v; | 
 |    | 
 |   v = PyObject_NEW (TkappObject, &Tkapp_Type); | 
 |   if (v == NULL) | 
 |     return NULL; | 
 |  | 
 |   v->interp = Tcl_CreateInterp (); | 
 |   v->tkwin = Tk_CreateMainWindow (v->interp, screenName,  | 
 | 				  baseName, className); | 
 |   if (v->tkwin == NULL) | 
 |     return (TkappObject *) Tkinter_Error ((PyObject *) v); | 
 |  | 
 |   Tk_GeometryRequest (v->tkwin, 200, 200); | 
 |  | 
 |   if (screenName != NULL) | 
 |     Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY); | 
 |  | 
 |   if (interactive) | 
 |     Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); | 
 |   else | 
 |     Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); | 
 |  | 
 |   if (Tcl_AppInit (v->interp) != TCL_OK) | 
 |     { | 
 |       PyErr_SetString (Tkinter_TclError, "Tcl_AppInit failed"); /* XXX */ | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   return v; | 
 | } | 
 |  | 
 | /** Tcl Eval **/ | 
 |  | 
 | static PyObject * | 
 | Tkapp_Call (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *cmd; | 
 |  | 
 |   cmd = Merge (args); | 
 |   if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR) | 
 |     { | 
 |       free (cmd); | 
 |       return Tkinter_Error (self); | 
 |     } | 
 |  | 
 |   free (cmd); | 
 |   return PyString_FromString (Tkapp_Result (self)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GlobalCall (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *cmd; | 
 |  | 
 |   cmd = Merge (args); | 
 |   if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR) | 
 |     { | 
 |       free (cmd); | 
 |       return Tkinter_Error (self); | 
 |     } | 
 |    | 
 |   free (cmd); | 
 |   return PyString_FromString (Tkapp_Result (self)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_Eval (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *script; | 
 |    | 
 |   if (!PyArg_Parse (args, "s", &script)) | 
 |     return NULL; | 
 |  | 
 |   if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |    | 
 |   return PyString_FromString (Tkapp_Result (self)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GlobalEval (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *script; | 
 |    | 
 |   if (!PyArg_Parse (args, "s", &script)) | 
 |     return NULL; | 
 |  | 
 |   if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   return PyString_FromString (Tkapp_Result (self)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_EvalFile (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *fileName; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &fileName)) | 
 |     return NULL; | 
 |  | 
 |   if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   return PyString_FromString (Tkapp_Result (self)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_Record (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *script; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &script)) | 
 |     return NULL; | 
 |  | 
 |   if (Tcl_RecordAndEval (Tkapp_Interp (self),  | 
 | 			 script, TCL_NO_EVAL) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   return PyString_FromString (Tkapp_Result (self)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_AddErrorInfo (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *msg; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &msg)) | 
 |     return NULL; | 
 |   Tcl_AddErrorInfo (Tkapp_Interp (self), msg); | 
 |  | 
 |   Py_INCREF(Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | /** Tcl Variable **/ | 
 |  | 
 | static PyObject * | 
 | SetVar (self, args, flags) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 |      int flags; | 
 | { | 
 |   char *name1, *name2, *ok; | 
 |   PyObject *newValue; | 
 |   PyObject *tmp; | 
 |  | 
 |   tmp = PyList_New (0); | 
 |  | 
 |   if (PyArg_Parse (args, "(sO)", &name1, &newValue)) | 
 |     ok = Tcl_SetVar (Tkapp_Interp (self), name1,  | 
 | 		     AsString (newValue, tmp), flags); /* XXX Merge? */ | 
 |   else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue)) | 
 |     ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,  | 
 | 		      AsString (newValue, tmp), flags); | 
 |   else | 
 |     { | 
 |       Py_DECREF (tmp); | 
 |       return NULL; | 
 |     } | 
 |   Py_DECREF (tmp); | 
 |  | 
 |   if (!ok) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_SetVar (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   return SetVar (self, args, TCL_LEAVE_ERR_MSG); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GlobalSetVar (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); | 
 | } | 
 |  | 
 | static PyObject * | 
 | GetVar (self, args, flags) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 |      int flags; | 
 | { | 
 |   char *name1, *name2, *s; | 
 |  | 
 |   if (PyArg_Parse (args, "s", &name1)) | 
 |     s = Tcl_GetVar (Tkapp_Interp (self), name1, flags); | 
 |   else if (PyArg_Parse (args, "(ss)", &name1, &name2)) | 
 |     s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags); | 
 |   else | 
 |     return NULL; | 
 |  | 
 |   if (s == NULL) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   return PyString_FromString (s); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GetVar (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   return GetVar (self, args, TCL_LEAVE_ERR_MSG); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GlobalGetVar (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); | 
 | } | 
 |  | 
 | static PyObject * | 
 | UnsetVar (self, args, flags) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 |      int flags; | 
 | { | 
 |   char *name1, *name2; | 
 |   int code; | 
 |  | 
 |   if (PyArg_Parse (args, "s", &name1)) | 
 |     code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags); | 
 |   else if (PyArg_Parse (args, "(ss)", &name1, &name2)) | 
 |     code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags); | 
 |   else | 
 |     return NULL; | 
 |  | 
 |   if (code == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_UnsetVar (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   return UnsetVar (self, args, TCL_LEAVE_ERR_MSG); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GlobalUnsetVar (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); | 
 | } | 
 |  | 
 | /** Tcl to Python **/ | 
 |  | 
 | static PyObject * | 
 | Tkapp_GetInt (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |   int v; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &s)) | 
 |     return NULL; | 
 |   if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |   return Py_BuildValue ("i", v); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GetDouble (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |   double v; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &s)) | 
 |     return NULL; | 
 |   if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |   return Py_BuildValue ("d", v); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GetBoolean (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |   int v; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &s)) | 
 |     return NULL; | 
 |   if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |   return Py_BuildValue ("i", v); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_ExprString (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &s)) | 
 |     return NULL; | 
 |   if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |   return Py_BuildValue ("s", Tkapp_Result (self)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_ExprLong (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |   long v; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &s)) | 
 |     return NULL; | 
 |   if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |   return Py_BuildValue ("l", v); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_ExprDouble (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |   double v; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &s)) | 
 |     return NULL; | 
 |   if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |   return Py_BuildValue ("d", v); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_ExprBoolean (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |   int v; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &s)) | 
 |     return NULL; | 
 |   if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |   return Py_BuildValue ("i", v); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_SplitList (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *list; | 
 |   int argc; | 
 |   char **argv; | 
 |   PyObject *v; | 
 |   int i; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &list)) | 
 |     return NULL; | 
 |  | 
 |   if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR) | 
 |     return Tkinter_Error (self); | 
 |  | 
 |   v = PyTuple_New (argc); | 
 |   for (i = 0; i < argc; i++) | 
 |     PyTuple_SetItem (v, i, PyString_FromString (argv[i])); | 
 |  | 
 |   free (argv); | 
 |   return v; | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_Split (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *list; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &list)) | 
 |     return NULL; | 
 |   return Split (self, list); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_Merge (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *s; | 
 |   PyObject *v; | 
 |  | 
 |   s = Merge (args); | 
 |   v = PyString_FromString (s); | 
 |   free (s); | 
 |   return v; | 
 | } | 
 |  | 
 | /** Tcl Command **/ | 
 |  | 
 | /* This is the Tcl command that acts as a wrapper for Python | 
 |    function or method.  */ | 
 | static int | 
 | PythonCmd (clientData, interp, argc, argv) | 
 |      ClientData clientData;	/* Is (self, func) */ | 
 |      Tcl_Interp *interp; | 
 |      int argc; | 
 |      char *argv[]; | 
 | { | 
 |   PyObject *self, *func, *arg, *res, *tmp; | 
 |   int i; | 
 |  | 
 |   self = PyTuple_GetItem ((PyObject *) clientData, 0); | 
 |   func = PyTuple_GetItem ((PyObject *) clientData, 1); | 
 |  | 
 |   /* Create argument list (argv1, ..., argvN) */ | 
 |   arg = PyTuple_New (argc - 1); | 
 |   for (i = 0; i < (argc - 1); i++) | 
 |     PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1])); | 
 |    | 
 |   res = PyEval_CallObject (func, arg); | 
 |   Py_DECREF (arg); | 
 |   if (res == NULL) | 
 |     return PythonCmd_Error (interp); | 
 |  | 
 |   tmp = PyList_New (0); | 
 |   Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE); | 
 |   Py_DECREF (res); | 
 |   Py_DECREF (tmp); | 
 |  | 
 |   return TCL_OK; | 
 | } | 
 |  | 
 | static void | 
 | PythonCmdDelete (clientData) | 
 |      ClientData clientData;	/* Is (self, func) */ | 
 | { | 
 |   Py_DECREF ((PyObject *) clientData); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_CreateCommand (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *cmdName; | 
 |   PyObject *data; | 
 |   PyObject *func; | 
 |    | 
 |   /* Args is: (cmdName, func) */ | 
 |   if (!PyTuple_Check (args)  | 
 |       || !(PyTuple_Size (args) == 2) | 
 |       || !PyString_Check (PyTuple_GetItem (args, 0)) | 
 |       || !(PyMethod_Check (PyTuple_GetItem (args, 1))  | 
 | 	   || PyFunction_Check (PyTuple_GetItem (args, 1)))) | 
 |     { | 
 |       PyErr_SetString (PyExc_TypeError, "bad argument list"); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   cmdName = PyString_AsString (PyTuple_GetItem (args, 0)); | 
 |   func = PyTuple_GetItem (args, 1); | 
 |  | 
 |   data = PyTuple_New (2);   /* ClientData is: (self, func) */ | 
 |  | 
 |   Py_INCREF (self); | 
 |   PyTuple_SetItem (data, 0, self); | 
 |  | 
 |   Py_INCREF (func); | 
 |   PyTuple_SetItem (data, 1, func); | 
 |  | 
 |   Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd, | 
 | 		     (ClientData) data, PythonCmdDelete); | 
 |  | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_DeleteCommand (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *cmdName; | 
 |  | 
 |   if (!PyArg_Parse (args, "s", &cmdName)) | 
 |     return NULL; | 
 |   if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1) | 
 |     { | 
 |       PyErr_SetString (Tkinter_TclError, "can't delete Tcl command"); | 
 |       return NULL; | 
 |     } | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | /** File Handler **/ | 
 |  | 
 | void | 
 | FileHandler (clientData, mask) | 
 |      ClientData clientData;	/* Is: (func, file) */ | 
 |      int mask; | 
 | { | 
 |   PyObject *func, *file, *arg, *res; | 
 |  | 
 |   func = PyTuple_GetItem ((PyObject *) clientData, 0); | 
 |   file = PyTuple_GetItem ((PyObject *) clientData, 1); | 
 |  | 
 |   arg = Py_BuildValue ("(Oi)", file, (long) mask); | 
 |   res = PyEval_CallObject (func, arg); | 
 |   Py_DECREF (arg); | 
 |   if (res == NULL) | 
 |     { | 
 |       errorInCmd = 1; | 
 |       PyErr_GetAndClear (&excInCmd, &valInCmd); | 
 |     } | 
 |   Py_DECREF (res); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_CreateFileHandler (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args;		/* Is (file, mask, func) */ | 
 | { | 
 |   PyObject *file, *func, *data; | 
 |   int mask, id; | 
 |  | 
 |   if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func)) | 
 |     return NULL; | 
 |   if (!PyFile_Check (file)  | 
 |       || !(PyMethod_Check(func) || PyFunction_Check(func))) | 
 |     { | 
 |       PyErr_SetString (PyExc_TypeError, "bad argument list"); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   /* ClientData is: (func, file) */ | 
 |   data = Py_BuildValue ("(OO)", func, file); | 
 |  | 
 |   id = fileno (PyFile_AsFile (file)); | 
 |   Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data); | 
 |   /* XXX fileHandlerDict */ | 
 |  | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_DeleteFileHandler (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args;		/* Args: file */ | 
 | { | 
 |   int id; | 
 |  | 
 |   if (!PyFile_Check (args)) | 
 |     { | 
 |       PyErr_SetString (PyExc_TypeError, "bad argument list"); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   id = fileno (PyFile_AsFile (args)); | 
 |   Tk_DeleteFileHandler (id); | 
 |   /* XXX fileHandlerDict */ | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | /** Event Loop **/ | 
 |  | 
 | static int quitMainLoop; | 
 |  | 
 | static PyObject * | 
 | Tkapp_MainLoop (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   if (!PyArg_Parse (args, "")) | 
 |     return NULL; | 
 |  | 
 |   quitMainLoop = 0; | 
 |   while (tk_NumMainWindows > 0 && !quitMainLoop && !errorInCmd) | 
 |     { | 
 |       if (PyOS_InterruptOccurred ()) | 
 | 	{ | 
 | 	  PyErr_SetNone (PyExc_KeyboardInterrupt); | 
 | 	  return NULL; | 
 | 	} | 
 |       Tk_DoOneEvent (0); | 
 |     } | 
 |  | 
 |   if (errorInCmd) | 
 |     { | 
 |       errorInCmd = 0; | 
 |       PyErr_SetObject (excInCmd, valInCmd); | 
 |       return NULL; | 
 |     } | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_Quit (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |  | 
 |   if (!PyArg_Parse (args, "")) | 
 |     return NULL; | 
 |   quitMainLoop = 1; | 
 |   Py_INCREF (Py_None); | 
 |   return Py_None; | 
 | } | 
 |  | 
 | /**** Tkapp Method List ****/ | 
 |  | 
 | static PyMethodDef Tkapp_methods[] = | 
 | { | 
 |   {"call", Tkapp_Call}, | 
 |   {"globalcall", Tkapp_GlobalCall}, | 
 |   {"eval", Tkapp_Eval}, | 
 |   {"globaleval", Tkapp_GlobalEval}, | 
 |   {"evalfile", Tkapp_EvalFile}, | 
 |   {"record", Tkapp_Record}, | 
 |   {"adderrorinfo", Tkapp_AddErrorInfo}, | 
 |   {"setvar", Tkapp_SetVar}, | 
 |   {"globalsetvar", Tkapp_GlobalSetVar}, | 
 |   {"getvar", Tkapp_GetVar}, | 
 |   {"globalgetvar", Tkapp_GlobalGetVar}, | 
 |   {"unsetvar", Tkapp_UnsetVar}, | 
 |   {"globalunsetvar", Tkapp_GlobalUnsetVar}, | 
 |   {"getint", Tkapp_GetInt}, | 
 |   {"getdouble", Tkapp_GetDouble}, | 
 |   {"getboolean", Tkapp_GetBoolean}, | 
 |   {"exprstring", Tkapp_ExprString}, | 
 |   {"exprlong", Tkapp_ExprLong}, | 
 |   {"exprdouble", Tkapp_ExprDouble}, | 
 |   {"exprboolean", Tkapp_ExprBoolean}, | 
 |   {"splitlist", Tkapp_SplitList}, | 
 |   {"split", Tkapp_Split}, | 
 |   {"merge", Tkapp_Merge}, | 
 |   {"createcommand", Tkapp_CreateCommand}, | 
 |   {"deletecommand", Tkapp_DeleteCommand}, | 
 |   {"createfilehandler", Tkapp_CreateFileHandler}, | 
 |   {"deletefilehandler", Tkapp_DeleteFileHandler}, | 
 |   {"mainloop", Tkapp_MainLoop}, | 
 |   {"quit", Tkapp_Quit}, | 
 |   {NULL, NULL} | 
 | }; | 
 |  | 
 | /**** Tkapp Type Methods ****/ | 
 |  | 
 | static void | 
 | Tkapp_Dealloc (self) | 
 |      PyObject *self; | 
 | { | 
 |   Tk_DestroyWindow (Tkapp_Tkwin (self)); | 
 |   Tcl_DeleteInterp (Tkapp_Interp (self)); | 
 |   PyMem_DEL (self); | 
 | } | 
 |  | 
 | static PyObject * | 
 | Tkapp_GetAttr (self, name) | 
 |      PyObject *self; | 
 |      char *name; | 
 | { | 
 |   return Py_FindMethod (Tkapp_methods, self, name); | 
 | } | 
 |  | 
 | static PyTypeObject Tkapp_Type = | 
 | { | 
 |   OB_HEAD_INIT (&PyType_Type) | 
 |   0,				/*ob_size */ | 
 |   "tkapp",			/*tp_name */ | 
 |   sizeof (TkappObject),		/*tp_basicsize */ | 
 |   0,				/*tp_itemsize */ | 
 |   Tkapp_Dealloc,		/*tp_dealloc */ | 
 |   0,				/*tp_print */ | 
 |   Tkapp_GetAttr,		/*tp_getattr */ | 
 |   0,				/*tp_setattr */ | 
 |   0,				/*tp_compare */ | 
 |   0,				/*tp_repr */ | 
 |   0,				/*tp_as_number */ | 
 |   0,				/*tp_as_sequence */ | 
 |   0,				/*tp_as_mapping */ | 
 |   0,				/*tp_hash */ | 
 | }; | 
 |  | 
 | /**** Tkinter Module ****/ | 
 |  | 
 | static PyObject * | 
 | Tkinter_Create (self, args) | 
 |      PyObject *self; | 
 |      PyObject *args; | 
 | { | 
 |   char *screenName = NULL; | 
 |   char *baseName; | 
 |   char *className; | 
 |   int interactive = 0; | 
 |  | 
 |   baseName = strrchr (getprogramname (), '/'); | 
 |   if (baseName != NULL) | 
 |     baseName++; | 
 |   else | 
 |     baseName = getprogramname (); | 
 |   className = "Tk"; | 
 |    | 
 |   if (PyArg_Parse (args, "")) | 
 |     /* VOID */ ; | 
 |   else if (PyArg_Parse (args, "z",  | 
 | 			&screenName)) | 
 |     /* VOID */ ; | 
 |   else if (PyArg_Parse (args, "(zs)",  | 
 | 			&screenName, &baseName)) | 
 |     /* VOID */ ; | 
 |   else if (PyArg_Parse (args, "(zss)",  | 
 | 			&screenName, &baseName, &className)) | 
 |     /* VOID */ ; | 
 |   else if (PyArg_Parse (args, "(zssi)",  | 
 | 			&screenName, &baseName, &className, &interactive)) | 
 |     /* VOID */ ; | 
 |   else | 
 |     return NULL; | 
 |  | 
 |   return (PyObject *) Tkapp_New (screenName, baseName, className,  | 
 | 				 interactive); | 
 | } | 
 |  | 
 | static PyMethodDef moduleMethods[] = | 
 | { | 
 |   {"create", Tkinter_Create}, | 
 |   {NULL, NULL} | 
 | }; | 
 |  | 
 | #ifdef WITH_READLINE | 
 | static int | 
 | EventHook () | 
 | { | 
 |   if (errorInCmd)		/* XXX Reset tty */ | 
 |     { | 
 |       errorInCmd = 0; | 
 |       PyErr_SetObject (excInCmd, valInCmd); | 
 |       PyErr_Print (); | 
 |      } | 
 |   if (tk_NumMainWindows > 0) | 
 |     Tk_DoOneEvent (0); | 
 |   return 0; | 
 | } | 
 | #endif /* WITH_READLINE */ | 
 |  | 
 | static void | 
 | StdinProc (clientData, mask) | 
 |      ClientData clientData; | 
 |      int mask; | 
 | { | 
 |   /* Do nothing. */ | 
 | } | 
 |  | 
 | void | 
 | PyInit_tkinter () | 
 | { | 
 | #ifdef WITH_READLINE | 
 |   extern int (*rl_event_hook) (); | 
 | #endif /* WITH_READLINE */ | 
 |   PyObject *m, *d, *v; | 
 |  | 
 |   m = Py_InitModule ("tkinter", moduleMethods); | 
 |  | 
 |   d = PyModule_GetDict (m); | 
 |   Tkinter_TclError = Py_BuildValue ("s", "TclError"); | 
 |   PyDict_SetItemString (d, "TclError", Tkinter_TclError); | 
 |  | 
 |   v = Py_BuildValue ("i", TK_READABLE); | 
 |   PyDict_SetItemString (d, "READABLE", v); | 
 |   v = Py_BuildValue ("i", TK_WRITABLE); | 
 |   PyDict_SetItemString (d, "WRITABLE", v); | 
 |   v = Py_BuildValue ("i", TK_EXCEPTION); | 
 |   PyDict_SetItemString (d, "EXCEPTION", v); | 
 |  | 
 |   /* Unblock stdin. */ | 
 |   Tk_CreateFileHandler (0, TK_READABLE, StdinProc, (ClientData) 0); | 
 |  | 
 | #ifdef WITH_READLINE | 
 |   rl_event_hook = EventHook; | 
 | #endif /* WITH_READLINE */ | 
 |  | 
 |   if (PyErr_Occurred ()) | 
 |     Py_FatalError ("can't initialize module tkinter"); | 
 | } |