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