Initial revision
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
new file mode 100644
index 0000000..2bb7060
--- /dev/null
+++ b/Modules/_tkinter.c
@@ -0,0 +1,1056 @@
+/* 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);
+
+#ifndef WITH_APPINIT
+  if (Tcl_AppInit (v->interp) != TCL_OK)
+    {
+      PyErr_SetString (Tkinter_TclError, "Tcl_AppInit failed"); /* XXX */
+      return NULL;
+    }
+#endif /* !WITH_APPINIT */
+
+  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 */
+     int mask;
+{
+  PyObject *func;
+  PyObject *arg, *res;
+
+  func = (PyObject *) clientData;
+
+  arg = PyInt_FromLong ((long) mask);
+  res = PyEval_CallObject (func, arg);
+  Py_DECREF (arg);
+  if (res == NULL)
+    {
+      errorInCmd = 1;
+      PyErr_GetAndClear (&excInCmd, &valInCmd);
+    }
+}
+
+static PyObject *
+Tkapp_CreateFileHandler (self, args)
+     PyObject *self;
+     PyObject *args;		/* Is (file, mask, func) */
+{
+  PyObject *file;
+  int mask;
+  PyObject *func;
+  int 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;
+    }
+
+  id = fileno (PyFile_AsFile (file));
+  Py_DECREF (file);
+  Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) func);
+  /* 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");
+}