blob: 1653408c1b08cba455a0da3937c71f43ad263163 [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
4#if 0
5#include <Py/Python.h>
6#else
7
8#include "allobjects.h"
9#include "pythonrun.h"
10#include "intrcheck.h"
11#include "modsupport.h"
12#include "sysmodule.h"
13
14#define PyObject object
15typedef struct methodlist PyMethodDef;
16#define PyInit_tkinter inittkinter
17
18#undef Py_True
19#define Py_True ((object *) &TrueObject)
20#undef True
21
22#undef Py_False
23#define Py_False ((object *) &FalseObject)
24#undef False
25
26#undef Py_None
27#define Py_None (&NoObject)
28#undef None
29
30#endif /* 0 */
31
32#include <tcl.h>
33#include <tk.h>
34
35extern char *getprogramname ();
Guido van Rossumd308e2b1994-07-07 09:25:12 +000036extern int isatty (int);
37
38/* Internal declarations from tkInt.h. */
Guido van Rossum18468821994-06-20 07:49:28 +000039extern int tk_NumMainWindows;
Guido van Rossumd308e2b1994-07-07 09:25:12 +000040extern struct { Tk_Window win; } *tkMainWindowList;
Guido van Rossum18468821994-06-20 07:49:28 +000041
42/**** Tkapp Object Declaration ****/
43
44staticforward PyTypeObject Tkapp_Type;
45
46typedef struct
47 {
48 PyObject_HEAD
49 Tcl_Interp *interp;
50 Tk_Window tkwin;
51 }
52TkappObject;
53
54#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
55#define Tkapp_Tkwin(v) (((TkappObject *) (v))->tkwin)
56#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
57#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
58
59#define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
60 (void *) v, ((PyObject *) v)->ob_refcnt))
61
62/**** Error Handling ****/
63
64static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +000065static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +000066static int errorInCmd = 0;
67static PyObject *excInCmd;
68static PyObject *valInCmd;
69
70static PyObject *
71Tkinter_Error (v)
72 PyObject *v;
73{
Guido van Rossum18468821994-06-20 07:49:28 +000074 PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
75 return NULL;
76}
77
78int
79PythonCmd_Error (interp)
80 Tcl_Interp *interp;
81{
82 errorInCmd = 1;
83 PyErr_GetAndClear (&excInCmd, &valInCmd);
84 return TCL_ERROR;
85}
86
87/**** Utils ****/
88
89static char *
90AsString (value, tmp)
91 PyObject *value;
92 PyObject *tmp;
93{
94 if (PyString_Check (value))
95 return PyString_AsString (value);
96 else
97 {
98 PyObject *v;
99
100 v = strobject (value);
101 PyList_Append (tmp, v);
102 Py_DECREF (v);
103 return PyString_AsString (v);
104 }
105}
106
107#define ARGSZ 64
108
109static char *
110Merge (args)
111 PyObject *args;
112{
113 PyObject *tmp;
114 char *argvStore[ARGSZ];
115 char **argv;
116 int fvStore[ARGSZ];
117 int *fv;
118 int argc;
119 char *res;
120 int i;
121
122 tmp = PyList_New (0);
123 argv = argvStore;
124 fv = fvStore;
125
126 if (!PyTuple_Check (args))
127 {
128 argc = 1;
129 fv[0] = 0;
130 argv[0] = AsString (args, tmp);
131 }
132 else
133 {
134 PyObject *v;
135
136 if (PyTuple_Size (args) > ARGSZ)
137 {
138 argv = malloc (PyTuple_Size (args) * sizeof (char *));
139 fv = malloc (PyTuple_Size (args) * sizeof (int));
140 if (argv == NULL || fv == NULL)
141 PyErr_NoMemory ();
142 }
143
144 argc = PyTuple_Size (args);
145 for (i = 0; i < argc; i++)
146 {
147 v = PyTuple_GetItem (args, i);
148 if (PyTuple_Check (v))
149 {
150 fv[i] = 1;
151 argv[i] = Merge (v);
152 }
153 else if (v == Py_None)
154 {
155 argc = i;
156 break;
157 }
158 else
159 {
160 fv[i] = 0;
161 argv[i] = AsString (v, tmp);
162 }
163 }
164 }
165
166 res = Tcl_Merge (argc, argv);
167
168 Py_DECREF (tmp);
169 for (i = 0; i < argc; i++)
170 if (fv[i]) free (argv[i]);
171 if (argv != argvStore)
172 free (argv);
173 if (fv != fvStore)
174 free (fv);
175
176 return res;
177}
178
179static PyObject *
180Split (self, list)
181 PyObject *self;
182 char *list;
183{
184 int argc;
185 char **argv;
186 PyObject *v;
187
188 if (list == NULL)
189 {
190 Py_INCREF (Py_None);
191 return Py_None;
192 }
193
194 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
195 return Tkinter_Error (self);
196
197 if (argc == 0)
198 v = PyString_FromString ("");
199 else if (argc == 1)
200 v = PyString_FromString (argv[0]);
201 else
202 {
203 int i;
204
205 v = PyTuple_New (argc);
206 for (i = 0; i < argc; i++)
207 PyTuple_SetItem (v, i, Split (self, argv[i]));
208 }
209
210 free (argv);
211 return v;
212}
213
214/**** Tkapp Object ****/
215
216#ifndef WITH_APPINIT
217int
218Tcl_AppInit (interp)
219 Tcl_Interp *interp;
220{
221 if (Tcl_Init (interp) == TCL_ERROR)
222 return TCL_ERROR;
223 if (Tk_Init (interp) == TCL_ERROR)
224 return TCL_ERROR;
225 return TCL_OK;
226}
227#endif /* !WITH_APPINIT */
228
229/* Initialize the Tk application; see the `main' function in
230 `tkMain.c'. */
231static TkappObject *
232Tkapp_New (screenName, baseName, className, interactive)
233 char *screenName;
234 char *baseName;
235 char *className;
236 int interactive;
237{
238 TkappObject *v;
239
240 v = PyObject_NEW (TkappObject, &Tkapp_Type);
241 if (v == NULL)
242 return NULL;
243
244 v->interp = Tcl_CreateInterp ();
245 v->tkwin = Tk_CreateMainWindow (v->interp, screenName,
246 baseName, className);
247 if (v->tkwin == NULL)
248 return (TkappObject *) Tkinter_Error ((PyObject *) v);
249
250 Tk_GeometryRequest (v->tkwin, 200, 200);
251
252 if (screenName != NULL)
253 Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
254
255 if (interactive)
256 Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
257 else
258 Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
259
Guido van Rossum18468821994-06-20 07:49:28 +0000260 if (Tcl_AppInit (v->interp) != TCL_OK)
261 {
262 PyErr_SetString (Tkinter_TclError, "Tcl_AppInit failed"); /* XXX */
263 return NULL;
264 }
Guido van Rossum18468821994-06-20 07:49:28 +0000265
266 return v;
267}
268
269/** Tcl Eval **/
270
271static PyObject *
272Tkapp_Call (self, args)
273 PyObject *self;
274 PyObject *args;
275{
276 char *cmd;
277
278 cmd = Merge (args);
279 if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
280 {
281 free (cmd);
282 return Tkinter_Error (self);
283 }
284
285 free (cmd);
286 return PyString_FromString (Tkapp_Result (self));
287}
288
289static PyObject *
290Tkapp_GlobalCall (self, args)
291 PyObject *self;
292 PyObject *args;
293{
294 char *cmd;
295
296 cmd = Merge (args);
297 if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
298 {
299 free (cmd);
300 return Tkinter_Error (self);
301 }
302
303 free (cmd);
304 return PyString_FromString (Tkapp_Result (self));
305}
306
307static PyObject *
308Tkapp_Eval (self, args)
309 PyObject *self;
310 PyObject *args;
311{
312 char *script;
313
314 if (!PyArg_Parse (args, "s", &script))
315 return NULL;
316
317 if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
318 return Tkinter_Error (self);
319
320 return PyString_FromString (Tkapp_Result (self));
321}
322
323static PyObject *
324Tkapp_GlobalEval (self, args)
325 PyObject *self;
326 PyObject *args;
327{
328 char *script;
329
330 if (!PyArg_Parse (args, "s", &script))
331 return NULL;
332
333 if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
334 return Tkinter_Error (self);
335
336 return PyString_FromString (Tkapp_Result (self));
337}
338
339static PyObject *
340Tkapp_EvalFile (self, args)
341 PyObject *self;
342 PyObject *args;
343{
344 char *fileName;
345
346 if (!PyArg_Parse (args, "s", &fileName))
347 return NULL;
348
349 if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
350 return Tkinter_Error (self);
351
352 return PyString_FromString (Tkapp_Result (self));
353}
354
355static PyObject *
356Tkapp_Record (self, args)
357 PyObject *self;
358 PyObject *args;
359{
360 char *script;
361
362 if (!PyArg_Parse (args, "s", &script))
363 return NULL;
364
365 if (Tcl_RecordAndEval (Tkapp_Interp (self),
366 script, TCL_NO_EVAL) == TCL_ERROR)
367 return Tkinter_Error (self);
368
369 return PyString_FromString (Tkapp_Result (self));
370}
371
372static PyObject *
373Tkapp_AddErrorInfo (self, args)
374 PyObject *self;
375 PyObject *args;
376{
377 char *msg;
378
379 if (!PyArg_Parse (args, "s", &msg))
380 return NULL;
381 Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
382
383 Py_INCREF(Py_None);
384 return Py_None;
385}
386
387/** Tcl Variable **/
388
389static PyObject *
390SetVar (self, args, flags)
391 PyObject *self;
392 PyObject *args;
393 int flags;
394{
395 char *name1, *name2, *ok;
396 PyObject *newValue;
397 PyObject *tmp;
398
399 tmp = PyList_New (0);
400
401 if (PyArg_Parse (args, "(sO)", &name1, &newValue))
402 ok = Tcl_SetVar (Tkapp_Interp (self), name1,
403 AsString (newValue, tmp), flags); /* XXX Merge? */
404 else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
405 ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,
406 AsString (newValue, tmp), flags);
407 else
408 {
409 Py_DECREF (tmp);
410 return NULL;
411 }
412 Py_DECREF (tmp);
413
414 if (!ok)
415 return Tkinter_Error (self);
416
417 Py_INCREF (Py_None);
418 return Py_None;
419}
420
421static PyObject *
422Tkapp_SetVar (self, args)
423 PyObject *self;
424 PyObject *args;
425{
426 return SetVar (self, args, TCL_LEAVE_ERR_MSG);
427}
428
429static PyObject *
430Tkapp_GlobalSetVar (self, args)
431 PyObject *self;
432 PyObject *args;
433{
434 return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
435}
436
437static PyObject *
438GetVar (self, args, flags)
439 PyObject *self;
440 PyObject *args;
441 int flags;
442{
443 char *name1, *name2, *s;
444
445 if (PyArg_Parse (args, "s", &name1))
446 s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
447 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
448 s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
449 else
450 return NULL;
451
452 if (s == NULL)
453 return Tkinter_Error (self);
454
455 return PyString_FromString (s);
456}
457
458static PyObject *
459Tkapp_GetVar (self, args)
460 PyObject *self;
461 PyObject *args;
462{
463 return GetVar (self, args, TCL_LEAVE_ERR_MSG);
464}
465
466static PyObject *
467Tkapp_GlobalGetVar (self, args)
468 PyObject *self;
469 PyObject *args;
470{
471 return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
472}
473
474static PyObject *
475UnsetVar (self, args, flags)
476 PyObject *self;
477 PyObject *args;
478 int flags;
479{
480 char *name1, *name2;
481 int code;
482
483 if (PyArg_Parse (args, "s", &name1))
484 code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
485 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
486 code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
487 else
488 return NULL;
489
490 if (code == TCL_ERROR)
491 return Tkinter_Error (self);
492
493 Py_INCREF (Py_None);
494 return Py_None;
495}
496
497static PyObject *
498Tkapp_UnsetVar (self, args)
499 PyObject *self;
500 PyObject *args;
501{
502 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
503}
504
505static PyObject *
506Tkapp_GlobalUnsetVar (self, args)
507 PyObject *self;
508 PyObject *args;
509{
510 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
511}
512
513/** Tcl to Python **/
514
515static PyObject *
516Tkapp_GetInt (self, args)
517 PyObject *self;
518 PyObject *args;
519{
520 char *s;
521 int v;
522
523 if (!PyArg_Parse (args, "s", &s))
524 return NULL;
525 if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
526 return Tkinter_Error (self);
527 return Py_BuildValue ("i", v);
528}
529
530static PyObject *
531Tkapp_GetDouble (self, args)
532 PyObject *self;
533 PyObject *args;
534{
535 char *s;
536 double v;
537
538 if (!PyArg_Parse (args, "s", &s))
539 return NULL;
540 if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
541 return Tkinter_Error (self);
542 return Py_BuildValue ("d", v);
543}
544
545static PyObject *
546Tkapp_GetBoolean (self, args)
547 PyObject *self;
548 PyObject *args;
549{
550 char *s;
551 int v;
552
553 if (!PyArg_Parse (args, "s", &s))
554 return NULL;
555 if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
556 return Tkinter_Error (self);
557 return Py_BuildValue ("i", v);
558}
559
560static PyObject *
561Tkapp_ExprString (self, args)
562 PyObject *self;
563 PyObject *args;
564{
565 char *s;
566
567 if (!PyArg_Parse (args, "s", &s))
568 return NULL;
569 if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
570 return Tkinter_Error (self);
571 return Py_BuildValue ("s", Tkapp_Result (self));
572}
573
574static PyObject *
575Tkapp_ExprLong (self, args)
576 PyObject *self;
577 PyObject *args;
578{
579 char *s;
580 long v;
581
582 if (!PyArg_Parse (args, "s", &s))
583 return NULL;
584 if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
585 return Tkinter_Error (self);
586 return Py_BuildValue ("l", v);
587}
588
589static PyObject *
590Tkapp_ExprDouble (self, args)
591 PyObject *self;
592 PyObject *args;
593{
594 char *s;
595 double v;
596
597 if (!PyArg_Parse (args, "s", &s))
598 return NULL;
599 if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
600 return Tkinter_Error (self);
601 return Py_BuildValue ("d", v);
602}
603
604static PyObject *
605Tkapp_ExprBoolean (self, args)
606 PyObject *self;
607 PyObject *args;
608{
609 char *s;
610 int v;
611
612 if (!PyArg_Parse (args, "s", &s))
613 return NULL;
614 if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
615 return Tkinter_Error (self);
616 return Py_BuildValue ("i", v);
617}
618
619static PyObject *
620Tkapp_SplitList (self, args)
621 PyObject *self;
622 PyObject *args;
623{
624 char *list;
625 int argc;
626 char **argv;
627 PyObject *v;
628 int i;
629
630 if (!PyArg_Parse (args, "s", &list))
631 return NULL;
632
633 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
634 return Tkinter_Error (self);
635
636 v = PyTuple_New (argc);
637 for (i = 0; i < argc; i++)
638 PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
639
640 free (argv);
641 return v;
642}
643
644static PyObject *
645Tkapp_Split (self, args)
646 PyObject *self;
647 PyObject *args;
648{
649 char *list;
650
651 if (!PyArg_Parse (args, "s", &list))
652 return NULL;
653 return Split (self, list);
654}
655
656static PyObject *
657Tkapp_Merge (self, args)
658 PyObject *self;
659 PyObject *args;
660{
661 char *s;
662 PyObject *v;
663
664 s = Merge (args);
665 v = PyString_FromString (s);
666 free (s);
667 return v;
668}
669
670/** Tcl Command **/
671
672/* This is the Tcl command that acts as a wrapper for Python
673 function or method. */
674static int
675PythonCmd (clientData, interp, argc, argv)
676 ClientData clientData; /* Is (self, func) */
677 Tcl_Interp *interp;
678 int argc;
679 char *argv[];
680{
681 PyObject *self, *func, *arg, *res, *tmp;
682 int i;
683
684 self = PyTuple_GetItem ((PyObject *) clientData, 0);
685 func = PyTuple_GetItem ((PyObject *) clientData, 1);
686
687 /* Create argument list (argv1, ..., argvN) */
688 arg = PyTuple_New (argc - 1);
689 for (i = 0; i < (argc - 1); i++)
690 PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
691
692 res = PyEval_CallObject (func, arg);
693 Py_DECREF (arg);
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000694
Guido van Rossum18468821994-06-20 07:49:28 +0000695 if (res == NULL)
696 return PythonCmd_Error (interp);
697
698 tmp = PyList_New (0);
699 Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
700 Py_DECREF (res);
701 Py_DECREF (tmp);
702
703 return TCL_OK;
704}
705
706static void
707PythonCmdDelete (clientData)
708 ClientData clientData; /* Is (self, func) */
709{
710 Py_DECREF ((PyObject *) clientData);
711}
712
713static PyObject *
714Tkapp_CreateCommand (self, args)
715 PyObject *self;
716 PyObject *args;
717{
718 char *cmdName;
719 PyObject *data;
720 PyObject *func;
721
722 /* Args is: (cmdName, func) */
723 if (!PyTuple_Check (args)
724 || !(PyTuple_Size (args) == 2)
725 || !PyString_Check (PyTuple_GetItem (args, 0))
726 || !(PyMethod_Check (PyTuple_GetItem (args, 1))
727 || PyFunction_Check (PyTuple_GetItem (args, 1))))
728 {
729 PyErr_SetString (PyExc_TypeError, "bad argument list");
730 return NULL;
731 }
732
733 cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
734 func = PyTuple_GetItem (args, 1);
735
736 data = PyTuple_New (2); /* ClientData is: (self, func) */
737
738 Py_INCREF (self);
739 PyTuple_SetItem (data, 0, self);
740
741 Py_INCREF (func);
742 PyTuple_SetItem (data, 1, func);
743
744 Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
745 (ClientData) data, PythonCmdDelete);
746
747 Py_INCREF (Py_None);
748 return Py_None;
749}
750
751static PyObject *
752Tkapp_DeleteCommand (self, args)
753 PyObject *self;
754 PyObject *args;
755{
756 char *cmdName;
757
758 if (!PyArg_Parse (args, "s", &cmdName))
759 return NULL;
760 if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
761 {
762 PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
763 return NULL;
764 }
765 Py_INCREF (Py_None);
766 return Py_None;
767}
768
769/** File Handler **/
770
771void
772FileHandler (clientData, mask)
Guido van Rossum76875221994-06-27 07:59:42 +0000773 ClientData clientData; /* Is: (func, file) */
Guido van Rossum18468821994-06-20 07:49:28 +0000774 int mask;
775{
Guido van Rossum76875221994-06-27 07:59:42 +0000776 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +0000777
Guido van Rossum76875221994-06-27 07:59:42 +0000778 func = PyTuple_GetItem ((PyObject *) clientData, 0);
779 file = PyTuple_GetItem ((PyObject *) clientData, 1);
Guido van Rossum18468821994-06-20 07:49:28 +0000780
Guido van Rossum76875221994-06-27 07:59:42 +0000781 arg = Py_BuildValue ("(Oi)", file, (long) mask);
Guido van Rossum18468821994-06-20 07:49:28 +0000782 res = PyEval_CallObject (func, arg);
783 Py_DECREF (arg);
784 if (res == NULL)
785 {
786 errorInCmd = 1;
787 PyErr_GetAndClear (&excInCmd, &valInCmd);
788 }
Guido van Rossum76875221994-06-27 07:59:42 +0000789 Py_DECREF (res);
Guido van Rossum18468821994-06-20 07:49:28 +0000790}
791
792static PyObject *
793Tkapp_CreateFileHandler (self, args)
794 PyObject *self;
795 PyObject *args; /* Is (file, mask, func) */
796{
Guido van Rossum76875221994-06-27 07:59:42 +0000797 PyObject *file, *func, *data;
798 int mask, id;
Guido van Rossum18468821994-06-20 07:49:28 +0000799
800 if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
801 return NULL;
802 if (!PyFile_Check (file)
803 || !(PyMethod_Check(func) || PyFunction_Check(func)))
804 {
805 PyErr_SetString (PyExc_TypeError, "bad argument list");
806 return NULL;
807 }
808
Guido van Rossum76875221994-06-27 07:59:42 +0000809 /* ClientData is: (func, file) */
810 data = Py_BuildValue ("(OO)", func, file);
811
Guido van Rossum18468821994-06-20 07:49:28 +0000812 id = fileno (PyFile_AsFile (file));
Guido van Rossum76875221994-06-27 07:59:42 +0000813 Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
Guido van Rossum18468821994-06-20 07:49:28 +0000814 /* XXX fileHandlerDict */
Guido van Rossum76875221994-06-27 07:59:42 +0000815
Guido van Rossum18468821994-06-20 07:49:28 +0000816 Py_INCREF (Py_None);
817 return Py_None;
818}
819
820static PyObject *
821Tkapp_DeleteFileHandler (self, args)
822 PyObject *self;
823 PyObject *args; /* Args: file */
824{
825 int id;
826
827 if (!PyFile_Check (args))
828 {
829 PyErr_SetString (PyExc_TypeError, "bad argument list");
830 return NULL;
831 }
832
833 id = fileno (PyFile_AsFile (args));
834 Tk_DeleteFileHandler (id);
835 /* XXX fileHandlerDict */
836 Py_INCREF (Py_None);
837 return Py_None;
838}
839
840/** Event Loop **/
841
Guido van Rossum18468821994-06-20 07:49:28 +0000842static PyObject *
843Tkapp_MainLoop (self, args)
844 PyObject *self;
845 PyObject *args;
846{
847 if (!PyArg_Parse (args, ""))
848 return NULL;
849
850 quitMainLoop = 0;
851 while (tk_NumMainWindows > 0 && !quitMainLoop && !errorInCmd)
852 {
853 if (PyOS_InterruptOccurred ())
854 {
855 PyErr_SetNone (PyExc_KeyboardInterrupt);
856 return NULL;
857 }
858 Tk_DoOneEvent (0);
859 }
860
861 if (errorInCmd)
862 {
863 errorInCmd = 0;
864 PyErr_SetObject (excInCmd, valInCmd);
865 return NULL;
866 }
867 Py_INCREF (Py_None);
868 return Py_None;
869}
870
871static PyObject *
872Tkapp_Quit (self, args)
873 PyObject *self;
874 PyObject *args;
875{
876
877 if (!PyArg_Parse (args, ""))
878 return NULL;
879 quitMainLoop = 1;
880 Py_INCREF (Py_None);
881 return Py_None;
882}
883
884/**** Tkapp Method List ****/
885
886static PyMethodDef Tkapp_methods[] =
887{
888 {"call", Tkapp_Call},
889 {"globalcall", Tkapp_GlobalCall},
890 {"eval", Tkapp_Eval},
891 {"globaleval", Tkapp_GlobalEval},
892 {"evalfile", Tkapp_EvalFile},
893 {"record", Tkapp_Record},
894 {"adderrorinfo", Tkapp_AddErrorInfo},
895 {"setvar", Tkapp_SetVar},
896 {"globalsetvar", Tkapp_GlobalSetVar},
897 {"getvar", Tkapp_GetVar},
898 {"globalgetvar", Tkapp_GlobalGetVar},
899 {"unsetvar", Tkapp_UnsetVar},
900 {"globalunsetvar", Tkapp_GlobalUnsetVar},
901 {"getint", Tkapp_GetInt},
902 {"getdouble", Tkapp_GetDouble},
903 {"getboolean", Tkapp_GetBoolean},
904 {"exprstring", Tkapp_ExprString},
905 {"exprlong", Tkapp_ExprLong},
906 {"exprdouble", Tkapp_ExprDouble},
907 {"exprboolean", Tkapp_ExprBoolean},
908 {"splitlist", Tkapp_SplitList},
909 {"split", Tkapp_Split},
910 {"merge", Tkapp_Merge},
911 {"createcommand", Tkapp_CreateCommand},
912 {"deletecommand", Tkapp_DeleteCommand},
913 {"createfilehandler", Tkapp_CreateFileHandler},
914 {"deletefilehandler", Tkapp_DeleteFileHandler},
915 {"mainloop", Tkapp_MainLoop},
916 {"quit", Tkapp_Quit},
917 {NULL, NULL}
918};
919
920/**** Tkapp Type Methods ****/
921
922static void
923Tkapp_Dealloc (self)
924 PyObject *self;
925{
926 Tk_DestroyWindow (Tkapp_Tkwin (self));
927 Tcl_DeleteInterp (Tkapp_Interp (self));
928 PyMem_DEL (self);
929}
930
931static PyObject *
932Tkapp_GetAttr (self, name)
933 PyObject *self;
934 char *name;
935{
936 return Py_FindMethod (Tkapp_methods, self, name);
937}
938
939static PyTypeObject Tkapp_Type =
940{
941 OB_HEAD_INIT (&PyType_Type)
942 0, /*ob_size */
943 "tkapp", /*tp_name */
944 sizeof (TkappObject), /*tp_basicsize */
945 0, /*tp_itemsize */
946 Tkapp_Dealloc, /*tp_dealloc */
947 0, /*tp_print */
948 Tkapp_GetAttr, /*tp_getattr */
949 0, /*tp_setattr */
950 0, /*tp_compare */
951 0, /*tp_repr */
952 0, /*tp_as_number */
953 0, /*tp_as_sequence */
954 0, /*tp_as_mapping */
955 0, /*tp_hash */
956};
957
958/**** Tkinter Module ****/
959
960static PyObject *
961Tkinter_Create (self, args)
962 PyObject *self;
963 PyObject *args;
964{
965 char *screenName = NULL;
966 char *baseName;
967 char *className;
968 int interactive = 0;
969
970 baseName = strrchr (getprogramname (), '/');
971 if (baseName != NULL)
972 baseName++;
973 else
974 baseName = getprogramname ();
975 className = "Tk";
976
977 if (PyArg_Parse (args, ""))
978 /* VOID */ ;
979 else if (PyArg_Parse (args, "z",
980 &screenName))
981 /* VOID */ ;
982 else if (PyArg_Parse (args, "(zs)",
983 &screenName, &baseName))
984 /* VOID */ ;
985 else if (PyArg_Parse (args, "(zss)",
986 &screenName, &baseName, &className))
987 /* VOID */ ;
988 else if (PyArg_Parse (args, "(zssi)",
989 &screenName, &baseName, &className, &interactive))
990 /* VOID */ ;
991 else
992 return NULL;
993
994 return (PyObject *) Tkapp_New (screenName, baseName, className,
995 interactive);
996}
997
998static PyMethodDef moduleMethods[] =
999{
1000 {"create", Tkinter_Create},
1001 {NULL, NULL}
1002};
1003
1004#ifdef WITH_READLINE
1005static int
1006EventHook ()
1007{
1008 if (errorInCmd) /* XXX Reset tty */
1009 {
1010 errorInCmd = 0;
1011 PyErr_SetObject (excInCmd, valInCmd);
1012 PyErr_Print ();
1013 }
1014 if (tk_NumMainWindows > 0)
1015 Tk_DoOneEvent (0);
1016 return 0;
1017}
1018#endif /* WITH_READLINE */
1019
1020static void
1021StdinProc (clientData, mask)
1022 ClientData clientData;
1023 int mask;
1024{
1025 /* Do nothing. */
1026}
1027
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001028static void
1029Tkinter_Cleanup ()
1030{
1031 /* XXX rl_deprep_terminal is static, damned! */
1032 while (tkMainWindowList != 0)
1033 Tk_DestroyWindow (tkMainWindowList->win);
1034}
1035
Guido van Rossum18468821994-06-20 07:49:28 +00001036void
1037PyInit_tkinter ()
1038{
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001039 static inited = 0;
1040
Guido van Rossum18468821994-06-20 07:49:28 +00001041#ifdef WITH_READLINE
1042 extern int (*rl_event_hook) ();
1043#endif /* WITH_READLINE */
1044 PyObject *m, *d, *v;
1045
1046 m = Py_InitModule ("tkinter", moduleMethods);
1047
1048 d = PyModule_GetDict (m);
1049 Tkinter_TclError = Py_BuildValue ("s", "TclError");
1050 PyDict_SetItemString (d, "TclError", Tkinter_TclError);
1051
1052 v = Py_BuildValue ("i", TK_READABLE);
1053 PyDict_SetItemString (d, "READABLE", v);
1054 v = Py_BuildValue ("i", TK_WRITABLE);
1055 PyDict_SetItemString (d, "WRITABLE", v);
1056 v = Py_BuildValue ("i", TK_EXCEPTION);
1057 PyDict_SetItemString (d, "EXCEPTION", v);
1058
1059 /* Unblock stdin. */
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001060 if (isatty (0))
1061 Tk_CreateFileHandler (0, TK_READABLE, StdinProc, (ClientData) 0);
Guido van Rossum18468821994-06-20 07:49:28 +00001062
1063#ifdef WITH_READLINE
1064 rl_event_hook = EventHook;
1065#endif /* WITH_READLINE */
1066
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001067 if (!inited)
1068 {
1069 inited = 1;
1070 if (atexit (Tkinter_Cleanup))
1071 PyErr_SetFromErrno (Tkinter_TclError);
1072 }
1073
Guido van Rossum18468821994-06-20 07:49:28 +00001074 if (PyErr_Occurred ())
1075 Py_FatalError ("can't initialize module tkinter");
1076}