blob: 3ce0faca379eccc2c4ab8580fc8e289c3f39f1c3 [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]);
Guido van Rossum0f868371996-12-17 01:02:18 +0000264 else if ((v = PyTuple_New (argc)) != NULL)
Guido van Rossum18468821994-06-20 07:49:28 +0000265 {
266 int i;
Guido van Rossum0f868371996-12-17 01:02:18 +0000267 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum0f868371996-12-17 01:02:18 +0000269 for (i = 0; i < argc; i++) {
270 if ((w = Split (self, argv[i])) == NULL)
271 {
272 Py_DECREF(v);
273 v = NULL;
274 break;
275 }
276 PyTuple_SetItem (v, i, w);
277 }
Guido van Rossum18468821994-06-20 07:49:28 +0000278 }
279
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000280 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000281 return v;
282}
283
284/**** Tkapp Object ****/
285
286#ifndef WITH_APPINIT
287int
288Tcl_AppInit (interp)
289 Tcl_Interp *interp;
290{
Guido van Rossumec22c921996-02-25 04:50:29 +0000291 Tk_Window main;
292
293 main = Tk_MainWindow(interp);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000294 if (Tcl_Init (interp) == TCL_ERROR) {
295 fprintf(stderr, "Tcl_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000296 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000297 }
298 if (Tk_Init (interp) == TCL_ERROR) {
299 fprintf(stderr, "Tk_Init error: %s\n", interp->result);
Guido van Rossum18468821994-06-20 07:49:28 +0000300 return TCL_ERROR;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000301 }
Guido van Rossum18468821994-06-20 07:49:28 +0000302 return TCL_OK;
303}
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000304
Guido van Rossum18468821994-06-20 07:49:28 +0000305#endif /* !WITH_APPINIT */
306
307/* Initialize the Tk application; see the `main' function in
308 `tkMain.c'. */
309static TkappObject *
310Tkapp_New (screenName, baseName, className, interactive)
311 char *screenName;
312 char *baseName;
313 char *className;
314 int interactive;
315{
316 TkappObject *v;
Guido van Rossum97867b21996-08-08 19:09:53 +0000317 char *argv0;
Guido van Rossum18468821994-06-20 07:49:28 +0000318
319 v = PyObject_NEW (TkappObject, &Tkapp_Type);
320 if (v == NULL)
321 return NULL;
322
323 v->interp = Tcl_CreateInterp ();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000324
325#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +0000326 v->tkwin = Tk_CreateMainWindow (v->interp, screenName,
327 baseName, className);
328 if (v->tkwin == NULL)
329 return (TkappObject *) Tkinter_Error ((PyObject *) v);
330
331 Tk_GeometryRequest (v->tkwin, 200, 200);
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000332#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000333
334 if (screenName != NULL)
335 Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
336
337 if (interactive)
338 Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
339 else
340 Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
341
Guido van Rossum97867b21996-08-08 19:09:53 +0000342 /* This is used to get the application class for Tk 4.1 and up */
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000343 argv0 = (char*) ckalloc (strlen (className) + 1);
Guido van Rossum97867b21996-08-08 19:09:53 +0000344 if (argv0 != NULL) {
345 strcpy (argv0, className);
346 if (isupper (argv0[0]))
347 argv0[0] = tolower (argv0[0]);
348 Tcl_SetVar (v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000349 ckfree (argv0);
Guido van Rossum97867b21996-08-08 19:09:53 +0000350 }
351
Guido van Rossum18468821994-06-20 07:49:28 +0000352 if (Tcl_AppInit (v->interp) != TCL_OK)
Guido van Rossum845547d1996-06-26 18:26:04 +0000353 return (TkappObject *) Tkinter_Error (v);
Guido van Rossum18468821994-06-20 07:49:28 +0000354
355 return v;
356}
357
358/** Tcl Eval **/
359
360static PyObject *
361Tkapp_Call (self, args)
362 PyObject *self;
363 PyObject *args;
364{
365 char *cmd;
366
367 cmd = Merge (args);
368 if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
369 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000370 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000371 return Tkinter_Error (self);
372 }
373
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000374 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000375 return PyString_FromString (Tkapp_Result (self));
376}
377
378static PyObject *
379Tkapp_GlobalCall (self, args)
380 PyObject *self;
381 PyObject *args;
382{
383 char *cmd;
384
385 cmd = Merge (args);
386 if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
387 {
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000388 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000389 return Tkinter_Error (self);
390 }
391
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000392 ckfree (cmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000393 return PyString_FromString (Tkapp_Result (self));
394}
395
396static PyObject *
397Tkapp_Eval (self, args)
398 PyObject *self;
399 PyObject *args;
400{
401 char *script;
402
403 if (!PyArg_Parse (args, "s", &script))
404 return NULL;
405
406 if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
407 return Tkinter_Error (self);
408
409 return PyString_FromString (Tkapp_Result (self));
410}
411
412static PyObject *
413Tkapp_GlobalEval (self, args)
414 PyObject *self;
415 PyObject *args;
416{
417 char *script;
418
419 if (!PyArg_Parse (args, "s", &script))
420 return NULL;
421
422 if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
423 return Tkinter_Error (self);
424
425 return PyString_FromString (Tkapp_Result (self));
426}
427
428static PyObject *
429Tkapp_EvalFile (self, args)
430 PyObject *self;
431 PyObject *args;
432{
433 char *fileName;
434
435 if (!PyArg_Parse (args, "s", &fileName))
436 return NULL;
437
438 if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
439 return Tkinter_Error (self);
440
441 return PyString_FromString (Tkapp_Result (self));
442}
443
444static PyObject *
445Tkapp_Record (self, args)
446 PyObject *self;
447 PyObject *args;
448{
449 char *script;
450
451 if (!PyArg_Parse (args, "s", &script))
452 return NULL;
453
454 if (Tcl_RecordAndEval (Tkapp_Interp (self),
455 script, TCL_NO_EVAL) == TCL_ERROR)
456 return Tkinter_Error (self);
457
458 return PyString_FromString (Tkapp_Result (self));
459}
460
461static PyObject *
462Tkapp_AddErrorInfo (self, args)
463 PyObject *self;
464 PyObject *args;
465{
466 char *msg;
467
468 if (!PyArg_Parse (args, "s", &msg))
469 return NULL;
470 Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
471
472 Py_INCREF(Py_None);
473 return Py_None;
474}
475
476/** Tcl Variable **/
477
478static PyObject *
479SetVar (self, args, flags)
480 PyObject *self;
481 PyObject *args;
482 int flags;
483{
484 char *name1, *name2, *ok;
485 PyObject *newValue;
486 PyObject *tmp;
487
488 tmp = PyList_New (0);
489
490 if (PyArg_Parse (args, "(sO)", &name1, &newValue))
491 ok = Tcl_SetVar (Tkapp_Interp (self), name1,
492 AsString (newValue, tmp), flags); /* XXX Merge? */
493 else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
494 ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2,
495 AsString (newValue, tmp), flags);
496 else
497 {
498 Py_DECREF (tmp);
499 return NULL;
500 }
501 Py_DECREF (tmp);
502
503 if (!ok)
504 return Tkinter_Error (self);
505
506 Py_INCREF (Py_None);
507 return Py_None;
508}
509
510static PyObject *
511Tkapp_SetVar (self, args)
512 PyObject *self;
513 PyObject *args;
514{
515 return SetVar (self, args, TCL_LEAVE_ERR_MSG);
516}
517
518static PyObject *
519Tkapp_GlobalSetVar (self, args)
520 PyObject *self;
521 PyObject *args;
522{
523 return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
524}
525
526static PyObject *
527GetVar (self, args, flags)
528 PyObject *self;
529 PyObject *args;
530 int flags;
531{
532 char *name1, *name2, *s;
533
534 if (PyArg_Parse (args, "s", &name1))
535 s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
536 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
537 s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
538 else
539 return NULL;
540
541 if (s == NULL)
542 return Tkinter_Error (self);
543
544 return PyString_FromString (s);
545}
546
547static PyObject *
548Tkapp_GetVar (self, args)
549 PyObject *self;
550 PyObject *args;
551{
552 return GetVar (self, args, TCL_LEAVE_ERR_MSG);
553}
554
555static PyObject *
556Tkapp_GlobalGetVar (self, args)
557 PyObject *self;
558 PyObject *args;
559{
560 return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
561}
562
563static PyObject *
564UnsetVar (self, args, flags)
565 PyObject *self;
566 PyObject *args;
567 int flags;
568{
569 char *name1, *name2;
570 int code;
571
572 if (PyArg_Parse (args, "s", &name1))
573 code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
574 else if (PyArg_Parse (args, "(ss)", &name1, &name2))
575 code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
576 else
577 return NULL;
578
579 if (code == TCL_ERROR)
580 return Tkinter_Error (self);
581
582 Py_INCREF (Py_None);
583 return Py_None;
584}
585
586static PyObject *
587Tkapp_UnsetVar (self, args)
588 PyObject *self;
589 PyObject *args;
590{
591 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
592}
593
594static PyObject *
595Tkapp_GlobalUnsetVar (self, args)
596 PyObject *self;
597 PyObject *args;
598{
599 return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
600}
601
602/** Tcl to Python **/
603
604static PyObject *
605Tkapp_GetInt (self, args)
606 PyObject *self;
607 PyObject *args;
608{
609 char *s;
610 int v;
611
612 if (!PyArg_Parse (args, "s", &s))
613 return NULL;
614 if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
615 return Tkinter_Error (self);
616 return Py_BuildValue ("i", v);
617}
618
619static PyObject *
620Tkapp_GetDouble (self, args)
621 PyObject *self;
622 PyObject *args;
623{
624 char *s;
625 double v;
626
627 if (!PyArg_Parse (args, "s", &s))
628 return NULL;
629 if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
630 return Tkinter_Error (self);
631 return Py_BuildValue ("d", v);
632}
633
634static PyObject *
635Tkapp_GetBoolean (self, args)
636 PyObject *self;
637 PyObject *args;
638{
639 char *s;
640 int v;
641
642 if (!PyArg_Parse (args, "s", &s))
643 return NULL;
644 if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
645 return Tkinter_Error (self);
646 return Py_BuildValue ("i", v);
647}
648
649static PyObject *
650Tkapp_ExprString (self, args)
651 PyObject *self;
652 PyObject *args;
653{
654 char *s;
655
656 if (!PyArg_Parse (args, "s", &s))
657 return NULL;
658 if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
659 return Tkinter_Error (self);
660 return Py_BuildValue ("s", Tkapp_Result (self));
661}
662
663static PyObject *
664Tkapp_ExprLong (self, args)
665 PyObject *self;
666 PyObject *args;
667{
668 char *s;
669 long v;
670
671 if (!PyArg_Parse (args, "s", &s))
672 return NULL;
673 if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
674 return Tkinter_Error (self);
675 return Py_BuildValue ("l", v);
676}
677
678static PyObject *
679Tkapp_ExprDouble (self, args)
680 PyObject *self;
681 PyObject *args;
682{
683 char *s;
684 double v;
685
686 if (!PyArg_Parse (args, "s", &s))
687 return NULL;
688 if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
689 return Tkinter_Error (self);
690 return Py_BuildValue ("d", v);
691}
692
693static PyObject *
694Tkapp_ExprBoolean (self, args)
695 PyObject *self;
696 PyObject *args;
697{
698 char *s;
699 int v;
700
701 if (!PyArg_Parse (args, "s", &s))
702 return NULL;
703 if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
704 return Tkinter_Error (self);
705 return Py_BuildValue ("i", v);
706}
707
708static PyObject *
709Tkapp_SplitList (self, args)
710 PyObject *self;
711 PyObject *args;
712{
713 char *list;
714 int argc;
715 char **argv;
716 PyObject *v;
717 int i;
718
719 if (!PyArg_Parse (args, "s", &list))
720 return NULL;
721
722 if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
723 return Tkinter_Error (self);
724
725 v = PyTuple_New (argc);
726 for (i = 0; i < argc; i++)
727 PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
728
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000729 ckfree (FREECAST argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000730 return v;
731}
732
733static PyObject *
734Tkapp_Split (self, args)
735 PyObject *self;
736 PyObject *args;
737{
738 char *list;
739
740 if (!PyArg_Parse (args, "s", &list))
741 return NULL;
742 return Split (self, list);
743}
744
745static PyObject *
746Tkapp_Merge (self, args)
747 PyObject *self;
748 PyObject *args;
749{
750 char *s;
751 PyObject *v;
752
753 s = Merge (args);
754 v = PyString_FromString (s);
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000755 ckfree (s);
Guido van Rossum18468821994-06-20 07:49:28 +0000756 return v;
757}
758
759/** Tcl Command **/
760
761/* This is the Tcl command that acts as a wrapper for Python
762 function or method. */
763static int
764PythonCmd (clientData, interp, argc, argv)
765 ClientData clientData; /* Is (self, func) */
766 Tcl_Interp *interp;
767 int argc;
768 char *argv[];
769{
770 PyObject *self, *func, *arg, *res, *tmp;
771 int i;
772
773 self = PyTuple_GetItem ((PyObject *) clientData, 0);
774 func = PyTuple_GetItem ((PyObject *) clientData, 1);
775
776 /* Create argument list (argv1, ..., argvN) */
777 arg = PyTuple_New (argc - 1);
778 for (i = 0; i < (argc - 1); i++)
779 PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
780
781 res = PyEval_CallObject (func, arg);
782 Py_DECREF (arg);
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000783
Guido van Rossum18468821994-06-20 07:49:28 +0000784 if (res == NULL)
785 return PythonCmd_Error (interp);
786
787 tmp = PyList_New (0);
788 Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
789 Py_DECREF (res);
790 Py_DECREF (tmp);
791
792 return TCL_OK;
793}
794
795static void
796PythonCmdDelete (clientData)
797 ClientData clientData; /* Is (self, func) */
798{
799 Py_DECREF ((PyObject *) clientData);
800}
801
802static PyObject *
803Tkapp_CreateCommand (self, args)
804 PyObject *self;
805 PyObject *args;
806{
807 char *cmdName;
808 PyObject *data;
809 PyObject *func;
810
811 /* Args is: (cmdName, func) */
812 if (!PyTuple_Check (args)
813 || !(PyTuple_Size (args) == 2)
814 || !PyString_Check (PyTuple_GetItem (args, 0))
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000815 || !PyCallable_Check (PyTuple_GetItem (args, 1)))
Guido van Rossum18468821994-06-20 07:49:28 +0000816 {
817 PyErr_SetString (PyExc_TypeError, "bad argument list");
818 return NULL;
819 }
820
821 cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
822 func = PyTuple_GetItem (args, 1);
823
824 data = PyTuple_New (2); /* ClientData is: (self, func) */
825
826 Py_INCREF (self);
827 PyTuple_SetItem (data, 0, self);
828
829 Py_INCREF (func);
830 PyTuple_SetItem (data, 1, func);
831
832 Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
833 (ClientData) data, PythonCmdDelete);
834
835 Py_INCREF (Py_None);
836 return Py_None;
837}
838
839static PyObject *
840Tkapp_DeleteCommand (self, args)
841 PyObject *self;
842 PyObject *args;
843{
844 char *cmdName;
845
846 if (!PyArg_Parse (args, "s", &cmdName))
847 return NULL;
848 if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
849 {
850 PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
851 return NULL;
852 }
853 Py_INCREF (Py_None);
854 return Py_None;
855}
856
857/** File Handler **/
858
Guido van Rossuma597dde1995-01-10 20:56:29 +0000859static void
Guido van Rossum18468821994-06-20 07:49:28 +0000860FileHandler (clientData, mask)
Guido van Rossum76875221994-06-27 07:59:42 +0000861 ClientData clientData; /* Is: (func, file) */
Guido van Rossum18468821994-06-20 07:49:28 +0000862 int mask;
863{
Guido van Rossum76875221994-06-27 07:59:42 +0000864 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +0000865
Guido van Rossum76875221994-06-27 07:59:42 +0000866 func = PyTuple_GetItem ((PyObject *) clientData, 0);
867 file = PyTuple_GetItem ((PyObject *) clientData, 1);
Guido van Rossum18468821994-06-20 07:49:28 +0000868
Guido van Rossum76875221994-06-27 07:59:42 +0000869 arg = Py_BuildValue ("(Oi)", file, (long) mask);
Guido van Rossum18468821994-06-20 07:49:28 +0000870 res = PyEval_CallObject (func, arg);
871 Py_DECREF (arg);
872 if (res == NULL)
873 {
874 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000875 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossum18468821994-06-20 07:49:28 +0000876 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000877 Py_XDECREF (res);
878}
879
880static int
881GetFileNo (file)
882 PyObject *file; /* Either an int >= 0 or an object with a
883 .fileno() method that returns an int >= 0 */
884{
Guido van Rossuma597dde1995-01-10 20:56:29 +0000885 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000886 int id;
887 if (PyInt_Check(file)) {
888 id = PyInt_AsLong(file);
889 if (id < 0)
890 PyErr_SetString(PyExc_ValueError, "invalid file id");
891 return id;
892 }
893 meth = PyObject_GetAttrString(file, "fileno");
894 if (meth == NULL)
895 return -1;
896 args = PyTuple_New(0);
897 if (args == NULL)
898 return -1;
899 res = PyEval_CallObject(meth, args);
900 Py_DECREF(args);
901 Py_DECREF(meth);
902 if (res == NULL)
903 return -1;
904 if (PyInt_Check(res))
905 id = PyInt_AsLong(res);
906 else
907 id = -1;
908 if (id < 0)
909 PyErr_SetString(PyExc_ValueError,
910 "invalid fileno() return value");
911 Py_DECREF(res);
912 return id;
Guido van Rossum18468821994-06-20 07:49:28 +0000913}
914
915static PyObject *
916Tkapp_CreateFileHandler (self, args)
917 PyObject *self;
918 PyObject *args; /* Is (file, mask, func) */
919{
Guido van Rossum76875221994-06-27 07:59:42 +0000920 PyObject *file, *func, *data;
921 int mask, id;
Guido van Rossum68784361996-05-16 17:17:31 +0000922#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
923 Tcl_File tfile;
924#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000925
926 if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
927 return NULL;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000928 id = GetFileNo (file);
929 if (id < 0)
930 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +0000931 if (!PyCallable_Check(func))
Guido van Rossum18468821994-06-20 07:49:28 +0000932 {
933 PyErr_SetString (PyExc_TypeError, "bad argument list");
934 return NULL;
935 }
936
Guido van Rossum76875221994-06-27 07:59:42 +0000937 /* ClientData is: (func, file) */
938 data = Py_BuildValue ("(OO)", func, file);
939
Guido van Rossum68784361996-05-16 17:17:31 +0000940#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum07886d01996-09-11 23:31:42 +0000941#ifdef MS_WINDOWS
Guido van Rossum845547d1996-06-26 18:26:04 +0000942 /* We assume this is a socket... */
943 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
944#else
Guido van Rossum68784361996-05-16 17:17:31 +0000945 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
Guido van Rossum845547d1996-06-26 18:26:04 +0000946#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000947 /* Oughtta check for null Tcl_File object... */
948 Tcl_CreateFileHandler (tfile, mask, FileHandler, (ClientData) data);
949#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000950 Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
Guido van Rossum68784361996-05-16 17:17:31 +0000951#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000952 /* XXX fileHandlerDict */
Guido van Rossum76875221994-06-27 07:59:42 +0000953
Guido van Rossum18468821994-06-20 07:49:28 +0000954 Py_INCREF (Py_None);
955 return Py_None;
956}
957
958static PyObject *
959Tkapp_DeleteFileHandler (self, args)
960 PyObject *self;
961 PyObject *args; /* Args: file */
962{
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000963 PyObject *file;
Guido van Rossum18468821994-06-20 07:49:28 +0000964 int id;
Guido van Rossum68784361996-05-16 17:17:31 +0000965#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
966 Tcl_File tfile;
967#endif
968
Guido van Rossum9bb4fd61994-08-09 14:15:19 +0000969 if (!PyArg_Parse (args, "O", &file))
970 return NULL;
971 id = GetFileNo (file);
972 if (id < 0)
973 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000974
Guido van Rossum68784361996-05-16 17:17:31 +0000975#if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
Guido van Rossum07886d01996-09-11 23:31:42 +0000976#ifdef MS_WINDOWS
Guido van Rossum845547d1996-06-26 18:26:04 +0000977 /* We assume this is a socket... */
978 tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
979#else
980 tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
981#endif
Guido van Rossum68784361996-05-16 17:17:31 +0000982 /* Oughtta check for null Tcl_File object... */
983 Tcl_DeleteFileHandler(tfile);
984#else
Guido van Rossum845547d1996-06-26 18:26:04 +0000985 Tk_DeleteFileHandler (id);
Guido van Rossum68784361996-05-16 17:17:31 +0000986#endif
Guido van Rossum18468821994-06-20 07:49:28 +0000987 /* XXX fileHandlerDict */
988 Py_INCREF (Py_None);
989 return Py_None;
990}
991
Guido van Rossumf34cadd1994-11-10 22:50:21 +0000992/**** Tktt Object (timer token) ****/
993
994staticforward PyTypeObject Tktt_Type;
995
996typedef struct
997 {
998 PyObject_HEAD
999 Tk_TimerToken token;
1000 PyObject *func;
1001 }
1002TkttObject;
1003
1004static PyObject *
1005Tktt_DeleteTimerHandler (self, args)
1006 PyObject *self;
1007 PyObject *args;
1008{
1009 TkttObject *v = (TkttObject *) self;
1010
1011 if (!PyArg_Parse (args, ""))
1012 return NULL;
1013 if (v->func != NULL)
1014 {
1015 Tk_DeleteTimerHandler (v->token);
1016 PyMem_DEL (v->func);
1017 v->func = NULL;
1018 }
1019 Py_INCREF (Py_None);
1020 return Py_None;
1021}
1022
1023static PyMethodDef Tktt_methods[] =
1024{
1025 {"deletetimerhandler", Tktt_DeleteTimerHandler},
1026 {NULL, NULL}
1027};
1028
1029static TkttObject *
1030Tktt_New (token, func)
1031 Tk_TimerToken token;
1032 PyObject *func;
1033{
1034 TkttObject *v;
1035
1036 v = PyObject_NEW (TkttObject, &Tktt_Type);
1037 if (v == NULL)
1038 return NULL;
1039
1040 v->token = token;
1041 v->func = func;
1042 Py_INCREF (v->func);
1043 return v;
1044}
1045
1046static void
1047Tktt_Dealloc (self)
1048 PyObject *self;
1049{
1050 PyMem_DEL (self);
1051}
1052
1053static int
1054Tktt_Print (self, fp, flags)
1055 PyObject *self;
1056 FILE *fp;
1057 int flags;
1058{
1059 TkttObject *v = (TkttObject *) self;
1060
Guido van Rossuma376cc51996-12-05 23:43:35 +00001061 fprintf(fp, "<tktimertoken at 0x%lx%s>", (long)v,
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001062 v->func == NULL ? ", handler deleted" : "");
1063 return 0;
1064}
1065
1066static PyObject *
1067Tktt_GetAttr (self, name)
1068 PyObject *self;
1069 char *name;
1070{
1071 return Py_FindMethod (Tktt_methods, self, name);
1072}
1073
1074static PyTypeObject Tktt_Type =
1075{
Guido van Rossumae92f011996-08-21 19:03:36 +00001076 PyObject_HEAD_INIT (NULL)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001077 0, /*ob_size */
1078 "tktimertoken", /*tp_name */
1079 sizeof (TkttObject), /*tp_basicsize */
1080 0, /*tp_itemsize */
1081 Tktt_Dealloc, /*tp_dealloc */
1082 Tktt_Print, /*tp_print */
1083 Tktt_GetAttr, /*tp_getattr */
1084 0, /*tp_setattr */
1085 0, /*tp_compare */
1086 0, /*tp_repr */
1087 0, /*tp_as_number */
1088 0, /*tp_as_sequence */
1089 0, /*tp_as_mapping */
1090 0, /*tp_hash */
1091};
1092
1093/** Timer Handler **/
1094
1095static void
1096TimerHandler (clientData)
1097 ClientData clientData;
1098{
1099 PyObject *func = (PyObject *) clientData;
1100 PyObject *arg, *res;
1101
1102 arg = PyTuple_New (0);
1103 res = PyEval_CallObject (func, arg);
1104 Py_DECREF (arg);
1105 if (res == NULL)
1106 {
1107 errorInCmd = 1;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001108 PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001109 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001110 else
1111 Py_DECREF (res);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001112}
1113
1114static PyObject *
1115Tkapp_CreateTimerHandler (self, args)
1116 PyObject *self;
1117 PyObject *args; /* Is (milliseconds, func) */
1118{
1119 int milliseconds;
1120 PyObject *func;
1121 Tk_TimerToken token;
1122
1123 if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
1124 return NULL;
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001125 if (!PyCallable_Check(func))
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001126 {
1127 PyErr_SetString (PyExc_TypeError, "bad argument list");
1128 return NULL;
1129 }
1130 token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
1131 return (PyObject *) Tktt_New (token, func);
1132}
1133
Guido van Rossum18468821994-06-20 07:49:28 +00001134/** Event Loop **/
1135
Guido van Rossum18468821994-06-20 07:49:28 +00001136static PyObject *
1137Tkapp_MainLoop (self, args)
1138 PyObject *self;
1139 PyObject *args;
1140{
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001141 int threshold = 0;
1142
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001143 if (!PyArg_ParseTuple (args, "|i", &threshold))
1144 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001145
1146 quitMainLoop = 0;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001147 while (Tk_GetNumMainWindows() > threshold && !quitMainLoop && !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001148 {
Guido van Rossuma376cc51996-12-05 23:43:35 +00001149 /* XXX Ought to check for other signals! */
Guido van Rossum18468821994-06-20 07:49:28 +00001150 if (PyOS_InterruptOccurred ())
1151 {
1152 PyErr_SetNone (PyExc_KeyboardInterrupt);
1153 return NULL;
1154 }
1155 Tk_DoOneEvent (0);
1156 }
Guido van Rossum64b24fb1995-09-30 17:00:24 +00001157 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001158
1159 if (errorInCmd)
1160 {
1161 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001162 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1163 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001164 return NULL;
1165 }
1166 Py_INCREF (Py_None);
1167 return Py_None;
1168}
1169
1170static PyObject *
Guido van Rossum062cfb01995-01-10 17:42:51 +00001171Tkapp_DoOneEvent (self, args)
1172 PyObject *self;
1173 PyObject *args;
1174{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001175 int flags = TK_ALL_EVENTS;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001176 int rv;
1177
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001178 if (!PyArg_ParseTuple (args, "|i", &flags))
1179 return NULL;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001180 rv = Tk_DoOneEvent(flags);
1181 return Py_BuildValue ("i", rv);
1182}
1183
1184static PyObject *
Guido van Rossum18468821994-06-20 07:49:28 +00001185Tkapp_Quit (self, args)
1186 PyObject *self;
1187 PyObject *args;
1188{
1189
1190 if (!PyArg_Parse (args, ""))
1191 return NULL;
1192 quitMainLoop = 1;
1193 Py_INCREF (Py_None);
1194 return Py_None;
1195}
1196
1197/**** Tkapp Method List ****/
1198
1199static PyMethodDef Tkapp_methods[] =
1200{
1201 {"call", Tkapp_Call},
1202 {"globalcall", Tkapp_GlobalCall},
1203 {"eval", Tkapp_Eval},
1204 {"globaleval", Tkapp_GlobalEval},
1205 {"evalfile", Tkapp_EvalFile},
1206 {"record", Tkapp_Record},
1207 {"adderrorinfo", Tkapp_AddErrorInfo},
1208 {"setvar", Tkapp_SetVar},
1209 {"globalsetvar", Tkapp_GlobalSetVar},
1210 {"getvar", Tkapp_GetVar},
1211 {"globalgetvar", Tkapp_GlobalGetVar},
1212 {"unsetvar", Tkapp_UnsetVar},
1213 {"globalunsetvar", Tkapp_GlobalUnsetVar},
1214 {"getint", Tkapp_GetInt},
1215 {"getdouble", Tkapp_GetDouble},
1216 {"getboolean", Tkapp_GetBoolean},
1217 {"exprstring", Tkapp_ExprString},
1218 {"exprlong", Tkapp_ExprLong},
1219 {"exprdouble", Tkapp_ExprDouble},
1220 {"exprboolean", Tkapp_ExprBoolean},
1221 {"splitlist", Tkapp_SplitList},
1222 {"split", Tkapp_Split},
1223 {"merge", Tkapp_Merge},
1224 {"createcommand", Tkapp_CreateCommand},
1225 {"deletecommand", Tkapp_DeleteCommand},
1226 {"createfilehandler", Tkapp_CreateFileHandler},
1227 {"deletefilehandler", Tkapp_DeleteFileHandler},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001228 {"createtimerhandler", Tkapp_CreateTimerHandler},
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001229 {"mainloop", Tkapp_MainLoop, 1},
1230 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum18468821994-06-20 07:49:28 +00001231 {"quit", Tkapp_Quit},
1232 {NULL, NULL}
1233};
1234
1235/**** Tkapp Type Methods ****/
1236
1237static void
1238Tkapp_Dealloc (self)
1239 PyObject *self;
1240{
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001241#ifdef NEED_TKCREATEMAINWINDOW
Guido van Rossum18468821994-06-20 07:49:28 +00001242 Tk_DestroyWindow (Tkapp_Tkwin (self));
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001243#endif
Guido van Rossum18468821994-06-20 07:49:28 +00001244 Tcl_DeleteInterp (Tkapp_Interp (self));
1245 PyMem_DEL (self);
1246}
1247
1248static PyObject *
1249Tkapp_GetAttr (self, name)
1250 PyObject *self;
1251 char *name;
1252{
1253 return Py_FindMethod (Tkapp_methods, self, name);
1254}
1255
1256static PyTypeObject Tkapp_Type =
1257{
Guido van Rossumae92f011996-08-21 19:03:36 +00001258 PyObject_HEAD_INIT (NULL)
Guido van Rossum18468821994-06-20 07:49:28 +00001259 0, /*ob_size */
1260 "tkapp", /*tp_name */
1261 sizeof (TkappObject), /*tp_basicsize */
1262 0, /*tp_itemsize */
1263 Tkapp_Dealloc, /*tp_dealloc */
1264 0, /*tp_print */
1265 Tkapp_GetAttr, /*tp_getattr */
1266 0, /*tp_setattr */
1267 0, /*tp_compare */
1268 0, /*tp_repr */
1269 0, /*tp_as_number */
1270 0, /*tp_as_sequence */
1271 0, /*tp_as_mapping */
1272 0, /*tp_hash */
1273};
1274
1275/**** Tkinter Module ****/
1276
1277static PyObject *
1278Tkinter_Create (self, args)
1279 PyObject *self;
1280 PyObject *args;
1281{
1282 char *screenName = NULL;
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001283 char *baseName = NULL;
1284 char *className = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001285 int interactive = 0;
1286
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001287 baseName = strrchr (Py_GetProgramName (), '/');
Guido van Rossum18468821994-06-20 07:49:28 +00001288 if (baseName != NULL)
1289 baseName++;
1290 else
Guido van Rossum32aa1a71996-07-31 19:51:15 +00001291 baseName = Py_GetProgramName ();
Guido van Rossum18468821994-06-20 07:49:28 +00001292 className = "Tk";
1293
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001294 if (!PyArg_ParseTuple (args, "|zssi",
1295 &screenName, &baseName, &className, &interactive))
Guido van Rossum18468821994-06-20 07:49:28 +00001296 return NULL;
1297
1298 return (PyObject *) Tkapp_New (screenName, baseName, className,
1299 interactive);
1300}
1301
1302static PyMethodDef moduleMethods[] =
1303{
Guido van Rossume42fc2f1995-07-26 17:29:45 +00001304 {"create", Tkinter_Create, 1},
1305 {"createfilehandler", Tkapp_CreateFileHandler, 0},
1306 {"deletefilehandler", Tkapp_DeleteFileHandler, 0},
1307 {"createtimerhandler", Tkapp_CreateTimerHandler, 0},
1308 {"mainloop", Tkapp_MainLoop, 1},
1309 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001310 {"quit", Tkapp_Quit},
Guido van Rossum18468821994-06-20 07:49:28 +00001311 {NULL, NULL}
1312};
1313
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001314#undef WITH_READLINE /* XXX */
Guido van Rossum18468821994-06-20 07:49:28 +00001315#ifdef WITH_READLINE
1316static int
1317EventHook ()
1318{
1319 if (errorInCmd) /* XXX Reset tty */
1320 {
1321 errorInCmd = 0;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001322 PyErr_Restore (excInCmd, valInCmd, trbInCmd);
1323 excInCmd = valInCmd = trbInCmd = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001324 PyErr_Print ();
1325 }
Guido van Rossum9722ad81995-09-22 23:49:28 +00001326 if (Tk_GetNumMainWindows() > 0)
Guido van Rossume2ca9bd1994-08-03 08:01:43 +00001327 Tk_DoOneEvent (TK_DONT_WAIT);
Guido van Rossum18468821994-06-20 07:49:28 +00001328 return 0;
1329}
1330#endif /* WITH_READLINE */
1331
1332static void
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001333Tkinter_Cleanup ()
1334{
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001335/* This segfault with Tk 4.0 beta and seems unnecessary there as well */
1336#if TK_MAJOR_VERSION < 4
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001337 /* XXX rl_deprep_terminal is static, damned! */
1338 while (tkMainWindowList != 0)
1339 Tk_DestroyWindow (tkMainWindowList->win);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001340#endif
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001341}
1342
Guido van Rossum18468821994-06-20 07:49:28 +00001343void
Guido van Rossumad1f7ee1996-02-13 00:11:37 +00001344init_tkinter ()
Guido van Rossum18468821994-06-20 07:49:28 +00001345{
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001346 static inited = 0;
1347
Guido van Rossum18468821994-06-20 07:49:28 +00001348#ifdef WITH_READLINE
1349 extern int (*rl_event_hook) ();
1350#endif /* WITH_READLINE */
1351 PyObject *m, *d, *v;
1352
Guido van Rossumae92f011996-08-21 19:03:36 +00001353 Tkapp_Type.ob_type = &PyType_Type;
1354 Tktt_Type.ob_type = &PyType_Type;
1355
Jack Jansenba0311e1995-10-23 14:34:14 +00001356 m = Py_InitModule ("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00001357
1358 d = PyModule_GetDict (m);
1359 Tkinter_TclError = Py_BuildValue ("s", "TclError");
1360 PyDict_SetItemString (d, "TclError", Tkinter_TclError);
1361
1362 v = Py_BuildValue ("i", TK_READABLE);
1363 PyDict_SetItemString (d, "READABLE", v);
1364 v = Py_BuildValue ("i", TK_WRITABLE);
1365 PyDict_SetItemString (d, "WRITABLE", v);
1366 v = Py_BuildValue ("i", TK_EXCEPTION);
1367 PyDict_SetItemString (d, "EXCEPTION", v);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001368 v = Py_BuildValue ("i", TK_X_EVENTS);
1369 PyDict_SetItemString (d, "X_EVENTS", v);
1370 v = Py_BuildValue ("i", TK_FILE_EVENTS);
1371 PyDict_SetItemString (d, "FILE_EVENTS", v);
1372 v = Py_BuildValue ("i", TK_TIMER_EVENTS);
1373 PyDict_SetItemString (d, "TIMER_EVENTS", v);
1374 v = Py_BuildValue ("i", TK_IDLE_EVENTS);
1375 PyDict_SetItemString (d, "IDLE_EVENTS", v);
1376 v = Py_BuildValue ("i", TK_ALL_EVENTS);
1377 PyDict_SetItemString (d, "ALL_EVENTS", v);
1378 v = Py_BuildValue ("i", TK_DONT_WAIT);
1379 PyDict_SetItemString (d, "DONT_WAIT", v);
Guido van Rossuma3c3f2c1995-02-07 15:41:02 +00001380 v = Py_BuildValue ("s", TK_VERSION);
1381 PyDict_SetItemString (d, "TK_VERSION", v);
1382 v = Py_BuildValue ("s", TCL_VERSION);
1383 PyDict_SetItemString (d, "TCL_VERSION", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001384
Guido van Rossum18468821994-06-20 07:49:28 +00001385#ifdef WITH_READLINE
1386 rl_event_hook = EventHook;
1387#endif /* WITH_READLINE */
1388
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001389 if (!inited)
1390 {
1391 inited = 1;
Guido van Rossume4485b01994-09-07 14:32:49 +00001392 if (Py_AtExit (Tkinter_Cleanup) != 0)
1393 fprintf(stderr,
1394 "Tkinter: warning: cleanup procedure not registered\n");
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001395 }
1396
Guido van Rossum18468821994-06-20 07:49:28 +00001397 if (PyErr_Occurred ())
Jack Jansenba0311e1995-10-23 14:34:14 +00001398 Py_FatalError ("can't initialize module _tkinter");
Jack Jansen34cc5c31995-10-31 16:15:12 +00001399#ifdef macintosh
Guido van Rossumec22c921996-02-25 04:50:29 +00001400 TclMacSetEventProc(PyMacConvertEvent);
1401#if GENERATINGCFM
Jack Jansen34cc5c31995-10-31 16:15:12 +00001402 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00001403#endif /* GENERATINGCFM */
1404#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00001405}
Guido van Rossum9722ad81995-09-22 23:49:28 +00001406
Guido van Rossumec22c921996-02-25 04:50:29 +00001407
Guido van Rossum9722ad81995-09-22 23:49:28 +00001408#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001409
1410/*
Guido van Rossumec22c921996-02-25 04:50:29 +00001411** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001412*/
1413
Guido van Rossum9722ad81995-09-22 23:49:28 +00001414void
1415panic(char * format, ...)
1416{
1417 va_list varg;
1418
1419 va_start(varg, format);
1420
1421 vfprintf(stderr, format, varg);
1422 (void) fflush(stderr);
1423
1424 va_end(varg);
1425
1426 Py_FatalError("Tcl/Tk panic");
1427}
Jack Jansen40b546d1995-11-14 10:34:45 +00001428
Guido van Rossumec22c921996-02-25 04:50:29 +00001429/*
1430** Pass events to SIOUX before passing them to Tk.
1431*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001432
Guido van Rossumec22c921996-02-25 04:50:29 +00001433static int
1434PyMacConvertEvent(eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001435 EventRecord *eventPtr;
1436{
Guido van Rossumec22c921996-02-25 04:50:29 +00001437 if (SIOUXHandleOneEvent(eventPtr))
1438 return 0; /* Nothing happened to the Tcl event queue */
1439 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001440}
1441
Guido van Rossumec22c921996-02-25 04:50:29 +00001442#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001443
1444/*
1445** Additional Mac specific code for dealing with shared libraries.
1446*/
1447
1448#include <Resources.h>
1449#include <CodeFragments.h>
1450
1451static int loaded_from_shlib = 0;
1452static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00001453
Jack Jansen34cc5c31995-10-31 16:15:12 +00001454/*
1455** If this module is dynamically loaded the following routine should
1456** be the init routine. It takes care of adding the shared library to
1457** the resource-file chain, so that the tk routines can find their
1458** resources.
1459*/
1460OSErr pascal
1461init_tkinter_shlib(InitBlockPtr data)
1462{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00001463 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00001464 if ( data == nil ) return noErr;
1465 if ( data->fragLocator.where == kOnDiskFlat ) {
1466 library_fss = *data->fragLocator.u.onDisk.fileSpec;
1467 loaded_from_shlib = 1;
1468 } else if ( data->fragLocator.where == kOnDiskSegmented ) {
1469 library_fss = *data->fragLocator.u.inSegs.fileSpec;
1470 loaded_from_shlib = 1;
1471 }
1472 return noErr;
1473}
1474
1475/*
1476** Insert the library resources into the search path. Put them after
1477** the resources from the application. Again, we ignore errors.
1478*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00001479static
Jack Jansen34cc5c31995-10-31 16:15:12 +00001480mac_addlibresources()
1481{
1482 if ( !loaded_from_shlib )
1483 return;
1484 (void)FSpOpenResFile(&library_fss, fsRdPerm);
1485}
1486
Guido van Rossumec22c921996-02-25 04:50:29 +00001487#endif /* GENERATINGCFM */
1488#endif /* macintosh */