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