blob: 6104960d8c7df73249d1abdcc4d7f867d07de06f [file] [log] [blame]
Guido van Rossum18468821994-06-20 07:49:28 +00001/* tkintermodule.c -- Interface to libtk.a and libtcl.a.
2 Copyright (C) 1994 Steen Lumholt */
3
Guido van Rossum602099a1994-09-14 13:32:22 +00004#include <Python.h>
Guido van Rossum18468821994-06-20 07:49:28 +00005
Guido van Rossum18468821994-06-20 07:49:28 +00006#define PyInit_tkinter inittkinter
7
Guido van Rossum18468821994-06-20 07:49:28 +00008#include <tcl.h>
9#include <tk.h>
10
11extern char *getprogramname ();
Guido van Rossumd308e2b1994-07-07 09:25:12 +000012
13/* Internal declarations from tkInt.h. */
Guido van Rossum18468821994-06-20 07:49:28 +000014extern int tk_NumMainWindows;
Guido van Rossumd308e2b1994-07-07 09:25:12 +000015extern struct { Tk_Window win; } *tkMainWindowList;
Guido van Rossum18468821994-06-20 07:49:28 +000016
17/**** Tkapp Object Declaration ****/
18
19staticforward PyTypeObject Tkapp_Type;
20
21typedef struct
22 {
23 PyObject_HEAD
24 Tcl_Interp *interp;
25 Tk_Window tkwin;
26 }
27TkappObject;
28
29#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
30#define Tkapp_Tkwin(v) (((TkappObject *) (v))->tkwin)
31#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
32#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
33
34#define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
35 (void *) v, ((PyObject *) v)->ob_refcnt))
36
37/**** Error Handling ****/
38
39static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +000040static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +000041static int errorInCmd = 0;
42static PyObject *excInCmd;
43static PyObject *valInCmd;
44
45static PyObject *
46Tkinter_Error (v)
47 PyObject *v;
48{
Guido van Rossum18468821994-06-20 07:49:28 +000049 PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
50 return NULL;
51}
52
53int
54PythonCmd_Error (interp)
55 Tcl_Interp *interp;
56{
57 errorInCmd = 1;
58 PyErr_GetAndClear (&excInCmd, &valInCmd);
59 return TCL_ERROR;
60}
61
62/**** Utils ****/
63
64static char *
65AsString (value, tmp)
66 PyObject *value;
67 PyObject *tmp;
68{
69 if (PyString_Check (value))
70 return PyString_AsString (value);
71 else
72 {
73 PyObject *v;
74
75 v = strobject (value);
76 PyList_Append (tmp, v);
77 Py_DECREF (v);
78 return PyString_AsString (v);
79 }
80}
81
82#define ARGSZ 64
83
84static char *
85Merge (args)
86 PyObject *args;
87{
88 PyObject *tmp;
89 char *argvStore[ARGSZ];
90 char **argv;
91 int fvStore[ARGSZ];
92 int *fv;
93 int argc;
94 char *res;
95 int i;
96
97 tmp = PyList_New (0);
98 argv = argvStore;
99 fv = fvStore;
100
101 if (!PyTuple_Check (args))
102 {
103 argc = 1;
104 fv[0] = 0;
105 argv[0] = AsString (args, tmp);
106 }
107 else
108 {
109 PyObject *v;
110
111 if (PyTuple_Size (args) > ARGSZ)
112 {
113 argv = malloc (PyTuple_Size (args) * sizeof (char *));
114 fv = malloc (PyTuple_Size (args) * sizeof (int));
115 if (argv == NULL || fv == NULL)
116 PyErr_NoMemory ();
117 }
118
119 argc = PyTuple_Size (args);
120 for (i = 0; i < argc; i++)
121 {
122 v = PyTuple_GetItem (args, i);
123 if (PyTuple_Check (v))
124 {
125 fv[i] = 1;
126 argv[i] = Merge (v);
127 }
128 else if (v == Py_None)
129 {
130 argc = i;
131 break;
132 }
133 else
134 {
135 fv[i] = 0;
136 argv[i] = AsString (v, tmp);
137 }
138 }
139 }
140
141 res = Tcl_Merge (argc, argv);
142
143 Py_DECREF (tmp);
144 for (i = 0; i < argc; i++)
145 if (fv[i]) free (argv[i]);
146 if (argv != argvStore)
147 free (argv);
148 if (fv != fvStore)
149 free (fv);
150
151 return res;
152}
153
154static PyObject *
155Split (self, list)
156 PyObject *self;
157 char *list;
158{
159 int argc;
160 char **argv;
161 PyObject *v;
162
163 if (list == NULL)
164 {
165 Py_INCREF (Py_None);
166 return Py_None;
167 }
168
169 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
170 return Tkinter_Error (self);
171
172 if (argc == 0)
173 v = PyString_FromString ("");
174 else if (argc == 1)
175 v = PyString_FromString (argv[0]);
176 else
177 {
178 int i;
179
180 v = PyTuple_New (argc);
181 for (i = 0; i < argc; i++)
182 PyTuple_SetItem (v, i, Split (self, argv[i]));
183 }
184
185 free (argv);
186 return v;
187}
188
189/**** Tkapp Object ****/
190
191#ifndef WITH_APPINIT
192int
193Tcl_AppInit (interp)
194 Tcl_Interp *interp;
195{
196 if (Tcl_Init (interp) == TCL_ERROR)
197 return TCL_ERROR;
198 if (Tk_Init (interp) == TCL_ERROR)
199 return TCL_ERROR;
200 return TCL_OK;
201}
202#endif /* !WITH_APPINIT */
203
204/* Initialize the Tk application; see the `main' function in
205 `tkMain.c'. */
206static TkappObject *
207Tkapp_New (screenName, baseName, className, interactive)
208 char *screenName;
209 char *baseName;
210 char *className;
211 int interactive;
212{
213 TkappObject *v;
214
215 v = PyObject_NEW (TkappObject, &Tkapp_Type);
216 if (v == NULL)
217 return NULL;
218
219 v->interp = Tcl_CreateInterp ();
220 v->tkwin = Tk_CreateMainWindow (v->interp, screenName,
221 baseName, className);
222 if (v->tkwin == NULL)
223 return (TkappObject *) Tkinter_Error ((PyObject *) v);
224
225 Tk_GeometryRequest (v->tkwin, 200, 200);
226
227 if (screenName != NULL)
228 Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
229
230 if (interactive)
231 Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
232 else
233 Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
234
Guido van Rossum18468821994-06-20 07:49:28 +0000235 if (Tcl_AppInit (v->interp) != TCL_OK)
236 {
237 PyErr_SetString (Tkinter_TclError, "Tcl_AppInit failed"); /* XXX */
238 return NULL;
239 }
Guido van Rossum18468821994-06-20 07:49:28 +0000240
241 return v;
242}
243
244/** Tcl Eval **/
245
246static PyObject *
247Tkapp_Call (self, args)
248 PyObject *self;
249 PyObject *args;
250{
251 char *cmd;
252
253 cmd = Merge (args);
254 if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
255 {
256 free (cmd);
257 return Tkinter_Error (self);
258 }
259
260 free (cmd);
261 return PyString_FromString (Tkapp_Result (self));
262}
263
264static PyObject *
265Tkapp_GlobalCall (self, args)
266 PyObject *self;
267 PyObject *args;
268{
269 char *cmd;
270
271 cmd = Merge (args);
272 if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
273 {
274 free (cmd);
275 return Tkinter_Error (self);
276 }
277
278 free (cmd);
279 return PyString_FromString (Tkapp_Result (self));
280}
281
282static PyObject *
283Tkapp_Eval (self, args)
284 PyObject *self;
285 PyObject *args;
286{
287 char *script;
288
289 if (!PyArg_Parse (args, "s", &script))
290 return NULL;
291
292 if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
293 return Tkinter_Error (self);
294
295 return PyString_FromString (Tkapp_Result (self));
296}
297
298static PyObject *
299Tkapp_GlobalEval (self, args)
300 PyObject *self;
301 PyObject *args;
302{
303 char *script;
304
305 if (!PyArg_Parse (args, "s", &script))
306 return NULL;
307
308 if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
309 return Tkinter_Error (self);
310
311 return PyString_FromString (Tkapp_Result (self));
312}
313
314static PyObject *
315Tkapp_EvalFile (self, args)
316 PyObject *self;
317 PyObject *args;
318{
319 char *fileName;
320
321 if (!PyArg_Parse (args, "s", &fileName))
322 return NULL;
323
324 if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
325 return Tkinter_Error (self);
326
327 return PyString_FromString (Tkapp_Result (self));
328}
329
330static PyObject *
331Tkapp_Record (self, args)
332 PyObject *self;
333 PyObject *args;
334{
335 char *script;
336
337 if (!PyArg_Parse (args, "s", &script))
338 return NULL;
339
340 if (Tcl_RecordAndEval (Tkapp_Interp (self),
341 script, TCL_NO_EVAL) == TCL_ERROR)
342 return Tkinter_Error (self);
343
344 return PyString_FromString (Tkapp_Result (self));
345}
346
347static PyObject *
348Tkapp_AddErrorInfo (self, args)
349 PyObject *self;
350 PyObject *args;
351{
352 char *msg;
353
354 if (!PyArg_Parse (args, "s", &msg))
355 return NULL;
356 Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
357
358 Py_INCREF(Py_None);
359 return Py_None;
360}
361
362/** Tcl Variable **/
363
364static PyObject *
365SetVar (self, args, flags)
366 PyObject *self;
367 PyObject *args;
368 int flags;
369{
370 char *name1, *name2, *ok;
371 PyObject *newValue;
372 PyObject *tmp;
373
374 tmp = PyList_New (0);
375
376 if (PyArg_Parse (args, "(sO)", &name1, &newValue))
377 ok = Tcl_SetVar (Tkapp_Interp (self), name1,
378 AsString (newValue, tmp), flags); /* XXX Merge? */
379 else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
380 ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,
381 AsString (newValue, tmp), flags);
382 else
383 {
384 Py_DECREF (tmp);
385 return NULL;
386 }
387 Py_DECREF (tmp);
388
389 if (!ok)
390 return Tkinter_Error (self);
391
392 Py_INCREF (Py_None);
393 return Py_None;
394}
395
396static PyObject *
397Tkapp_SetVar (self, args)
398 PyObject *self;
399 PyObject *args;
400{
401 return SetVar (self, args, TCL_LEAVE_ERR_MSG);
402}
403
404static PyObject *
405Tkapp_GlobalSetVar (self, args)
406 PyObject *self;
407 PyObject *args;
408{
409 return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
410}
411
412static PyObject *
413GetVar (self, args, flags)
414 PyObject *self;
415 PyObject *args;
416 int flags;
417{
418 char *name1, *name2, *s;
419
420 if (PyArg_Parse (args, "s", &name1))
421 s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
422 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
423 s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
424 else
425 return NULL;
426
427 if (s == NULL)
428 return Tkinter_Error (self);
429
430 return PyString_FromString (s);
431}
432
433static PyObject *
434Tkapp_GetVar (self, args)
435 PyObject *self;
436 PyObject *args;
437{
438 return GetVar (self, args, TCL_LEAVE_ERR_MSG);
439}
440
441static PyObject *
442Tkapp_GlobalGetVar (self, args)
443 PyObject *self;
444 PyObject *args;
445{
446 return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
447}
448
449static PyObject *
450UnsetVar (self, args, flags)
451 PyObject *self;
452 PyObject *args;
453 int flags;
454{
455 char *name1, *name2;
456 int code;
457
458 if (PyArg_Parse (args, "s", &name1))
459 code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
460 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
461 code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
462 else
463 return NULL;
464
465 if (code == TCL_ERROR)
466 return Tkinter_Error (self);
467
468 Py_INCREF (Py_None);
469 return Py_None;
470}
471
472static PyObject *
473Tkapp_UnsetVar (self, args)
474 PyObject *self;
475 PyObject *args;
476{
477 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
478}
479
480static PyObject *
481Tkapp_GlobalUnsetVar (self, args)
482 PyObject *self;
483 PyObject *args;
484{
485 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
486}
487
488/** Tcl to Python **/
489
490static PyObject *
491Tkapp_GetInt (self, args)
492 PyObject *self;
493 PyObject *args;
494{
495 char *s;
496 int v;
497
498 if (!PyArg_Parse (args, "s", &s))
499 return NULL;
500 if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
501 return Tkinter_Error (self);
502 return Py_BuildValue ("i", v);
503}
504
505static PyObject *
506Tkapp_GetDouble (self, args)
507 PyObject *self;
508 PyObject *args;
509{
510 char *s;
511 double v;
512
513 if (!PyArg_Parse (args, "s", &s))
514 return NULL;
515 if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
516 return Tkinter_Error (self);
517 return Py_BuildValue ("d", v);
518}
519
520static PyObject *
521Tkapp_GetBoolean (self, args)
522 PyObject *self;
523 PyObject *args;
524{
525 char *s;
526 int v;
527
528 if (!PyArg_Parse (args, "s", &s))
529 return NULL;
530 if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
531 return Tkinter_Error (self);
532 return Py_BuildValue ("i", v);
533}
534
535static PyObject *
536Tkapp_ExprString (self, args)
537 PyObject *self;
538 PyObject *args;
539{
540 char *s;
541
542 if (!PyArg_Parse (args, "s", &s))
543 return NULL;
544 if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
545 return Tkinter_Error (self);
546 return Py_BuildValue ("s", Tkapp_Result (self));
547}
548
549static PyObject *
550Tkapp_ExprLong (self, args)
551 PyObject *self;
552 PyObject *args;
553{
554 char *s;
555 long v;
556
557 if (!PyArg_Parse (args, "s", &s))
558 return NULL;
559 if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
560 return Tkinter_Error (self);
561 return Py_BuildValue ("l", v);
562}
563
564static PyObject *
565Tkapp_ExprDouble (self, args)
566 PyObject *self;
567 PyObject *args;
568{
569 char *s;
570 double v;
571
572 if (!PyArg_Parse (args, "s", &s))
573 return NULL;
574 if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
575 return Tkinter_Error (self);
576 return Py_BuildValue ("d", v);
577}
578
579static PyObject *
580Tkapp_ExprBoolean (self, args)
581 PyObject *self;
582 PyObject *args;
583{
584 char *s;
585 int v;
586
587 if (!PyArg_Parse (args, "s", &s))
588 return NULL;
589 if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
590 return Tkinter_Error (self);
591 return Py_BuildValue ("i", v);
592}
593
594static PyObject *
595Tkapp_SplitList (self, args)
596 PyObject *self;
597 PyObject *args;
598{
599 char *list;
600 int argc;
601 char **argv;
602 PyObject *v;
603 int i;
604
605 if (!PyArg_Parse (args, "s", &list))
606 return NULL;
607
608 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
609 return Tkinter_Error (self);
610
611 v = PyTuple_New (argc);
612 for (i = 0; i < argc; i++)
613 PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
614
615 free (argv);
616 return v;
617}
618
619static PyObject *
620Tkapp_Split (self, args)
621 PyObject *self;
622 PyObject *args;
623{
624 char *list;
625
626 if (!PyArg_Parse (args, "s", &list))
627 return NULL;
628 return Split (self, list);
629}
630
631static PyObject *
632Tkapp_Merge (self, args)
633 PyObject *self;
634 PyObject *args;
635{
636 char *s;
637 PyObject *v;
638
639 s = Merge (args);
640 v = PyString_FromString (s);
641 free (s);
642 return v;
643}
644
645/** Tcl Command **/
646
647/* This is the Tcl command that acts as a wrapper for Python
648 function or method. */
649static int
650PythonCmd (clientData, interp, argc, argv)
651 ClientData clientData; /* Is (self, func) */
652 Tcl_Interp *interp;
653 int argc;
654 char *argv[];
655{
656 PyObject *self, *func, *arg, *res, *tmp;
657 int i;
658
659 self = PyTuple_GetItem ((PyObject *) clientData, 0);
660 func = PyTuple_GetItem ((PyObject *) clientData, 1);
661
662 /* Create argument list (argv1, ..., argvN) */
663 arg = PyTuple_New (argc - 1);
664 for (i = 0; i < (argc - 1); i++)
665 PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
666
667 res = PyEval_CallObject (func, arg);
668 Py_DECREF (arg);
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000669
Guido van Rossum18468821994-06-20 07:49:28 +0000670 if (res == NULL)
671 return PythonCmd_Error (interp);
672
673 tmp = PyList_New (0);
674 Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
675 Py_DECREF (res);
676 Py_DECREF (tmp);
677
678 return TCL_OK;
679}
680
681static void
682PythonCmdDelete (clientData)
683 ClientData clientData; /* Is (self, func) */
684{
685 Py_DECREF ((PyObject *) clientData);
686}
687
688static PyObject *
689Tkapp_CreateCommand (self, args)
690 PyObject *self;
691 PyObject *args;
692{
693 char *cmdName;
694 PyObject *data;
695 PyObject *func;
696
697 /* Args is: (cmdName, func) */
698 if (!PyTuple_Check (args)
699 || !(PyTuple_Size (args) == 2)
700 || !PyString_Check (PyTuple_GetItem (args, 0))
701 || !(PyMethod_Check (PyTuple_GetItem (args, 1))
702 || PyFunction_Check (PyTuple_GetItem (args, 1))))
703 {
704 PyErr_SetString (PyExc_TypeError, "bad argument list");
705 return NULL;
706 }
707
708 cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
709 func = PyTuple_GetItem (args, 1);
710
711 data = PyTuple_New (2); /* ClientData is: (self, func) */
712
713 Py_INCREF (self);
714 PyTuple_SetItem (data, 0, self);
715
716 Py_INCREF (func);
717 PyTuple_SetItem (data, 1, func);
718
719 Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
720 (ClientData) data, PythonCmdDelete);
721
722 Py_INCREF (Py_None);
723 return Py_None;
724}
725
726static PyObject *
727Tkapp_DeleteCommand (self, args)
728 PyObject *self;
729 PyObject *args;
730{
731 char *cmdName;
732
733 if (!PyArg_Parse (args, "s", &cmdName))
734 return NULL;
735 if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
736 {
737 PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
738 return NULL;
739 }
740 Py_INCREF (Py_None);
741 return Py_None;
742}
743
744/** File Handler **/
745
746void
747FileHandler (clientData, mask)
Guido van Rossum76875221994-06-27 07:59:42 +0000748 ClientData clientData; /* Is: (func, file) */
Guido van Rossum18468821994-06-20 07:49:28 +0000749 int mask;
750{
Guido van Rossum76875221994-06-27 07:59:42 +0000751 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +0000752
Guido van Rossum76875221994-06-27 07:59:42 +0000753 func = PyTuple_GetItem ((PyObject *) clientData, 0);
754 file = PyTuple_GetItem ((PyObject *) clientData, 1);
Guido van Rossum18468821994-06-20 07:49:28 +0000755
Guido van Rossum76875221994-06-27 07:59:42 +0000756 arg = Py_BuildValue ("(Oi)", file, (long) mask);
Guido van Rossum18468821994-06-20 07:49:28 +0000757 res = PyEval_CallObject (func, arg);
758 Py_DECREF (arg);
759 if (res == NULL)
760 {
761 errorInCmd = 1;
762 PyErr_GetAndClear (&excInCmd, &valInCmd);
763 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000764 Py_XDECREF (res);
765}
766
767static int
768GetFileNo (file)
769 PyObject *file; /* Either an int >= 0 or an object with a
770 .fileno() method that returns an int >= 0 */
771{
772 object *meth, *args, *res;
773 int id;
774 if (PyInt_Check(file)) {
775 id = PyInt_AsLong(file);
776 if (id < 0)
777 PyErr_SetString(PyExc_ValueError, "invalid file id");
778 return id;
779 }
780 meth = PyObject_GetAttrString(file, "fileno");
781 if (meth == NULL)
782 return -1;
783 args = PyTuple_New(0);
784 if (args == NULL)
785 return -1;
786 res = PyEval_CallObject(meth, args);
787 Py_DECREF(args);
788 Py_DECREF(meth);
789 if (res == NULL)
790 return -1;
791 if (PyInt_Check(res))
792 id = PyInt_AsLong(res);
793 else
794 id = -1;
795 if (id < 0)
796 PyErr_SetString(PyExc_ValueError,
797 "invalid fileno() return value");
798 Py_DECREF(res);
799 return id;
Guido van Rossum18468821994-06-20 07:49:28 +0000800}
801
802static PyObject *
803Tkapp_CreateFileHandler (self, args)
804 PyObject *self;
805 PyObject *args; /* Is (file, mask, func) */
806{
Guido van Rossum76875221994-06-27 07:59:42 +0000807 PyObject *file, *func, *data;
808 int mask, id;
Guido van Rossum18468821994-06-20 07:49:28 +0000809
810 if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
811 return NULL;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000812 id = GetFileNo (file);
813 if (id < 0)
814 return NULL;
815 if (!(PyMethod_Check(func) || PyFunction_Check(func)))
Guido van Rossum18468821994-06-20 07:49:28 +0000816 {
817 PyErr_SetString (PyExc_TypeError, "bad argument list");
818 return NULL;
819 }
820
Guido van Rossum76875221994-06-27 07:59:42 +0000821 /* ClientData is: (func, file) */
822 data = Py_BuildValue ("(OO)", func, file);
823
Guido van Rossum76875221994-06-27 07:59:42 +0000824 Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
Guido van Rossum18468821994-06-20 07:49:28 +0000825 /* XXX fileHandlerDict */
Guido van Rossum76875221994-06-27 07:59:42 +0000826
Guido van Rossum18468821994-06-20 07:49:28 +0000827 Py_INCREF (Py_None);
828 return Py_None;
829}
830
831static PyObject *
832Tkapp_DeleteFileHandler (self, args)
833 PyObject *self;
834 PyObject *args; /* Args: file */
835{
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000836 PyObject *file;
Guido van Rossum18468821994-06-20 07:49:28 +0000837 int id;
838
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000839 if (!PyArg_Parse (args, "O", &file))
840 return NULL;
841 id = GetFileNo (file);
842 if (id < 0)
843 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000844
Guido van Rossum18468821994-06-20 07:49:28 +0000845 Tk_DeleteFileHandler (id);
846 /* XXX fileHandlerDict */
847 Py_INCREF (Py_None);
848 return Py_None;
849}
850
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000851/**** Tktt Object (timer token) ****/
852
853staticforward PyTypeObject Tktt_Type;
854
855typedef struct
856 {
857 PyObject_HEAD
858 Tk_TimerToken token;
859 PyObject *func;
860 }
861TkttObject;
862
863static PyObject *
864Tktt_DeleteTimerHandler (self, args)
865 PyObject *self;
866 PyObject *args;
867{
868 TkttObject *v = (TkttObject *) self;
869
870 if (!PyArg_Parse (args, ""))
871 return NULL;
872 if (v->func != NULL)
873 {
874 Tk_DeleteTimerHandler (v->token);
875 PyMem_DEL (v->func);
876 v->func = NULL;
877 }
878 Py_INCREF (Py_None);
879 return Py_None;
880}
881
882static PyMethodDef Tktt_methods[] =
883{
884 {"deletetimerhandler", Tktt_DeleteTimerHandler},
885 {NULL, NULL}
886};
887
888static TkttObject *
889Tktt_New (token, func)
890 Tk_TimerToken token;
891 PyObject *func;
892{
893 TkttObject *v;
894
895 v = PyObject_NEW (TkttObject, &Tktt_Type);
896 if (v == NULL)
897 return NULL;
898
899 v->token = token;
900 v->func = func;
901 Py_INCREF (v->func);
902 return v;
903}
904
905static void
906Tktt_Dealloc (self)
907 PyObject *self;
908{
909 PyMem_DEL (self);
910}
911
912static int
913Tktt_Print (self, fp, flags)
914 PyObject *self;
915 FILE *fp;
916 int flags;
917{
918 TkttObject *v = (TkttObject *) self;
919
920 fprintf(fp, "<tktimertoken at 0x%x%s>", v,
921 v->func == NULL ? ", handler deleted" : "");
922 return 0;
923}
924
925static PyObject *
926Tktt_GetAttr (self, name)
927 PyObject *self;
928 char *name;
929{
930 return Py_FindMethod (Tktt_methods, self, name);
931}
932
933static PyTypeObject Tktt_Type =
934{
935 OB_HEAD_INIT (&PyType_Type)
936 0, /*ob_size */
937 "tktimertoken", /*tp_name */
938 sizeof (TkttObject), /*tp_basicsize */
939 0, /*tp_itemsize */
940 Tktt_Dealloc, /*tp_dealloc */
941 Tktt_Print, /*tp_print */
942 Tktt_GetAttr, /*tp_getattr */
943 0, /*tp_setattr */
944 0, /*tp_compare */
945 0, /*tp_repr */
946 0, /*tp_as_number */
947 0, /*tp_as_sequence */
948 0, /*tp_as_mapping */
949 0, /*tp_hash */
950};
951
952/** Timer Handler **/
953
954static void
955TimerHandler (clientData)
956 ClientData clientData;
957{
958 PyObject *func = (PyObject *) clientData;
959 PyObject *arg, *res;
960
961 arg = PyTuple_New (0);
962 res = PyEval_CallObject (func, arg);
963 Py_DECREF (arg);
964 if (res == NULL)
965 {
966 errorInCmd = 1;
967 PyErr_GetAndClear (&excInCmd, &valInCmd);
968 }
969 Py_DECREF (res);
970}
971
972static PyObject *
973Tkapp_CreateTimerHandler (self, args)
974 PyObject *self;
975 PyObject *args; /* Is (milliseconds, func) */
976{
977 int milliseconds;
978 PyObject *func;
979 Tk_TimerToken token;
980
981 if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
982 return NULL;
983 if (!(PyMethod_Check(func) || PyFunction_Check(func) ||
984 PyCFunction_Check(func)))
985 {
986 PyErr_SetString (PyExc_TypeError, "bad argument list");
987 return NULL;
988 }
989 token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
990 return (PyObject *) Tktt_New (token, func);
991}
992
Guido van Rossum18468821994-06-20 07:49:28 +0000993/** Event Loop **/
994
Guido van Rossum18468821994-06-20 07:49:28 +0000995static PyObject *
996Tkapp_MainLoop (self, args)
997 PyObject *self;
998 PyObject *args;
999{
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001000 int threshold = 0;
1001
Guido van Rossum18468821994-06-20 07:49:28 +00001002 if (!PyArg_Parse (args, ""))
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001003 {
1004 PyErr_Clear();
1005 if (!PyArg_Parse (args, "i", &threshold))
1006 return NULL;
1007 }
Guido van Rossum18468821994-06-20 07:49:28 +00001008
1009 quitMainLoop = 0;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001010 while (tk_NumMainWindows > threshold && !quitMainLoop && !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001011 {
1012 if (PyOS_InterruptOccurred ())
1013 {
1014 PyErr_SetNone (PyExc_KeyboardInterrupt);
1015 return NULL;
1016 }
1017 Tk_DoOneEvent (0);
1018 }
1019
1020 if (errorInCmd)
1021 {
1022 errorInCmd = 0;
1023 PyErr_SetObject (excInCmd, valInCmd);
1024 return NULL;
1025 }
1026 Py_INCREF (Py_None);
1027 return Py_None;
1028}
1029
1030static PyObject *
1031Tkapp_Quit (self, args)
1032 PyObject *self;
1033 PyObject *args;
1034{
1035
1036 if (!PyArg_Parse (args, ""))
1037 return NULL;
1038 quitMainLoop = 1;
1039 Py_INCREF (Py_None);
1040 return Py_None;
1041}
1042
1043/**** Tkapp Method List ****/
1044
1045static PyMethodDef Tkapp_methods[] =
1046{
1047 {"call", Tkapp_Call},
1048 {"globalcall", Tkapp_GlobalCall},
1049 {"eval", Tkapp_Eval},
1050 {"globaleval", Tkapp_GlobalEval},
1051 {"evalfile", Tkapp_EvalFile},
1052 {"record", Tkapp_Record},
1053 {"adderrorinfo", Tkapp_AddErrorInfo},
1054 {"setvar", Tkapp_SetVar},
1055 {"globalsetvar", Tkapp_GlobalSetVar},
1056 {"getvar", Tkapp_GetVar},
1057 {"globalgetvar", Tkapp_GlobalGetVar},
1058 {"unsetvar", Tkapp_UnsetVar},
1059 {"globalunsetvar", Tkapp_GlobalUnsetVar},
1060 {"getint", Tkapp_GetInt},
1061 {"getdouble", Tkapp_GetDouble},
1062 {"getboolean", Tkapp_GetBoolean},
1063 {"exprstring", Tkapp_ExprString},
1064 {"exprlong", Tkapp_ExprLong},
1065 {"exprdouble", Tkapp_ExprDouble},
1066 {"exprboolean", Tkapp_ExprBoolean},
1067 {"splitlist", Tkapp_SplitList},
1068 {"split", Tkapp_Split},
1069 {"merge", Tkapp_Merge},
1070 {"createcommand", Tkapp_CreateCommand},
1071 {"deletecommand", Tkapp_DeleteCommand},
1072 {"createfilehandler", Tkapp_CreateFileHandler},
1073 {"deletefilehandler", Tkapp_DeleteFileHandler},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001074 {"createtimerhandler", Tkapp_CreateTimerHandler},
Guido van Rossum18468821994-06-20 07:49:28 +00001075 {"mainloop", Tkapp_MainLoop},
1076 {"quit", Tkapp_Quit},
1077 {NULL, NULL}
1078};
1079
1080/**** Tkapp Type Methods ****/
1081
1082static void
1083Tkapp_Dealloc (self)
1084 PyObject *self;
1085{
1086 Tk_DestroyWindow (Tkapp_Tkwin (self));
1087 Tcl_DeleteInterp (Tkapp_Interp (self));
1088 PyMem_DEL (self);
1089}
1090
1091static PyObject *
1092Tkapp_GetAttr (self, name)
1093 PyObject *self;
1094 char *name;
1095{
1096 return Py_FindMethod (Tkapp_methods, self, name);
1097}
1098
1099static PyTypeObject Tkapp_Type =
1100{
1101 OB_HEAD_INIT (&PyType_Type)
1102 0, /*ob_size */
1103 "tkapp", /*tp_name */
1104 sizeof (TkappObject), /*tp_basicsize */
1105 0, /*tp_itemsize */
1106 Tkapp_Dealloc, /*tp_dealloc */
1107 0, /*tp_print */
1108 Tkapp_GetAttr, /*tp_getattr */
1109 0, /*tp_setattr */
1110 0, /*tp_compare */
1111 0, /*tp_repr */
1112 0, /*tp_as_number */
1113 0, /*tp_as_sequence */
1114 0, /*tp_as_mapping */
1115 0, /*tp_hash */
1116};
1117
1118/**** Tkinter Module ****/
1119
1120static PyObject *
1121Tkinter_Create (self, args)
1122 PyObject *self;
1123 PyObject *args;
1124{
1125 char *screenName = NULL;
1126 char *baseName;
1127 char *className;
1128 int interactive = 0;
1129
1130 baseName = strrchr (getprogramname (), '/');
1131 if (baseName != NULL)
1132 baseName++;
1133 else
1134 baseName = getprogramname ();
1135 className = "Tk";
1136
1137 if (PyArg_Parse (args, ""))
1138 /* VOID */ ;
1139 else if (PyArg_Parse (args, "z",
1140 &screenName))
1141 /* VOID */ ;
1142 else if (PyArg_Parse (args, "(zs)",
1143 &screenName, &baseName))
1144 /* VOID */ ;
1145 else if (PyArg_Parse (args, "(zss)",
1146 &screenName, &baseName, &className))
1147 /* VOID */ ;
1148 else if (PyArg_Parse (args, "(zssi)",
1149 &screenName, &baseName, &className, &interactive))
1150 /* VOID */ ;
1151 else
1152 return NULL;
1153
1154 return (PyObject *) Tkapp_New (screenName, baseName, className,
1155 interactive);
1156}
1157
1158static PyMethodDef moduleMethods[] =
1159{
1160 {"create", Tkinter_Create},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001161 {"createfilehandler", Tkapp_CreateFileHandler},
1162 {"deletefilehandler", Tkapp_DeleteFileHandler},
1163 {"createtimerhandler", Tkapp_CreateTimerHandler},
1164 {"mainloop", Tkapp_MainLoop},
1165 {"quit", Tkapp_Quit},
Guido van Rossum18468821994-06-20 07:49:28 +00001166 {NULL, NULL}
1167};
1168
1169#ifdef WITH_READLINE
1170static int
1171EventHook ()
1172{
1173 if (errorInCmd) /* XXX Reset tty */
1174 {
1175 errorInCmd = 0;
1176 PyErr_SetObject (excInCmd, valInCmd);
1177 PyErr_Print ();
1178 }
1179 if (tk_NumMainWindows > 0)
Guido van Rossume2ca9bd1994-08-03 08:01:43 +00001180 Tk_DoOneEvent (TK_DONT_WAIT);
Guido van Rossum18468821994-06-20 07:49:28 +00001181 return 0;
1182}
1183#endif /* WITH_READLINE */
1184
1185static void
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001186Tkinter_Cleanup ()
1187{
1188 /* XXX rl_deprep_terminal is static, damned! */
1189 while (tkMainWindowList != 0)
1190 Tk_DestroyWindow (tkMainWindowList->win);
1191}
1192
Guido van Rossum18468821994-06-20 07:49:28 +00001193void
1194PyInit_tkinter ()
1195{
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001196 static inited = 0;
1197
Guido van Rossum18468821994-06-20 07:49:28 +00001198#ifdef WITH_READLINE
1199 extern int (*rl_event_hook) ();
1200#endif /* WITH_READLINE */
1201 PyObject *m, *d, *v;
1202
1203 m = Py_InitModule ("tkinter", moduleMethods);
1204
1205 d = PyModule_GetDict (m);
1206 Tkinter_TclError = Py_BuildValue ("s", "TclError");
1207 PyDict_SetItemString (d, "TclError", Tkinter_TclError);
1208
1209 v = Py_BuildValue ("i", TK_READABLE);
1210 PyDict_SetItemString (d, "READABLE", v);
1211 v = Py_BuildValue ("i", TK_WRITABLE);
1212 PyDict_SetItemString (d, "WRITABLE", v);
1213 v = Py_BuildValue ("i", TK_EXCEPTION);
1214 PyDict_SetItemString (d, "EXCEPTION", v);
1215
Guido van Rossum18468821994-06-20 07:49:28 +00001216#ifdef WITH_READLINE
1217 rl_event_hook = EventHook;
1218#endif /* WITH_READLINE */
1219
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001220 if (!inited)
1221 {
1222 inited = 1;
Guido van Rossume4485b01994-09-07 14:32:49 +00001223 if (Py_AtExit (Tkinter_Cleanup) != 0)
1224 fprintf(stderr,
1225 "Tkinter: warning: cleanup procedure not registered\n");
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001226 }
1227
Guido van Rossum18468821994-06-20 07:49:28 +00001228 if (PyErr_Occurred ())
1229 Py_FatalError ("can't initialize module tkinter");
1230}