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