blob: 10d9f9f66fafd9645bc8419e19428786352aaea2 [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
Guido van Rossumd266eb41996-10-25 14:44:06 +00008Permission to use, copy, modify, and distribute this software and its
9documentation for any purpose and without fee is hereby granted,
Guido van Rossum845547d1996-06-26 18:26:04 +000010provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000011both that copyright notice and this permission notice appear in
Guido van Rossum845547d1996-06-26 18:26:04 +000012supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000013Centrum or CWI or Corporation for National Research Initiatives or
14CNRI not be used in advertising or publicity pertaining to
15distribution of the software without specific, written prior
16permission.
Guido van Rossum845547d1996-06-26 18:26:04 +000017
Guido van Rossumd266eb41996-10-25 14:44:06 +000018While CWI is the initial source for this software, a modified version
19is made available by the Corporation for National Research Initiatives
20(CNRI) at the Internet address ftp://ftp.python.org.
21
22STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
23REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
24MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
25CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
26DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
27PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
28TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum845547d1996-06-26 18:26:04 +000030
31******************************************************************/
32
33/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +000034
Guido van Rossum7ffa7611996-08-13 21:10:16 +000035/* TCL/TK VERSION INFO:
36
37 Unix:
38 This should work with any version from Tcl 4.0 / Tck 7.4.
39 Do not use older versions.
40
41 Mac and Windows:
42 Use Tcl 4.1p1 / Tk 7.5p1 or possibly newer.
43 It does not seem to work reliably with the original 4.1/7.5
44 release. (4.0/7.4 were never released for these platforms.)
45*/
46
Guido van Rossum9722ad81995-09-22 23:49:28 +000047#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000048#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000049
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000050#ifdef macintosh
51#define MAC_TCL
52#endif
53
Guido van Rossum18468821994-06-20 07:49:28 +000054#include <tcl.h>
55#include <tk.h>
56
Guido van Rossum32aa1a71996-07-31 19:51:15 +000057extern char *Py_GetProgramName ();
Guido van Rossumd308e2b1994-07-07 09:25:12 +000058
Guido van Rossum9722ad81995-09-22 23:49:28 +000059/* Internal declarations from tkInt.h. */
60#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
61extern int Tk_GetNumMainWindows();
62#else
Guido van Rossum18468821994-06-20 07:49:28 +000063extern int tk_NumMainWindows;
Guido van Rossum9722ad81995-09-22 23:49:28 +000064#define Tk_GetNumMainWindows() (tk_NumMainWindows)
Guido van Rossumdfd428d1996-02-25 04:46:40 +000065#define NEED_TKCREATEMAINWINDOW 1
Guido van Rossum9722ad81995-09-22 23:49:28 +000066#endif
67
68#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +000069extern struct { Tk_Window win; } *tkMainWindowList;
Guido van Rossum9722ad81995-09-22 23:49:28 +000070#endif
Guido van Rossum18468821994-06-20 07:49:28 +000071
Guido van Rossumec22c921996-02-25 04:50:29 +000072#ifdef macintosh
73
74/*
75** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +000076** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +000077*/
78
Guido van Rossum7ffa7611996-08-13 21:10:16 +000079/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +000080#define FREECAST (char *)
81
Guido van Rossumec22c921996-02-25 04:50:29 +000082#include <Events.h> /* For EventRecord */
83
84typedef int (*TclMacConvertEventPtr) Py_PROTO((EventRecord *eventPtr));
85void TclMacSetEventProc Py_PROTO((TclMacConvertEventPtr procPtr));
86int TkMacConvertEvent Py_PROTO((EventRecord *eventPtr));
87
88staticforward int PyMacConvertEvent Py_PROTO((EventRecord *eventPtr));
89
90#endif /* macintosh */
91
Guido van Rossum97867b21996-08-08 19:09:53 +000092#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +000093#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +000094#endif
95
Guido van Rossum18468821994-06-20 07:49:28 +000096/**** Tkapp Object Declaration ****/
97
98staticforward PyTypeObject Tkapp_Type;
99
100typedef struct
101 {
102 PyObject_HEAD
103 Tcl_Interp *interp;
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000104#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +0000105 Tk_Window tkwin;
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000106#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000107 }
108TkappObject;
109
110#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000111#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +0000112#define Tkapp_Tkwin(v) (((TkappObject *) (v))->tkwin)
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000113#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000114#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
115#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
116
117#define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
118 (void *) v, ((PyObject *) v)->ob_refcnt))
119
120/**** Error Handling ****/
121
122static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000123static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000124static int errorInCmd = 0;
125static PyObject *excInCmd;
126static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000127static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000128
129static PyObject *
130Tkinter_Error (v)
131 PyObject *v;
132{
Guido van Rossum18468821994-06-20 07:49:28 +0000133 PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
134 return NULL;
135}
136
137int
138PythonCmd_Error (interp)
139 Tcl_Interp *interp;
140{
141 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000142 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000143 return TCL_ERROR;
144}
145
146/**** Utils ****/
147
148static char *
149AsString (value, tmp)
150 PyObject *value;
151 PyObject *tmp;
152{
153 if (PyString_Check (value))
154 return PyString_AsString (value);
155 else
156 {
157 PyObject *v;
158
Guido van Rossumcd938fc1995-01-17 16:13:48 +0000159 v = PyObject_Str (value);
Guido van Rossum18468821994-06-20 07:49:28 +0000160 PyList_Append (tmp, v);
161 Py_DECREF (v);
162 return PyString_AsString (v);
163 }
164}
165
166#define ARGSZ 64
167
168static char *
169Merge (args)
170 PyObject *args;
171{
172 PyObject *tmp;
173 char *argvStore[ARGSZ];
174 char **argv;
175 int fvStore[ARGSZ];
176 int *fv;
177 int argc;
178 char *res;
179 int i;
180
181 tmp = PyList_New (0);
182 argv = argvStore;
183 fv = fvStore;
184
Guido van Rossum845547d1996-06-26 18:26:04 +0000185 if (args == NULL)
186 {
187 argc = 0;
188 }
189 else if (!PyTuple_Check (args))
Guido van Rossum18468821994-06-20 07:49:28 +0000190 {
191 argc = 1;
192 fv[0] = 0;
193 argv[0] = AsString (args, tmp);
194 }
195 else
196 {
197 PyObject *v;
198
199 if (PyTuple_Size (args) > ARGSZ)
200 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000201 argv = (char **) ckalloc (PyTuple_Size (args) * sizeof (char *));
202 fv = (int *) ckalloc (PyTuple_Size (args) * sizeof (int));
Guido van Rossum18468821994-06-20 07:49:28 +0000203 if (argv == NULL || fv == NULL)
204 PyErr_NoMemory ();
205 }
206
207 argc = PyTuple_Size (args);
208 for (i = 0; i < argc; i++)
209 {
210 v = PyTuple_GetItem (args, i);
211 if (PyTuple_Check (v))
212 {
213 fv[i] = 1;
214 argv[i] = Merge (v);
215 }
216 else if (v == Py_None)
217 {
218 argc = i;
219 break;
220 }
221 else
222 {
223 fv[i] = 0;
224 argv[i] = AsString (v, tmp);
225 }
226 }
227 }
228
229 res = Tcl_Merge (argc, argv);
230
231 Py_DECREF (tmp);
232 for (i = 0; i < argc; i++)
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000233 if (fv[i]) ckfree (argv[i]);
Guido van Rossum18468821994-06-20 07:49:28 +0000234 if (argv != argvStore)
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000235 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000236 if (fv != fvStore)
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000237 ckfree (FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000238
239 return res;
240}
241
242static PyObject *
243Split (self, list)
244 PyObject *self;
245 char *list;
246{
247 int argc;
248 char **argv;
249 PyObject *v;
250
251 if (list == NULL)
252 {
253 Py_INCREF (Py_None);
254 return Py_None;
255 }
256
257 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
258 return Tkinter_Error (self);
259
260 if (argc == 0)
261 v = PyString_FromString ("");
262 else if (argc == 1)
263 v = PyString_FromString (argv[0]);
264 else
265 {
266 int i;
267
268 v = PyTuple_New (argc);
269 for (i = 0; i < argc; i++)
270 PyTuple_SetItem (v, i, Split (self, argv[i]));
271 }
272
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000273 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000274 return v;
275}
276
277/**** Tkapp Object ****/
278
279#ifndef WITH_APPINIT
280int
281Tcl_AppInit (interp)
282 Tcl_Interp *interp;
283{
Guido van Rossumec22c921996-02-25 04:50:29 +0000284 Tk_Window main;
285
286 main = Tk_MainWindow(interp);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000287 if (Tcl_Init (interp) == TCL_ERROR) {
288 fprintf(stderr, "Tcl_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000289 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000290 }
291 if (Tk_Init (interp) == TCL_ERROR) {
292 fprintf(stderr, "Tk_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000293 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000294 }
Guido van Rossum18468821994-06-20 07:49:28 +0000295 return TCL_OK;
296}
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000297
Guido van Rossum18468821994-06-20 07:49:28 +0000298#endif /* !WITH_APPINIT */
299
300/* Initialize the Tk application; see the `main' function in
301 `tkMain.c'. */
302static TkappObject *
303Tkapp_New (screenName, baseName, className, interactive)
304 char *screenName;
305 char *baseName;
306 char *className;
307 int interactive;
308{
309 TkappObject *v;
Guido van Rossum97867b21996-08-08 19:09:53 +0000310 char *argv0;
Guido van Rossum18468821994-06-20 07:49:28 +0000311
312 v = PyObject_NEW (TkappObject, &Tkapp_Type);
313 if (v == NULL)
314 return NULL;
315
316 v->interp = Tcl_CreateInterp ();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000317
318#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +0000319 v->tkwin = Tk_CreateMainWindow (v->interp, screenName,
320 baseName, className);
321 if (v->tkwin == NULL)
322 return (TkappObject *) Tkinter_Error ((PyObject *) v);
323
324 Tk_GeometryRequest (v->tkwin, 200, 200);
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000325#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000326
327 if (screenName != NULL)
328 Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
329
330 if (interactive)
331 Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
332 else
333 Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
334
Guido van Rossum97867b21996-08-08 19:09:53 +0000335 /* This is used to get the application class for Tk 4.1 and up */
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000336 argv0 = (char*) ckalloc (strlen (className) + 1);
Guido van Rossum97867b21996-08-08 19:09:53 +0000337 if (argv0 != NULL) {
338 strcpy (argv0, className);
339 if (isupper (argv0[0]))
340 argv0[0] = tolower (argv0[0]);
341 Tcl_SetVar (v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000342 ckfree (argv0);
Guido van Rossum97867b21996-08-08 19:09:53 +0000343 }
344
Guido van Rossum18468821994-06-20 07:49:28 +0000345 if (Tcl_AppInit (v->interp) != TCL_OK)
Guido van Rossum845547d1996-06-26 18:26:04 +0000346 return (TkappObject *) Tkinter_Error (v);
Guido van Rossum18468821994-06-20 07:49:28 +0000347
348 return v;
349}
350
351/** Tcl Eval **/
352
353static PyObject *
354Tkapp_Call (self, args)
355 PyObject *self;
356 PyObject *args;
357{
358 char *cmd;
359
360 cmd = Merge (args);
361 if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
362 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000363 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000364 return Tkinter_Error (self);
365 }
366
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000367 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000368 return PyString_FromString (Tkapp_Result (self));
369}
370
371static PyObject *
372Tkapp_GlobalCall (self, args)
373 PyObject *self;
374 PyObject *args;
375{
376 char *cmd;
377
378 cmd = Merge (args);
379 if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
380 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000381 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000382 return Tkinter_Error (self);
383 }
384
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000385 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000386 return PyString_FromString (Tkapp_Result (self));
387}
388
389static PyObject *
390Tkapp_Eval (self, args)
391 PyObject *self;
392 PyObject *args;
393{
394 char *script;
395
396 if (!PyArg_Parse (args, "s", &script))
397 return NULL;
398
399 if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
400 return Tkinter_Error (self);
401
402 return PyString_FromString (Tkapp_Result (self));
403}
404
405static PyObject *
406Tkapp_GlobalEval (self, args)
407 PyObject *self;
408 PyObject *args;
409{
410 char *script;
411
412 if (!PyArg_Parse (args, "s", &script))
413 return NULL;
414
415 if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
416 return Tkinter_Error (self);
417
418 return PyString_FromString (Tkapp_Result (self));
419}
420
421static PyObject *
422Tkapp_EvalFile (self, args)
423 PyObject *self;
424 PyObject *args;
425{
426 char *fileName;
427
428 if (!PyArg_Parse (args, "s", &fileName))
429 return NULL;
430
431 if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
432 return Tkinter_Error (self);
433
434 return PyString_FromString (Tkapp_Result (self));
435}
436
437static PyObject *
438Tkapp_Record (self, args)
439 PyObject *self;
440 PyObject *args;
441{
442 char *script;
443
444 if (!PyArg_Parse (args, "s", &script))
445 return NULL;
446
447 if (Tcl_RecordAndEval (Tkapp_Interp (self),
448 script, TCL_NO_EVAL) == TCL_ERROR)
449 return Tkinter_Error (self);
450
451 return PyString_FromString (Tkapp_Result (self));
452}
453
454static PyObject *
455Tkapp_AddErrorInfo (self, args)
456 PyObject *self;
457 PyObject *args;
458{
459 char *msg;
460
461 if (!PyArg_Parse (args, "s", &msg))
462 return NULL;
463 Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
464
465 Py_INCREF(Py_None);
466 return Py_None;
467}
468
469/** Tcl Variable **/
470
471static PyObject *
472SetVar (self, args, flags)
473 PyObject *self;
474 PyObject *args;
475 int flags;
476{
477 char *name1, *name2, *ok;
478 PyObject *newValue;
479 PyObject *tmp;
480
481 tmp = PyList_New (0);
482
483 if (PyArg_Parse (args, "(sO)", &name1, &newValue))
484 ok = Tcl_SetVar (Tkapp_Interp (self), name1,
485 AsString (newValue, tmp), flags); /* XXX Merge? */
486 else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
487 ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,
488 AsString (newValue, tmp), flags);
489 else
490 {
491 Py_DECREF (tmp);
492 return NULL;
493 }
494 Py_DECREF (tmp);
495
496 if (!ok)
497 return Tkinter_Error (self);
498
499 Py_INCREF (Py_None);
500 return Py_None;
501}
502
503static PyObject *
504Tkapp_SetVar (self, args)
505 PyObject *self;
506 PyObject *args;
507{
508 return SetVar (self, args, TCL_LEAVE_ERR_MSG);
509}
510
511static PyObject *
512Tkapp_GlobalSetVar (self, args)
513 PyObject *self;
514 PyObject *args;
515{
516 return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
517}
518
519static PyObject *
520GetVar (self, args, flags)
521 PyObject *self;
522 PyObject *args;
523 int flags;
524{
525 char *name1, *name2, *s;
526
527 if (PyArg_Parse (args, "s", &name1))
528 s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
529 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
530 s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
531 else
532 return NULL;
533
534 if (s == NULL)
535 return Tkinter_Error (self);
536
537 return PyString_FromString (s);
538}
539
540static PyObject *
541Tkapp_GetVar (self, args)
542 PyObject *self;
543 PyObject *args;
544{
545 return GetVar (self, args, TCL_LEAVE_ERR_MSG);
546}
547
548static PyObject *
549Tkapp_GlobalGetVar (self, args)
550 PyObject *self;
551 PyObject *args;
552{
553 return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
554}
555
556static PyObject *
557UnsetVar (self, args, flags)
558 PyObject *self;
559 PyObject *args;
560 int flags;
561{
562 char *name1, *name2;
563 int code;
564
565 if (PyArg_Parse (args, "s", &name1))
566 code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
567 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
568 code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
569 else
570 return NULL;
571
572 if (code == TCL_ERROR)
573 return Tkinter_Error (self);
574
575 Py_INCREF (Py_None);
576 return Py_None;
577}
578
579static PyObject *
580Tkapp_UnsetVar (self, args)
581 PyObject *self;
582 PyObject *args;
583{
584 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
585}
586
587static PyObject *
588Tkapp_GlobalUnsetVar (self, args)
589 PyObject *self;
590 PyObject *args;
591{
592 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
593}
594
595/** Tcl to Python **/
596
597static PyObject *
598Tkapp_GetInt (self, args)
599 PyObject *self;
600 PyObject *args;
601{
602 char *s;
603 int v;
604
605 if (!PyArg_Parse (args, "s", &s))
606 return NULL;
607 if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
608 return Tkinter_Error (self);
609 return Py_BuildValue ("i", v);
610}
611
612static PyObject *
613Tkapp_GetDouble (self, args)
614 PyObject *self;
615 PyObject *args;
616{
617 char *s;
618 double v;
619
620 if (!PyArg_Parse (args, "s", &s))
621 return NULL;
622 if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
623 return Tkinter_Error (self);
624 return Py_BuildValue ("d", v);
625}
626
627static PyObject *
628Tkapp_GetBoolean (self, args)
629 PyObject *self;
630 PyObject *args;
631{
632 char *s;
633 int v;
634
635 if (!PyArg_Parse (args, "s", &s))
636 return NULL;
637 if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
638 return Tkinter_Error (self);
639 return Py_BuildValue ("i", v);
640}
641
642static PyObject *
643Tkapp_ExprString (self, args)
644 PyObject *self;
645 PyObject *args;
646{
647 char *s;
648
649 if (!PyArg_Parse (args, "s", &s))
650 return NULL;
651 if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
652 return Tkinter_Error (self);
653 return Py_BuildValue ("s", Tkapp_Result (self));
654}
655
656static PyObject *
657Tkapp_ExprLong (self, args)
658 PyObject *self;
659 PyObject *args;
660{
661 char *s;
662 long v;
663
664 if (!PyArg_Parse (args, "s", &s))
665 return NULL;
666 if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
667 return Tkinter_Error (self);
668 return Py_BuildValue ("l", v);
669}
670
671static PyObject *
672Tkapp_ExprDouble (self, args)
673 PyObject *self;
674 PyObject *args;
675{
676 char *s;
677 double v;
678
679 if (!PyArg_Parse (args, "s", &s))
680 return NULL;
681 if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
682 return Tkinter_Error (self);
683 return Py_BuildValue ("d", v);
684}
685
686static PyObject *
687Tkapp_ExprBoolean (self, args)
688 PyObject *self;
689 PyObject *args;
690{
691 char *s;
692 int v;
693
694 if (!PyArg_Parse (args, "s", &s))
695 return NULL;
696 if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
697 return Tkinter_Error (self);
698 return Py_BuildValue ("i", v);
699}
700
701static PyObject *
702Tkapp_SplitList (self, args)
703 PyObject *self;
704 PyObject *args;
705{
706 char *list;
707 int argc;
708 char **argv;
709 PyObject *v;
710 int i;
711
712 if (!PyArg_Parse (args, "s", &list))
713 return NULL;
714
715 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
716 return Tkinter_Error (self);
717
718 v = PyTuple_New (argc);
719 for (i = 0; i < argc; i++)
720 PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
721
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000722 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000723 return v;
724}
725
726static PyObject *
727Tkapp_Split (self, args)
728 PyObject *self;
729 PyObject *args;
730{
731 char *list;
732
733 if (!PyArg_Parse (args, "s", &list))
734 return NULL;
735 return Split (self, list);
736}
737
738static PyObject *
739Tkapp_Merge (self, args)
740 PyObject *self;
741 PyObject *args;
742{
743 char *s;
744 PyObject *v;
745
746 s = Merge (args);
747 v = PyString_FromString (s);
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000748 ckfree (s);
Guido van Rossum18468821994-06-20 07:49:28 +0000749 return v;
750}
751
752/** Tcl Command **/
753
754/* This is the Tcl command that acts as a wrapper for Python
755 function or method. */
756static int
757PythonCmd (clientData, interp, argc, argv)
758 ClientData clientData; /* Is (self, func) */
759 Tcl_Interp *interp;
760 int argc;
761 char *argv[];
762{
763 PyObject *self, *func, *arg, *res, *tmp;
764 int i;
765
766 self = PyTuple_GetItem ((PyObject *) clientData, 0);
767 func = PyTuple_GetItem ((PyObject *) clientData, 1);
768
769 /* Create argument list (argv1, ..., argvN) */
770 arg = PyTuple_New (argc - 1);
771 for (i = 0; i < (argc - 1); i++)
772 PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
773
774 res = PyEval_CallObject (func, arg);
775 Py_DECREF (arg);
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000776
Guido van Rossum18468821994-06-20 07:49:28 +0000777 if (res == NULL)
778 return PythonCmd_Error (interp);
779
780 tmp = PyList_New (0);
781 Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
782 Py_DECREF (res);
783 Py_DECREF (tmp);
784
785 return TCL_OK;
786}
787
788static void
789PythonCmdDelete (clientData)
790 ClientData clientData; /* Is (self, func) */
791{
792 Py_DECREF ((PyObject *) clientData);
793}
794
795static PyObject *
796Tkapp_CreateCommand (self, args)
797 PyObject *self;
798 PyObject *args;
799{
800 char *cmdName;
801 PyObject *data;
802 PyObject *func;
803
804 /* Args is: (cmdName, func) */
805 if (!PyTuple_Check (args)
806 || !(PyTuple_Size (args) == 2)
807 || !PyString_Check (PyTuple_GetItem (args, 0))
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000808 || !PyCallable_Check (PyTuple_GetItem (args, 1)))
Guido van Rossum18468821994-06-20 07:49:28 +0000809 {
810 PyErr_SetString (PyExc_TypeError, "bad argument list");
811 return NULL;
812 }
813
814 cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
815 func = PyTuple_GetItem (args, 1);
816
817 data = PyTuple_New (2); /* ClientData is: (self, func) */
818
819 Py_INCREF (self);
820 PyTuple_SetItem (data, 0, self);
821
822 Py_INCREF (func);
823 PyTuple_SetItem (data, 1, func);
824
825 Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
826 (ClientData) data, PythonCmdDelete);
827
828 Py_INCREF (Py_None);
829 return Py_None;
830}
831
832static PyObject *
833Tkapp_DeleteCommand (self, args)
834 PyObject *self;
835 PyObject *args;
836{
837 char *cmdName;
838
839 if (!PyArg_Parse (args, "s", &cmdName))
840 return NULL;
841 if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
842 {
843 PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
844 return NULL;
845 }
846 Py_INCREF (Py_None);
847 return Py_None;
848}
849
850/** File Handler **/
851
Guido van Rossuma597dde1995-01-10 20:56:29 +0000852static void
Guido van Rossum18468821994-06-20 07:49:28 +0000853FileHandler (clientData, mask)
Guido van Rossum76875221994-06-27 07:59:42 +0000854 ClientData clientData; /* Is: (func, file) */
Guido van Rossum18468821994-06-20 07:49:28 +0000855 int mask;
856{
Guido van Rossum76875221994-06-27 07:59:42 +0000857 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +0000858
Guido van Rossum76875221994-06-27 07:59:42 +0000859 func = PyTuple_GetItem ((PyObject *) clientData, 0);
860 file = PyTuple_GetItem ((PyObject *) clientData, 1);
Guido van Rossum18468821994-06-20 07:49:28 +0000861
Guido van Rossum76875221994-06-27 07:59:42 +0000862 arg = Py_BuildValue ("(Oi)", file, (long) mask);
Guido van Rossum18468821994-06-20 07:49:28 +0000863 res = PyEval_CallObject (func, arg);
864 Py_DECREF (arg);
865 if (res == NULL)
866 {
867 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000868 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000869 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000870 Py_XDECREF (res);
871}
872
873static int
874GetFileNo (file)
875 PyObject *file; /* Either an int >= 0 or an object with a
876 .fileno() method that returns an int >= 0 */
877{
Guido van Rossuma597dde1995-01-10 20:56:29 +0000878 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000879 int id;
880 if (PyInt_Check(file)) {
881 id = PyInt_AsLong(file);
882 if (id < 0)
883 PyErr_SetString(PyExc_ValueError, "invalid file id");
884 return id;
885 }
886 meth = PyObject_GetAttrString(file, "fileno");
887 if (meth == NULL)
888 return -1;
889 args = PyTuple_New(0);
890 if (args == NULL)
891 return -1;
892 res = PyEval_CallObject(meth, args);
893 Py_DECREF(args);
894 Py_DECREF(meth);
895 if (res == NULL)
896 return -1;
897 if (PyInt_Check(res))
898 id = PyInt_AsLong(res);
899 else
900 id = -1;
901 if (id < 0)
902 PyErr_SetString(PyExc_ValueError,
903 "invalid fileno() return value");
904 Py_DECREF(res);
905 return id;
Guido van Rossum18468821994-06-20 07:49:28 +0000906}
907
908static PyObject *
909Tkapp_CreateFileHandler (self, args)
910 PyObject *self;
911 PyObject *args; /* Is (file, mask, func) */
912{
Guido van Rossum76875221994-06-27 07:59:42 +0000913 PyObject *file, *func, *data;
914 int mask, id;
Guido van Rossum68784361996-05-16 17:17:31 +0000915#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
916 Tcl_File tfile;
917#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000918
919 if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
920 return NULL;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000921 id = GetFileNo (file);
922 if (id < 0)
923 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000924 if (!PyCallable_Check(func))
Guido van Rossum18468821994-06-20 07:49:28 +0000925 {
926 PyErr_SetString (PyExc_TypeError, "bad argument list");
927 return NULL;
928 }
929
Guido van Rossum76875221994-06-27 07:59:42 +0000930 /* ClientData is: (func, file) */
931 data = Py_BuildValue ("(OO)", func, file);
932
Guido van Rossum68784361996-05-16 17:17:31 +0000933#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum07886d01996-09-11 23:31:42 +0000934#ifdef MS_WINDOWS
Guido van Rossum845547d1996-06-26 18:26:04 +0000935 /* We assume this is a socket... */
936 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
937#else
Guido van Rossum68784361996-05-16 17:17:31 +0000938 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
Guido van Rossum845547d1996-06-26 18:26:04 +0000939#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000940 /* Oughtta check for null Tcl_File object... */
941 Tcl_CreateFileHandler (tfile, mask, FileHandler, (ClientData) data);
942#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000943 Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
Guido van Rossum68784361996-05-16 17:17:31 +0000944#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000945 /* XXX fileHandlerDict */
Guido van Rossum76875221994-06-27 07:59:42 +0000946
Guido van Rossum18468821994-06-20 07:49:28 +0000947 Py_INCREF (Py_None);
948 return Py_None;
949}
950
951static PyObject *
952Tkapp_DeleteFileHandler (self, args)
953 PyObject *self;
954 PyObject *args; /* Args: file */
955{
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000956 PyObject *file;
Guido van Rossum18468821994-06-20 07:49:28 +0000957 int id;
Guido van Rossum68784361996-05-16 17:17:31 +0000958#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
959 Tcl_File tfile;
960#endif
961
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000962 if (!PyArg_Parse (args, "O", &file))
963 return NULL;
964 id = GetFileNo (file);
965 if (id < 0)
966 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000967
Guido van Rossum68784361996-05-16 17:17:31 +0000968#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum07886d01996-09-11 23:31:42 +0000969#ifdef MS_WINDOWS
Guido van Rossum845547d1996-06-26 18:26:04 +0000970 /* We assume this is a socket... */
971 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
972#else
973 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
974#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000975 /* Oughtta check for null Tcl_File object... */
976 Tcl_DeleteFileHandler(tfile);
977#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000978 Tk_DeleteFileHandler (id);
Guido van Rossum68784361996-05-16 17:17:31 +0000979#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000980 /* XXX fileHandlerDict */
981 Py_INCREF (Py_None);
982 return Py_None;
983}
984
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000985/**** Tktt Object (timer token) ****/
986
987staticforward PyTypeObject Tktt_Type;
988
989typedef struct
990 {
991 PyObject_HEAD
992 Tk_TimerToken token;
993 PyObject *func;
994 }
995TkttObject;
996
997static PyObject *
998Tktt_DeleteTimerHandler (self, args)
999 PyObject *self;
1000 PyObject *args;
1001{
1002 TkttObject *v = (TkttObject *) self;
1003
1004 if (!PyArg_Parse (args, ""))
1005 return NULL;
1006 if (v->func != NULL)
1007 {
1008 Tk_DeleteTimerHandler (v->token);
1009 PyMem_DEL (v->func);
1010 v->func = NULL;
1011 }
1012 Py_INCREF (Py_None);
1013 return Py_None;
1014}
1015
1016static PyMethodDef Tktt_methods[] =
1017{
1018 {"deletetimerhandler", Tktt_DeleteTimerHandler},
1019 {NULL, NULL}
1020};
1021
1022static TkttObject *
1023Tktt_New (token, func)
1024 Tk_TimerToken token;
1025 PyObject *func;
1026{
1027 TkttObject *v;
1028
1029 v = PyObject_NEW (TkttObject, &Tktt_Type);
1030 if (v == NULL)
1031 return NULL;
1032
1033 v->token = token;
1034 v->func = func;
1035 Py_INCREF (v->func);
1036 return v;
1037}
1038
1039static void
1040Tktt_Dealloc (self)
1041 PyObject *self;
1042{
1043 PyMem_DEL (self);
1044}
1045
1046static int
1047Tktt_Print (self, fp, flags)
1048 PyObject *self;
1049 FILE *fp;
1050 int flags;
1051{
1052 TkttObject *v = (TkttObject *) self;
1053
Guido van Rossuma376cc51996-12-05 23:43:35 +00001054 fprintf(fp, "<tktimertoken at 0x%lx%s>", (long)v,
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001055 v->func == NULL ? ", handler deleted" : "");
1056 return 0;
1057}
1058
1059static PyObject *
1060Tktt_GetAttr (self, name)
1061 PyObject *self;
1062 char *name;
1063{
1064 return Py_FindMethod (Tktt_methods, self, name);
1065}
1066
1067static PyTypeObject Tktt_Type =
1068{
Guido van Rossumae92f011996-08-21 19:03:36 +00001069 PyObject_HEAD_INIT (NULL)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001070 0, /*ob_size */
1071 "tktimertoken", /*tp_name */
1072 sizeof (TkttObject), /*tp_basicsize */
1073 0, /*tp_itemsize */
1074 Tktt_Dealloc, /*tp_dealloc */
1075 Tktt_Print, /*tp_print */
1076 Tktt_GetAttr, /*tp_getattr */
1077 0, /*tp_setattr */
1078 0, /*tp_compare */
1079 0, /*tp_repr */
1080 0, /*tp_as_number */
1081 0, /*tp_as_sequence */
1082 0, /*tp_as_mapping */
1083 0, /*tp_hash */
1084};
1085
1086/** Timer Handler **/
1087
1088static void
1089TimerHandler (clientData)
1090 ClientData clientData;
1091{
1092 PyObject *func = (PyObject *) clientData;
1093 PyObject *arg, *res;
1094
1095 arg = PyTuple_New (0);
1096 res = PyEval_CallObject (func, arg);
1097 Py_DECREF (arg);
1098 if (res == NULL)
1099 {
1100 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001101 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001102 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001103 else
1104 Py_DECREF (res);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001105}
1106
1107static PyObject *
1108Tkapp_CreateTimerHandler (self, args)
1109 PyObject *self;
1110 PyObject *args; /* Is (milliseconds, func) */
1111{
1112 int milliseconds;
1113 PyObject *func;
1114 Tk_TimerToken token;
1115
1116 if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
1117 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001118 if (!PyCallable_Check(func))
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001119 {
1120 PyErr_SetString (PyExc_TypeError, "bad argument list");
1121 return NULL;
1122 }
1123 token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
1124 return (PyObject *) Tktt_New (token, func);
1125}
1126
Guido van Rossum18468821994-06-20 07:49:28 +00001127/** Event Loop **/
1128
Guido van Rossum18468821994-06-20 07:49:28 +00001129static PyObject *
1130Tkapp_MainLoop (self, args)
1131 PyObject *self;
1132 PyObject *args;
1133{
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001134 int threshold = 0;
1135
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001136 if (!PyArg_ParseTuple (args, "|i", &threshold))
1137 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001138
1139 quitMainLoop = 0;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001140 while (Tk_GetNumMainWindows() > threshold && !quitMainLoop && !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001141 {
Guido van Rossuma376cc51996-12-05 23:43:35 +00001142 /* XXX Ought to check for other signals! */
Guido van Rossum18468821994-06-20 07:49:28 +00001143 if (PyOS_InterruptOccurred ())
1144 {
1145 PyErr_SetNone (PyExc_KeyboardInterrupt);
1146 return NULL;
1147 }
1148 Tk_DoOneEvent (0);
1149 }
Guido van Rossum64b24fb1995-09-30 17:00:24 +00001150 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001151
1152 if (errorInCmd)
1153 {
1154 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001155 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1156 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001157 return NULL;
1158 }
1159 Py_INCREF (Py_None);
1160 return Py_None;
1161}
1162
1163static PyObject *
Guido van Rossum062cfb01995-01-10 17:42:51 +00001164Tkapp_DoOneEvent (self, args)
1165 PyObject *self;
1166 PyObject *args;
1167{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001168 int flags = TK_ALL_EVENTS;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001169 int rv;
1170
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001171 if (!PyArg_ParseTuple (args, "|i", &flags))
1172 return NULL;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001173 rv = Tk_DoOneEvent(flags);
1174 return Py_BuildValue ("i", rv);
1175}
1176
1177static PyObject *
Guido van Rossum18468821994-06-20 07:49:28 +00001178Tkapp_Quit (self, args)
1179 PyObject *self;
1180 PyObject *args;
1181{
1182
1183 if (!PyArg_Parse (args, ""))
1184 return NULL;
1185 quitMainLoop = 1;
1186 Py_INCREF (Py_None);
1187 return Py_None;
1188}
1189
1190/**** Tkapp Method List ****/
1191
1192static PyMethodDef Tkapp_methods[] =
1193{
1194 {"call", Tkapp_Call},
1195 {"globalcall", Tkapp_GlobalCall},
1196 {"eval", Tkapp_Eval},
1197 {"globaleval", Tkapp_GlobalEval},
1198 {"evalfile", Tkapp_EvalFile},
1199 {"record", Tkapp_Record},
1200 {"adderrorinfo", Tkapp_AddErrorInfo},
1201 {"setvar", Tkapp_SetVar},
1202 {"globalsetvar", Tkapp_GlobalSetVar},
1203 {"getvar", Tkapp_GetVar},
1204 {"globalgetvar", Tkapp_GlobalGetVar},
1205 {"unsetvar", Tkapp_UnsetVar},
1206 {"globalunsetvar", Tkapp_GlobalUnsetVar},
1207 {"getint", Tkapp_GetInt},
1208 {"getdouble", Tkapp_GetDouble},
1209 {"getboolean", Tkapp_GetBoolean},
1210 {"exprstring", Tkapp_ExprString},
1211 {"exprlong", Tkapp_ExprLong},
1212 {"exprdouble", Tkapp_ExprDouble},
1213 {"exprboolean", Tkapp_ExprBoolean},
1214 {"splitlist", Tkapp_SplitList},
1215 {"split", Tkapp_Split},
1216 {"merge", Tkapp_Merge},
1217 {"createcommand", Tkapp_CreateCommand},
1218 {"deletecommand", Tkapp_DeleteCommand},
1219 {"createfilehandler", Tkapp_CreateFileHandler},
1220 {"deletefilehandler", Tkapp_DeleteFileHandler},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001221 {"createtimerhandler", Tkapp_CreateTimerHandler},
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001222 {"mainloop", Tkapp_MainLoop, 1},
1223 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum18468821994-06-20 07:49:28 +00001224 {"quit", Tkapp_Quit},
1225 {NULL, NULL}
1226};
1227
1228/**** Tkapp Type Methods ****/
1229
1230static void
1231Tkapp_Dealloc (self)
1232 PyObject *self;
1233{
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001234#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +00001235 Tk_DestroyWindow (Tkapp_Tkwin (self));
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001236#endif
Guido van Rossum18468821994-06-20 07:49:28 +00001237 Tcl_DeleteInterp (Tkapp_Interp (self));
1238 PyMem_DEL (self);
1239}
1240
1241static PyObject *
1242Tkapp_GetAttr (self, name)
1243 PyObject *self;
1244 char *name;
1245{
1246 return Py_FindMethod (Tkapp_methods, self, name);
1247}
1248
1249static PyTypeObject Tkapp_Type =
1250{
Guido van Rossumae92f011996-08-21 19:03:36 +00001251 PyObject_HEAD_INIT (NULL)
Guido van Rossum18468821994-06-20 07:49:28 +00001252 0, /*ob_size */
1253 "tkapp", /*tp_name */
1254 sizeof (TkappObject), /*tp_basicsize */
1255 0, /*tp_itemsize */
1256 Tkapp_Dealloc, /*tp_dealloc */
1257 0, /*tp_print */
1258 Tkapp_GetAttr, /*tp_getattr */
1259 0, /*tp_setattr */
1260 0, /*tp_compare */
1261 0, /*tp_repr */
1262 0, /*tp_as_number */
1263 0, /*tp_as_sequence */
1264 0, /*tp_as_mapping */
1265 0, /*tp_hash */
1266};
1267
1268/**** Tkinter Module ****/
1269
1270static PyObject *
1271Tkinter_Create (self, args)
1272 PyObject *self;
1273 PyObject *args;
1274{
1275 char *screenName = NULL;
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001276 char *baseName = NULL;
1277 char *className = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001278 int interactive = 0;
1279
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001280 baseName = strrchr (Py_GetProgramName (), '/');
Guido van Rossum18468821994-06-20 07:49:28 +00001281 if (baseName != NULL)
1282 baseName++;
1283 else
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001284 baseName = Py_GetProgramName ();
Guido van Rossum18468821994-06-20 07:49:28 +00001285 className = "Tk";
1286
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001287 if (!PyArg_ParseTuple (args, "|zssi",
1288 &screenName, &baseName, &className, &interactive))
Guido van Rossum18468821994-06-20 07:49:28 +00001289 return NULL;
1290
1291 return (PyObject *) Tkapp_New (screenName, baseName, className,
1292 interactive);
1293}
1294
1295static PyMethodDef moduleMethods[] =
1296{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001297 {"create", Tkinter_Create, 1},
1298 {"createfilehandler", Tkapp_CreateFileHandler, 0},
1299 {"deletefilehandler", Tkapp_DeleteFileHandler, 0},
1300 {"createtimerhandler", Tkapp_CreateTimerHandler, 0},
1301 {"mainloop", Tkapp_MainLoop, 1},
1302 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001303 {"quit", Tkapp_Quit},
Guido van Rossum18468821994-06-20 07:49:28 +00001304 {NULL, NULL}
1305};
1306
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001307#undef WITH_READLINE /* XXX */
Guido van Rossum18468821994-06-20 07:49:28 +00001308#ifdef WITH_READLINE
1309static int
1310EventHook ()
1311{
1312 if (errorInCmd) /* XXX Reset tty */
1313 {
1314 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001315 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1316 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001317 PyErr_Print ();
1318 }
Guido van Rossum9722ad81995-09-22 23:49:28 +00001319 if (Tk_GetNumMainWindows() > 0)
Guido van Rossume2ca9bd1994-08-03 08:01:43 +00001320 Tk_DoOneEvent (TK_DONT_WAIT);
Guido van Rossum18468821994-06-20 07:49:28 +00001321 return 0;
1322}
1323#endif /* WITH_READLINE */
1324
1325static void
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001326Tkinter_Cleanup ()
1327{
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001328/* This segfault with Tk 4.0 beta and seems unnecessary there as well */
1329#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001330 /* XXX rl_deprep_terminal is static, damned! */
1331 while (tkMainWindowList != 0)
1332 Tk_DestroyWindow (tkMainWindowList->win);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001333#endif
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001334}
1335
Guido van Rossum18468821994-06-20 07:49:28 +00001336void
Guido van Rossumad1f7ee1996-02-13 00:11:37 +00001337init_tkinter ()
Guido van Rossum18468821994-06-20 07:49:28 +00001338{
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001339 static inited = 0;
1340
Guido van Rossum18468821994-06-20 07:49:28 +00001341#ifdef WITH_READLINE
1342 extern int (*rl_event_hook) ();
1343#endif /* WITH_READLINE */
1344 PyObject *m, *d, *v;
1345
Guido van Rossumae92f011996-08-21 19:03:36 +00001346 Tkapp_Type.ob_type = &PyType_Type;
1347 Tktt_Type.ob_type = &PyType_Type;
1348
Jack Jansenba0311e1995-10-23 14:34:14 +00001349 m = Py_InitModule ("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00001350
1351 d = PyModule_GetDict (m);
1352 Tkinter_TclError = Py_BuildValue ("s", "TclError");
1353 PyDict_SetItemString (d, "TclError", Tkinter_TclError);
1354
1355 v = Py_BuildValue ("i", TK_READABLE);
1356 PyDict_SetItemString (d, "READABLE", v);
1357 v = Py_BuildValue ("i", TK_WRITABLE);
1358 PyDict_SetItemString (d, "WRITABLE", v);
1359 v = Py_BuildValue ("i", TK_EXCEPTION);
1360 PyDict_SetItemString (d, "EXCEPTION", v);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001361 v = Py_BuildValue ("i", TK_X_EVENTS);
1362 PyDict_SetItemString (d, "X_EVENTS", v);
1363 v = Py_BuildValue ("i", TK_FILE_EVENTS);
1364 PyDict_SetItemString (d, "FILE_EVENTS", v);
1365 v = Py_BuildValue ("i", TK_TIMER_EVENTS);
1366 PyDict_SetItemString (d, "TIMER_EVENTS", v);
1367 v = Py_BuildValue ("i", TK_IDLE_EVENTS);
1368 PyDict_SetItemString (d, "IDLE_EVENTS", v);
1369 v = Py_BuildValue ("i", TK_ALL_EVENTS);
1370 PyDict_SetItemString (d, "ALL_EVENTS", v);
1371 v = Py_BuildValue ("i", TK_DONT_WAIT);
1372 PyDict_SetItemString (d, "DONT_WAIT", v);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001373 v = Py_BuildValue ("s", TK_VERSION);
1374 PyDict_SetItemString (d, "TK_VERSION", v);
1375 v = Py_BuildValue ("s", TCL_VERSION);
1376 PyDict_SetItemString (d, "TCL_VERSION", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001377
Guido van Rossum18468821994-06-20 07:49:28 +00001378#ifdef WITH_READLINE
1379 rl_event_hook = EventHook;
1380#endif /* WITH_READLINE */
1381
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001382 if (!inited)
1383 {
1384 inited = 1;
Guido van Rossume4485b01994-09-07 14:32:49 +00001385 if (Py_AtExit (Tkinter_Cleanup) != 0)
1386 fprintf(stderr,
1387 "Tkinter: warning: cleanup procedure not registered\n");
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001388 }
1389
Guido van Rossum18468821994-06-20 07:49:28 +00001390 if (PyErr_Occurred ())
Jack Jansenba0311e1995-10-23 14:34:14 +00001391 Py_FatalError ("can't initialize module _tkinter");
Jack Jansen34cc5c31995-10-31 16:15:12 +00001392#ifdef macintosh
Guido van Rossumec22c921996-02-25 04:50:29 +00001393 TclMacSetEventProc(PyMacConvertEvent);
1394#if GENERATINGCFM
Jack Jansen34cc5c31995-10-31 16:15:12 +00001395 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00001396#endif /* GENERATINGCFM */
1397#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00001398}
Guido van Rossum9722ad81995-09-22 23:49:28 +00001399
Guido van Rossumec22c921996-02-25 04:50:29 +00001400
Guido van Rossum9722ad81995-09-22 23:49:28 +00001401#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001402
1403/*
Guido van Rossumec22c921996-02-25 04:50:29 +00001404** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001405*/
1406
Guido van Rossum9722ad81995-09-22 23:49:28 +00001407void
1408panic(char * format, ...)
1409{
1410 va_list varg;
1411
1412 va_start(varg, format);
1413
1414 vfprintf(stderr, format, varg);
1415 (void) fflush(stderr);
1416
1417 va_end(varg);
1418
1419 Py_FatalError("Tcl/Tk panic");
1420}
Jack Jansen40b546d1995-11-14 10:34:45 +00001421
Guido van Rossumec22c921996-02-25 04:50:29 +00001422/*
1423** Pass events to SIOUX before passing them to Tk.
1424*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001425
Guido van Rossumec22c921996-02-25 04:50:29 +00001426static int
1427PyMacConvertEvent(eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001428 EventRecord *eventPtr;
1429{
Guido van Rossumec22c921996-02-25 04:50:29 +00001430 if (SIOUXHandleOneEvent(eventPtr))
1431 return 0; /* Nothing happened to the Tcl event queue */
1432 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001433}
1434
Guido van Rossumec22c921996-02-25 04:50:29 +00001435#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001436
1437/*
1438** Additional Mac specific code for dealing with shared libraries.
1439*/
1440
1441#include <Resources.h>
1442#include <CodeFragments.h>
1443
1444static int loaded_from_shlib = 0;
1445static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001446
Jack Jansen34cc5c31995-10-31 16:15:12 +00001447/*
1448** If this module is dynamically loaded the following routine should
1449** be the init routine. It takes care of adding the shared library to
1450** the resource-file chain, so that the tk routines can find their
1451** resources.
1452*/
1453OSErr pascal
1454init_tkinter_shlib(InitBlockPtr data)
1455{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00001456 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00001457 if ( data == nil ) return noErr;
1458 if ( data->fragLocator.where == kOnDiskFlat ) {
1459 library_fss = *data->fragLocator.u.onDisk.fileSpec;
1460 loaded_from_shlib = 1;
1461 } else if ( data->fragLocator.where == kOnDiskSegmented ) {
1462 library_fss = *data->fragLocator.u.inSegs.fileSpec;
1463 loaded_from_shlib = 1;
1464 }
1465 return noErr;
1466}
1467
1468/*
1469** Insert the library resources into the search path. Put them after
1470** the resources from the application. Again, we ignore errors.
1471*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001472static
Jack Jansen34cc5c31995-10-31 16:15:12 +00001473mac_addlibresources()
1474{
1475 if ( !loaded_from_shlib )
1476 return;
1477 (void)FSpOpenResFile(&library_fss, fsRdPerm);
1478}
1479
Guido van Rossumec22c921996-02-25 04:50:29 +00001480#endif /* GENERATINGCFM */
1481#endif /* macintosh */