cpython/Modules/_tkinter.c
Guido van Rossum 3bbc62e9c2 Another bulky set of minor changes.
Note addition of gethostbyaddr() and improved repr() for sockets,
renaming of md5.md5() to md5.new(), and fixing of leaks in threads.
1995-01-02 19:30:30 +00:00

1234 lines
25 KiB
C

/* tkintermodule.c -- Interface to libtk.a and libtcl.a.
Copyright (C) 1994 Steen Lumholt */
#include <Python.h>
#define PyInit_tkinter inittkinter
#include <tcl.h>
#include <tk.h>
extern char *getprogramname ();
/* Internal declarations from tkInt.h. */
extern int tk_NumMainWindows;
extern struct { Tk_Window win; } *tkMainWindowList;
/**** 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 quitMainLoop = 0;
static int errorInCmd = 0;
static PyObject *excInCmd;
static PyObject *valInCmd;
static PyObject *trbInCmd;
static PyObject *
Tkinter_Error (v)
PyObject *v;
{
PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
return NULL;
}
int
PythonCmd_Error (interp)
Tcl_Interp *interp;
{
errorInCmd = 1;
PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
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_Fetch (&excInCmd, &valInCmd, &trbInCmd);
}
Py_XDECREF (res);
}
static int
GetFileNo (file)
PyObject *file; /* Either an int >= 0 or an object with a
.fileno() method that returns an int >= 0 */
{
object *meth, *args, *res;
int id;
if (PyInt_Check(file)) {
id = PyInt_AsLong(file);
if (id < 0)
PyErr_SetString(PyExc_ValueError, "invalid file id");
return id;
}
meth = PyObject_GetAttrString(file, "fileno");
if (meth == NULL)
return -1;
args = PyTuple_New(0);
if (args == NULL)
return -1;
res = PyEval_CallObject(meth, args);
Py_DECREF(args);
Py_DECREF(meth);
if (res == NULL)
return -1;
if (PyInt_Check(res))
id = PyInt_AsLong(res);
else
id = -1;
if (id < 0)
PyErr_SetString(PyExc_ValueError,
"invalid fileno() return value");
Py_DECREF(res);
return id;
}
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;
id = GetFileNo (file);
if (id < 0)
return NULL;
if (!(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);
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 */
{
PyObject *file;
int id;
if (!PyArg_Parse (args, "O", &file))
return NULL;
id = GetFileNo (file);
if (id < 0)
return NULL;
Tk_DeleteFileHandler (id);
/* XXX fileHandlerDict */
Py_INCREF (Py_None);
return Py_None;
}
/**** Tktt Object (timer token) ****/
staticforward PyTypeObject Tktt_Type;
typedef struct
{
PyObject_HEAD
Tk_TimerToken token;
PyObject *func;
}
TkttObject;
static PyObject *
Tktt_DeleteTimerHandler (self, args)
PyObject *self;
PyObject *args;
{
TkttObject *v = (TkttObject *) self;
if (!PyArg_Parse (args, ""))
return NULL;
if (v->func != NULL)
{
Tk_DeleteTimerHandler (v->token);
PyMem_DEL (v->func);
v->func = NULL;
}
Py_INCREF (Py_None);
return Py_None;
}
static PyMethodDef Tktt_methods[] =
{
{"deletetimerhandler", Tktt_DeleteTimerHandler},
{NULL, NULL}
};
static TkttObject *
Tktt_New (token, func)
Tk_TimerToken token;
PyObject *func;
{
TkttObject *v;
v = PyObject_NEW (TkttObject, &Tktt_Type);
if (v == NULL)
return NULL;
v->token = token;
v->func = func;
Py_INCREF (v->func);
return v;
}
static void
Tktt_Dealloc (self)
PyObject *self;
{
PyMem_DEL (self);
}
static int
Tktt_Print (self, fp, flags)
PyObject *self;
FILE *fp;
int flags;
{
TkttObject *v = (TkttObject *) self;
fprintf(fp, "<tktimertoken at 0x%x%s>", v,
v->func == NULL ? ", handler deleted" : "");
return 0;
}
static PyObject *
Tktt_GetAttr (self, name)
PyObject *self;
char *name;
{
return Py_FindMethod (Tktt_methods, self, name);
}
static PyTypeObject Tktt_Type =
{
OB_HEAD_INIT (&PyType_Type)
0, /*ob_size */
"tktimertoken", /*tp_name */
sizeof (TkttObject), /*tp_basicsize */
0, /*tp_itemsize */
Tktt_Dealloc, /*tp_dealloc */
Tktt_Print, /*tp_print */
Tktt_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 */
};
/** Timer Handler **/
static void
TimerHandler (clientData)
ClientData clientData;
{
PyObject *func = (PyObject *) clientData;
PyObject *arg, *res;
arg = PyTuple_New (0);
res = PyEval_CallObject (func, arg);
Py_DECREF (arg);
if (res == NULL)
{
errorInCmd = 1;
PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
}
else
Py_DECREF (res);
}
static PyObject *
Tkapp_CreateTimerHandler (self, args)
PyObject *self;
PyObject *args; /* Is (milliseconds, func) */
{
int milliseconds;
PyObject *func;
Tk_TimerToken token;
if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
return NULL;
if (!(PyMethod_Check(func) || PyFunction_Check(func) ||
PyCFunction_Check(func)))
{
PyErr_SetString (PyExc_TypeError, "bad argument list");
return NULL;
}
token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
return (PyObject *) Tktt_New (token, func);
}
/** Event Loop **/
static PyObject *
Tkapp_MainLoop (self, args)
PyObject *self;
PyObject *args;
{
int threshold = 0;
if (!PyArg_Parse (args, ""))
{
PyErr_Clear();
if (!PyArg_Parse (args, "i", &threshold))
return NULL;
}
quitMainLoop = 0;
while (tk_NumMainWindows > threshold && !quitMainLoop && !errorInCmd)
{
if (PyOS_InterruptOccurred ())
{
PyErr_SetNone (PyExc_KeyboardInterrupt);
return NULL;
}
Tk_DoOneEvent (0);
}
if (errorInCmd)
{
errorInCmd = 0;
PyErr_Restore (excInCmd, valInCmd, trbInCmd);
excInCmd = valInCmd = trbInCmd = NULL;
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},
{"createtimerhandler", Tkapp_CreateTimerHandler},
{"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},
{"createfilehandler", Tkapp_CreateFileHandler},
{"deletefilehandler", Tkapp_DeleteFileHandler},
{"createtimerhandler", Tkapp_CreateTimerHandler},
{"mainloop", Tkapp_MainLoop},
{"quit", Tkapp_Quit},
{NULL, NULL}
};
#ifdef WITH_READLINE
static int
EventHook ()
{
if (errorInCmd) /* XXX Reset tty */
{
errorInCmd = 0;
PyErr_Restore (excInCmd, valInCmd, trbInCmd);
excInCmd = valInCmd = trbInCmd = NULL;
PyErr_Print ();
}
if (tk_NumMainWindows > 0)
Tk_DoOneEvent (TK_DONT_WAIT);
return 0;
}
#endif /* WITH_READLINE */
static void
Tkinter_Cleanup ()
{
/* XXX rl_deprep_terminal is static, damned! */
while (tkMainWindowList != 0)
Tk_DestroyWindow (tkMainWindowList->win);
}
void
PyInit_tkinter ()
{
static inited = 0;
#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);
#ifdef WITH_READLINE
rl_event_hook = EventHook;
#endif /* WITH_READLINE */
if (!inited)
{
inited = 1;
if (Py_AtExit (Tkinter_Cleanup) != 0)
fprintf(stderr,
"Tkinter: warning: cleanup procedure not registered\n");
}
if (PyErr_Occurred ())
Py_FatalError ("can't initialize module tkinter");
}