blob: 5f5b859e34b25da1f25f80142d927d52e3b7d33f [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 Rossum7ffa7611996-08-13 21:10:16 +000028/* TCL/TK VERSION INFO:
29
30 Unix:
31 This should work with any version from Tcl 4.0 / Tck 7.4.
32 Do not use older versions.
33
34 Mac and Windows:
35 Use Tcl 4.1p1 / Tk 7.5p1 or possibly newer.
36 It does not seem to work reliably with the original 4.1/7.5
37 release. (4.0/7.4 were never released for these platforms.)
38*/
39
Guido van Rossum9722ad81995-09-22 23:49:28 +000040#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000041#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000042
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000043#ifdef macintosh
44#define MAC_TCL
45#endif
46
Guido van Rossum18468821994-06-20 07:49:28 +000047#include <tcl.h>
48#include <tk.h>
49
Guido van Rossum32aa1a71996-07-31 19:51:15 +000050extern char *Py_GetProgramName ();
Guido van Rossumd308e2b1994-07-07 09:25:12 +000051
Guido van Rossum9722ad81995-09-22 23:49:28 +000052/* Internal declarations from tkInt.h. */
53#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
54extern int Tk_GetNumMainWindows();
55#else
Guido van Rossum18468821994-06-20 07:49:28 +000056extern int tk_NumMainWindows;
Guido van Rossum9722ad81995-09-22 23:49:28 +000057#define Tk_GetNumMainWindows() (tk_NumMainWindows)
Guido van Rossumdfd428d1996-02-25 04:46:40 +000058#define NEED_TKCREATEMAINWINDOW 1
Guido van Rossum9722ad81995-09-22 23:49:28 +000059#endif
60
61#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +000062extern struct { Tk_Window win; } *tkMainWindowList;
Guido van Rossum9722ad81995-09-22 23:49:28 +000063#endif
Guido van Rossum18468821994-06-20 07:49:28 +000064
Guido van Rossumec22c921996-02-25 04:50:29 +000065#ifdef macintosh
66
67/*
68** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +000069** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +000070*/
71
Guido van Rossum7ffa7611996-08-13 21:10:16 +000072/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +000073#define FREECAST (char *)
74
Guido van Rossumec22c921996-02-25 04:50:29 +000075#include <Events.h> /* For EventRecord */
76
77typedef int (*TclMacConvertEventPtr) Py_PROTO((EventRecord *eventPtr));
78void TclMacSetEventProc Py_PROTO((TclMacConvertEventPtr procPtr));
79int TkMacConvertEvent Py_PROTO((EventRecord *eventPtr));
80
81staticforward int PyMacConvertEvent Py_PROTO((EventRecord *eventPtr));
82
83#endif /* macintosh */
84
Guido van Rossum97867b21996-08-08 19:09:53 +000085#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +000086#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +000087#endif
88
Guido van Rossum18468821994-06-20 07:49:28 +000089/**** Tkapp Object Declaration ****/
90
91staticforward PyTypeObject Tkapp_Type;
92
93typedef struct
94 {
95 PyObject_HEAD
96 Tcl_Interp *interp;
Guido van Rossumdfd428d1996-02-25 04:46:40 +000097#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +000098 Tk_Window tkwin;
Guido van Rossumdfd428d1996-02-25 04:46:40 +000099#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000100 }
101TkappObject;
102
103#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000104#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +0000105#define Tkapp_Tkwin(v) (((TkappObject *) (v))->tkwin)
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000106#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000107#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
108#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
109
110#define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
111 (void *) v, ((PyObject *) v)->ob_refcnt))
112
113/**** Error Handling ****/
114
115static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000116static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000117static int errorInCmd = 0;
118static PyObject *excInCmd;
119static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000120static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000121
122static PyObject *
123Tkinter_Error (v)
124 PyObject *v;
125{
Guido van Rossum18468821994-06-20 07:49:28 +0000126 PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
127 return NULL;
128}
129
130int
131PythonCmd_Error (interp)
132 Tcl_Interp *interp;
133{
134 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000135 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000136 return TCL_ERROR;
137}
138
139/**** Utils ****/
140
141static char *
142AsString (value, tmp)
143 PyObject *value;
144 PyObject *tmp;
145{
146 if (PyString_Check (value))
147 return PyString_AsString (value);
148 else
149 {
150 PyObject *v;
151
Guido van Rossumcd938fc1995-01-17 16:13:48 +0000152 v = PyObject_Str (value);
Guido van Rossum18468821994-06-20 07:49:28 +0000153 PyList_Append (tmp, v);
154 Py_DECREF (v);
155 return PyString_AsString (v);
156 }
157}
158
159#define ARGSZ 64
160
161static char *
162Merge (args)
163 PyObject *args;
164{
165 PyObject *tmp;
166 char *argvStore[ARGSZ];
167 char **argv;
168 int fvStore[ARGSZ];
169 int *fv;
170 int argc;
171 char *res;
172 int i;
173
174 tmp = PyList_New (0);
175 argv = argvStore;
176 fv = fvStore;
177
Guido van Rossum845547d1996-06-26 18:26:04 +0000178 if (args == NULL)
179 {
180 argc = 0;
181 }
182 else if (!PyTuple_Check (args))
Guido van Rossum18468821994-06-20 07:49:28 +0000183 {
184 argc = 1;
185 fv[0] = 0;
186 argv[0] = AsString (args, tmp);
187 }
188 else
189 {
190 PyObject *v;
191
192 if (PyTuple_Size (args) > ARGSZ)
193 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000194 argv = (char **) ckalloc (PyTuple_Size (args) * sizeof (char *));
195 fv = (int *) ckalloc (PyTuple_Size (args) * sizeof (int));
Guido van Rossum18468821994-06-20 07:49:28 +0000196 if (argv == NULL || fv == NULL)
197 PyErr_NoMemory ();
198 }
199
200 argc = PyTuple_Size (args);
201 for (i = 0; i < argc; i++)
202 {
203 v = PyTuple_GetItem (args, i);
204 if (PyTuple_Check (v))
205 {
206 fv[i] = 1;
207 argv[i] = Merge (v);
208 }
209 else if (v == Py_None)
210 {
211 argc = i;
212 break;
213 }
214 else
215 {
216 fv[i] = 0;
217 argv[i] = AsString (v, tmp);
218 }
219 }
220 }
221
222 res = Tcl_Merge (argc, argv);
223
224 Py_DECREF (tmp);
225 for (i = 0; i < argc; i++)
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000226 if (fv[i]) ckfree (argv[i]);
Guido van Rossum18468821994-06-20 07:49:28 +0000227 if (argv != argvStore)
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000228 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000229 if (fv != fvStore)
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000230 ckfree (FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000231
232 return res;
233}
234
235static PyObject *
236Split (self, list)
237 PyObject *self;
238 char *list;
239{
240 int argc;
241 char **argv;
242 PyObject *v;
243
244 if (list == NULL)
245 {
246 Py_INCREF (Py_None);
247 return Py_None;
248 }
249
250 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
251 return Tkinter_Error (self);
252
253 if (argc == 0)
254 v = PyString_FromString ("");
255 else if (argc == 1)
256 v = PyString_FromString (argv[0]);
257 else
258 {
259 int i;
260
261 v = PyTuple_New (argc);
262 for (i = 0; i < argc; i++)
263 PyTuple_SetItem (v, i, Split (self, argv[i]));
264 }
265
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000266 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000267 return v;
268}
269
270/**** Tkapp Object ****/
271
272#ifndef WITH_APPINIT
273int
274Tcl_AppInit (interp)
275 Tcl_Interp *interp;
276{
Guido van Rossumec22c921996-02-25 04:50:29 +0000277 Tk_Window main;
278
279 main = Tk_MainWindow(interp);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000280 if (Tcl_Init (interp) == TCL_ERROR) {
281 fprintf(stderr, "Tcl_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000282 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000283 }
284 if (Tk_Init (interp) == TCL_ERROR) {
285 fprintf(stderr, "Tk_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000286 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000287 }
Guido van Rossum18468821994-06-20 07:49:28 +0000288 return TCL_OK;
289}
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000290
Guido van Rossum18468821994-06-20 07:49:28 +0000291#endif /* !WITH_APPINIT */
292
293/* Initialize the Tk application; see the `main' function in
294 `tkMain.c'. */
295static TkappObject *
296Tkapp_New (screenName, baseName, className, interactive)
297 char *screenName;
298 char *baseName;
299 char *className;
300 int interactive;
301{
302 TkappObject *v;
Guido van Rossum97867b21996-08-08 19:09:53 +0000303 char *argv0;
Guido van Rossum18468821994-06-20 07:49:28 +0000304
305 v = PyObject_NEW (TkappObject, &Tkapp_Type);
306 if (v == NULL)
307 return NULL;
308
309 v->interp = Tcl_CreateInterp ();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000310
311#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +0000312 v->tkwin = Tk_CreateMainWindow (v->interp, screenName,
313 baseName, className);
314 if (v->tkwin == NULL)
315 return (TkappObject *) Tkinter_Error ((PyObject *) v);
316
317 Tk_GeometryRequest (v->tkwin, 200, 200);
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000318#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000319
320 if (screenName != NULL)
321 Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
322
323 if (interactive)
324 Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
325 else
326 Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
327
Guido van Rossum97867b21996-08-08 19:09:53 +0000328 /* This is used to get the application class for Tk 4.1 and up */
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000329 argv0 = (char*) ckalloc (strlen (className) + 1);
Guido van Rossum97867b21996-08-08 19:09:53 +0000330 if (argv0 != NULL) {
331 strcpy (argv0, className);
332 if (isupper (argv0[0]))
333 argv0[0] = tolower (argv0[0]);
334 Tcl_SetVar (v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000335 ckfree (argv0);
Guido van Rossum97867b21996-08-08 19:09:53 +0000336 }
337
Guido van Rossum18468821994-06-20 07:49:28 +0000338 if (Tcl_AppInit (v->interp) != TCL_OK)
Guido van Rossum845547d1996-06-26 18:26:04 +0000339 return (TkappObject *) Tkinter_Error (v);
Guido van Rossum18468821994-06-20 07:49:28 +0000340
341 return v;
342}
343
344/** Tcl Eval **/
345
346static PyObject *
347Tkapp_Call (self, args)
348 PyObject *self;
349 PyObject *args;
350{
351 char *cmd;
352
353 cmd = Merge (args);
354 if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
355 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000356 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000357 return Tkinter_Error (self);
358 }
359
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000360 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000361 return PyString_FromString (Tkapp_Result (self));
362}
363
364static PyObject *
365Tkapp_GlobalCall (self, args)
366 PyObject *self;
367 PyObject *args;
368{
369 char *cmd;
370
371 cmd = Merge (args);
372 if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
373 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000374 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000375 return Tkinter_Error (self);
376 }
377
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000378 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000379 return PyString_FromString (Tkapp_Result (self));
380}
381
382static PyObject *
383Tkapp_Eval (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_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
393 return Tkinter_Error (self);
394
395 return PyString_FromString (Tkapp_Result (self));
396}
397
398static PyObject *
399Tkapp_GlobalEval (self, args)
400 PyObject *self;
401 PyObject *args;
402{
403 char *script;
404
405 if (!PyArg_Parse (args, "s", &script))
406 return NULL;
407
408 if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
409 return Tkinter_Error (self);
410
411 return PyString_FromString (Tkapp_Result (self));
412}
413
414static PyObject *
415Tkapp_EvalFile (self, args)
416 PyObject *self;
417 PyObject *args;
418{
419 char *fileName;
420
421 if (!PyArg_Parse (args, "s", &fileName))
422 return NULL;
423
424 if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
425 return Tkinter_Error (self);
426
427 return PyString_FromString (Tkapp_Result (self));
428}
429
430static PyObject *
431Tkapp_Record (self, args)
432 PyObject *self;
433 PyObject *args;
434{
435 char *script;
436
437 if (!PyArg_Parse (args, "s", &script))
438 return NULL;
439
440 if (Tcl_RecordAndEval (Tkapp_Interp (self),
441 script, TCL_NO_EVAL) == TCL_ERROR)
442 return Tkinter_Error (self);
443
444 return PyString_FromString (Tkapp_Result (self));
445}
446
447static PyObject *
448Tkapp_AddErrorInfo (self, args)
449 PyObject *self;
450 PyObject *args;
451{
452 char *msg;
453
454 if (!PyArg_Parse (args, "s", &msg))
455 return NULL;
456 Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
457
458 Py_INCREF(Py_None);
459 return Py_None;
460}
461
462/** Tcl Variable **/
463
464static PyObject *
465SetVar (self, args, flags)
466 PyObject *self;
467 PyObject *args;
468 int flags;
469{
470 char *name1, *name2, *ok;
471 PyObject *newValue;
472 PyObject *tmp;
473
474 tmp = PyList_New (0);
475
476 if (PyArg_Parse (args, "(sO)", &name1, &newValue))
477 ok = Tcl_SetVar (Tkapp_Interp (self), name1,
478 AsString (newValue, tmp), flags); /* XXX Merge? */
479 else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
480 ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,
481 AsString (newValue, tmp), flags);
482 else
483 {
484 Py_DECREF (tmp);
485 return NULL;
486 }
487 Py_DECREF (tmp);
488
489 if (!ok)
490 return Tkinter_Error (self);
491
492 Py_INCREF (Py_None);
493 return Py_None;
494}
495
496static PyObject *
497Tkapp_SetVar (self, args)
498 PyObject *self;
499 PyObject *args;
500{
501 return SetVar (self, args, TCL_LEAVE_ERR_MSG);
502}
503
504static PyObject *
505Tkapp_GlobalSetVar (self, args)
506 PyObject *self;
507 PyObject *args;
508{
509 return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
510}
511
512static PyObject *
513GetVar (self, args, flags)
514 PyObject *self;
515 PyObject *args;
516 int flags;
517{
518 char *name1, *name2, *s;
519
520 if (PyArg_Parse (args, "s", &name1))
521 s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
522 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
523 s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
524 else
525 return NULL;
526
527 if (s == NULL)
528 return Tkinter_Error (self);
529
530 return PyString_FromString (s);
531}
532
533static PyObject *
534Tkapp_GetVar (self, args)
535 PyObject *self;
536 PyObject *args;
537{
538 return GetVar (self, args, TCL_LEAVE_ERR_MSG);
539}
540
541static PyObject *
542Tkapp_GlobalGetVar (self, args)
543 PyObject *self;
544 PyObject *args;
545{
546 return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
547}
548
549static PyObject *
550UnsetVar (self, args, flags)
551 PyObject *self;
552 PyObject *args;
553 int flags;
554{
555 char *name1, *name2;
556 int code;
557
558 if (PyArg_Parse (args, "s", &name1))
559 code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
560 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
561 code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
562 else
563 return NULL;
564
565 if (code == TCL_ERROR)
566 return Tkinter_Error (self);
567
568 Py_INCREF (Py_None);
569 return Py_None;
570}
571
572static PyObject *
573Tkapp_UnsetVar (self, args)
574 PyObject *self;
575 PyObject *args;
576{
577 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
578}
579
580static PyObject *
581Tkapp_GlobalUnsetVar (self, args)
582 PyObject *self;
583 PyObject *args;
584{
585 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
586}
587
588/** Tcl to Python **/
589
590static PyObject *
591Tkapp_GetInt (self, args)
592 PyObject *self;
593 PyObject *args;
594{
595 char *s;
596 int v;
597
598 if (!PyArg_Parse (args, "s", &s))
599 return NULL;
600 if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
601 return Tkinter_Error (self);
602 return Py_BuildValue ("i", v);
603}
604
605static PyObject *
606Tkapp_GetDouble (self, args)
607 PyObject *self;
608 PyObject *args;
609{
610 char *s;
611 double v;
612
613 if (!PyArg_Parse (args, "s", &s))
614 return NULL;
615 if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
616 return Tkinter_Error (self);
617 return Py_BuildValue ("d", v);
618}
619
620static PyObject *
621Tkapp_GetBoolean (self, args)
622 PyObject *self;
623 PyObject *args;
624{
625 char *s;
626 int v;
627
628 if (!PyArg_Parse (args, "s", &s))
629 return NULL;
630 if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
631 return Tkinter_Error (self);
632 return Py_BuildValue ("i", v);
633}
634
635static PyObject *
636Tkapp_ExprString (self, args)
637 PyObject *self;
638 PyObject *args;
639{
640 char *s;
641
642 if (!PyArg_Parse (args, "s", &s))
643 return NULL;
644 if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
645 return Tkinter_Error (self);
646 return Py_BuildValue ("s", Tkapp_Result (self));
647}
648
649static PyObject *
650Tkapp_ExprLong (self, args)
651 PyObject *self;
652 PyObject *args;
653{
654 char *s;
655 long v;
656
657 if (!PyArg_Parse (args, "s", &s))
658 return NULL;
659 if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
660 return Tkinter_Error (self);
661 return Py_BuildValue ("l", v);
662}
663
664static PyObject *
665Tkapp_ExprDouble (self, args)
666 PyObject *self;
667 PyObject *args;
668{
669 char *s;
670 double v;
671
672 if (!PyArg_Parse (args, "s", &s))
673 return NULL;
674 if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
675 return Tkinter_Error (self);
676 return Py_BuildValue ("d", v);
677}
678
679static PyObject *
680Tkapp_ExprBoolean (self, args)
681 PyObject *self;
682 PyObject *args;
683{
684 char *s;
685 int v;
686
687 if (!PyArg_Parse (args, "s", &s))
688 return NULL;
689 if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
690 return Tkinter_Error (self);
691 return Py_BuildValue ("i", v);
692}
693
694static PyObject *
695Tkapp_SplitList (self, args)
696 PyObject *self;
697 PyObject *args;
698{
699 char *list;
700 int argc;
701 char **argv;
702 PyObject *v;
703 int i;
704
705 if (!PyArg_Parse (args, "s", &list))
706 return NULL;
707
708 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
709 return Tkinter_Error (self);
710
711 v = PyTuple_New (argc);
712 for (i = 0; i < argc; i++)
713 PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
714
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000715 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000716 return v;
717}
718
719static PyObject *
720Tkapp_Split (self, args)
721 PyObject *self;
722 PyObject *args;
723{
724 char *list;
725
726 if (!PyArg_Parse (args, "s", &list))
727 return NULL;
728 return Split (self, list);
729}
730
731static PyObject *
732Tkapp_Merge (self, args)
733 PyObject *self;
734 PyObject *args;
735{
736 char *s;
737 PyObject *v;
738
739 s = Merge (args);
740 v = PyString_FromString (s);
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000741 ckfree (s);
Guido van Rossum18468821994-06-20 07:49:28 +0000742 return v;
743}
744
745/** Tcl Command **/
746
747/* This is the Tcl command that acts as a wrapper for Python
748 function or method. */
749static int
750PythonCmd (clientData, interp, argc, argv)
751 ClientData clientData; /* Is (self, func) */
752 Tcl_Interp *interp;
753 int argc;
754 char *argv[];
755{
756 PyObject *self, *func, *arg, *res, *tmp;
757 int i;
758
759 self = PyTuple_GetItem ((PyObject *) clientData, 0);
760 func = PyTuple_GetItem ((PyObject *) clientData, 1);
761
762 /* Create argument list (argv1, ..., argvN) */
763 arg = PyTuple_New (argc - 1);
764 for (i = 0; i < (argc - 1); i++)
765 PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
766
767 res = PyEval_CallObject (func, arg);
768 Py_DECREF (arg);
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000769
Guido van Rossum18468821994-06-20 07:49:28 +0000770 if (res == NULL)
771 return PythonCmd_Error (interp);
772
773 tmp = PyList_New (0);
774 Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
775 Py_DECREF (res);
776 Py_DECREF (tmp);
777
778 return TCL_OK;
779}
780
781static void
782PythonCmdDelete (clientData)
783 ClientData clientData; /* Is (self, func) */
784{
785 Py_DECREF ((PyObject *) clientData);
786}
787
788static PyObject *
789Tkapp_CreateCommand (self, args)
790 PyObject *self;
791 PyObject *args;
792{
793 char *cmdName;
794 PyObject *data;
795 PyObject *func;
796
797 /* Args is: (cmdName, func) */
798 if (!PyTuple_Check (args)
799 || !(PyTuple_Size (args) == 2)
800 || !PyString_Check (PyTuple_GetItem (args, 0))
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000801 || !PyCallable_Check (PyTuple_GetItem (args, 1)))
Guido van Rossum18468821994-06-20 07:49:28 +0000802 {
803 PyErr_SetString (PyExc_TypeError, "bad argument list");
804 return NULL;
805 }
806
807 cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
808 func = PyTuple_GetItem (args, 1);
809
810 data = PyTuple_New (2); /* ClientData is: (self, func) */
811
812 Py_INCREF (self);
813 PyTuple_SetItem (data, 0, self);
814
815 Py_INCREF (func);
816 PyTuple_SetItem (data, 1, func);
817
818 Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
819 (ClientData) data, PythonCmdDelete);
820
821 Py_INCREF (Py_None);
822 return Py_None;
823}
824
825static PyObject *
826Tkapp_DeleteCommand (self, args)
827 PyObject *self;
828 PyObject *args;
829{
830 char *cmdName;
831
832 if (!PyArg_Parse (args, "s", &cmdName))
833 return NULL;
834 if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
835 {
836 PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
837 return NULL;
838 }
839 Py_INCREF (Py_None);
840 return Py_None;
841}
842
843/** File Handler **/
844
Guido van Rossuma597dde1995-01-10 20:56:29 +0000845static void
Guido van Rossum18468821994-06-20 07:49:28 +0000846FileHandler (clientData, mask)
Guido van Rossum76875221994-06-27 07:59:42 +0000847 ClientData clientData; /* Is: (func, file) */
Guido van Rossum18468821994-06-20 07:49:28 +0000848 int mask;
849{
Guido van Rossum76875221994-06-27 07:59:42 +0000850 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +0000851
Guido van Rossum76875221994-06-27 07:59:42 +0000852 func = PyTuple_GetItem ((PyObject *) clientData, 0);
853 file = PyTuple_GetItem ((PyObject *) clientData, 1);
Guido van Rossum18468821994-06-20 07:49:28 +0000854
Guido van Rossum76875221994-06-27 07:59:42 +0000855 arg = Py_BuildValue ("(Oi)", file, (long) mask);
Guido van Rossum18468821994-06-20 07:49:28 +0000856 res = PyEval_CallObject (func, arg);
857 Py_DECREF (arg);
858 if (res == NULL)
859 {
860 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000861 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000862 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000863 Py_XDECREF (res);
864}
865
866static int
867GetFileNo (file)
868 PyObject *file; /* Either an int >= 0 or an object with a
869 .fileno() method that returns an int >= 0 */
870{
Guido van Rossuma597dde1995-01-10 20:56:29 +0000871 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000872 int id;
873 if (PyInt_Check(file)) {
874 id = PyInt_AsLong(file);
875 if (id < 0)
876 PyErr_SetString(PyExc_ValueError, "invalid file id");
877 return id;
878 }
879 meth = PyObject_GetAttrString(file, "fileno");
880 if (meth == NULL)
881 return -1;
882 args = PyTuple_New(0);
883 if (args == NULL)
884 return -1;
885 res = PyEval_CallObject(meth, args);
886 Py_DECREF(args);
887 Py_DECREF(meth);
888 if (res == NULL)
889 return -1;
890 if (PyInt_Check(res))
891 id = PyInt_AsLong(res);
892 else
893 id = -1;
894 if (id < 0)
895 PyErr_SetString(PyExc_ValueError,
896 "invalid fileno() return value");
897 Py_DECREF(res);
898 return id;
Guido van Rossum18468821994-06-20 07:49:28 +0000899}
900
901static PyObject *
902Tkapp_CreateFileHandler (self, args)
903 PyObject *self;
904 PyObject *args; /* Is (file, mask, func) */
905{
Guido van Rossum76875221994-06-27 07:59:42 +0000906 PyObject *file, *func, *data;
907 int mask, id;
Guido van Rossum68784361996-05-16 17:17:31 +0000908#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
909 Tcl_File tfile;
910#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000911
912 if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
913 return NULL;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000914 id = GetFileNo (file);
915 if (id < 0)
916 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000917 if (!PyCallable_Check(func))
Guido van Rossum18468821994-06-20 07:49:28 +0000918 {
919 PyErr_SetString (PyExc_TypeError, "bad argument list");
920 return NULL;
921 }
922
Guido van Rossum76875221994-06-27 07:59:42 +0000923 /* ClientData is: (func, file) */
924 data = Py_BuildValue ("(OO)", func, file);
925
Guido van Rossum68784361996-05-16 17:17:31 +0000926#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum07886d01996-09-11 23:31:42 +0000927#ifdef MS_WINDOWS
Guido van Rossum845547d1996-06-26 18:26:04 +0000928 /* We assume this is a socket... */
929 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
930#else
Guido van Rossum68784361996-05-16 17:17:31 +0000931 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
Guido van Rossum845547d1996-06-26 18:26:04 +0000932#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000933 /* Oughtta check for null Tcl_File object... */
934 Tcl_CreateFileHandler (tfile, mask, FileHandler, (ClientData) data);
935#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000936 Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
Guido van Rossum68784361996-05-16 17:17:31 +0000937#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000938 /* XXX fileHandlerDict */
Guido van Rossum76875221994-06-27 07:59:42 +0000939
Guido van Rossum18468821994-06-20 07:49:28 +0000940 Py_INCREF (Py_None);
941 return Py_None;
942}
943
944static PyObject *
945Tkapp_DeleteFileHandler (self, args)
946 PyObject *self;
947 PyObject *args; /* Args: file */
948{
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000949 PyObject *file;
Guido van Rossum18468821994-06-20 07:49:28 +0000950 int id;
Guido van Rossum68784361996-05-16 17:17:31 +0000951#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
952 Tcl_File tfile;
953#endif
954
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000955 if (!PyArg_Parse (args, "O", &file))
956 return NULL;
957 id = GetFileNo (file);
958 if (id < 0)
959 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000960
Guido van Rossum68784361996-05-16 17:17:31 +0000961#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum07886d01996-09-11 23:31:42 +0000962#ifdef MS_WINDOWS
Guido van Rossum845547d1996-06-26 18:26:04 +0000963 /* We assume this is a socket... */
964 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
965#else
966 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
967#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000968 /* Oughtta check for null Tcl_File object... */
969 Tcl_DeleteFileHandler(tfile);
970#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000971 Tk_DeleteFileHandler (id);
Guido van Rossum68784361996-05-16 17:17:31 +0000972#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000973 /* XXX fileHandlerDict */
974 Py_INCREF (Py_None);
975 return Py_None;
976}
977
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000978/**** Tktt Object (timer token) ****/
979
980staticforward PyTypeObject Tktt_Type;
981
982typedef struct
983 {
984 PyObject_HEAD
985 Tk_TimerToken token;
986 PyObject *func;
987 }
988TkttObject;
989
990static PyObject *
991Tktt_DeleteTimerHandler (self, args)
992 PyObject *self;
993 PyObject *args;
994{
995 TkttObject *v = (TkttObject *) self;
996
997 if (!PyArg_Parse (args, ""))
998 return NULL;
999 if (v->func != NULL)
1000 {
1001 Tk_DeleteTimerHandler (v->token);
1002 PyMem_DEL (v->func);
1003 v->func = NULL;
1004 }
1005 Py_INCREF (Py_None);
1006 return Py_None;
1007}
1008
1009static PyMethodDef Tktt_methods[] =
1010{
1011 {"deletetimerhandler", Tktt_DeleteTimerHandler},
1012 {NULL, NULL}
1013};
1014
1015static TkttObject *
1016Tktt_New (token, func)
1017 Tk_TimerToken token;
1018 PyObject *func;
1019{
1020 TkttObject *v;
1021
1022 v = PyObject_NEW (TkttObject, &Tktt_Type);
1023 if (v == NULL)
1024 return NULL;
1025
1026 v->token = token;
1027 v->func = func;
1028 Py_INCREF (v->func);
1029 return v;
1030}
1031
1032static void
1033Tktt_Dealloc (self)
1034 PyObject *self;
1035{
1036 PyMem_DEL (self);
1037}
1038
1039static int
1040Tktt_Print (self, fp, flags)
1041 PyObject *self;
1042 FILE *fp;
1043 int flags;
1044{
1045 TkttObject *v = (TkttObject *) self;
1046
1047 fprintf(fp, "<tktimertoken at 0x%x%s>", v,
1048 v->func == NULL ? ", handler deleted" : "");
1049 return 0;
1050}
1051
1052static PyObject *
1053Tktt_GetAttr (self, name)
1054 PyObject *self;
1055 char *name;
1056{
1057 return Py_FindMethod (Tktt_methods, self, name);
1058}
1059
1060static PyTypeObject Tktt_Type =
1061{
Guido van Rossumae92f011996-08-21 19:03:36 +00001062 PyObject_HEAD_INIT (NULL)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001063 0, /*ob_size */
1064 "tktimertoken", /*tp_name */
1065 sizeof (TkttObject), /*tp_basicsize */
1066 0, /*tp_itemsize */
1067 Tktt_Dealloc, /*tp_dealloc */
1068 Tktt_Print, /*tp_print */
1069 Tktt_GetAttr, /*tp_getattr */
1070 0, /*tp_setattr */
1071 0, /*tp_compare */
1072 0, /*tp_repr */
1073 0, /*tp_as_number */
1074 0, /*tp_as_sequence */
1075 0, /*tp_as_mapping */
1076 0, /*tp_hash */
1077};
1078
1079/** Timer Handler **/
1080
1081static void
1082TimerHandler (clientData)
1083 ClientData clientData;
1084{
1085 PyObject *func = (PyObject *) clientData;
1086 PyObject *arg, *res;
1087
1088 arg = PyTuple_New (0);
1089 res = PyEval_CallObject (func, arg);
1090 Py_DECREF (arg);
1091 if (res == NULL)
1092 {
1093 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001094 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001095 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001096 else
1097 Py_DECREF (res);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001098}
1099
1100static PyObject *
1101Tkapp_CreateTimerHandler (self, args)
1102 PyObject *self;
1103 PyObject *args; /* Is (milliseconds, func) */
1104{
1105 int milliseconds;
1106 PyObject *func;
1107 Tk_TimerToken token;
1108
1109 if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
1110 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001111 if (!PyCallable_Check(func))
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001112 {
1113 PyErr_SetString (PyExc_TypeError, "bad argument list");
1114 return NULL;
1115 }
1116 token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
1117 return (PyObject *) Tktt_New (token, func);
1118}
1119
Guido van Rossum18468821994-06-20 07:49:28 +00001120/** Event Loop **/
1121
Guido van Rossum18468821994-06-20 07:49:28 +00001122static PyObject *
1123Tkapp_MainLoop (self, args)
1124 PyObject *self;
1125 PyObject *args;
1126{
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001127 int threshold = 0;
1128
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001129 if (!PyArg_ParseTuple (args, "|i", &threshold))
1130 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001131
1132 quitMainLoop = 0;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001133 while (Tk_GetNumMainWindows() > threshold && !quitMainLoop && !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001134 {
1135 if (PyOS_InterruptOccurred ())
1136 {
1137 PyErr_SetNone (PyExc_KeyboardInterrupt);
1138 return NULL;
1139 }
1140 Tk_DoOneEvent (0);
1141 }
Guido van Rossum64b24fb1995-09-30 17:00:24 +00001142 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001143
1144 if (errorInCmd)
1145 {
1146 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001147 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1148 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001149 return NULL;
1150 }
1151 Py_INCREF (Py_None);
1152 return Py_None;
1153}
1154
1155static PyObject *
Guido van Rossum062cfb01995-01-10 17:42:51 +00001156Tkapp_DoOneEvent (self, args)
1157 PyObject *self;
1158 PyObject *args;
1159{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001160 int flags = TK_ALL_EVENTS;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001161 int rv;
1162
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001163 if (!PyArg_ParseTuple (args, "|i", &flags))
1164 return NULL;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001165 rv = Tk_DoOneEvent(flags);
1166 return Py_BuildValue ("i", rv);
1167}
1168
1169static PyObject *
Guido van Rossum18468821994-06-20 07:49:28 +00001170Tkapp_Quit (self, args)
1171 PyObject *self;
1172 PyObject *args;
1173{
1174
1175 if (!PyArg_Parse (args, ""))
1176 return NULL;
1177 quitMainLoop = 1;
1178 Py_INCREF (Py_None);
1179 return Py_None;
1180}
1181
1182/**** Tkapp Method List ****/
1183
1184static PyMethodDef Tkapp_methods[] =
1185{
1186 {"call", Tkapp_Call},
1187 {"globalcall", Tkapp_GlobalCall},
1188 {"eval", Tkapp_Eval},
1189 {"globaleval", Tkapp_GlobalEval},
1190 {"evalfile", Tkapp_EvalFile},
1191 {"record", Tkapp_Record},
1192 {"adderrorinfo", Tkapp_AddErrorInfo},
1193 {"setvar", Tkapp_SetVar},
1194 {"globalsetvar", Tkapp_GlobalSetVar},
1195 {"getvar", Tkapp_GetVar},
1196 {"globalgetvar", Tkapp_GlobalGetVar},
1197 {"unsetvar", Tkapp_UnsetVar},
1198 {"globalunsetvar", Tkapp_GlobalUnsetVar},
1199 {"getint", Tkapp_GetInt},
1200 {"getdouble", Tkapp_GetDouble},
1201 {"getboolean", Tkapp_GetBoolean},
1202 {"exprstring", Tkapp_ExprString},
1203 {"exprlong", Tkapp_ExprLong},
1204 {"exprdouble", Tkapp_ExprDouble},
1205 {"exprboolean", Tkapp_ExprBoolean},
1206 {"splitlist", Tkapp_SplitList},
1207 {"split", Tkapp_Split},
1208 {"merge", Tkapp_Merge},
1209 {"createcommand", Tkapp_CreateCommand},
1210 {"deletecommand", Tkapp_DeleteCommand},
1211 {"createfilehandler", Tkapp_CreateFileHandler},
1212 {"deletefilehandler", Tkapp_DeleteFileHandler},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001213 {"createtimerhandler", Tkapp_CreateTimerHandler},
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001214 {"mainloop", Tkapp_MainLoop, 1},
1215 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum18468821994-06-20 07:49:28 +00001216 {"quit", Tkapp_Quit},
1217 {NULL, NULL}
1218};
1219
1220/**** Tkapp Type Methods ****/
1221
1222static void
1223Tkapp_Dealloc (self)
1224 PyObject *self;
1225{
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001226#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +00001227 Tk_DestroyWindow (Tkapp_Tkwin (self));
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001228#endif
Guido van Rossum18468821994-06-20 07:49:28 +00001229 Tcl_DeleteInterp (Tkapp_Interp (self));
1230 PyMem_DEL (self);
1231}
1232
1233static PyObject *
1234Tkapp_GetAttr (self, name)
1235 PyObject *self;
1236 char *name;
1237{
1238 return Py_FindMethod (Tkapp_methods, self, name);
1239}
1240
1241static PyTypeObject Tkapp_Type =
1242{
Guido van Rossumae92f011996-08-21 19:03:36 +00001243 PyObject_HEAD_INIT (NULL)
Guido van Rossum18468821994-06-20 07:49:28 +00001244 0, /*ob_size */
1245 "tkapp", /*tp_name */
1246 sizeof (TkappObject), /*tp_basicsize */
1247 0, /*tp_itemsize */
1248 Tkapp_Dealloc, /*tp_dealloc */
1249 0, /*tp_print */
1250 Tkapp_GetAttr, /*tp_getattr */
1251 0, /*tp_setattr */
1252 0, /*tp_compare */
1253 0, /*tp_repr */
1254 0, /*tp_as_number */
1255 0, /*tp_as_sequence */
1256 0, /*tp_as_mapping */
1257 0, /*tp_hash */
1258};
1259
1260/**** Tkinter Module ****/
1261
1262static PyObject *
1263Tkinter_Create (self, args)
1264 PyObject *self;
1265 PyObject *args;
1266{
1267 char *screenName = NULL;
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001268 char *baseName = NULL;
1269 char *className = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001270 int interactive = 0;
1271
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001272 baseName = strrchr (Py_GetProgramName (), '/');
Guido van Rossum18468821994-06-20 07:49:28 +00001273 if (baseName != NULL)
1274 baseName++;
1275 else
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001276 baseName = Py_GetProgramName ();
Guido van Rossum18468821994-06-20 07:49:28 +00001277 className = "Tk";
1278
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001279 if (!PyArg_ParseTuple (args, "|zssi",
1280 &screenName, &baseName, &className, &interactive))
Guido van Rossum18468821994-06-20 07:49:28 +00001281 return NULL;
1282
1283 return (PyObject *) Tkapp_New (screenName, baseName, className,
1284 interactive);
1285}
1286
1287static PyMethodDef moduleMethods[] =
1288{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001289 {"create", Tkinter_Create, 1},
1290 {"createfilehandler", Tkapp_CreateFileHandler, 0},
1291 {"deletefilehandler", Tkapp_DeleteFileHandler, 0},
1292 {"createtimerhandler", Tkapp_CreateTimerHandler, 0},
1293 {"mainloop", Tkapp_MainLoop, 1},
1294 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001295 {"quit", Tkapp_Quit},
Guido van Rossum18468821994-06-20 07:49:28 +00001296 {NULL, NULL}
1297};
1298
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001299#undef WITH_READLINE /* XXX */
Guido van Rossum18468821994-06-20 07:49:28 +00001300#ifdef WITH_READLINE
1301static int
1302EventHook ()
1303{
1304 if (errorInCmd) /* XXX Reset tty */
1305 {
1306 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001307 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1308 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001309 PyErr_Print ();
1310 }
Guido van Rossum9722ad81995-09-22 23:49:28 +00001311 if (Tk_GetNumMainWindows() > 0)
Guido van Rossume2ca9bd1994-08-03 08:01:43 +00001312 Tk_DoOneEvent (TK_DONT_WAIT);
Guido van Rossum18468821994-06-20 07:49:28 +00001313 return 0;
1314}
1315#endif /* WITH_READLINE */
1316
1317static void
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001318Tkinter_Cleanup ()
1319{
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001320/* This segfault with Tk 4.0 beta and seems unnecessary there as well */
1321#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001322 /* XXX rl_deprep_terminal is static, damned! */
1323 while (tkMainWindowList != 0)
1324 Tk_DestroyWindow (tkMainWindowList->win);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001325#endif
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001326}
1327
Guido van Rossum18468821994-06-20 07:49:28 +00001328void
Guido van Rossumad1f7ee1996-02-13 00:11:37 +00001329init_tkinter ()
Guido van Rossum18468821994-06-20 07:49:28 +00001330{
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001331 static inited = 0;
1332
Guido van Rossum18468821994-06-20 07:49:28 +00001333#ifdef WITH_READLINE
1334 extern int (*rl_event_hook) ();
1335#endif /* WITH_READLINE */
1336 PyObject *m, *d, *v;
1337
Guido van Rossumae92f011996-08-21 19:03:36 +00001338 Tkapp_Type.ob_type = &PyType_Type;
1339 Tktt_Type.ob_type = &PyType_Type;
1340
Jack Jansenba0311e1995-10-23 14:34:14 +00001341 m = Py_InitModule ("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00001342
1343 d = PyModule_GetDict (m);
1344 Tkinter_TclError = Py_BuildValue ("s", "TclError");
1345 PyDict_SetItemString (d, "TclError", Tkinter_TclError);
1346
1347 v = Py_BuildValue ("i", TK_READABLE);
1348 PyDict_SetItemString (d, "READABLE", v);
1349 v = Py_BuildValue ("i", TK_WRITABLE);
1350 PyDict_SetItemString (d, "WRITABLE", v);
1351 v = Py_BuildValue ("i", TK_EXCEPTION);
1352 PyDict_SetItemString (d, "EXCEPTION", v);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001353 v = Py_BuildValue ("i", TK_X_EVENTS);
1354 PyDict_SetItemString (d, "X_EVENTS", v);
1355 v = Py_BuildValue ("i", TK_FILE_EVENTS);
1356 PyDict_SetItemString (d, "FILE_EVENTS", v);
1357 v = Py_BuildValue ("i", TK_TIMER_EVENTS);
1358 PyDict_SetItemString (d, "TIMER_EVENTS", v);
1359 v = Py_BuildValue ("i", TK_IDLE_EVENTS);
1360 PyDict_SetItemString (d, "IDLE_EVENTS", v);
1361 v = Py_BuildValue ("i", TK_ALL_EVENTS);
1362 PyDict_SetItemString (d, "ALL_EVENTS", v);
1363 v = Py_BuildValue ("i", TK_DONT_WAIT);
1364 PyDict_SetItemString (d, "DONT_WAIT", v);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001365 v = Py_BuildValue ("s", TK_VERSION);
1366 PyDict_SetItemString (d, "TK_VERSION", v);
1367 v = Py_BuildValue ("s", TCL_VERSION);
1368 PyDict_SetItemString (d, "TCL_VERSION", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001369
Guido van Rossum18468821994-06-20 07:49:28 +00001370#ifdef WITH_READLINE
1371 rl_event_hook = EventHook;
1372#endif /* WITH_READLINE */
1373
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001374 if (!inited)
1375 {
1376 inited = 1;
Guido van Rossume4485b01994-09-07 14:32:49 +00001377 if (Py_AtExit (Tkinter_Cleanup) != 0)
1378 fprintf(stderr,
1379 "Tkinter: warning: cleanup procedure not registered\n");
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001380 }
1381
Guido van Rossum18468821994-06-20 07:49:28 +00001382 if (PyErr_Occurred ())
Jack Jansenba0311e1995-10-23 14:34:14 +00001383 Py_FatalError ("can't initialize module _tkinter");
Jack Jansen34cc5c31995-10-31 16:15:12 +00001384#ifdef macintosh
Guido van Rossumec22c921996-02-25 04:50:29 +00001385 TclMacSetEventProc(PyMacConvertEvent);
1386#if GENERATINGCFM
Jack Jansen34cc5c31995-10-31 16:15:12 +00001387 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00001388#endif /* GENERATINGCFM */
1389#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00001390}
Guido van Rossum9722ad81995-09-22 23:49:28 +00001391
Guido van Rossumec22c921996-02-25 04:50:29 +00001392
Guido van Rossum9722ad81995-09-22 23:49:28 +00001393#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001394
1395/*
Guido van Rossumec22c921996-02-25 04:50:29 +00001396** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001397*/
1398
Guido van Rossum9722ad81995-09-22 23:49:28 +00001399void
1400panic(char * format, ...)
1401{
1402 va_list varg;
1403
1404 va_start(varg, format);
1405
1406 vfprintf(stderr, format, varg);
1407 (void) fflush(stderr);
1408
1409 va_end(varg);
1410
1411 Py_FatalError("Tcl/Tk panic");
1412}
Jack Jansen40b546d1995-11-14 10:34:45 +00001413
Guido van Rossumec22c921996-02-25 04:50:29 +00001414/*
1415** Pass events to SIOUX before passing them to Tk.
1416*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001417
Guido van Rossumec22c921996-02-25 04:50:29 +00001418static int
1419PyMacConvertEvent(eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001420 EventRecord *eventPtr;
1421{
Guido van Rossumec22c921996-02-25 04:50:29 +00001422 if (SIOUXHandleOneEvent(eventPtr))
1423 return 0; /* Nothing happened to the Tcl event queue */
1424 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001425}
1426
Guido van Rossumec22c921996-02-25 04:50:29 +00001427#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001428
1429/*
1430** Additional Mac specific code for dealing with shared libraries.
1431*/
1432
1433#include <Resources.h>
1434#include <CodeFragments.h>
1435
1436static int loaded_from_shlib = 0;
1437static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001438
Jack Jansen34cc5c31995-10-31 16:15:12 +00001439/*
1440** If this module is dynamically loaded the following routine should
1441** be the init routine. It takes care of adding the shared library to
1442** the resource-file chain, so that the tk routines can find their
1443** resources.
1444*/
1445OSErr pascal
1446init_tkinter_shlib(InitBlockPtr data)
1447{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00001448 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00001449 if ( data == nil ) return noErr;
1450 if ( data->fragLocator.where == kOnDiskFlat ) {
1451 library_fss = *data->fragLocator.u.onDisk.fileSpec;
1452 loaded_from_shlib = 1;
1453 } else if ( data->fragLocator.where == kOnDiskSegmented ) {
1454 library_fss = *data->fragLocator.u.inSegs.fileSpec;
1455 loaded_from_shlib = 1;
1456 }
1457 return noErr;
1458}
1459
1460/*
1461** Insert the library resources into the search path. Put them after
1462** the resources from the application. Again, we ignore errors.
1463*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001464static
Jack Jansen34cc5c31995-10-31 16:15:12 +00001465mac_addlibresources()
1466{
1467 if ( !loaded_from_shlib )
1468 return;
1469 (void)FSpOpenResFile(&library_fss, fsRdPerm);
1470}
1471
Guido van Rossumec22c921996-02-25 04:50:29 +00001472#endif /* GENERATINGCFM */
1473#endif /* macintosh */