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