blob: 5825eff95d831290d37be4682a0dbcec9121d5d2 [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 Rossum9722ad81995-09-22 23:49:28 +00004#include "Python.h"
5
6#ifdef macintosh
7#define MAC_TCL
8#endif
9
10#ifdef MAC_TCL
11#define WITH_APPINIT
12#endif
Guido van Rossum18468821994-06-20 07:49:28 +000013
Guido van Rossum18468821994-06-20 07:49:28 +000014#define PyInit_tkinter inittkinter
15
Guido van Rossum18468821994-06-20 07:49:28 +000016#include <tcl.h>
17#include <tk.h>
18
19extern char *getprogramname ();
Guido van Rossumd308e2b1994-07-07 09:25:12 +000020
Guido van Rossum9722ad81995-09-22 23:49:28 +000021/* Internal declarations from tkInt.h. */
22#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
23extern int Tk_GetNumMainWindows();
24#else
Guido van Rossum18468821994-06-20 07:49:28 +000025extern int tk_NumMainWindows;
Guido van Rossum9722ad81995-09-22 23:49:28 +000026#define Tk_GetNumMainWindows() (tk_NumMainWindows)
27#endif
28
29#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +000030extern struct { Tk_Window win; } *tkMainWindowList;
Guido van Rossum9722ad81995-09-22 23:49:28 +000031#endif
Guido van Rossum18468821994-06-20 07:49:28 +000032
33/**** Tkapp Object Declaration ****/
34
35staticforward PyTypeObject Tkapp_Type;
36
37typedef struct
38 {
39 PyObject_HEAD
40 Tcl_Interp *interp;
41 Tk_Window tkwin;
42 }
43TkappObject;
44
45#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
46#define Tkapp_Tkwin(v) (((TkappObject *) (v))->tkwin)
47#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
48#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
49
50#define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
51 (void *) v, ((PyObject *) v)->ob_refcnt))
52
53/**** Error Handling ****/
54
55static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +000056static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +000057static int errorInCmd = 0;
58static PyObject *excInCmd;
59static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +000060static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +000061
62static PyObject *
63Tkinter_Error (v)
64 PyObject *v;
65{
Guido van Rossum18468821994-06-20 07:49:28 +000066 PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
67 return NULL;
68}
69
70int
71PythonCmd_Error (interp)
72 Tcl_Interp *interp;
73{
74 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +000075 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +000076 return TCL_ERROR;
77}
78
79/**** Utils ****/
80
81static char *
82AsString (value, tmp)
83 PyObject *value;
84 PyObject *tmp;
85{
86 if (PyString_Check (value))
87 return PyString_AsString (value);
88 else
89 {
90 PyObject *v;
91
Guido van Rossumcd938fc1995-01-17 16:13:48 +000092 v = PyObject_Str (value);
Guido van Rossum18468821994-06-20 07:49:28 +000093 PyList_Append (tmp, v);
94 Py_DECREF (v);
95 return PyString_AsString (v);
96 }
97}
98
99#define ARGSZ 64
100
101static char *
102Merge (args)
103 PyObject *args;
104{
105 PyObject *tmp;
106 char *argvStore[ARGSZ];
107 char **argv;
108 int fvStore[ARGSZ];
109 int *fv;
110 int argc;
111 char *res;
112 int i;
113
114 tmp = PyList_New (0);
115 argv = argvStore;
116 fv = fvStore;
117
118 if (!PyTuple_Check (args))
119 {
120 argc = 1;
121 fv[0] = 0;
122 argv[0] = AsString (args, tmp);
123 }
124 else
125 {
126 PyObject *v;
127
128 if (PyTuple_Size (args) > ARGSZ)
129 {
Guido van Rossumb6fe7041995-03-09 12:13:43 +0000130 argv = (char **) malloc (PyTuple_Size (args) * sizeof (char *));
131 fv = (int *) malloc (PyTuple_Size (args) * sizeof (int));
Guido van Rossum18468821994-06-20 07:49:28 +0000132 if (argv == NULL || fv == NULL)
133 PyErr_NoMemory ();
134 }
135
136 argc = PyTuple_Size (args);
137 for (i = 0; i < argc; i++)
138 {
139 v = PyTuple_GetItem (args, i);
140 if (PyTuple_Check (v))
141 {
142 fv[i] = 1;
143 argv[i] = Merge (v);
144 }
145 else if (v == Py_None)
146 {
147 argc = i;
148 break;
149 }
150 else
151 {
152 fv[i] = 0;
153 argv[i] = AsString (v, tmp);
154 }
155 }
156 }
157
158 res = Tcl_Merge (argc, argv);
159
160 Py_DECREF (tmp);
161 for (i = 0; i < argc; i++)
162 if (fv[i]) free (argv[i]);
163 if (argv != argvStore)
164 free (argv);
165 if (fv != fvStore)
166 free (fv);
167
168 return res;
169}
170
171static PyObject *
172Split (self, list)
173 PyObject *self;
174 char *list;
175{
176 int argc;
177 char **argv;
178 PyObject *v;
179
180 if (list == NULL)
181 {
182 Py_INCREF (Py_None);
183 return Py_None;
184 }
185
186 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
187 return Tkinter_Error (self);
188
189 if (argc == 0)
190 v = PyString_FromString ("");
191 else if (argc == 1)
192 v = PyString_FromString (argv[0]);
193 else
194 {
195 int i;
196
197 v = PyTuple_New (argc);
198 for (i = 0; i < argc; i++)
199 PyTuple_SetItem (v, i, Split (self, argv[i]));
200 }
201
202 free (argv);
203 return v;
204}
205
206/**** Tkapp Object ****/
207
208#ifndef WITH_APPINIT
209int
210Tcl_AppInit (interp)
211 Tcl_Interp *interp;
212{
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000213 Tk_Window main;
214 main = Tk_MainWindow(interp);
215 if (Tcl_Init (interp) == TCL_ERROR) {
216 fprintf(stderr, "Tcl_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000217 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000218 }
219 if (Tk_Init (interp) == TCL_ERROR) {
220 fprintf(stderr, "Tk_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000221 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000222 }
Guido van Rossum18468821994-06-20 07:49:28 +0000223 return TCL_OK;
224}
225#endif /* !WITH_APPINIT */
226
227/* Initialize the Tk application; see the `main' function in
228 `tkMain.c'. */
229static TkappObject *
230Tkapp_New (screenName, baseName, className, interactive)
231 char *screenName;
232 char *baseName;
233 char *className;
234 int interactive;
235{
236 TkappObject *v;
237
238 v = PyObject_NEW (TkappObject, &Tkapp_Type);
239 if (v == NULL)
240 return NULL;
241
242 v->interp = Tcl_CreateInterp ();
243 v->tkwin = Tk_CreateMainWindow (v->interp, screenName,
244 baseName, className);
245 if (v->tkwin == NULL)
246 return (TkappObject *) Tkinter_Error ((PyObject *) v);
247
248 Tk_GeometryRequest (v->tkwin, 200, 200);
249
250 if (screenName != NULL)
251 Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
252
253 if (interactive)
254 Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
255 else
256 Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
257
Guido van Rossum18468821994-06-20 07:49:28 +0000258 if (Tcl_AppInit (v->interp) != TCL_OK)
259 {
260 PyErr_SetString (Tkinter_TclError, "Tcl_AppInit failed"); /* XXX */
261 return NULL;
262 }
Guido van Rossum18468821994-06-20 07:49:28 +0000263
264 return v;
265}
266
267/** Tcl Eval **/
268
269static PyObject *
270Tkapp_Call (self, args)
271 PyObject *self;
272 PyObject *args;
273{
274 char *cmd;
275
276 cmd = Merge (args);
277 if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
278 {
279 free (cmd);
280 return Tkinter_Error (self);
281 }
282
283 free (cmd);
284 return PyString_FromString (Tkapp_Result (self));
285}
286
287static PyObject *
288Tkapp_GlobalCall (self, args)
289 PyObject *self;
290 PyObject *args;
291{
292 char *cmd;
293
294 cmd = Merge (args);
295 if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
296 {
297 free (cmd);
298 return Tkinter_Error (self);
299 }
300
301 free (cmd);
302 return PyString_FromString (Tkapp_Result (self));
303}
304
305static PyObject *
306Tkapp_Eval (self, args)
307 PyObject *self;
308 PyObject *args;
309{
310 char *script;
311
312 if (!PyArg_Parse (args, "s", &script))
313 return NULL;
314
315 if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
316 return Tkinter_Error (self);
317
318 return PyString_FromString (Tkapp_Result (self));
319}
320
321static PyObject *
322Tkapp_GlobalEval (self, args)
323 PyObject *self;
324 PyObject *args;
325{
326 char *script;
327
328 if (!PyArg_Parse (args, "s", &script))
329 return NULL;
330
331 if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
332 return Tkinter_Error (self);
333
334 return PyString_FromString (Tkapp_Result (self));
335}
336
337static PyObject *
338Tkapp_EvalFile (self, args)
339 PyObject *self;
340 PyObject *args;
341{
342 char *fileName;
343
344 if (!PyArg_Parse (args, "s", &fileName))
345 return NULL;
346
347 if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
348 return Tkinter_Error (self);
349
350 return PyString_FromString (Tkapp_Result (self));
351}
352
353static PyObject *
354Tkapp_Record (self, args)
355 PyObject *self;
356 PyObject *args;
357{
358 char *script;
359
360 if (!PyArg_Parse (args, "s", &script))
361 return NULL;
362
363 if (Tcl_RecordAndEval (Tkapp_Interp (self),
364 script, TCL_NO_EVAL) == TCL_ERROR)
365 return Tkinter_Error (self);
366
367 return PyString_FromString (Tkapp_Result (self));
368}
369
370static PyObject *
371Tkapp_AddErrorInfo (self, args)
372 PyObject *self;
373 PyObject *args;
374{
375 char *msg;
376
377 if (!PyArg_Parse (args, "s", &msg))
378 return NULL;
379 Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
380
381 Py_INCREF(Py_None);
382 return Py_None;
383}
384
385/** Tcl Variable **/
386
387static PyObject *
388SetVar (self, args, flags)
389 PyObject *self;
390 PyObject *args;
391 int flags;
392{
393 char *name1, *name2, *ok;
394 PyObject *newValue;
395 PyObject *tmp;
396
397 tmp = PyList_New (0);
398
399 if (PyArg_Parse (args, "(sO)", &name1, &newValue))
400 ok = Tcl_SetVar (Tkapp_Interp (self), name1,
401 AsString (newValue, tmp), flags); /* XXX Merge? */
402 else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
403 ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,
404 AsString (newValue, tmp), flags);
405 else
406 {
407 Py_DECREF (tmp);
408 return NULL;
409 }
410 Py_DECREF (tmp);
411
412 if (!ok)
413 return Tkinter_Error (self);
414
415 Py_INCREF (Py_None);
416 return Py_None;
417}
418
419static PyObject *
420Tkapp_SetVar (self, args)
421 PyObject *self;
422 PyObject *args;
423{
424 return SetVar (self, args, TCL_LEAVE_ERR_MSG);
425}
426
427static PyObject *
428Tkapp_GlobalSetVar (self, args)
429 PyObject *self;
430 PyObject *args;
431{
432 return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
433}
434
435static PyObject *
436GetVar (self, args, flags)
437 PyObject *self;
438 PyObject *args;
439 int flags;
440{
441 char *name1, *name2, *s;
442
443 if (PyArg_Parse (args, "s", &name1))
444 s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
445 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
446 s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
447 else
448 return NULL;
449
450 if (s == NULL)
451 return Tkinter_Error (self);
452
453 return PyString_FromString (s);
454}
455
456static PyObject *
457Tkapp_GetVar (self, args)
458 PyObject *self;
459 PyObject *args;
460{
461 return GetVar (self, args, TCL_LEAVE_ERR_MSG);
462}
463
464static PyObject *
465Tkapp_GlobalGetVar (self, args)
466 PyObject *self;
467 PyObject *args;
468{
469 return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
470}
471
472static PyObject *
473UnsetVar (self, args, flags)
474 PyObject *self;
475 PyObject *args;
476 int flags;
477{
478 char *name1, *name2;
479 int code;
480
481 if (PyArg_Parse (args, "s", &name1))
482 code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
483 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
484 code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
485 else
486 return NULL;
487
488 if (code == TCL_ERROR)
489 return Tkinter_Error (self);
490
491 Py_INCREF (Py_None);
492 return Py_None;
493}
494
495static PyObject *
496Tkapp_UnsetVar (self, args)
497 PyObject *self;
498 PyObject *args;
499{
500 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
501}
502
503static PyObject *
504Tkapp_GlobalUnsetVar (self, args)
505 PyObject *self;
506 PyObject *args;
507{
508 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
509}
510
511/** Tcl to Python **/
512
513static PyObject *
514Tkapp_GetInt (self, args)
515 PyObject *self;
516 PyObject *args;
517{
518 char *s;
519 int v;
520
521 if (!PyArg_Parse (args, "s", &s))
522 return NULL;
523 if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
524 return Tkinter_Error (self);
525 return Py_BuildValue ("i", v);
526}
527
528static PyObject *
529Tkapp_GetDouble (self, args)
530 PyObject *self;
531 PyObject *args;
532{
533 char *s;
534 double v;
535
536 if (!PyArg_Parse (args, "s", &s))
537 return NULL;
538 if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
539 return Tkinter_Error (self);
540 return Py_BuildValue ("d", v);
541}
542
543static PyObject *
544Tkapp_GetBoolean (self, args)
545 PyObject *self;
546 PyObject *args;
547{
548 char *s;
549 int v;
550
551 if (!PyArg_Parse (args, "s", &s))
552 return NULL;
553 if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
554 return Tkinter_Error (self);
555 return Py_BuildValue ("i", v);
556}
557
558static PyObject *
559Tkapp_ExprString (self, args)
560 PyObject *self;
561 PyObject *args;
562{
563 char *s;
564
565 if (!PyArg_Parse (args, "s", &s))
566 return NULL;
567 if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
568 return Tkinter_Error (self);
569 return Py_BuildValue ("s", Tkapp_Result (self));
570}
571
572static PyObject *
573Tkapp_ExprLong (self, args)
574 PyObject *self;
575 PyObject *args;
576{
577 char *s;
578 long v;
579
580 if (!PyArg_Parse (args, "s", &s))
581 return NULL;
582 if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
583 return Tkinter_Error (self);
584 return Py_BuildValue ("l", v);
585}
586
587static PyObject *
588Tkapp_ExprDouble (self, args)
589 PyObject *self;
590 PyObject *args;
591{
592 char *s;
593 double v;
594
595 if (!PyArg_Parse (args, "s", &s))
596 return NULL;
597 if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
598 return Tkinter_Error (self);
599 return Py_BuildValue ("d", v);
600}
601
602static PyObject *
603Tkapp_ExprBoolean (self, args)
604 PyObject *self;
605 PyObject *args;
606{
607 char *s;
608 int v;
609
610 if (!PyArg_Parse (args, "s", &s))
611 return NULL;
612 if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
613 return Tkinter_Error (self);
614 return Py_BuildValue ("i", v);
615}
616
617static PyObject *
618Tkapp_SplitList (self, args)
619 PyObject *self;
620 PyObject *args;
621{
622 char *list;
623 int argc;
624 char **argv;
625 PyObject *v;
626 int i;
627
628 if (!PyArg_Parse (args, "s", &list))
629 return NULL;
630
631 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
632 return Tkinter_Error (self);
633
634 v = PyTuple_New (argc);
635 for (i = 0; i < argc; i++)
636 PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
637
638 free (argv);
639 return v;
640}
641
642static PyObject *
643Tkapp_Split (self, args)
644 PyObject *self;
645 PyObject *args;
646{
647 char *list;
648
649 if (!PyArg_Parse (args, "s", &list))
650 return NULL;
651 return Split (self, list);
652}
653
654static PyObject *
655Tkapp_Merge (self, args)
656 PyObject *self;
657 PyObject *args;
658{
659 char *s;
660 PyObject *v;
661
662 s = Merge (args);
663 v = PyString_FromString (s);
664 free (s);
665 return v;
666}
667
668/** Tcl Command **/
669
670/* This is the Tcl command that acts as a wrapper for Python
671 function or method. */
672static int
673PythonCmd (clientData, interp, argc, argv)
674 ClientData clientData; /* Is (self, func) */
675 Tcl_Interp *interp;
676 int argc;
677 char *argv[];
678{
679 PyObject *self, *func, *arg, *res, *tmp;
680 int i;
681
682 self = PyTuple_GetItem ((PyObject *) clientData, 0);
683 func = PyTuple_GetItem ((PyObject *) clientData, 1);
684
685 /* Create argument list (argv1, ..., argvN) */
686 arg = PyTuple_New (argc - 1);
687 for (i = 0; i < (argc - 1); i++)
688 PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
689
690 res = PyEval_CallObject (func, arg);
691 Py_DECREF (arg);
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000692
Guido van Rossum18468821994-06-20 07:49:28 +0000693 if (res == NULL)
694 return PythonCmd_Error (interp);
695
696 tmp = PyList_New (0);
697 Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
698 Py_DECREF (res);
699 Py_DECREF (tmp);
700
701 return TCL_OK;
702}
703
704static void
705PythonCmdDelete (clientData)
706 ClientData clientData; /* Is (self, func) */
707{
708 Py_DECREF ((PyObject *) clientData);
709}
710
711static PyObject *
712Tkapp_CreateCommand (self, args)
713 PyObject *self;
714 PyObject *args;
715{
716 char *cmdName;
717 PyObject *data;
718 PyObject *func;
719
720 /* Args is: (cmdName, func) */
721 if (!PyTuple_Check (args)
722 || !(PyTuple_Size (args) == 2)
723 || !PyString_Check (PyTuple_GetItem (args, 0))
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000724 || !PyCallable_Check (PyTuple_GetItem (args, 1)))
Guido van Rossum18468821994-06-20 07:49:28 +0000725 {
726 PyErr_SetString (PyExc_TypeError, "bad argument list");
727 return NULL;
728 }
729
730 cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
731 func = PyTuple_GetItem (args, 1);
732
733 data = PyTuple_New (2); /* ClientData is: (self, func) */
734
735 Py_INCREF (self);
736 PyTuple_SetItem (data, 0, self);
737
738 Py_INCREF (func);
739 PyTuple_SetItem (data, 1, func);
740
741 Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
742 (ClientData) data, PythonCmdDelete);
743
744 Py_INCREF (Py_None);
745 return Py_None;
746}
747
748static PyObject *
749Tkapp_DeleteCommand (self, args)
750 PyObject *self;
751 PyObject *args;
752{
753 char *cmdName;
754
755 if (!PyArg_Parse (args, "s", &cmdName))
756 return NULL;
757 if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
758 {
759 PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
760 return NULL;
761 }
762 Py_INCREF (Py_None);
763 return Py_None;
764}
765
766/** File Handler **/
767
Guido van Rossuma597dde1995-01-10 20:56:29 +0000768static void
Guido van Rossum18468821994-06-20 07:49:28 +0000769FileHandler (clientData, mask)
Guido van Rossum76875221994-06-27 07:59:42 +0000770 ClientData clientData; /* Is: (func, file) */
Guido van Rossum18468821994-06-20 07:49:28 +0000771 int mask;
772{
Guido van Rossum76875221994-06-27 07:59:42 +0000773 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +0000774
Guido van Rossum76875221994-06-27 07:59:42 +0000775 func = PyTuple_GetItem ((PyObject *) clientData, 0);
776 file = PyTuple_GetItem ((PyObject *) clientData, 1);
Guido van Rossum18468821994-06-20 07:49:28 +0000777
Guido van Rossum76875221994-06-27 07:59:42 +0000778 arg = Py_BuildValue ("(Oi)", file, (long) mask);
Guido van Rossum18468821994-06-20 07:49:28 +0000779 res = PyEval_CallObject (func, arg);
780 Py_DECREF (arg);
781 if (res == NULL)
782 {
783 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000784 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000785 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000786 Py_XDECREF (res);
787}
788
789static int
790GetFileNo (file)
791 PyObject *file; /* Either an int >= 0 or an object with a
792 .fileno() method that returns an int >= 0 */
793{
Guido van Rossuma597dde1995-01-10 20:56:29 +0000794 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000795 int id;
796 if (PyInt_Check(file)) {
797 id = PyInt_AsLong(file);
798 if (id < 0)
799 PyErr_SetString(PyExc_ValueError, "invalid file id");
800 return id;
801 }
802 meth = PyObject_GetAttrString(file, "fileno");
803 if (meth == NULL)
804 return -1;
805 args = PyTuple_New(0);
806 if (args == NULL)
807 return -1;
808 res = PyEval_CallObject(meth, args);
809 Py_DECREF(args);
810 Py_DECREF(meth);
811 if (res == NULL)
812 return -1;
813 if (PyInt_Check(res))
814 id = PyInt_AsLong(res);
815 else
816 id = -1;
817 if (id < 0)
818 PyErr_SetString(PyExc_ValueError,
819 "invalid fileno() return value");
820 Py_DECREF(res);
821 return id;
Guido van Rossum18468821994-06-20 07:49:28 +0000822}
823
824static PyObject *
825Tkapp_CreateFileHandler (self, args)
826 PyObject *self;
827 PyObject *args; /* Is (file, mask, func) */
828{
Guido van Rossum76875221994-06-27 07:59:42 +0000829 PyObject *file, *func, *data;
830 int mask, id;
Guido van Rossum18468821994-06-20 07:49:28 +0000831
832 if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
833 return NULL;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000834 id = GetFileNo (file);
835 if (id < 0)
836 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000837 if (!PyCallable_Check(func))
Guido van Rossum18468821994-06-20 07:49:28 +0000838 {
839 PyErr_SetString (PyExc_TypeError, "bad argument list");
840 return NULL;
841 }
842
Guido van Rossum76875221994-06-27 07:59:42 +0000843 /* ClientData is: (func, file) */
844 data = Py_BuildValue ("(OO)", func, file);
845
Guido van Rossum76875221994-06-27 07:59:42 +0000846 Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
Guido van Rossum18468821994-06-20 07:49:28 +0000847 /* XXX fileHandlerDict */
Guido van Rossum76875221994-06-27 07:59:42 +0000848
Guido van Rossum18468821994-06-20 07:49:28 +0000849 Py_INCREF (Py_None);
850 return Py_None;
851}
852
853static PyObject *
854Tkapp_DeleteFileHandler (self, args)
855 PyObject *self;
856 PyObject *args; /* Args: file */
857{
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000858 PyObject *file;
Guido van Rossum18468821994-06-20 07:49:28 +0000859 int id;
860
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000861 if (!PyArg_Parse (args, "O", &file))
862 return NULL;
863 id = GetFileNo (file);
864 if (id < 0)
865 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000866
Guido van Rossum18468821994-06-20 07:49:28 +0000867 Tk_DeleteFileHandler (id);
868 /* XXX fileHandlerDict */
869 Py_INCREF (Py_None);
870 return Py_None;
871}
872
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000873/**** Tktt Object (timer token) ****/
874
875staticforward PyTypeObject Tktt_Type;
876
877typedef struct
878 {
879 PyObject_HEAD
880 Tk_TimerToken token;
881 PyObject *func;
882 }
883TkttObject;
884
885static PyObject *
886Tktt_DeleteTimerHandler (self, args)
887 PyObject *self;
888 PyObject *args;
889{
890 TkttObject *v = (TkttObject *) self;
891
892 if (!PyArg_Parse (args, ""))
893 return NULL;
894 if (v->func != NULL)
895 {
896 Tk_DeleteTimerHandler (v->token);
897 PyMem_DEL (v->func);
898 v->func = NULL;
899 }
900 Py_INCREF (Py_None);
901 return Py_None;
902}
903
904static PyMethodDef Tktt_methods[] =
905{
906 {"deletetimerhandler", Tktt_DeleteTimerHandler},
907 {NULL, NULL}
908};
909
910static TkttObject *
911Tktt_New (token, func)
912 Tk_TimerToken token;
913 PyObject *func;
914{
915 TkttObject *v;
916
917 v = PyObject_NEW (TkttObject, &Tktt_Type);
918 if (v == NULL)
919 return NULL;
920
921 v->token = token;
922 v->func = func;
923 Py_INCREF (v->func);
924 return v;
925}
926
927static void
928Tktt_Dealloc (self)
929 PyObject *self;
930{
931 PyMem_DEL (self);
932}
933
934static int
935Tktt_Print (self, fp, flags)
936 PyObject *self;
937 FILE *fp;
938 int flags;
939{
940 TkttObject *v = (TkttObject *) self;
941
942 fprintf(fp, "<tktimertoken at 0x%x%s>", v,
943 v->func == NULL ? ", handler deleted" : "");
944 return 0;
945}
946
947static PyObject *
948Tktt_GetAttr (self, name)
949 PyObject *self;
950 char *name;
951{
952 return Py_FindMethod (Tktt_methods, self, name);
953}
954
955static PyTypeObject Tktt_Type =
956{
Guido van Rossuma597dde1995-01-10 20:56:29 +0000957 PyObject_HEAD_INIT (&PyType_Type)
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000958 0, /*ob_size */
959 "tktimertoken", /*tp_name */
960 sizeof (TkttObject), /*tp_basicsize */
961 0, /*tp_itemsize */
962 Tktt_Dealloc, /*tp_dealloc */
963 Tktt_Print, /*tp_print */
964 Tktt_GetAttr, /*tp_getattr */
965 0, /*tp_setattr */
966 0, /*tp_compare */
967 0, /*tp_repr */
968 0, /*tp_as_number */
969 0, /*tp_as_sequence */
970 0, /*tp_as_mapping */
971 0, /*tp_hash */
972};
973
974/** Timer Handler **/
975
976static void
977TimerHandler (clientData)
978 ClientData clientData;
979{
980 PyObject *func = (PyObject *) clientData;
981 PyObject *arg, *res;
982
983 arg = PyTuple_New (0);
984 res = PyEval_CallObject (func, arg);
985 Py_DECREF (arg);
986 if (res == NULL)
987 {
988 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000989 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000990 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000991 else
992 Py_DECREF (res);
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000993}
994
995static PyObject *
996Tkapp_CreateTimerHandler (self, args)
997 PyObject *self;
998 PyObject *args; /* Is (milliseconds, func) */
999{
1000 int milliseconds;
1001 PyObject *func;
1002 Tk_TimerToken token;
1003
1004 if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
1005 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001006 if (!PyCallable_Check(func))
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001007 {
1008 PyErr_SetString (PyExc_TypeError, "bad argument list");
1009 return NULL;
1010 }
1011 token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
1012 return (PyObject *) Tktt_New (token, func);
1013}
1014
Guido van Rossum18468821994-06-20 07:49:28 +00001015/** Event Loop **/
1016
Guido van Rossum18468821994-06-20 07:49:28 +00001017static PyObject *
1018Tkapp_MainLoop (self, args)
1019 PyObject *self;
1020 PyObject *args;
1021{
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001022 int threshold = 0;
1023
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001024 if (!PyArg_ParseTuple (args, "|i", &threshold))
1025 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001026
1027 quitMainLoop = 0;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001028 while (Tk_GetNumMainWindows() > threshold && !quitMainLoop && !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001029 {
1030 if (PyOS_InterruptOccurred ())
1031 {
1032 PyErr_SetNone (PyExc_KeyboardInterrupt);
1033 return NULL;
1034 }
1035 Tk_DoOneEvent (0);
1036 }
1037
1038 if (errorInCmd)
1039 {
1040 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001041 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1042 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001043 return NULL;
1044 }
1045 Py_INCREF (Py_None);
1046 return Py_None;
1047}
1048
1049static PyObject *
Guido van Rossum062cfb01995-01-10 17:42:51 +00001050Tkapp_DoOneEvent (self, args)
1051 PyObject *self;
1052 PyObject *args;
1053{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001054 int flags = TK_ALL_EVENTS;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001055 int rv;
1056
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001057 if (!PyArg_ParseTuple (args, "|i", &flags))
1058 return NULL;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001059 rv = Tk_DoOneEvent(flags);
1060 return Py_BuildValue ("i", rv);
1061}
1062
1063static PyObject *
Guido van Rossum18468821994-06-20 07:49:28 +00001064Tkapp_Quit (self, args)
1065 PyObject *self;
1066 PyObject *args;
1067{
1068
1069 if (!PyArg_Parse (args, ""))
1070 return NULL;
1071 quitMainLoop = 1;
1072 Py_INCREF (Py_None);
1073 return Py_None;
1074}
1075
1076/**** Tkapp Method List ****/
1077
1078static PyMethodDef Tkapp_methods[] =
1079{
1080 {"call", Tkapp_Call},
1081 {"globalcall", Tkapp_GlobalCall},
1082 {"eval", Tkapp_Eval},
1083 {"globaleval", Tkapp_GlobalEval},
1084 {"evalfile", Tkapp_EvalFile},
1085 {"record", Tkapp_Record},
1086 {"adderrorinfo", Tkapp_AddErrorInfo},
1087 {"setvar", Tkapp_SetVar},
1088 {"globalsetvar", Tkapp_GlobalSetVar},
1089 {"getvar", Tkapp_GetVar},
1090 {"globalgetvar", Tkapp_GlobalGetVar},
1091 {"unsetvar", Tkapp_UnsetVar},
1092 {"globalunsetvar", Tkapp_GlobalUnsetVar},
1093 {"getint", Tkapp_GetInt},
1094 {"getdouble", Tkapp_GetDouble},
1095 {"getboolean", Tkapp_GetBoolean},
1096 {"exprstring", Tkapp_ExprString},
1097 {"exprlong", Tkapp_ExprLong},
1098 {"exprdouble", Tkapp_ExprDouble},
1099 {"exprboolean", Tkapp_ExprBoolean},
1100 {"splitlist", Tkapp_SplitList},
1101 {"split", Tkapp_Split},
1102 {"merge", Tkapp_Merge},
1103 {"createcommand", Tkapp_CreateCommand},
1104 {"deletecommand", Tkapp_DeleteCommand},
1105 {"createfilehandler", Tkapp_CreateFileHandler},
1106 {"deletefilehandler", Tkapp_DeleteFileHandler},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001107 {"createtimerhandler", Tkapp_CreateTimerHandler},
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001108 {"mainloop", Tkapp_MainLoop, 1},
1109 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum18468821994-06-20 07:49:28 +00001110 {"quit", Tkapp_Quit},
1111 {NULL, NULL}
1112};
1113
1114/**** Tkapp Type Methods ****/
1115
1116static void
1117Tkapp_Dealloc (self)
1118 PyObject *self;
1119{
1120 Tk_DestroyWindow (Tkapp_Tkwin (self));
1121 Tcl_DeleteInterp (Tkapp_Interp (self));
1122 PyMem_DEL (self);
1123}
1124
1125static PyObject *
1126Tkapp_GetAttr (self, name)
1127 PyObject *self;
1128 char *name;
1129{
1130 return Py_FindMethod (Tkapp_methods, self, name);
1131}
1132
1133static PyTypeObject Tkapp_Type =
1134{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001135 PyObject_HEAD_INIT (&PyType_Type)
Guido van Rossum18468821994-06-20 07:49:28 +00001136 0, /*ob_size */
1137 "tkapp", /*tp_name */
1138 sizeof (TkappObject), /*tp_basicsize */
1139 0, /*tp_itemsize */
1140 Tkapp_Dealloc, /*tp_dealloc */
1141 0, /*tp_print */
1142 Tkapp_GetAttr, /*tp_getattr */
1143 0, /*tp_setattr */
1144 0, /*tp_compare */
1145 0, /*tp_repr */
1146 0, /*tp_as_number */
1147 0, /*tp_as_sequence */
1148 0, /*tp_as_mapping */
1149 0, /*tp_hash */
1150};
1151
1152/**** Tkinter Module ****/
1153
1154static PyObject *
1155Tkinter_Create (self, args)
1156 PyObject *self;
1157 PyObject *args;
1158{
1159 char *screenName = NULL;
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001160 char *baseName = NULL;
1161 char *className = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001162 int interactive = 0;
1163
1164 baseName = strrchr (getprogramname (), '/');
1165 if (baseName != NULL)
1166 baseName++;
1167 else
1168 baseName = getprogramname ();
1169 className = "Tk";
1170
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001171 if (!PyArg_ParseTuple (args, "|zssi",
1172 &screenName, &baseName, &className, &interactive))
Guido van Rossum18468821994-06-20 07:49:28 +00001173 return NULL;
1174
1175 return (PyObject *) Tkapp_New (screenName, baseName, className,
1176 interactive);
1177}
1178
1179static PyMethodDef moduleMethods[] =
1180{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001181 {"create", Tkinter_Create, 1},
1182 {"createfilehandler", Tkapp_CreateFileHandler, 0},
1183 {"deletefilehandler", Tkapp_DeleteFileHandler, 0},
1184 {"createtimerhandler", Tkapp_CreateTimerHandler, 0},
1185 {"mainloop", Tkapp_MainLoop, 1},
1186 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001187 {"quit", Tkapp_Quit},
Guido van Rossum18468821994-06-20 07:49:28 +00001188 {NULL, NULL}
1189};
1190
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001191#undef WITH_READLINE /* XXX */
Guido van Rossum18468821994-06-20 07:49:28 +00001192#ifdef WITH_READLINE
1193static int
1194EventHook ()
1195{
1196 if (errorInCmd) /* XXX Reset tty */
1197 {
1198 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001199 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1200 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001201 PyErr_Print ();
1202 }
Guido van Rossum9722ad81995-09-22 23:49:28 +00001203 if (Tk_GetNumMainWindows() > 0)
Guido van Rossume2ca9bd1994-08-03 08:01:43 +00001204 Tk_DoOneEvent (TK_DONT_WAIT);
Guido van Rossum18468821994-06-20 07:49:28 +00001205 return 0;
1206}
1207#endif /* WITH_READLINE */
1208
1209static void
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001210Tkinter_Cleanup ()
1211{
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001212/* This segfault with Tk 4.0 beta and seems unnecessary there as well */
1213#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001214 /* XXX rl_deprep_terminal is static, damned! */
1215 while (tkMainWindowList != 0)
1216 Tk_DestroyWindow (tkMainWindowList->win);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001217#endif
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001218}
1219
Guido van Rossum18468821994-06-20 07:49:28 +00001220void
1221PyInit_tkinter ()
1222{
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001223 static inited = 0;
1224
Guido van Rossum18468821994-06-20 07:49:28 +00001225#ifdef WITH_READLINE
1226 extern int (*rl_event_hook) ();
1227#endif /* WITH_READLINE */
1228 PyObject *m, *d, *v;
1229
1230 m = Py_InitModule ("tkinter", moduleMethods);
1231
1232 d = PyModule_GetDict (m);
1233 Tkinter_TclError = Py_BuildValue ("s", "TclError");
1234 PyDict_SetItemString (d, "TclError", Tkinter_TclError);
1235
1236 v = Py_BuildValue ("i", TK_READABLE);
1237 PyDict_SetItemString (d, "READABLE", v);
1238 v = Py_BuildValue ("i", TK_WRITABLE);
1239 PyDict_SetItemString (d, "WRITABLE", v);
1240 v = Py_BuildValue ("i", TK_EXCEPTION);
1241 PyDict_SetItemString (d, "EXCEPTION", v);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001242 v = Py_BuildValue ("i", TK_X_EVENTS);
1243 PyDict_SetItemString (d, "X_EVENTS", v);
1244 v = Py_BuildValue ("i", TK_FILE_EVENTS);
1245 PyDict_SetItemString (d, "FILE_EVENTS", v);
1246 v = Py_BuildValue ("i", TK_TIMER_EVENTS);
1247 PyDict_SetItemString (d, "TIMER_EVENTS", v);
1248 v = Py_BuildValue ("i", TK_IDLE_EVENTS);
1249 PyDict_SetItemString (d, "IDLE_EVENTS", v);
1250 v = Py_BuildValue ("i", TK_ALL_EVENTS);
1251 PyDict_SetItemString (d, "ALL_EVENTS", v);
1252 v = Py_BuildValue ("i", TK_DONT_WAIT);
1253 PyDict_SetItemString (d, "DONT_WAIT", v);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001254 v = Py_BuildValue ("s", TK_VERSION);
1255 PyDict_SetItemString (d, "TK_VERSION", v);
1256 v = Py_BuildValue ("s", TCL_VERSION);
1257 PyDict_SetItemString (d, "TCL_VERSION", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001258
Guido van Rossum18468821994-06-20 07:49:28 +00001259#ifdef WITH_READLINE
1260 rl_event_hook = EventHook;
1261#endif /* WITH_READLINE */
1262
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001263 if (!inited)
1264 {
1265 inited = 1;
Guido van Rossume4485b01994-09-07 14:32:49 +00001266 if (Py_AtExit (Tkinter_Cleanup) != 0)
1267 fprintf(stderr,
1268 "Tkinter: warning: cleanup procedure not registered\n");
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001269 }
1270
Guido van Rossum18468821994-06-20 07:49:28 +00001271 if (PyErr_Occurred ())
1272 Py_FatalError ("can't initialize module tkinter");
1273}
Guido van Rossum9722ad81995-09-22 23:49:28 +00001274
1275#ifdef macintosh
1276void
1277panic(char * format, ...)
1278{
1279 va_list varg;
1280
1281 va_start(varg, format);
1282
1283 vfprintf(stderr, format, varg);
1284 (void) fflush(stderr);
1285
1286 va_end(varg);
1287
1288 Py_FatalError("Tcl/Tk panic");
1289}
1290
1291#endif