blob: 1be788baad8a82c022c1dbe2f43171e11ccf0b6f [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
3Copyright 1994-1995 by Stichting Mathematisch Centrum, Amsterdam,
4The Netherlands.
5
6 All Rights Reserved
7
8Permission to use, copy, modify, and distribute this software and its
9documentation for any purpose and without fee is hereby granted,
10provided that the above copyright notice appear in all copies and that
11both that copyright notice and this permission notice appear in
12supporting documentation, and that the names of Stichting Mathematisch
13Centrum or CWI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior permission.
15
16STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
17THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
19FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
22OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
24******************************************************************/
25
26/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +000027
Guido van Rossum9722ad81995-09-22 23:49:28 +000028#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000029#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000030
Guido van Rossum18468821994-06-20 07:49:28 +000031#include <tcl.h>
32#include <tk.h>
33
Guido van Rossum32aa1a71996-07-31 19:51:15 +000034extern char *Py_GetProgramName ();
Guido van Rossumd308e2b1994-07-07 09:25:12 +000035
Guido van Rossum9722ad81995-09-22 23:49:28 +000036/* Internal declarations from tkInt.h. */
37#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
38extern int Tk_GetNumMainWindows();
39#else
Guido van Rossum18468821994-06-20 07:49:28 +000040extern int tk_NumMainWindows;
Guido van Rossum9722ad81995-09-22 23:49:28 +000041#define Tk_GetNumMainWindows() (tk_NumMainWindows)
Guido van Rossumdfd428d1996-02-25 04:46:40 +000042#define NEED_TKCREATEMAINWINDOW 1
Guido van Rossum9722ad81995-09-22 23:49:28 +000043#endif
44
45#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +000046extern struct { Tk_Window win; } *tkMainWindowList;
Guido van Rossum9722ad81995-09-22 23:49:28 +000047#endif
Guido van Rossum18468821994-06-20 07:49:28 +000048
Guido van Rossumec22c921996-02-25 04:50:29 +000049#ifdef macintosh
50
51/*
52** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +000053** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +000054*/
55
Guido van Rossum97867b21996-08-08 19:09:53 +000056/* free() expects a char* */
57#define FREECAST (char *)
58
Guido van Rossumec22c921996-02-25 04:50:29 +000059#include <Events.h> /* For EventRecord */
60
61typedef int (*TclMacConvertEventPtr) Py_PROTO((EventRecord *eventPtr));
62void TclMacSetEventProc Py_PROTO((TclMacConvertEventPtr procPtr));
63int TkMacConvertEvent Py_PROTO((EventRecord *eventPtr));
64
65staticforward int PyMacConvertEvent Py_PROTO((EventRecord *eventPtr));
66
67#endif /* macintosh */
68
Guido van Rossum97867b21996-08-08 19:09:53 +000069#ifndef FREECAST
70#define FREECAST
71#endif
72
Guido van Rossum18468821994-06-20 07:49:28 +000073/**** Tkapp Object Declaration ****/
74
75staticforward PyTypeObject Tkapp_Type;
76
77typedef struct
78 {
79 PyObject_HEAD
80 Tcl_Interp *interp;
Guido van Rossumdfd428d1996-02-25 04:46:40 +000081#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +000082 Tk_Window tkwin;
Guido van Rossumdfd428d1996-02-25 04:46:40 +000083#endif
Guido van Rossum18468821994-06-20 07:49:28 +000084 }
85TkappObject;
86
87#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossumdfd428d1996-02-25 04:46:40 +000088#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +000089#define Tkapp_Tkwin(v) (((TkappObject *) (v))->tkwin)
Guido van Rossumdfd428d1996-02-25 04:46:40 +000090#endif
Guido van Rossum18468821994-06-20 07:49:28 +000091#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
92#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
93
94#define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
95 (void *) v, ((PyObject *) v)->ob_refcnt))
96
97/**** Error Handling ****/
98
99static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000100static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000101static int errorInCmd = 0;
102static PyObject *excInCmd;
103static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000104static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000105
106static PyObject *
107Tkinter_Error (v)
108 PyObject *v;
109{
Guido van Rossum18468821994-06-20 07:49:28 +0000110 PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
111 return NULL;
112}
113
114int
115PythonCmd_Error (interp)
116 Tcl_Interp *interp;
117{
118 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000119 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000120 return TCL_ERROR;
121}
122
123/**** Utils ****/
124
125static char *
126AsString (value, tmp)
127 PyObject *value;
128 PyObject *tmp;
129{
130 if (PyString_Check (value))
131 return PyString_AsString (value);
132 else
133 {
134 PyObject *v;
135
Guido van Rossumcd938fc1995-01-17 16:13:48 +0000136 v = PyObject_Str (value);
Guido van Rossum18468821994-06-20 07:49:28 +0000137 PyList_Append (tmp, v);
138 Py_DECREF (v);
139 return PyString_AsString (v);
140 }
141}
142
143#define ARGSZ 64
144
145static char *
146Merge (args)
147 PyObject *args;
148{
149 PyObject *tmp;
150 char *argvStore[ARGSZ];
151 char **argv;
152 int fvStore[ARGSZ];
153 int *fv;
154 int argc;
155 char *res;
156 int i;
157
158 tmp = PyList_New (0);
159 argv = argvStore;
160 fv = fvStore;
161
Guido van Rossum845547d1996-06-26 18:26:04 +0000162 if (args == NULL)
163 {
164 argc = 0;
165 }
166 else if (!PyTuple_Check (args))
Guido van Rossum18468821994-06-20 07:49:28 +0000167 {
168 argc = 1;
169 fv[0] = 0;
170 argv[0] = AsString (args, tmp);
171 }
172 else
173 {
174 PyObject *v;
175
176 if (PyTuple_Size (args) > ARGSZ)
177 {
Guido van Rossumb6fe7041995-03-09 12:13:43 +0000178 argv = (char **) malloc (PyTuple_Size (args) * sizeof (char *));
179 fv = (int *) malloc (PyTuple_Size (args) * sizeof (int));
Guido van Rossum18468821994-06-20 07:49:28 +0000180 if (argv == NULL || fv == NULL)
181 PyErr_NoMemory ();
182 }
183
184 argc = PyTuple_Size (args);
185 for (i = 0; i < argc; i++)
186 {
187 v = PyTuple_GetItem (args, i);
188 if (PyTuple_Check (v))
189 {
190 fv[i] = 1;
191 argv[i] = Merge (v);
192 }
193 else if (v == Py_None)
194 {
195 argc = i;
196 break;
197 }
198 else
199 {
200 fv[i] = 0;
201 argv[i] = AsString (v, tmp);
202 }
203 }
204 }
205
206 res = Tcl_Merge (argc, argv);
207
208 Py_DECREF (tmp);
209 for (i = 0; i < argc; i++)
210 if (fv[i]) free (argv[i]);
211 if (argv != argvStore)
Guido van Rossum97867b21996-08-08 19:09:53 +0000212 free (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000213 if (fv != fvStore)
Guido van Rossum97867b21996-08-08 19:09:53 +0000214 free (FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000215
216 return res;
217}
218
219static PyObject *
220Split (self, list)
221 PyObject *self;
222 char *list;
223{
224 int argc;
225 char **argv;
226 PyObject *v;
227
228 if (list == NULL)
229 {
230 Py_INCREF (Py_None);
231 return Py_None;
232 }
233
234 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
235 return Tkinter_Error (self);
236
237 if (argc == 0)
238 v = PyString_FromString ("");
239 else if (argc == 1)
240 v = PyString_FromString (argv[0]);
241 else
242 {
243 int i;
244
245 v = PyTuple_New (argc);
246 for (i = 0; i < argc; i++)
247 PyTuple_SetItem (v, i, Split (self, argv[i]));
248 }
249
Guido van Rossum97867b21996-08-08 19:09:53 +0000250 free (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000251 return v;
252}
253
254/**** Tkapp Object ****/
255
256#ifndef WITH_APPINIT
257int
258Tcl_AppInit (interp)
259 Tcl_Interp *interp;
260{
Guido van Rossumec22c921996-02-25 04:50:29 +0000261 Tk_Window main;
262
263 main = Tk_MainWindow(interp);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000264 if (Tcl_Init (interp) == TCL_ERROR) {
265 fprintf(stderr, "Tcl_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000266 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000267 }
268 if (Tk_Init (interp) == TCL_ERROR) {
269 fprintf(stderr, "Tk_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000270 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000271 }
Guido van Rossum18468821994-06-20 07:49:28 +0000272 return TCL_OK;
273}
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000274
Guido van Rossum18468821994-06-20 07:49:28 +0000275#endif /* !WITH_APPINIT */
276
277/* Initialize the Tk application; see the `main' function in
278 `tkMain.c'. */
279static TkappObject *
280Tkapp_New (screenName, baseName, className, interactive)
281 char *screenName;
282 char *baseName;
283 char *className;
284 int interactive;
285{
286 TkappObject *v;
Guido van Rossum97867b21996-08-08 19:09:53 +0000287 char *argv0;
Guido van Rossum18468821994-06-20 07:49:28 +0000288
289 v = PyObject_NEW (TkappObject, &Tkapp_Type);
290 if (v == NULL)
291 return NULL;
292
293 v->interp = Tcl_CreateInterp ();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000294
295#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +0000296 v->tkwin = Tk_CreateMainWindow (v->interp, screenName,
297 baseName, className);
298 if (v->tkwin == NULL)
299 return (TkappObject *) Tkinter_Error ((PyObject *) v);
300
301 Tk_GeometryRequest (v->tkwin, 200, 200);
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000302#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000303
304 if (screenName != NULL)
305 Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
306
307 if (interactive)
308 Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
309 else
310 Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
311
Guido van Rossum97867b21996-08-08 19:09:53 +0000312 /* This is used to get the application class for Tk 4.1 and up */
313 argv0 = (char*) malloc (strlen (className) + 1);
314 if (argv0 != NULL) {
315 strcpy (argv0, className);
316 if (isupper (argv0[0]))
317 argv0[0] = tolower (argv0[0]);
318 Tcl_SetVar (v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
319 free (argv0);
320 }
321
Guido van Rossum18468821994-06-20 07:49:28 +0000322 if (Tcl_AppInit (v->interp) != TCL_OK)
Guido van Rossum845547d1996-06-26 18:26:04 +0000323 return (TkappObject *) Tkinter_Error (v);
Guido van Rossum18468821994-06-20 07:49:28 +0000324
325 return v;
326}
327
328/** Tcl Eval **/
329
330static PyObject *
331Tkapp_Call (self, args)
332 PyObject *self;
333 PyObject *args;
334{
335 char *cmd;
336
337 cmd = Merge (args);
338 if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
339 {
340 free (cmd);
341 return Tkinter_Error (self);
342 }
343
344 free (cmd);
345 return PyString_FromString (Tkapp_Result (self));
346}
347
348static PyObject *
349Tkapp_GlobalCall (self, args)
350 PyObject *self;
351 PyObject *args;
352{
353 char *cmd;
354
355 cmd = Merge (args);
356 if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
357 {
358 free (cmd);
359 return Tkinter_Error (self);
360 }
361
362 free (cmd);
363 return PyString_FromString (Tkapp_Result (self));
364}
365
366static PyObject *
367Tkapp_Eval (self, args)
368 PyObject *self;
369 PyObject *args;
370{
371 char *script;
372
373 if (!PyArg_Parse (args, "s", &script))
374 return NULL;
375
376 if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
377 return Tkinter_Error (self);
378
379 return PyString_FromString (Tkapp_Result (self));
380}
381
382static PyObject *
383Tkapp_GlobalEval (self, args)
384 PyObject *self;
385 PyObject *args;
386{
387 char *script;
388
389 if (!PyArg_Parse (args, "s", &script))
390 return NULL;
391
392 if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
393 return Tkinter_Error (self);
394
395 return PyString_FromString (Tkapp_Result (self));
396}
397
398static PyObject *
399Tkapp_EvalFile (self, args)
400 PyObject *self;
401 PyObject *args;
402{
403 char *fileName;
404
405 if (!PyArg_Parse (args, "s", &fileName))
406 return NULL;
407
408 if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
409 return Tkinter_Error (self);
410
411 return PyString_FromString (Tkapp_Result (self));
412}
413
414static PyObject *
415Tkapp_Record (self, args)
416 PyObject *self;
417 PyObject *args;
418{
419 char *script;
420
421 if (!PyArg_Parse (args, "s", &script))
422 return NULL;
423
424 if (Tcl_RecordAndEval (Tkapp_Interp (self),
425 script, TCL_NO_EVAL) == TCL_ERROR)
426 return Tkinter_Error (self);
427
428 return PyString_FromString (Tkapp_Result (self));
429}
430
431static PyObject *
432Tkapp_AddErrorInfo (self, args)
433 PyObject *self;
434 PyObject *args;
435{
436 char *msg;
437
438 if (!PyArg_Parse (args, "s", &msg))
439 return NULL;
440 Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
441
442 Py_INCREF(Py_None);
443 return Py_None;
444}
445
446/** Tcl Variable **/
447
448static PyObject *
449SetVar (self, args, flags)
450 PyObject *self;
451 PyObject *args;
452 int flags;
453{
454 char *name1, *name2, *ok;
455 PyObject *newValue;
456 PyObject *tmp;
457
458 tmp = PyList_New (0);
459
460 if (PyArg_Parse (args, "(sO)", &name1, &newValue))
461 ok = Tcl_SetVar (Tkapp_Interp (self), name1,
462 AsString (newValue, tmp), flags); /* XXX Merge? */
463 else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
464 ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,
465 AsString (newValue, tmp), flags);
466 else
467 {
468 Py_DECREF (tmp);
469 return NULL;
470 }
471 Py_DECREF (tmp);
472
473 if (!ok)
474 return Tkinter_Error (self);
475
476 Py_INCREF (Py_None);
477 return Py_None;
478}
479
480static PyObject *
481Tkapp_SetVar (self, args)
482 PyObject *self;
483 PyObject *args;
484{
485 return SetVar (self, args, TCL_LEAVE_ERR_MSG);
486}
487
488static PyObject *
489Tkapp_GlobalSetVar (self, args)
490 PyObject *self;
491 PyObject *args;
492{
493 return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
494}
495
496static PyObject *
497GetVar (self, args, flags)
498 PyObject *self;
499 PyObject *args;
500 int flags;
501{
502 char *name1, *name2, *s;
503
504 if (PyArg_Parse (args, "s", &name1))
505 s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
506 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
507 s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
508 else
509 return NULL;
510
511 if (s == NULL)
512 return Tkinter_Error (self);
513
514 return PyString_FromString (s);
515}
516
517static PyObject *
518Tkapp_GetVar (self, args)
519 PyObject *self;
520 PyObject *args;
521{
522 return GetVar (self, args, TCL_LEAVE_ERR_MSG);
523}
524
525static PyObject *
526Tkapp_GlobalGetVar (self, args)
527 PyObject *self;
528 PyObject *args;
529{
530 return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
531}
532
533static PyObject *
534UnsetVar (self, args, flags)
535 PyObject *self;
536 PyObject *args;
537 int flags;
538{
539 char *name1, *name2;
540 int code;
541
542 if (PyArg_Parse (args, "s", &name1))
543 code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
544 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
545 code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
546 else
547 return NULL;
548
549 if (code == TCL_ERROR)
550 return Tkinter_Error (self);
551
552 Py_INCREF (Py_None);
553 return Py_None;
554}
555
556static PyObject *
557Tkapp_UnsetVar (self, args)
558 PyObject *self;
559 PyObject *args;
560{
561 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
562}
563
564static PyObject *
565Tkapp_GlobalUnsetVar (self, args)
566 PyObject *self;
567 PyObject *args;
568{
569 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
570}
571
572/** Tcl to Python **/
573
574static PyObject *
575Tkapp_GetInt (self, args)
576 PyObject *self;
577 PyObject *args;
578{
579 char *s;
580 int v;
581
582 if (!PyArg_Parse (args, "s", &s))
583 return NULL;
584 if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
585 return Tkinter_Error (self);
586 return Py_BuildValue ("i", v);
587}
588
589static PyObject *
590Tkapp_GetDouble (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_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
600 return Tkinter_Error (self);
601 return Py_BuildValue ("d", v);
602}
603
604static PyObject *
605Tkapp_GetBoolean (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_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
615 return Tkinter_Error (self);
616 return Py_BuildValue ("i", v);
617}
618
619static PyObject *
620Tkapp_ExprString (self, args)
621 PyObject *self;
622 PyObject *args;
623{
624 char *s;
625
626 if (!PyArg_Parse (args, "s", &s))
627 return NULL;
628 if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
629 return Tkinter_Error (self);
630 return Py_BuildValue ("s", Tkapp_Result (self));
631}
632
633static PyObject *
634Tkapp_ExprLong (self, args)
635 PyObject *self;
636 PyObject *args;
637{
638 char *s;
639 long v;
640
641 if (!PyArg_Parse (args, "s", &s))
642 return NULL;
643 if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
644 return Tkinter_Error (self);
645 return Py_BuildValue ("l", v);
646}
647
648static PyObject *
649Tkapp_ExprDouble (self, args)
650 PyObject *self;
651 PyObject *args;
652{
653 char *s;
654 double v;
655
656 if (!PyArg_Parse (args, "s", &s))
657 return NULL;
658 if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
659 return Tkinter_Error (self);
660 return Py_BuildValue ("d", v);
661}
662
663static PyObject *
664Tkapp_ExprBoolean (self, args)
665 PyObject *self;
666 PyObject *args;
667{
668 char *s;
669 int v;
670
671 if (!PyArg_Parse (args, "s", &s))
672 return NULL;
673 if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
674 return Tkinter_Error (self);
675 return Py_BuildValue ("i", v);
676}
677
678static PyObject *
679Tkapp_SplitList (self, args)
680 PyObject *self;
681 PyObject *args;
682{
683 char *list;
684 int argc;
685 char **argv;
686 PyObject *v;
687 int i;
688
689 if (!PyArg_Parse (args, "s", &list))
690 return NULL;
691
692 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
693 return Tkinter_Error (self);
694
695 v = PyTuple_New (argc);
696 for (i = 0; i < argc; i++)
697 PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
698
Guido van Rossum97867b21996-08-08 19:09:53 +0000699 free (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000700 return v;
701}
702
703static PyObject *
704Tkapp_Split (self, args)
705 PyObject *self;
706 PyObject *args;
707{
708 char *list;
709
710 if (!PyArg_Parse (args, "s", &list))
711 return NULL;
712 return Split (self, list);
713}
714
715static PyObject *
716Tkapp_Merge (self, args)
717 PyObject *self;
718 PyObject *args;
719{
720 char *s;
721 PyObject *v;
722
723 s = Merge (args);
724 v = PyString_FromString (s);
725 free (s);
726 return v;
727}
728
729/** Tcl Command **/
730
731/* This is the Tcl command that acts as a wrapper for Python
732 function or method. */
733static int
734PythonCmd (clientData, interp, argc, argv)
735 ClientData clientData; /* Is (self, func) */
736 Tcl_Interp *interp;
737 int argc;
738 char *argv[];
739{
740 PyObject *self, *func, *arg, *res, *tmp;
741 int i;
742
743 self = PyTuple_GetItem ((PyObject *) clientData, 0);
744 func = PyTuple_GetItem ((PyObject *) clientData, 1);
745
746 /* Create argument list (argv1, ..., argvN) */
747 arg = PyTuple_New (argc - 1);
748 for (i = 0; i < (argc - 1); i++)
749 PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
750
751 res = PyEval_CallObject (func, arg);
752 Py_DECREF (arg);
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000753
Guido van Rossum18468821994-06-20 07:49:28 +0000754 if (res == NULL)
755 return PythonCmd_Error (interp);
756
757 tmp = PyList_New (0);
758 Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
759 Py_DECREF (res);
760 Py_DECREF (tmp);
761
762 return TCL_OK;
763}
764
765static void
766PythonCmdDelete (clientData)
767 ClientData clientData; /* Is (self, func) */
768{
769 Py_DECREF ((PyObject *) clientData);
770}
771
772static PyObject *
773Tkapp_CreateCommand (self, args)
774 PyObject *self;
775 PyObject *args;
776{
777 char *cmdName;
778 PyObject *data;
779 PyObject *func;
780
781 /* Args is: (cmdName, func) */
782 if (!PyTuple_Check (args)
783 || !(PyTuple_Size (args) == 2)
784 || !PyString_Check (PyTuple_GetItem (args, 0))
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000785 || !PyCallable_Check (PyTuple_GetItem (args, 1)))
Guido van Rossum18468821994-06-20 07:49:28 +0000786 {
787 PyErr_SetString (PyExc_TypeError, "bad argument list");
788 return NULL;
789 }
790
791 cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
792 func = PyTuple_GetItem (args, 1);
793
794 data = PyTuple_New (2); /* ClientData is: (self, func) */
795
796 Py_INCREF (self);
797 PyTuple_SetItem (data, 0, self);
798
799 Py_INCREF (func);
800 PyTuple_SetItem (data, 1, func);
801
802 Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
803 (ClientData) data, PythonCmdDelete);
804
805 Py_INCREF (Py_None);
806 return Py_None;
807}
808
809static PyObject *
810Tkapp_DeleteCommand (self, args)
811 PyObject *self;
812 PyObject *args;
813{
814 char *cmdName;
815
816 if (!PyArg_Parse (args, "s", &cmdName))
817 return NULL;
818 if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
819 {
820 PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
821 return NULL;
822 }
823 Py_INCREF (Py_None);
824 return Py_None;
825}
826
827/** File Handler **/
828
Guido van Rossuma597dde1995-01-10 20:56:29 +0000829static void
Guido van Rossum18468821994-06-20 07:49:28 +0000830FileHandler (clientData, mask)
Guido van Rossum76875221994-06-27 07:59:42 +0000831 ClientData clientData; /* Is: (func, file) */
Guido van Rossum18468821994-06-20 07:49:28 +0000832 int mask;
833{
Guido van Rossum76875221994-06-27 07:59:42 +0000834 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +0000835
Guido van Rossum76875221994-06-27 07:59:42 +0000836 func = PyTuple_GetItem ((PyObject *) clientData, 0);
837 file = PyTuple_GetItem ((PyObject *) clientData, 1);
Guido van Rossum18468821994-06-20 07:49:28 +0000838
Guido van Rossum76875221994-06-27 07:59:42 +0000839 arg = Py_BuildValue ("(Oi)", file, (long) mask);
Guido van Rossum18468821994-06-20 07:49:28 +0000840 res = PyEval_CallObject (func, arg);
841 Py_DECREF (arg);
842 if (res == NULL)
843 {
844 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000845 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000846 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000847 Py_XDECREF (res);
848}
849
850static int
851GetFileNo (file)
852 PyObject *file; /* Either an int >= 0 or an object with a
853 .fileno() method that returns an int >= 0 */
854{
Guido van Rossuma597dde1995-01-10 20:56:29 +0000855 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000856 int id;
857 if (PyInt_Check(file)) {
858 id = PyInt_AsLong(file);
859 if (id < 0)
860 PyErr_SetString(PyExc_ValueError, "invalid file id");
861 return id;
862 }
863 meth = PyObject_GetAttrString(file, "fileno");
864 if (meth == NULL)
865 return -1;
866 args = PyTuple_New(0);
867 if (args == NULL)
868 return -1;
869 res = PyEval_CallObject(meth, args);
870 Py_DECREF(args);
871 Py_DECREF(meth);
872 if (res == NULL)
873 return -1;
874 if (PyInt_Check(res))
875 id = PyInt_AsLong(res);
876 else
877 id = -1;
878 if (id < 0)
879 PyErr_SetString(PyExc_ValueError,
880 "invalid fileno() return value");
881 Py_DECREF(res);
882 return id;
Guido van Rossum18468821994-06-20 07:49:28 +0000883}
884
885static PyObject *
886Tkapp_CreateFileHandler (self, args)
887 PyObject *self;
888 PyObject *args; /* Is (file, mask, func) */
889{
Guido van Rossum76875221994-06-27 07:59:42 +0000890 PyObject *file, *func, *data;
891 int mask, id;
Guido van Rossum68784361996-05-16 17:17:31 +0000892#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
893 Tcl_File tfile;
894#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000895
896 if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
897 return NULL;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000898 id = GetFileNo (file);
899 if (id < 0)
900 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000901 if (!PyCallable_Check(func))
Guido van Rossum18468821994-06-20 07:49:28 +0000902 {
903 PyErr_SetString (PyExc_TypeError, "bad argument list");
904 return NULL;
905 }
906
Guido van Rossum76875221994-06-27 07:59:42 +0000907 /* ClientData is: (func, file) */
908 data = Py_BuildValue ("(OO)", func, file);
909
Guido van Rossum68784361996-05-16 17:17:31 +0000910#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum845547d1996-06-26 18:26:04 +0000911#ifdef NT
912 /* We assume this is a socket... */
913 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
914#else
Guido van Rossum68784361996-05-16 17:17:31 +0000915 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
Guido van Rossum845547d1996-06-26 18:26:04 +0000916#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000917 /* Oughtta check for null Tcl_File object... */
918 Tcl_CreateFileHandler (tfile, mask, FileHandler, (ClientData) data);
919#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000920 Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
Guido van Rossum68784361996-05-16 17:17:31 +0000921#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000922 /* XXX fileHandlerDict */
Guido van Rossum76875221994-06-27 07:59:42 +0000923
Guido van Rossum18468821994-06-20 07:49:28 +0000924 Py_INCREF (Py_None);
925 return Py_None;
926}
927
928static PyObject *
929Tkapp_DeleteFileHandler (self, args)
930 PyObject *self;
931 PyObject *args; /* Args: file */
932{
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000933 PyObject *file;
Guido van Rossum18468821994-06-20 07:49:28 +0000934 int id;
Guido van Rossum68784361996-05-16 17:17:31 +0000935#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
936 Tcl_File tfile;
937#endif
938
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000939 if (!PyArg_Parse (args, "O", &file))
940 return NULL;
941 id = GetFileNo (file);
942 if (id < 0)
943 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000944
Guido van Rossum68784361996-05-16 17:17:31 +0000945#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum845547d1996-06-26 18:26:04 +0000946#ifdef NT
947 /* We assume this is a socket... */
948 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
949#else
950 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
951#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000952 /* Oughtta check for null Tcl_File object... */
953 Tcl_DeleteFileHandler(tfile);
954#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000955 Tk_DeleteFileHandler (id);
Guido van Rossum68784361996-05-16 17:17:31 +0000956#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000957 /* XXX fileHandlerDict */
958 Py_INCREF (Py_None);
959 return Py_None;
960}
961
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000962/**** Tktt Object (timer token) ****/
963
964staticforward PyTypeObject Tktt_Type;
965
966typedef struct
967 {
968 PyObject_HEAD
969 Tk_TimerToken token;
970 PyObject *func;
971 }
972TkttObject;
973
974static PyObject *
975Tktt_DeleteTimerHandler (self, args)
976 PyObject *self;
977 PyObject *args;
978{
979 TkttObject *v = (TkttObject *) self;
980
981 if (!PyArg_Parse (args, ""))
982 return NULL;
983 if (v->func != NULL)
984 {
985 Tk_DeleteTimerHandler (v->token);
986 PyMem_DEL (v->func);
987 v->func = NULL;
988 }
989 Py_INCREF (Py_None);
990 return Py_None;
991}
992
993static PyMethodDef Tktt_methods[] =
994{
995 {"deletetimerhandler", Tktt_DeleteTimerHandler},
996 {NULL, NULL}
997};
998
999static TkttObject *
1000Tktt_New (token, func)
1001 Tk_TimerToken token;
1002 PyObject *func;
1003{
1004 TkttObject *v;
1005
1006 v = PyObject_NEW (TkttObject, &Tktt_Type);
1007 if (v == NULL)
1008 return NULL;
1009
1010 v->token = token;
1011 v->func = func;
1012 Py_INCREF (v->func);
1013 return v;
1014}
1015
1016static void
1017Tktt_Dealloc (self)
1018 PyObject *self;
1019{
1020 PyMem_DEL (self);
1021}
1022
1023static int
1024Tktt_Print (self, fp, flags)
1025 PyObject *self;
1026 FILE *fp;
1027 int flags;
1028{
1029 TkttObject *v = (TkttObject *) self;
1030
1031 fprintf(fp, "<tktimertoken at 0x%x%s>", v,
1032 v->func == NULL ? ", handler deleted" : "");
1033 return 0;
1034}
1035
1036static PyObject *
1037Tktt_GetAttr (self, name)
1038 PyObject *self;
1039 char *name;
1040{
1041 return Py_FindMethod (Tktt_methods, self, name);
1042}
1043
1044static PyTypeObject Tktt_Type =
1045{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001046 PyObject_HEAD_INIT (&PyType_Type)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001047 0, /*ob_size */
1048 "tktimertoken", /*tp_name */
1049 sizeof (TkttObject), /*tp_basicsize */
1050 0, /*tp_itemsize */
1051 Tktt_Dealloc, /*tp_dealloc */
1052 Tktt_Print, /*tp_print */
1053 Tktt_GetAttr, /*tp_getattr */
1054 0, /*tp_setattr */
1055 0, /*tp_compare */
1056 0, /*tp_repr */
1057 0, /*tp_as_number */
1058 0, /*tp_as_sequence */
1059 0, /*tp_as_mapping */
1060 0, /*tp_hash */
1061};
1062
1063/** Timer Handler **/
1064
1065static void
1066TimerHandler (clientData)
1067 ClientData clientData;
1068{
1069 PyObject *func = (PyObject *) clientData;
1070 PyObject *arg, *res;
1071
1072 arg = PyTuple_New (0);
1073 res = PyEval_CallObject (func, arg);
1074 Py_DECREF (arg);
1075 if (res == NULL)
1076 {
1077 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001078 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001079 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001080 else
1081 Py_DECREF (res);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001082}
1083
1084static PyObject *
1085Tkapp_CreateTimerHandler (self, args)
1086 PyObject *self;
1087 PyObject *args; /* Is (milliseconds, func) */
1088{
1089 int milliseconds;
1090 PyObject *func;
1091 Tk_TimerToken token;
1092
1093 if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
1094 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001095 if (!PyCallable_Check(func))
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001096 {
1097 PyErr_SetString (PyExc_TypeError, "bad argument list");
1098 return NULL;
1099 }
1100 token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
1101 return (PyObject *) Tktt_New (token, func);
1102}
1103
Guido van Rossum18468821994-06-20 07:49:28 +00001104/** Event Loop **/
1105
Guido van Rossum18468821994-06-20 07:49:28 +00001106static PyObject *
1107Tkapp_MainLoop (self, args)
1108 PyObject *self;
1109 PyObject *args;
1110{
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001111 int threshold = 0;
1112
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001113 if (!PyArg_ParseTuple (args, "|i", &threshold))
1114 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001115
1116 quitMainLoop = 0;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001117 while (Tk_GetNumMainWindows() > threshold && !quitMainLoop && !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001118 {
1119 if (PyOS_InterruptOccurred ())
1120 {
1121 PyErr_SetNone (PyExc_KeyboardInterrupt);
1122 return NULL;
1123 }
1124 Tk_DoOneEvent (0);
1125 }
Guido van Rossum64b24fb1995-09-30 17:00:24 +00001126 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001127
1128 if (errorInCmd)
1129 {
1130 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001131 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1132 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001133 return NULL;
1134 }
1135 Py_INCREF (Py_None);
1136 return Py_None;
1137}
1138
1139static PyObject *
Guido van Rossum062cfb01995-01-10 17:42:51 +00001140Tkapp_DoOneEvent (self, args)
1141 PyObject *self;
1142 PyObject *args;
1143{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001144 int flags = TK_ALL_EVENTS;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001145 int rv;
1146
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001147 if (!PyArg_ParseTuple (args, "|i", &flags))
1148 return NULL;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001149 rv = Tk_DoOneEvent(flags);
1150 return Py_BuildValue ("i", rv);
1151}
1152
1153static PyObject *
Guido van Rossum18468821994-06-20 07:49:28 +00001154Tkapp_Quit (self, args)
1155 PyObject *self;
1156 PyObject *args;
1157{
1158
1159 if (!PyArg_Parse (args, ""))
1160 return NULL;
1161 quitMainLoop = 1;
1162 Py_INCREF (Py_None);
1163 return Py_None;
1164}
1165
1166/**** Tkapp Method List ****/
1167
1168static PyMethodDef Tkapp_methods[] =
1169{
1170 {"call", Tkapp_Call},
1171 {"globalcall", Tkapp_GlobalCall},
1172 {"eval", Tkapp_Eval},
1173 {"globaleval", Tkapp_GlobalEval},
1174 {"evalfile", Tkapp_EvalFile},
1175 {"record", Tkapp_Record},
1176 {"adderrorinfo", Tkapp_AddErrorInfo},
1177 {"setvar", Tkapp_SetVar},
1178 {"globalsetvar", Tkapp_GlobalSetVar},
1179 {"getvar", Tkapp_GetVar},
1180 {"globalgetvar", Tkapp_GlobalGetVar},
1181 {"unsetvar", Tkapp_UnsetVar},
1182 {"globalunsetvar", Tkapp_GlobalUnsetVar},
1183 {"getint", Tkapp_GetInt},
1184 {"getdouble", Tkapp_GetDouble},
1185 {"getboolean", Tkapp_GetBoolean},
1186 {"exprstring", Tkapp_ExprString},
1187 {"exprlong", Tkapp_ExprLong},
1188 {"exprdouble", Tkapp_ExprDouble},
1189 {"exprboolean", Tkapp_ExprBoolean},
1190 {"splitlist", Tkapp_SplitList},
1191 {"split", Tkapp_Split},
1192 {"merge", Tkapp_Merge},
1193 {"createcommand", Tkapp_CreateCommand},
1194 {"deletecommand", Tkapp_DeleteCommand},
1195 {"createfilehandler", Tkapp_CreateFileHandler},
1196 {"deletefilehandler", Tkapp_DeleteFileHandler},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001197 {"createtimerhandler", Tkapp_CreateTimerHandler},
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001198 {"mainloop", Tkapp_MainLoop, 1},
1199 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum18468821994-06-20 07:49:28 +00001200 {"quit", Tkapp_Quit},
1201 {NULL, NULL}
1202};
1203
1204/**** Tkapp Type Methods ****/
1205
1206static void
1207Tkapp_Dealloc (self)
1208 PyObject *self;
1209{
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001210#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +00001211 Tk_DestroyWindow (Tkapp_Tkwin (self));
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001212#endif
Guido van Rossum18468821994-06-20 07:49:28 +00001213 Tcl_DeleteInterp (Tkapp_Interp (self));
1214 PyMem_DEL (self);
1215}
1216
1217static PyObject *
1218Tkapp_GetAttr (self, name)
1219 PyObject *self;
1220 char *name;
1221{
1222 return Py_FindMethod (Tkapp_methods, self, name);
1223}
1224
1225static PyTypeObject Tkapp_Type =
1226{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001227 PyObject_HEAD_INIT (&PyType_Type)
Guido van Rossum18468821994-06-20 07:49:28 +00001228 0, /*ob_size */
1229 "tkapp", /*tp_name */
1230 sizeof (TkappObject), /*tp_basicsize */
1231 0, /*tp_itemsize */
1232 Tkapp_Dealloc, /*tp_dealloc */
1233 0, /*tp_print */
1234 Tkapp_GetAttr, /*tp_getattr */
1235 0, /*tp_setattr */
1236 0, /*tp_compare */
1237 0, /*tp_repr */
1238 0, /*tp_as_number */
1239 0, /*tp_as_sequence */
1240 0, /*tp_as_mapping */
1241 0, /*tp_hash */
1242};
1243
1244/**** Tkinter Module ****/
1245
1246static PyObject *
1247Tkinter_Create (self, args)
1248 PyObject *self;
1249 PyObject *args;
1250{
1251 char *screenName = NULL;
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001252 char *baseName = NULL;
1253 char *className = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001254 int interactive = 0;
1255
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001256 baseName = strrchr (Py_GetProgramName (), '/');
Guido van Rossum18468821994-06-20 07:49:28 +00001257 if (baseName != NULL)
1258 baseName++;
1259 else
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001260 baseName = Py_GetProgramName ();
Guido van Rossum18468821994-06-20 07:49:28 +00001261 className = "Tk";
1262
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001263 if (!PyArg_ParseTuple (args, "|zssi",
1264 &screenName, &baseName, &className, &interactive))
Guido van Rossum18468821994-06-20 07:49:28 +00001265 return NULL;
1266
1267 return (PyObject *) Tkapp_New (screenName, baseName, className,
1268 interactive);
1269}
1270
1271static PyMethodDef moduleMethods[] =
1272{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001273 {"create", Tkinter_Create, 1},
1274 {"createfilehandler", Tkapp_CreateFileHandler, 0},
1275 {"deletefilehandler", Tkapp_DeleteFileHandler, 0},
1276 {"createtimerhandler", Tkapp_CreateTimerHandler, 0},
1277 {"mainloop", Tkapp_MainLoop, 1},
1278 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001279 {"quit", Tkapp_Quit},
Guido van Rossum18468821994-06-20 07:49:28 +00001280 {NULL, NULL}
1281};
1282
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001283#undef WITH_READLINE /* XXX */
Guido van Rossum18468821994-06-20 07:49:28 +00001284#ifdef WITH_READLINE
1285static int
1286EventHook ()
1287{
1288 if (errorInCmd) /* XXX Reset tty */
1289 {
1290 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001291 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1292 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001293 PyErr_Print ();
1294 }
Guido van Rossum9722ad81995-09-22 23:49:28 +00001295 if (Tk_GetNumMainWindows() > 0)
Guido van Rossume2ca9bd1994-08-03 08:01:43 +00001296 Tk_DoOneEvent (TK_DONT_WAIT);
Guido van Rossum18468821994-06-20 07:49:28 +00001297 return 0;
1298}
1299#endif /* WITH_READLINE */
1300
1301static void
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001302Tkinter_Cleanup ()
1303{
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001304/* This segfault with Tk 4.0 beta and seems unnecessary there as well */
1305#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001306 /* XXX rl_deprep_terminal is static, damned! */
1307 while (tkMainWindowList != 0)
1308 Tk_DestroyWindow (tkMainWindowList->win);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001309#endif
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001310}
1311
Guido van Rossum18468821994-06-20 07:49:28 +00001312void
Guido van Rossumad1f7ee1996-02-13 00:11:37 +00001313init_tkinter ()
Guido van Rossum18468821994-06-20 07:49:28 +00001314{
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001315 static inited = 0;
1316
Guido van Rossum18468821994-06-20 07:49:28 +00001317#ifdef WITH_READLINE
1318 extern int (*rl_event_hook) ();
1319#endif /* WITH_READLINE */
1320 PyObject *m, *d, *v;
1321
Jack Jansenba0311e1995-10-23 14:34:14 +00001322 m = Py_InitModule ("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00001323
1324 d = PyModule_GetDict (m);
1325 Tkinter_TclError = Py_BuildValue ("s", "TclError");
1326 PyDict_SetItemString (d, "TclError", Tkinter_TclError);
1327
1328 v = Py_BuildValue ("i", TK_READABLE);
1329 PyDict_SetItemString (d, "READABLE", v);
1330 v = Py_BuildValue ("i", TK_WRITABLE);
1331 PyDict_SetItemString (d, "WRITABLE", v);
1332 v = Py_BuildValue ("i", TK_EXCEPTION);
1333 PyDict_SetItemString (d, "EXCEPTION", v);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001334 v = Py_BuildValue ("i", TK_X_EVENTS);
1335 PyDict_SetItemString (d, "X_EVENTS", v);
1336 v = Py_BuildValue ("i", TK_FILE_EVENTS);
1337 PyDict_SetItemString (d, "FILE_EVENTS", v);
1338 v = Py_BuildValue ("i", TK_TIMER_EVENTS);
1339 PyDict_SetItemString (d, "TIMER_EVENTS", v);
1340 v = Py_BuildValue ("i", TK_IDLE_EVENTS);
1341 PyDict_SetItemString (d, "IDLE_EVENTS", v);
1342 v = Py_BuildValue ("i", TK_ALL_EVENTS);
1343 PyDict_SetItemString (d, "ALL_EVENTS", v);
1344 v = Py_BuildValue ("i", TK_DONT_WAIT);
1345 PyDict_SetItemString (d, "DONT_WAIT", v);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001346 v = Py_BuildValue ("s", TK_VERSION);
1347 PyDict_SetItemString (d, "TK_VERSION", v);
1348 v = Py_BuildValue ("s", TCL_VERSION);
1349 PyDict_SetItemString (d, "TCL_VERSION", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001350
Guido van Rossum18468821994-06-20 07:49:28 +00001351#ifdef WITH_READLINE
1352 rl_event_hook = EventHook;
1353#endif /* WITH_READLINE */
1354
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001355 if (!inited)
1356 {
1357 inited = 1;
Guido van Rossume4485b01994-09-07 14:32:49 +00001358 if (Py_AtExit (Tkinter_Cleanup) != 0)
1359 fprintf(stderr,
1360 "Tkinter: warning: cleanup procedure not registered\n");
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001361 }
1362
Guido van Rossum18468821994-06-20 07:49:28 +00001363 if (PyErr_Occurred ())
Jack Jansenba0311e1995-10-23 14:34:14 +00001364 Py_FatalError ("can't initialize module _tkinter");
Jack Jansen34cc5c31995-10-31 16:15:12 +00001365#ifdef macintosh
Guido van Rossumec22c921996-02-25 04:50:29 +00001366 TclMacSetEventProc(PyMacConvertEvent);
1367#if GENERATINGCFM
Jack Jansen34cc5c31995-10-31 16:15:12 +00001368 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00001369#endif /* GENERATINGCFM */
1370#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00001371}
Guido van Rossum9722ad81995-09-22 23:49:28 +00001372
Guido van Rossumec22c921996-02-25 04:50:29 +00001373
Guido van Rossum9722ad81995-09-22 23:49:28 +00001374#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001375
1376/*
Guido van Rossumec22c921996-02-25 04:50:29 +00001377** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001378*/
1379
Guido van Rossum9722ad81995-09-22 23:49:28 +00001380void
1381panic(char * format, ...)
1382{
1383 va_list varg;
1384
1385 va_start(varg, format);
1386
1387 vfprintf(stderr, format, varg);
1388 (void) fflush(stderr);
1389
1390 va_end(varg);
1391
1392 Py_FatalError("Tcl/Tk panic");
1393}
Jack Jansen40b546d1995-11-14 10:34:45 +00001394
Guido van Rossumec22c921996-02-25 04:50:29 +00001395/*
1396** Pass events to SIOUX before passing them to Tk.
1397*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001398
Guido van Rossumec22c921996-02-25 04:50:29 +00001399static int
1400PyMacConvertEvent(eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001401 EventRecord *eventPtr;
1402{
Guido van Rossumec22c921996-02-25 04:50:29 +00001403 if (SIOUXHandleOneEvent(eventPtr))
1404 return 0; /* Nothing happened to the Tcl event queue */
1405 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001406}
1407
Guido van Rossumec22c921996-02-25 04:50:29 +00001408#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001409
1410/*
1411** Additional Mac specific code for dealing with shared libraries.
1412*/
1413
1414#include <Resources.h>
1415#include <CodeFragments.h>
1416
1417static int loaded_from_shlib = 0;
1418static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001419
Jack Jansen34cc5c31995-10-31 16:15:12 +00001420/*
1421** If this module is dynamically loaded the following routine should
1422** be the init routine. It takes care of adding the shared library to
1423** the resource-file chain, so that the tk routines can find their
1424** resources.
1425*/
1426OSErr pascal
1427init_tkinter_shlib(InitBlockPtr data)
1428{
Guido van Rossum54ac1891996-05-16 17:14:03 +00001429 __sinit(); /* Sez Jack */
Jack Jansen34cc5c31995-10-31 16:15:12 +00001430 if ( data == nil ) return noErr;
1431 if ( data->fragLocator.where == kOnDiskFlat ) {
1432 library_fss = *data->fragLocator.u.onDisk.fileSpec;
1433 loaded_from_shlib = 1;
1434 } else if ( data->fragLocator.where == kOnDiskSegmented ) {
1435 library_fss = *data->fragLocator.u.inSegs.fileSpec;
1436 loaded_from_shlib = 1;
1437 }
1438 return noErr;
1439}
1440
1441/*
1442** Insert the library resources into the search path. Put them after
1443** the resources from the application. Again, we ignore errors.
1444*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001445static
Jack Jansen34cc5c31995-10-31 16:15:12 +00001446mac_addlibresources()
1447{
1448 if ( !loaded_from_shlib )
1449 return;
1450 (void)FSpOpenResFile(&library_fss, fsRdPerm);
1451}
1452
Guido van Rossumec22c921996-02-25 04:50:29 +00001453#endif /* GENERATINGCFM */
1454#endif /* macintosh */