blob: e0688721922ce6a941a5e2ffc02b83dac906576d [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:
Guido van Rossum496f8f61997-07-19 19:57:42 +000038 Tcl/Tk 8.0 (even alpha or beta) or 7.6/4.2 are recommended.
Guido van Rossum35d43371997-08-02 00:09:09 +000039 Versions 7.5/4.1 are the earliest versions still supported.
40 Versions 7.4/4.0 or Tk 3.x are no longer supported.
Guido van Rossum7ffa7611996-08-13 21:10:16 +000041
42 Mac and Windows:
Guido van Rossum496f8f61997-07-19 19:57:42 +000043 Use Tcl 8.0 if available (even alpha or beta).
44 The oldest usable version is 4.1p1/7.5p1.
45
Guido van Rossum212643f1998-04-29 16:22:14 +000046 XXX Further speed-up ideas, involving Tcl 8.0 features:
47
48 - In Tcl_Call(), create Tcl objects from the arguments, possibly using
49 intelligent mappings between Python objects and Tcl objects (e.g. ints,
50 floats and Tcl window pointers could be handled specially).
51
52 - Register a new Tcl type, "Python callable", which can be called more
53 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
54
Guido van Rossum7ffa7611996-08-13 21:10:16 +000055*/
56
Guido van Rossum35d43371997-08-02 00:09:09 +000057
Guido van Rossum9722ad81995-09-22 23:49:28 +000058#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000059#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000060
Guido van Rossum00d93061998-05-28 23:06:38 +000061#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000062#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000063#endif
64
Guido van Rossum2a5119b1998-05-29 01:28:40 +000065#ifdef MS_WINDOWS
66#include <windows.h>
67#endif
68
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000069#ifdef macintosh
70#define MAC_TCL
Guido van Rossum290283b1997-06-02 22:16:43 +000071#include "myselect.h"
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000072#endif
73
Guido van Rossum49b56061998-10-01 20:42:43 +000074#ifdef PYOS_OS2
75#include "myselect.h"
76#endif
77
Guido van Rossum18468821994-06-20 07:49:28 +000078#include <tcl.h>
79#include <tk.h>
80
Guido van Rossum3e819a71997-08-01 19:29:02 +000081#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
82
Guido van Rossum00d93061998-05-28 23:06:38 +000083#if TKMAJORMINOR < 4001
84 #error "Tk 4.0 or 3.x are not supported -- use 4.1 or higher"
85#endif
86
Guido van Rossum0d2390c1997-08-14 19:57:07 +000087#if TKMAJORMINOR >= 8000 && defined(macintosh)
88/* Sigh, we have to include this to get at the tcl qd pointer */
89#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000090/* And this one we need to clear the menu bar */
91#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000092#endif
93
Guido van Rossumb0105441997-10-08 15:25:37 +000094#if TKMAJORMINOR < 8000 || !defined(MS_WINDOWS)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000095#define HAVE_CREATEFILEHANDLER
96#endif
97
Guido van Rossum00d93061998-05-28 23:06:38 +000098#ifdef HAVE_CREATEFILEHANDLER
99
100/* Tcl_CreateFileHandler() changed several times; these macros deal with the
101 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
102 Unix, only because Jack added it back); when available on Windows, it only
103 applies to sockets. */
104
Guido van Rossum7bf15641998-05-22 18:28:17 +0000105#ifdef MS_WINDOWS
106#define FHANDLETYPE TCL_WIN_SOCKET
107#else
108#define FHANDLETYPE TCL_UNIX_FD
109#endif
110
111#if TKMAJORMINOR < 8000
112#define FHANDLE Tcl_File
113#define MAKEFHANDLE(fd) Tcl_GetFile((ClientData)(fd), FHANDLETYPE)
114#else
115#define FHANDLE int
116#define MAKEFHANDLE(fd) (fd)
117#endif
118
Guido van Rossum00d93061998-05-28 23:06:38 +0000119/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
120 which uses this to handle Tcl events while the user is typing commands. */
121
122#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000123#define WAIT_FOR_STDIN
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126#endif /* HAVE_CREATEFILEHANDLER */
127
Guido van Rossumad4db171998-06-13 13:56:28 +0000128#ifdef MS_WINDOWS
129#include <conio.h>
130#define WAIT_FOR_STDIN
131#endif
132
Guido van Rossum00d93061998-05-28 23:06:38 +0000133#ifdef WITH_THREAD
134
135/* The threading situation is complicated. Tcl is not thread-safe, except for
136 Tcl 8.1, which will probably remain in alpha status for another 6 months
137 (and the README says that Tk will probably remain thread-unsafe forever).
138 So we need to use a lock around all uses of Tcl. Previously, the Python
139 interpreter lock was used for this. However, this causes problems when
140 other Python threads need to run while Tcl is blocked waiting for events.
141
142 To solve this problem, a separate lock for Tcl is introduced. Holding it
143 is incompatible with holding Python's interpreter lock. The following four
144 macros manipulate both locks together.
145
146 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
147 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
148 that could call an event handler, or otherwise affect the state of a Tcl
149 interpreter. These assume that the surrounding code has the Python
150 interpreter lock; inside the brackets, the Python interpreter lock has been
151 released and the lock for Tcl has been acquired.
152
Guido van Rossum5e977831998-06-15 14:03:52 +0000153 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
154 (For example, when transferring data from the Tcl interpreter result to a
155 Python string object.) This can be done by using different macros to close
156 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
157 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
158 releases the Tcl lock.
159
Guido van Rossum00d93061998-05-28 23:06:38 +0000160 By contrast, ENTER_PYTHON(tstate) and LEAVE_PYTHON are used in Tcl event
161 handlers when the handler needs to use Python. Such event handlers are
162 entered while the lock for Tcl is held; the event handler presumably needs
163 to use Python. ENTER_PYTHON(tstate) releases the lock for Tcl and acquires
164 the Python interpreter lock, restoring the appropriate thread state, and
165 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
166 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
167 the code between ENTER_PYTHON(tstate) and LEAVE_PYTHON.
168
169 These locks expand to several statements and brackets; they should not be
170 used in branches of if statements and the like.
171
172*/
173
174static type_lock tcl_lock = 0;
175
176#define ENTER_TCL \
177 Py_BEGIN_ALLOW_THREADS acquire_lock(tcl_lock, 1);
178
179#define LEAVE_TCL \
180 release_lock(tcl_lock); Py_END_ALLOW_THREADS
181
Guido van Rossum62320c91998-06-15 04:36:09 +0000182#define ENTER_OVERLAP \
183 Py_END_ALLOW_THREADS
184
185#define LEAVE_OVERLAP_TCL \
186 release_lock(tcl_lock);
187
Guido van Rossum00d93061998-05-28 23:06:38 +0000188#define ENTER_PYTHON(tstate) \
Guido van Rossum00d93061998-05-28 23:06:38 +0000189 release_lock(tcl_lock); PyEval_RestoreThread((tstate));
190
191#define LEAVE_PYTHON \
192 PyEval_SaveThread(); acquire_lock(tcl_lock, 1);
193
194#else
195
196#define ENTER_TCL
197#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000198#define ENTER_OVERLAP
199#define LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000200#define ENTER_PYTHON(tstate)
201#define LEAVE_PYTHON
202
203#endif
204
Guido van Rossum35d43371997-08-02 00:09:09 +0000205extern int Tk_GetNumMainWindows();
206
Guido van Rossumec22c921996-02-25 04:50:29 +0000207#ifdef macintosh
208
209/*
210** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000211** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000212*/
213
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000214/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000215#define FREECAST (char *)
216
Guido van Rossumec22c921996-02-25 04:50:29 +0000217#include <Events.h> /* For EventRecord */
218
219typedef int (*TclMacConvertEventPtr) Py_PROTO((EventRecord *eventPtr));
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000220/* They changed the name... */
221#if TKMAJORMINOR < 8000
222#define Tcl_MacSetEventProc TclMacSetEventProc
223#endif
224void Tcl_MacSetEventProc Py_PROTO((TclMacConvertEventPtr procPtr));
Guido van Rossumec22c921996-02-25 04:50:29 +0000225int TkMacConvertEvent Py_PROTO((EventRecord *eventPtr));
226
227staticforward int PyMacConvertEvent Py_PROTO((EventRecord *eventPtr));
228
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000229#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
230 #pragma import on
231#endif
232
233#include <SIOUX.h>
234extern int SIOUXIsAppWindow(WindowPtr);
235
236#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
237 #pragma import reset
238#endif
Guido van Rossumec22c921996-02-25 04:50:29 +0000239#endif /* macintosh */
240
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000242#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000243#endif
244
Guido van Rossum18468821994-06-20 07:49:28 +0000245/**** Tkapp Object Declaration ****/
246
247staticforward PyTypeObject Tkapp_Type;
248
Guido van Rossum00d93061998-05-28 23:06:38 +0000249typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000250 PyObject_HEAD
251 Tcl_Interp *interp;
Guido van Rossum00d93061998-05-28 23:06:38 +0000252} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000253
254#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000255#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
256#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
257
Guido van Rossum35d43371997-08-02 00:09:09 +0000258#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000259(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000260
Barry Warsawfa701a81997-01-16 00:15:11 +0000261
262
Guido van Rossum18468821994-06-20 07:49:28 +0000263/**** Error Handling ****/
264
265static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000266static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000267static int errorInCmd = 0;
268static PyObject *excInCmd;
269static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000270static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
273
Guido van Rossum18468821994-06-20 07:49:28 +0000274static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000275Tkinter_Error(v)
276 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000277{
Barry Warsawfa701a81997-01-16 00:15:11 +0000278 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
279 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000280}
281
Barry Warsawfa701a81997-01-16 00:15:11 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Guido van Rossum18468821994-06-20 07:49:28 +0000284/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000285
286#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000287#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000288#include "mytime.h"
289
Guido van Rossum00d93061998-05-28 23:06:38 +0000290/* Millisecond sleep() for Unix platforms. */
291
292static void
293Sleep(milli)
294 int milli;
295{
296 /* XXX Too bad if you don't have select(). */
297 struct timeval t;
298 double frac;
299 t.tv_sec = milli/1000;
300 t.tv_usec = (milli%1000) * 1000;
301 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
302}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000303#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000304#endif /* WITH_THREAD */
305
306
Guido van Rossum18468821994-06-20 07:49:28 +0000307static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000308AsString(value, tmp)
309 PyObject *value;
310 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000311{
Guido van Rossum35d43371997-08-02 00:09:09 +0000312 if (PyString_Check(value))
313 return PyString_AsString(value);
Barry Warsawfa701a81997-01-16 00:15:11 +0000314 else {
315 PyObject *v = PyObject_Str(value);
316 PyList_Append(tmp, v);
317 Py_DECREF(v);
318 return PyString_AsString(v);
319 }
Guido van Rossum18468821994-06-20 07:49:28 +0000320}
321
Barry Warsawfa701a81997-01-16 00:15:11 +0000322
323
Guido van Rossum18468821994-06-20 07:49:28 +0000324#define ARGSZ 64
325
326static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000327Merge(args)
328 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000329{
Barry Warsawfa701a81997-01-16 00:15:11 +0000330 PyObject *tmp = NULL;
331 char *argvStore[ARGSZ];
332 char **argv = NULL;
333 int fvStore[ARGSZ];
334 int *fv = NULL;
335 int argc = 0, i;
336 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000337
Barry Warsawfa701a81997-01-16 00:15:11 +0000338 if (!(tmp = PyList_New(0)))
339 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000340
Barry Warsawfa701a81997-01-16 00:15:11 +0000341 argv = argvStore;
342 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000343
Barry Warsawfa701a81997-01-16 00:15:11 +0000344 if (args == NULL)
345 argc = 0;
346
347 else if (!PyTuple_Check(args)) {
348 argc = 1;
349 fv[0] = 0;
350 argv[0] = AsString(args, tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000351 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000352 else {
353 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000354
Barry Warsawfa701a81997-01-16 00:15:11 +0000355 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000356 argv = (char **)ckalloc(argc * sizeof(char *));
357 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000358 if (argv == NULL || fv == NULL) {
359 PyErr_NoMemory();
360 goto finally;
361 }
362 }
363
364 for (i = 0; i < argc; i++) {
365 PyObject *v = PyTuple_GetItem(args, i);
366 if (PyTuple_Check(v)) {
367 fv[i] = 1;
368 if (!(argv[i] = Merge(v)))
369 goto finally;
370 }
371 else if (v == Py_None) {
372 argc = i;
373 break;
374 }
375 else {
376 fv[i] = 0;
377 argv[i] = AsString(v, tmp);
378 }
379 }
Guido van Rossum18468821994-06-20 07:49:28 +0000380 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000381 res = Tcl_Merge(argc, argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000382
Barry Warsawfa701a81997-01-16 00:15:11 +0000383 finally:
384 for (i = 0; i < argc; i++)
385 if (fv[i]) {
386 ckfree(argv[i]);
387 }
388 if (argv != argvStore)
389 ckfree(FREECAST argv);
390 if (fv != fvStore)
391 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000392
Barry Warsawfa701a81997-01-16 00:15:11 +0000393 Py_DECREF(tmp);
394 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000395}
396
Barry Warsawfa701a81997-01-16 00:15:11 +0000397
398
Guido van Rossum18468821994-06-20 07:49:28 +0000399static PyObject *
Guido van Rossum00d93061998-05-28 23:06:38 +0000400Split(list)
Barry Warsawfa701a81997-01-16 00:15:11 +0000401 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +0000402{
Barry Warsawfa701a81997-01-16 00:15:11 +0000403 int argc;
404 char **argv;
405 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000406
Barry Warsawfa701a81997-01-16 00:15:11 +0000407 if (list == NULL) {
408 Py_INCREF(Py_None);
409 return Py_None;
410 }
Guido van Rossum18468821994-06-20 07:49:28 +0000411
Guido van Rossum00d93061998-05-28 23:06:38 +0000412 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 /* Not a list.
414 * Could be a quoted string containing funnies, e.g. {"}.
415 * Return the string itself.
416 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000417 return PyString_FromString(list);
418 }
Guido van Rossum18468821994-06-20 07:49:28 +0000419
Barry Warsawfa701a81997-01-16 00:15:11 +0000420 if (argc == 0)
421 v = PyString_FromString("");
422 else if (argc == 1)
423 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000424 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000425 int i;
426 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000427
Barry Warsawfa701a81997-01-16 00:15:11 +0000428 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000429 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 Py_DECREF(v);
431 v = NULL;
432 break;
433 }
434 PyTuple_SetItem(v, i, w);
435 }
436 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000437 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000438 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000439}
440
Barry Warsawfa701a81997-01-16 00:15:11 +0000441
442
Guido van Rossum18468821994-06-20 07:49:28 +0000443/**** Tkapp Object ****/
444
445#ifndef WITH_APPINIT
446int
Guido van Rossum35d43371997-08-02 00:09:09 +0000447Tcl_AppInit(interp)
Barry Warsawfa701a81997-01-16 00:15:11 +0000448 Tcl_Interp *interp;
Guido van Rossum18468821994-06-20 07:49:28 +0000449{
Barry Warsawfa701a81997-01-16 00:15:11 +0000450 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000451
Barry Warsawfa701a81997-01-16 00:15:11 +0000452 main = Tk_MainWindow(interp);
453 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000454 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 return TCL_ERROR;
456 }
457 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000458 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 return TCL_ERROR;
460 }
461 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000462}
463#endif /* !WITH_APPINIT */
464
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466
467
468/* Initialize the Tk application; see the `main' function in
469 * `tkMain.c'.
470 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000471
472static void EnableEventHook(); /* Forward */
473static void DisableEventHook(); /* Forward */
474
Barry Warsawfa701a81997-01-16 00:15:11 +0000475static TkappObject *
476Tkapp_New(screenName, baseName, className, interactive)
477 char *screenName;
478 char *baseName;
479 char *className;
480 int interactive;
481{
482 TkappObject *v;
483 char *argv0;
484
485 v = PyObject_NEW(TkappObject, &Tkapp_Type);
486 if (v == NULL)
487 return NULL;
488
489 v->interp = Tcl_CreateInterp();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000490
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000491#if defined(macintosh) && TKMAJORMINOR >= 8000
492 /* This seems to be needed since Tk 8.0 */
493 ClearMenuBar();
494 TkMacInitMenus(v->interp);
495#endif
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000496 /* Delete the 'exit' command, which can screw things up */
497 Tcl_DeleteCommand(v->interp, "exit");
498
Barry Warsawfa701a81997-01-16 00:15:11 +0000499 if (screenName != NULL)
500 Tcl_SetVar2(v->interp, "env", "DISPLAY",
501 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000502
Barry Warsawfa701a81997-01-16 00:15:11 +0000503 if (interactive)
504 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
505 else
506 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000507
Barry Warsawfa701a81997-01-16 00:15:11 +0000508 /* This is used to get the application class for Tk 4.1 and up */
509 argv0 = (char*)ckalloc(strlen(className) + 1);
510 if (!argv0) {
511 PyErr_NoMemory();
512 Py_DECREF(v);
513 return NULL;
514 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000515
Barry Warsawfa701a81997-01-16 00:15:11 +0000516 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000517 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000518 argv0[0] = tolower(argv0[0]);
519 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
520 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000521
Barry Warsawfa701a81997-01-16 00:15:11 +0000522 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000523 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000524
Guido van Rossum7bf15641998-05-22 18:28:17 +0000525 EnableEventHook();
526
Barry Warsawfa701a81997-01-16 00:15:11 +0000527 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000528}
529
Barry Warsawfa701a81997-01-16 00:15:11 +0000530
531
Guido van Rossum18468821994-06-20 07:49:28 +0000532/** Tcl Eval **/
533
534static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000535Tkapp_Call(self, args)
536 PyObject *self;
537 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000538{
Guido van Rossum212643f1998-04-29 16:22:14 +0000539 /* This is copied from Merge() */
540 PyObject *tmp = NULL;
541 char *argvStore[ARGSZ];
542 char **argv = NULL;
543 int fvStore[ARGSZ];
544 int *fv = NULL;
545 int argc = 0, i;
546 PyObject *res = NULL; /* except this has a different type */
547 Tcl_CmdInfo info; /* and this is added */
548 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
Guido van Rossum18468821994-06-20 07:49:28 +0000549
Guido van Rossum212643f1998-04-29 16:22:14 +0000550 if (!(tmp = PyList_New(0)))
551 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000552
Guido van Rossum212643f1998-04-29 16:22:14 +0000553 argv = argvStore;
554 fv = fvStore;
Barry Warsawfa701a81997-01-16 00:15:11 +0000555
Guido van Rossum212643f1998-04-29 16:22:14 +0000556 if (args == NULL)
557 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000558
Guido van Rossum212643f1998-04-29 16:22:14 +0000559 else if (!PyTuple_Check(args)) {
560 argc = 1;
561 fv[0] = 0;
562 argv[0] = AsString(args, tmp);
563 }
564 else {
565 argc = PyTuple_Size(args);
566
567 if (argc > ARGSZ) {
568 argv = (char **)ckalloc(argc * sizeof(char *));
569 fv = (int *)ckalloc(argc * sizeof(int));
570 if (argv == NULL || fv == NULL) {
571 PyErr_NoMemory();
572 goto finally;
573 }
574 }
575
576 for (i = 0; i < argc; i++) {
577 PyObject *v = PyTuple_GetItem(args, i);
578 if (PyTuple_Check(v)) {
579 fv[i] = 1;
580 if (!(argv[i] = Merge(v)))
581 goto finally;
582 }
583 else if (v == Py_None) {
584 argc = i;
585 break;
586 }
587 else {
588 fv[i] = 0;
589 argv[i] = AsString(v, tmp);
590 }
591 }
592 }
593 /* End code copied from Merge() */
594
595 /* All this to avoid a call to Tcl_Merge() and the corresponding call
596 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
597 if (Py_VerboseFlag >= 2) {
598 for (i = 0; i < argc; i++)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000599 PySys_WriteStderr("%s ", argv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000600 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000601 ENTER_TCL
602 info.proc = NULL;
Guido van Rossum212643f1998-04-29 16:22:14 +0000603 if (argc < 1 ||
604 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
605 info.proc == NULL)
606 {
607 char *cmd;
Guido van Rossum212643f1998-04-29 16:22:14 +0000608 cmd = Tcl_Merge(argc, argv);
609 i = Tcl_Eval(interp, cmd);
Barry Warsawfa701a81997-01-16 00:15:11 +0000610 ckfree(cmd);
Guido van Rossum212643f1998-04-29 16:22:14 +0000611 }
612 else {
613 Tcl_ResetResult(interp);
614 i = (*info.proc)(info.clientData, interp, argc, argv);
615 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000616 ENTER_OVERLAP
617 if (info.proc == NULL && Py_VerboseFlag >= 2)
618 PySys_WriteStderr("... use TclEval ");
Guido van Rossum212643f1998-04-29 16:22:14 +0000619 if (i == TCL_ERROR) {
620 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000621 PySys_WriteStderr("... error: '%s'\n",
Guido van Rossum212643f1998-04-29 16:22:14 +0000622 interp->result);
623 Tkinter_Error(self);
624 }
625 else {
626 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000627 PySys_WriteStderr("-> '%s'\n", interp->result);
Guido van Rossum212643f1998-04-29 16:22:14 +0000628 res = PyString_FromString(interp->result);
629 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000630 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000631
Guido van Rossum212643f1998-04-29 16:22:14 +0000632 /* Copied from Merge() again */
633 finally:
634 for (i = 0; i < argc; i++)
635 if (fv[i]) {
636 ckfree(argv[i]);
637 }
638 if (argv != argvStore)
639 ckfree(FREECAST argv);
640 if (fv != fvStore)
641 ckfree(FREECAST fv);
642
643 Py_DECREF(tmp);
Barry Warsawfa701a81997-01-16 00:15:11 +0000644 return res;
645}
646
647
648static PyObject *
649Tkapp_GlobalCall(self, args)
650 PyObject *self;
651 PyObject *args;
652{
Guido van Rossum212643f1998-04-29 16:22:14 +0000653 /* Could do the same here as for Tkapp_Call(), but this is not used
654 much, so I can't be bothered. Unfortunately Tcl doesn't export a
655 way for the user to do what all its Global* variants do (save and
656 reset the scope pointer, call the local version, restore the saved
657 scope pointer). */
658
Guido van Rossum62320c91998-06-15 04:36:09 +0000659 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +0000660 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000661
Guido van Rossum62320c91998-06-15 04:36:09 +0000662 cmd = Merge(args);
Barry Warsawfa701a81997-01-16 00:15:11 +0000663 if (!cmd)
664 PyErr_SetString(Tkinter_TclError, "merge failed");
665
Guido van Rossum00d93061998-05-28 23:06:38 +0000666 else {
667 int err;
668 ENTER_TCL
669 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +0000670 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000671 if (err == TCL_ERROR)
672 res = Tkinter_Error(self);
673 else
674 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +0000675 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000676 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000677
678 if (cmd)
679 ckfree(cmd);
680
681 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000682}
683
684static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000685Tkapp_Eval(self, args)
686 PyObject *self;
687 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000688{
Barry Warsawfa701a81997-01-16 00:15:11 +0000689 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000690 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000691 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000692
Guido van Rossum35d43371997-08-02 00:09:09 +0000693 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000694 return NULL;
695
Guido van Rossum00d93061998-05-28 23:06:38 +0000696 ENTER_TCL
697 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000698 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000699 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000700 res = Tkinter_Error(self);
701 else
702 res = PyString_FromString(Tkapp_Result(self));
703 LEAVE_OVERLAP_TCL
704 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000705}
706
707static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000708Tkapp_GlobalEval(self, args)
709 PyObject *self;
710 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000711{
Barry Warsawfa701a81997-01-16 00:15:11 +0000712 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000713 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000714 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +0000715
Guido van Rossum35d43371997-08-02 00:09:09 +0000716 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000717 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000718
Guido van Rossum00d93061998-05-28 23:06:38 +0000719 ENTER_TCL
720 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000721 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000722 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000723 res = Tkinter_Error(self);
724 else
725 res = PyString_FromString(Tkapp_Result(self));
726 LEAVE_OVERLAP_TCL
727 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000728}
729
730static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000731Tkapp_EvalFile(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000732 PyObject *self;
733 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000734{
Barry Warsawfa701a81997-01-16 00:15:11 +0000735 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +0000736 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000737 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000738
Guido van Rossum35d43371997-08-02 00:09:09 +0000739 if (!PyArg_ParseTuple(args, "s", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +0000740 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000741
Guido van Rossum00d93061998-05-28 23:06:38 +0000742 ENTER_TCL
743 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +0000744 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000745 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000746 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +0000747
Guido van Rossum62320c91998-06-15 04:36:09 +0000748 else
749 res = PyString_FromString(Tkapp_Result(self));
750 LEAVE_OVERLAP_TCL
751 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000752}
753
754static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000755Tkapp_Record(self, args)
756 PyObject *self;
757 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000758{
Barry Warsawfa701a81997-01-16 00:15:11 +0000759 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000760 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000761 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000762
Guido van Rossum35d43371997-08-02 00:09:09 +0000763 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000764 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000765
Guido van Rossum00d93061998-05-28 23:06:38 +0000766 ENTER_TCL
767 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +0000768 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000769 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000770 res = Tkinter_Error(self);
771 else
772 res = PyString_FromString(Tkapp_Result(self));
773 LEAVE_OVERLAP_TCL
774 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000775}
776
777static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000778Tkapp_AddErrorInfo(self, args)
779 PyObject *self;
780 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000781{
Barry Warsawfa701a81997-01-16 00:15:11 +0000782 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +0000783
Guido van Rossum35d43371997-08-02 00:09:09 +0000784 if (!PyArg_ParseTuple(args, "s", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +0000785 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000786 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000787 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +0000788 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +0000789
Barry Warsawfa701a81997-01-16 00:15:11 +0000790 Py_INCREF(Py_None);
791 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000792}
793
Barry Warsawfa701a81997-01-16 00:15:11 +0000794
795
Guido van Rossum18468821994-06-20 07:49:28 +0000796/** Tcl Variable **/
797
798static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000799SetVar(self, args, flags)
800 PyObject *self;
801 PyObject *args;
802 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000803{
Guido van Rossum00d93061998-05-28 23:06:38 +0000804 char *name1, *name2, *ok, *s;
Barry Warsawfa701a81997-01-16 00:15:11 +0000805 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +0000806 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000807
Guido van Rossum62320c91998-06-15 04:36:09 +0000808 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +0000809 if (!tmp)
810 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000811
Guido van Rossum00d93061998-05-28 23:06:38 +0000812 if (PyArg_ParseTuple(args, "sO", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000813 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +0000814 s = AsString(newValue, tmp);
815 ENTER_TCL
816 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
817 LEAVE_TCL
818 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000819 else {
Guido van Rossum35d43371997-08-02 00:09:09 +0000820 PyErr_Clear();
Guido van Rossum00d93061998-05-28 23:06:38 +0000821 if (PyArg_ParseTuple(args, "ssO", &name1, &name2, &newValue)) {
822 s = AsString (newValue, tmp);
823 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000824 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
Guido van Rossum00d93061998-05-28 23:06:38 +0000825 s, flags);
826 LEAVE_TCL
827 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000828 else {
Guido van Rossum00d93061998-05-28 23:06:38 +0000829 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +0000830 return NULL;
831 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000832 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000833 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000834
Barry Warsawfa701a81997-01-16 00:15:11 +0000835 if (!ok)
836 return Tkinter_Error(self);
837
838 Py_INCREF(Py_None);
839 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000840}
841
842static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000843Tkapp_SetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000844 PyObject *self;
845 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000846{
Barry Warsawfa701a81997-01-16 00:15:11 +0000847 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000848}
849
850static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000851Tkapp_GlobalSetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000852 PyObject *self;
853 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000854{
Barry Warsawfa701a81997-01-16 00:15:11 +0000855 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000856}
857
Barry Warsawfa701a81997-01-16 00:15:11 +0000858
859
Guido van Rossum18468821994-06-20 07:49:28 +0000860static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000861GetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000862 PyObject *self;
863 PyObject *args;
864 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000865{
Guido van Rossum35d43371997-08-02 00:09:09 +0000866 char *name1, *name2=NULL, *s;
Guido van Rossum62320c91998-06-15 04:36:09 +0000867 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000868
Guido van Rossum35d43371997-08-02 00:09:09 +0000869 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
870 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000871 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000872 if (name2 == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000873 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
Guido van Rossum18468821994-06-20 07:49:28 +0000874
Barry Warsawfa701a81997-01-16 00:15:11 +0000875 else
Guido van Rossum35d43371997-08-02 00:09:09 +0000876 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000877 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000878
Barry Warsawfa701a81997-01-16 00:15:11 +0000879 if (s == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000880 res = Tkinter_Error(self);
881 else
882 res = PyString_FromString(s);
883 LEAVE_OVERLAP_TCL
884 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000885}
886
887static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000888Tkapp_GetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000889 PyObject *self;
890 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000891{
Barry Warsawfa701a81997-01-16 00:15:11 +0000892 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000893}
894
895static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000896Tkapp_GlobalGetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000897 PyObject *self;
898 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000899{
Barry Warsawfa701a81997-01-16 00:15:11 +0000900 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000901}
902
Barry Warsawfa701a81997-01-16 00:15:11 +0000903
904
Guido van Rossum18468821994-06-20 07:49:28 +0000905static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000906UnsetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000907 PyObject *self;
908 PyObject *args;
909 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000910{
Guido van Rossum35d43371997-08-02 00:09:09 +0000911 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +0000912 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000913 int code;
Guido van Rossum18468821994-06-20 07:49:28 +0000914
Guido van Rossum35d43371997-08-02 00:09:09 +0000915 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +0000916 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000917 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000918 if (name2 == NULL)
919 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
920
921 else
922 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000923 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000924
Barry Warsawfa701a81997-01-16 00:15:11 +0000925 if (code == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000926 res = Tkinter_Error(self);
927 else {
928 Py_INCREF(Py_None);
929 res = Py_None;
930 }
931 LEAVE_OVERLAP_TCL
932 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000933}
934
935static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000936Tkapp_UnsetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000937 PyObject *self;
938 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000939{
Barry Warsawfa701a81997-01-16 00:15:11 +0000940 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000941}
942
943static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000944Tkapp_GlobalUnsetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000945 PyObject *self;
946 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000947{
Barry Warsawfa701a81997-01-16 00:15:11 +0000948 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000949}
950
Barry Warsawfa701a81997-01-16 00:15:11 +0000951
952
Guido van Rossum18468821994-06-20 07:49:28 +0000953/** Tcl to Python **/
954
955static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000956Tkapp_GetInt(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000957 PyObject *self;
958 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000959{
Barry Warsawfa701a81997-01-16 00:15:11 +0000960 char *s;
961 int v;
Guido van Rossum18468821994-06-20 07:49:28 +0000962
Guido van Rossum35d43371997-08-02 00:09:09 +0000963 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000964 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000965 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +0000966 return Tkinter_Error(self);
967 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000968}
969
970static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000971Tkapp_GetDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000972 PyObject *self;
973 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000974{
Barry Warsawfa701a81997-01-16 00:15:11 +0000975 char *s;
976 double v;
Guido van Rossum18468821994-06-20 07:49:28 +0000977
Guido van Rossum35d43371997-08-02 00:09:09 +0000978 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000979 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000980 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +0000981 return Tkinter_Error(self);
982 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000983}
984
985static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000986Tkapp_GetBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000987 PyObject *self;
988 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000989{
Barry Warsawfa701a81997-01-16 00:15:11 +0000990 char *s;
991 int v;
Guido van Rossum18468821994-06-20 07:49:28 +0000992
Guido van Rossum35d43371997-08-02 00:09:09 +0000993 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000994 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000995 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
996 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +0000997 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000998}
999
1000static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001001Tkapp_ExprString(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001002 PyObject *self;
1003 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001004{
Barry Warsawfa701a81997-01-16 00:15:11 +00001005 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001006 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001007 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001008
Guido van Rossum35d43371997-08-02 00:09:09 +00001009 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001010 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001011 ENTER_TCL
1012 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001013 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001014 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001015 res = Tkinter_Error(self);
1016 else
1017 res = Py_BuildValue("s", Tkapp_Result(self));
1018 LEAVE_OVERLAP_TCL
1019 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001020}
1021
1022static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001023Tkapp_ExprLong(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001024 PyObject *self;
1025 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001026{
Barry Warsawfa701a81997-01-16 00:15:11 +00001027 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001028 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001029 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001030 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001031
Guido van Rossum35d43371997-08-02 00:09:09 +00001032 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001033 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001034 ENTER_TCL
1035 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001036 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001037 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001038 res = Tkinter_Error(self);
1039 else
1040 res = Py_BuildValue("l", v);
1041 LEAVE_OVERLAP_TCL
1042 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001043}
1044
1045static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001046Tkapp_ExprDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001047 PyObject *self;
1048 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001049{
Barry Warsawfa701a81997-01-16 00:15:11 +00001050 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001051 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001052 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001053 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001054
Guido van Rossum35d43371997-08-02 00:09:09 +00001055 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001056 return NULL;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001057 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001058 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001059 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001060 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001061 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001062 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001063 res = Tkinter_Error(self);
1064 else
1065 res = Py_BuildValue("d", v);
1066 LEAVE_OVERLAP_TCL
1067 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001068}
1069
1070static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001071Tkapp_ExprBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001072 PyObject *self;
1073 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001074{
Barry Warsawfa701a81997-01-16 00:15:11 +00001075 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001076 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001077 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001078 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001079
Guido van Rossum35d43371997-08-02 00:09:09 +00001080 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001081 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001082 ENTER_TCL
1083 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001084 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001085 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001086 res = Tkinter_Error(self);
1087 else
1088 res = Py_BuildValue("i", v);
1089 LEAVE_OVERLAP_TCL
1090 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001091}
1092
Barry Warsawfa701a81997-01-16 00:15:11 +00001093
1094
Guido van Rossum18468821994-06-20 07:49:28 +00001095static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001096Tkapp_SplitList(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001097 PyObject *self;
1098 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001099{
Barry Warsawfa701a81997-01-16 00:15:11 +00001100 char *list;
1101 int argc;
1102 char **argv;
1103 PyObject *v;
1104 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001105
Guido van Rossum35d43371997-08-02 00:09:09 +00001106 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001107 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001108
Barry Warsawfa701a81997-01-16 00:15:11 +00001109 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1110 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001111
Barry Warsawfa701a81997-01-16 00:15:11 +00001112 if (!(v = PyTuple_New(argc)))
1113 return NULL;
1114
1115 for (i = 0; i < argc; i++) {
1116 PyObject *s = PyString_FromString(argv[i]);
1117 if (!s || PyTuple_SetItem(v, i, s)) {
1118 Py_DECREF(v);
1119 v = NULL;
1120 goto finally;
1121 }
1122 }
Guido van Rossum18468821994-06-20 07:49:28 +00001123
Barry Warsawfa701a81997-01-16 00:15:11 +00001124 finally:
1125 ckfree(FREECAST argv);
1126 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001127}
1128
1129static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001130Tkapp_Split(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001131 PyObject *self;
1132 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001133{
Barry Warsawfa701a81997-01-16 00:15:11 +00001134 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001135
Guido van Rossum35d43371997-08-02 00:09:09 +00001136 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001137 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001138 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001139}
1140
1141static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001142Tkapp_Merge(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001143 PyObject *self;
1144 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001145{
Barry Warsawfa701a81997-01-16 00:15:11 +00001146 char *s = Merge(args);
1147 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001148
Barry Warsawfa701a81997-01-16 00:15:11 +00001149 if (s) {
1150 res = PyString_FromString(s);
1151 ckfree(s);
1152 }
1153 else
1154 PyErr_SetString(Tkinter_TclError, "merge failed");
1155
1156 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001157}
1158
Barry Warsawfa701a81997-01-16 00:15:11 +00001159
1160
Guido van Rossum18468821994-06-20 07:49:28 +00001161/** Tcl Command **/
1162
Guido van Rossum00d93061998-05-28 23:06:38 +00001163/* Client data struct */
1164typedef struct {
1165 PyThreadState *tstate;
1166 PyObject *self;
1167 PyObject *func;
1168} PythonCmd_ClientData;
1169
1170static int
1171PythonCmd_Error(interp)
1172 Tcl_Interp *interp;
1173{
1174 errorInCmd = 1;
1175 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1176 LEAVE_PYTHON
1177 return TCL_ERROR;
1178}
1179
Guido van Rossum18468821994-06-20 07:49:28 +00001180/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001181 * function or method.
1182 */
Guido van Rossum18468821994-06-20 07:49:28 +00001183static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001184PythonCmd(clientData, interp, argc, argv)
Guido van Rossum00d93061998-05-28 23:06:38 +00001185 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001186 Tcl_Interp *interp;
1187 int argc;
1188 char *argv[];
Guido van Rossum18468821994-06-20 07:49:28 +00001189{
Guido van Rossum00d93061998-05-28 23:06:38 +00001190 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001191 PyObject *self, *func, *arg, *res, *tmp;
1192 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001193
Guido van Rossum00d93061998-05-28 23:06:38 +00001194 /* XXX Should create fresh thread state? */
1195 ENTER_PYTHON(data->tstate)
1196
Barry Warsawfa701a81997-01-16 00:15:11 +00001197 /* TBD: no error checking here since we know, via the
1198 * Tkapp_CreateCommand() that the client data is a two-tuple
1199 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001200 self = data->self;
1201 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001202
Barry Warsawfa701a81997-01-16 00:15:11 +00001203 /* Create argument list (argv1, ..., argvN) */
1204 if (!(arg = PyTuple_New(argc - 1)))
1205 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001206
Barry Warsawfa701a81997-01-16 00:15:11 +00001207 for (i = 0; i < (argc - 1); i++) {
1208 PyObject *s = PyString_FromString(argv[i + 1]);
1209 if (!s || PyTuple_SetItem(arg, i, s)) {
1210 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001211 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001212 }
1213 }
1214 res = PyEval_CallObject(func, arg);
1215 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001216
Barry Warsawfa701a81997-01-16 00:15:11 +00001217 if (res == NULL)
1218 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001219
Barry Warsawfa701a81997-01-16 00:15:11 +00001220 if (!(tmp = PyList_New(0))) {
1221 Py_DECREF(res);
1222 return PythonCmd_Error(interp);
1223 }
1224
1225 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1226 Py_DECREF(res);
1227 Py_DECREF(tmp);
1228
Guido van Rossum00d93061998-05-28 23:06:38 +00001229 LEAVE_PYTHON
1230
Barry Warsawfa701a81997-01-16 00:15:11 +00001231 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00001232}
1233
1234static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001235PythonCmdDelete(clientData)
Guido van Rossum00d93061998-05-28 23:06:38 +00001236 ClientData clientData;
Guido van Rossum18468821994-06-20 07:49:28 +00001237{
Guido van Rossum00d93061998-05-28 23:06:38 +00001238 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1239
1240 ENTER_PYTHON(data->tstate)
1241 Py_XDECREF(data->self);
1242 Py_XDECREF(data->func);
1243 PyMem_DEL(data);
1244 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001245}
1246
Barry Warsawfa701a81997-01-16 00:15:11 +00001247
1248
Guido van Rossum18468821994-06-20 07:49:28 +00001249static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001250Tkapp_CreateCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001251 PyObject *self;
1252 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001253{
Guido van Rossum00d93061998-05-28 23:06:38 +00001254 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001255 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001256 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001257 Tcl_Command err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001258
1259 if (!PyArg_ParseTuple(args, "sO", &cmdName, &func))
1260 return NULL;
1261 if (!PyCallable_Check(func)) {
1262 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001263 return NULL;
1264 }
Guido van Rossum18468821994-06-20 07:49:28 +00001265
Guido van Rossum00d93061998-05-28 23:06:38 +00001266 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001267 if (!data)
1268 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001269 data->tstate = PyThreadState_Get();
1270 Py_XINCREF(self);
1271 Py_XINCREF(func);
1272 data->self = self;
1273 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00001274
Guido van Rossum00d93061998-05-28 23:06:38 +00001275 ENTER_TCL
1276 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1277 (ClientData)data, PythonCmdDelete);
1278 LEAVE_TCL
1279 if (err == NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001280 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001281 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001282 return NULL;
1283 }
Guido van Rossum18468821994-06-20 07:49:28 +00001284
Barry Warsawfa701a81997-01-16 00:15:11 +00001285 Py_INCREF(Py_None);
1286 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001287}
1288
Barry Warsawfa701a81997-01-16 00:15:11 +00001289
1290
Guido van Rossum18468821994-06-20 07:49:28 +00001291static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001292Tkapp_DeleteCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001293 PyObject *self;
1294 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001295{
Barry Warsawfa701a81997-01-16 00:15:11 +00001296 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001297 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001298
Guido van Rossum35d43371997-08-02 00:09:09 +00001299 if (!PyArg_ParseTuple(args, "s", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001300 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001301 ENTER_TCL
1302 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1303 LEAVE_TCL
1304 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001305 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1306 return NULL;
1307 }
1308 Py_INCREF(Py_None);
1309 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001310}
1311
Barry Warsawfa701a81997-01-16 00:15:11 +00001312
1313
Guido van Rossum00d93061998-05-28 23:06:38 +00001314#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00001315/** File Handler **/
1316
Guido van Rossum00d93061998-05-28 23:06:38 +00001317typedef struct _fhcdata {
1318 PyThreadState *tstate;
1319 PyObject *func;
1320 PyObject *file;
1321 int id;
1322 struct _fhcdata *next;
1323} FileHandler_ClientData;
1324
1325static FileHandler_ClientData *HeadFHCD;
1326
1327static FileHandler_ClientData *
1328NewFHCD(func, file, id)
1329 PyObject *func;
1330 PyObject *file;
1331 int id;
1332{
1333 FileHandler_ClientData *p;
1334 p = PyMem_NEW(FileHandler_ClientData, 1);
1335 if (p != NULL) {
1336 Py_XINCREF(func);
1337 Py_XINCREF(file);
1338 p->tstate = PyThreadState_Get();
1339 p->func = func;
1340 p->file = file;
1341 p->id = id;
1342 p->next = HeadFHCD;
1343 HeadFHCD = p;
1344 }
1345 return p;
1346}
1347
1348static void
1349DeleteFHCD(id)
1350 int id;
1351{
1352 FileHandler_ClientData *p, **pp;
1353
1354 pp = &HeadFHCD;
1355 while ((p = *pp) != NULL) {
1356 if (p->id == id) {
1357 *pp = p->next;
1358 Py_XDECREF(p->func);
1359 Py_XDECREF(p->file);
1360 PyMem_DEL(p);
1361 }
1362 else
1363 pp = &p->next;
1364 }
1365}
1366
Guido van Rossuma597dde1995-01-10 20:56:29 +00001367static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001368FileHandler(clientData, mask)
Guido van Rossum00d93061998-05-28 23:06:38 +00001369 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001370 int mask;
Guido van Rossum18468821994-06-20 07:49:28 +00001371{
Guido van Rossum00d93061998-05-28 23:06:38 +00001372 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001373 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00001374
Guido van Rossum00d93061998-05-28 23:06:38 +00001375 /* XXX Should create fresh thread state? */
1376 ENTER_PYTHON(data->tstate)
1377 func = data->func;
1378 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00001379
Barry Warsawfa701a81997-01-16 00:15:11 +00001380 arg = Py_BuildValue("(Oi)", file, (long) mask);
1381 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00001382 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00001383
1384 if (res == NULL) {
1385 errorInCmd = 1;
1386 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1387 }
1388 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001389 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001390}
1391
1392static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001393GetFileNo(file)
Barry Warsawfa701a81997-01-16 00:15:11 +00001394 /* Either an int >= 0 or an object with a
1395 *.fileno() method that returns an int >= 0
1396 */
1397 PyObject *file;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001398{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001399 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001400 int id;
1401 if (PyInt_Check(file)) {
1402 id = PyInt_AsLong(file);
1403 if (id < 0)
1404 PyErr_SetString(PyExc_ValueError, "invalid file id");
1405 return id;
1406 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001407 args = PyTuple_New(0);
1408 if (args == NULL)
1409 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001410
1411 meth = PyObject_GetAttrString(file, "fileno");
1412 if (meth == NULL) {
1413 Py_DECREF(args);
1414 return -1;
1415 }
1416
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001417 res = PyEval_CallObject(meth, args);
1418 Py_DECREF(args);
1419 Py_DECREF(meth);
1420 if (res == NULL)
1421 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001422
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001423 if (PyInt_Check(res))
1424 id = PyInt_AsLong(res);
1425 else
1426 id = -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001427
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001428 if (id < 0)
1429 PyErr_SetString(PyExc_ValueError,
1430 "invalid fileno() return value");
1431 Py_DECREF(res);
1432 return id;
Guido van Rossum18468821994-06-20 07:49:28 +00001433}
1434
1435static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001436Tkapp_CreateFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001437 PyObject *self;
1438 PyObject *args; /* Is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00001439{
Guido van Rossum00d93061998-05-28 23:06:38 +00001440 FileHandler_ClientData *data;
1441 PyObject *file, *func;
Barry Warsawfa701a81997-01-16 00:15:11 +00001442 int mask, id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001443 FHANDLE tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00001444
Guido van Rossum35d43371997-08-02 00:09:09 +00001445 if (!PyArg_ParseTuple(args, "OiO", &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001446 return NULL;
1447 id = GetFileNo(file);
1448 if (id < 0)
1449 return NULL;
1450 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001451 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001452 return NULL;
1453 }
1454
Guido van Rossum00d93061998-05-28 23:06:38 +00001455 data = NewFHCD(func, file, id);
1456 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001457 return NULL;
1458
Guido van Rossum7bf15641998-05-22 18:28:17 +00001459 tfile = MAKEFHANDLE(id);
Barry Warsawfa701a81997-01-16 00:15:11 +00001460 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001461 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001462 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00001463 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001464 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001465 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001466}
1467
1468static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001469Tkapp_DeleteFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001470 PyObject *self;
1471 PyObject *args; /* Args: file */
Guido van Rossum18468821994-06-20 07:49:28 +00001472{
Barry Warsawfa701a81997-01-16 00:15:11 +00001473 PyObject *file;
Guido van Rossum00d93061998-05-28 23:06:38 +00001474 FileHandler_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001475 int id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001476 FHANDLE tfile;
Guido van Rossum68784361996-05-16 17:17:31 +00001477
Guido van Rossum35d43371997-08-02 00:09:09 +00001478 if (!PyArg_ParseTuple(args, "O", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00001479 return NULL;
1480 id = GetFileNo(file);
1481 if (id < 0)
1482 return NULL;
1483
Guido van Rossum00d93061998-05-28 23:06:38 +00001484 DeleteFHCD(id);
Guido van Rossum18468821994-06-20 07:49:28 +00001485
Guido van Rossum7bf15641998-05-22 18:28:17 +00001486 tfile = MAKEFHANDLE(id);
Barry Warsawfa701a81997-01-16 00:15:11 +00001487 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001488 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001489 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001490 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001491 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001492 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001493}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001494#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00001495
Barry Warsawfa701a81997-01-16 00:15:11 +00001496
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001497/**** Tktt Object (timer token) ****/
1498
1499staticforward PyTypeObject Tktt_Type;
1500
Guido van Rossum00d93061998-05-28 23:06:38 +00001501typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00001502 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00001503 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00001504 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001505 PyThreadState *tstate;
1506} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001507
1508static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001509Tktt_DeleteTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001510 PyObject *self;
1511 PyObject *args;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001512{
Barry Warsawfa701a81997-01-16 00:15:11 +00001513 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001514 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001515
Guido van Rossum35d43371997-08-02 00:09:09 +00001516 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001517 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001518 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001519 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00001520 v->token = NULL;
1521 }
1522 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001523 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001524 Py_DECREF(func);
1525 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00001526 }
1527 Py_INCREF(Py_None);
1528 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001529}
1530
1531static PyMethodDef Tktt_methods[] =
1532{
Guido van Rossum35d43371997-08-02 00:09:09 +00001533 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001534 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001535};
1536
1537static TkttObject *
Guido van Rossum00d93061998-05-28 23:06:38 +00001538Tktt_New(func)
Barry Warsawfa701a81997-01-16 00:15:11 +00001539 PyObject *func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001540{
Barry Warsawfa701a81997-01-16 00:15:11 +00001541 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001542
Barry Warsawfa701a81997-01-16 00:15:11 +00001543 v = PyObject_NEW(TkttObject, &Tktt_Type);
1544 if (v == NULL)
1545 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001546
Guido van Rossum00d93061998-05-28 23:06:38 +00001547 Py_INCREF(func);
1548 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001549 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001550 v->tstate = PyThreadState_Get();
1551
1552 /* Extra reference, deleted when called or when handler is deleted */
1553 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001554 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001555}
1556
1557static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001558Tktt_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001559 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001560{
Guido van Rossum00d93061998-05-28 23:06:38 +00001561 TkttObject *v = (TkttObject *)self;
1562 PyObject *func = v->func;
1563
1564 Py_XDECREF(func);
1565
Guido van Rossum35d43371997-08-02 00:09:09 +00001566 PyMem_DEL(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001567}
1568
Guido van Rossum597ac201998-05-12 14:36:19 +00001569static PyObject *
1570Tktt_Repr(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001571 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001572{
Barry Warsawfa701a81997-01-16 00:15:11 +00001573 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00001574 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001575
Guido van Rossum597ac201998-05-12 14:36:19 +00001576 sprintf(buf, "<tktimertoken at 0x%lx%s>", (long)v,
Barry Warsawfa701a81997-01-16 00:15:11 +00001577 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00001578 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001579}
1580
1581static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001582Tktt_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001583 PyObject *self;
1584 char *name;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001585{
Barry Warsawfa701a81997-01-16 00:15:11 +00001586 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001587}
1588
1589static PyTypeObject Tktt_Type =
1590{
Guido van Rossum35d43371997-08-02 00:09:09 +00001591 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001592 0, /*ob_size */
1593 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001594 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001595 0, /*tp_itemsize */
1596 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00001597 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00001598 Tktt_GetAttr, /*tp_getattr */
1599 0, /*tp_setattr */
1600 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00001601 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00001602 0, /*tp_as_number */
1603 0, /*tp_as_sequence */
1604 0, /*tp_as_mapping */
1605 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001606};
1607
Barry Warsawfa701a81997-01-16 00:15:11 +00001608
1609
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001610/** Timer Handler **/
1611
1612static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001613TimerHandler(clientData)
Barry Warsawfa701a81997-01-16 00:15:11 +00001614 ClientData clientData;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001615{
Guido van Rossum00d93061998-05-28 23:06:38 +00001616 TkttObject *v = (TkttObject *)clientData;
1617 PyObject *func = v->func;
1618 PyObject *res;
1619
1620 if (func == NULL)
1621 return;
1622
1623 v->func = NULL;
1624
1625 ENTER_PYTHON(v->tstate)
1626
1627 res = PyEval_CallObject(func, NULL);
1628 Py_DECREF(func);
1629 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001630
Barry Warsawfa701a81997-01-16 00:15:11 +00001631 if (res == NULL) {
1632 errorInCmd = 1;
1633 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1634 }
1635 else
1636 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001637
1638 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001639}
1640
1641static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001642Tkapp_CreateTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001643 PyObject *self;
1644 PyObject *args; /* Is (milliseconds, func) */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001645{
Barry Warsawfa701a81997-01-16 00:15:11 +00001646 int milliseconds;
1647 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001648 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001649
Guido van Rossum35d43371997-08-02 00:09:09 +00001650 if (!PyArg_ParseTuple(args, "iO", &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001651 return NULL;
1652 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001653 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001654 return NULL;
1655 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001656 v = Tktt_New(func);
1657 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1658 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001659
Guido van Rossum00d93061998-05-28 23:06:38 +00001660 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001661}
1662
Barry Warsawfa701a81997-01-16 00:15:11 +00001663
Guido van Rossum18468821994-06-20 07:49:28 +00001664/** Event Loop **/
1665
Guido van Rossum18468821994-06-20 07:49:28 +00001666static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001667Tkapp_MainLoop(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001668 PyObject *self;
1669 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001670{
Barry Warsawfa701a81997-01-16 00:15:11 +00001671 int threshold = 0;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001672
Barry Warsawfa701a81997-01-16 00:15:11 +00001673 if (!PyArg_ParseTuple(args, "|i", &threshold))
1674 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001675
Barry Warsawfa701a81997-01-16 00:15:11 +00001676 quitMainLoop = 0;
1677 while (Tk_GetNumMainWindows() > threshold &&
1678 !quitMainLoop &&
1679 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001680 {
Guido van Rossum35d43371997-08-02 00:09:09 +00001681 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00001682
1683#ifdef WITH_THREAD
Guido van Rossum62320c91998-06-15 04:36:09 +00001684 Py_BEGIN_ALLOW_THREADS
1685 acquire_lock(tcl_lock, 1);
Guido van Rossum35d43371997-08-02 00:09:09 +00001686 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossum00d93061998-05-28 23:06:38 +00001687 release_lock(tcl_lock);
1688 if (result == 0)
1689 Sleep(20);
Guido van Rossum35d43371997-08-02 00:09:09 +00001690 Py_END_ALLOW_THREADS
Guido van Rossum5b020781997-08-19 01:00:50 +00001691#else
1692 result = Tcl_DoOneEvent(0);
1693#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001694
Guido van Rossum35d43371997-08-02 00:09:09 +00001695 if (PyErr_CheckSignals() != 0)
1696 return NULL;
1697 if (result < 0)
1698 break;
Guido van Rossum18468821994-06-20 07:49:28 +00001699 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001700 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001701
Barry Warsawfa701a81997-01-16 00:15:11 +00001702 if (errorInCmd) {
1703 errorInCmd = 0;
1704 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1705 excInCmd = valInCmd = trbInCmd = NULL;
1706 return NULL;
1707 }
1708 Py_INCREF(Py_None);
1709 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001710}
1711
1712static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001713Tkapp_DoOneEvent(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001714 PyObject *self;
1715 PyObject *args;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001716{
Guido van Rossum35d43371997-08-02 00:09:09 +00001717 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00001718 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001719
Barry Warsawfa701a81997-01-16 00:15:11 +00001720 if (!PyArg_ParseTuple(args, "|i", &flags))
1721 return NULL;
1722
Guido van Rossum00d93061998-05-28 23:06:38 +00001723 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001724 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00001725 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001726 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001727}
1728
1729static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001730Tkapp_Quit(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 PyObject *self;
1732 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001733{
1734
Guido van Rossum35d43371997-08-02 00:09:09 +00001735 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001736 return NULL;
1737
1738 quitMainLoop = 1;
1739 Py_INCREF(Py_None);
1740 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001741}
1742
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001743static PyObject *
1744Tkapp_InterpAddr(self, args)
1745 PyObject *self;
1746 PyObject *args;
1747{
1748
1749 if (!PyArg_ParseTuple(args, ""))
1750 return NULL;
1751
1752 return PyInt_FromLong((long)Tkapp_Interp(self));
1753}
1754
Barry Warsawfa701a81997-01-16 00:15:11 +00001755
1756
Guido van Rossum18468821994-06-20 07:49:28 +00001757/**** Tkapp Method List ****/
1758
1759static PyMethodDef Tkapp_methods[] =
1760{
Guido van Rossum35d43371997-08-02 00:09:09 +00001761 {"call", Tkapp_Call, 0},
1762 {"globalcall", Tkapp_GlobalCall, 0},
1763 {"eval", Tkapp_Eval, 1},
1764 {"globaleval", Tkapp_GlobalEval, 1},
1765 {"evalfile", Tkapp_EvalFile, 1},
1766 {"record", Tkapp_Record, 1},
1767 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1768 {"setvar", Tkapp_SetVar, 1},
1769 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1770 {"getvar", Tkapp_GetVar, 1},
1771 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1772 {"unsetvar", Tkapp_UnsetVar, 1},
1773 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1774 {"getint", Tkapp_GetInt, 1},
1775 {"getdouble", Tkapp_GetDouble, 1},
1776 {"getboolean", Tkapp_GetBoolean, 1},
1777 {"exprstring", Tkapp_ExprString, 1},
1778 {"exprlong", Tkapp_ExprLong, 1},
1779 {"exprdouble", Tkapp_ExprDouble, 1},
1780 {"exprboolean", Tkapp_ExprBoolean, 1},
1781 {"splitlist", Tkapp_SplitList, 1},
1782 {"split", Tkapp_Split, 1},
1783 {"merge", Tkapp_Merge, 0},
1784 {"createcommand", Tkapp_CreateCommand, 1},
1785 {"deletecommand", Tkapp_DeleteCommand, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001786#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001787 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1788 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001789#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001790 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001791 {"mainloop", Tkapp_MainLoop, 1},
1792 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001793 {"quit", Tkapp_Quit, 1},
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001794 {"interpaddr", Tkapp_InterpAddr, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001795 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001796};
1797
Barry Warsawfa701a81997-01-16 00:15:11 +00001798
1799
Guido van Rossum18468821994-06-20 07:49:28 +00001800/**** Tkapp Type Methods ****/
1801
1802static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001803Tkapp_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001804 PyObject *self;
Guido van Rossum18468821994-06-20 07:49:28 +00001805{
Guido van Rossum00d93061998-05-28 23:06:38 +00001806 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001807 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00001808 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001809 PyMem_DEL(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001810 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00001811}
1812
1813static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001814Tkapp_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001815 PyObject *self;
1816 char *name;
Guido van Rossum18468821994-06-20 07:49:28 +00001817{
Guido van Rossum35d43371997-08-02 00:09:09 +00001818 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00001819}
1820
1821static PyTypeObject Tkapp_Type =
1822{
Guido van Rossum35d43371997-08-02 00:09:09 +00001823 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001824 0, /*ob_size */
1825 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001826 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001827 0, /*tp_itemsize */
1828 Tkapp_Dealloc, /*tp_dealloc */
1829 0, /*tp_print */
1830 Tkapp_GetAttr, /*tp_getattr */
1831 0, /*tp_setattr */
1832 0, /*tp_compare */
1833 0, /*tp_repr */
1834 0, /*tp_as_number */
1835 0, /*tp_as_sequence */
1836 0, /*tp_as_mapping */
1837 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00001838};
1839
Barry Warsawfa701a81997-01-16 00:15:11 +00001840
1841
Guido van Rossum18468821994-06-20 07:49:28 +00001842/**** Tkinter Module ****/
1843
1844static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001845Tkinter_Create(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001846 PyObject *self;
1847 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001848{
Barry Warsawfa701a81997-01-16 00:15:11 +00001849 char *screenName = NULL;
1850 char *baseName = NULL;
1851 char *className = NULL;
1852 int interactive = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001853
Guido van Rossum35d43371997-08-02 00:09:09 +00001854 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00001855 if (baseName != NULL)
1856 baseName++;
1857 else
1858 baseName = Py_GetProgramName();
1859 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00001860
Barry Warsawfa701a81997-01-16 00:15:11 +00001861 if (!PyArg_ParseTuple(args, "|zssi",
1862 &screenName, &baseName, &className,
1863 &interactive))
1864 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001865
Barry Warsawfa701a81997-01-16 00:15:11 +00001866 return (PyObject *) Tkapp_New(screenName, baseName, className,
1867 interactive);
Guido van Rossum18468821994-06-20 07:49:28 +00001868}
1869
1870static PyMethodDef moduleMethods[] =
1871{
Barry Warsawfa701a81997-01-16 00:15:11 +00001872 {"create", Tkinter_Create, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001873#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001874 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1875 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001876#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001877 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 {"mainloop", Tkapp_MainLoop, 1},
1879 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001880 {"quit", Tkapp_Quit, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001881 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001882};
1883
Guido van Rossum7bf15641998-05-22 18:28:17 +00001884#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001885
1886static int stdin_ready = 0;
1887
Guido van Rossumad4db171998-06-13 13:56:28 +00001888#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00001889static void
1890MyFileProc(clientData, mask)
1891 void *clientData;
1892 int mask;
1893{
1894 stdin_ready = 1;
1895}
Guido van Rossumad4db171998-06-13 13:56:28 +00001896#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001897
Guido van Rossum00d93061998-05-28 23:06:38 +00001898static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00001899
Guido van Rossum18468821994-06-20 07:49:28 +00001900static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001901EventHook()
Guido van Rossum18468821994-06-20 07:49:28 +00001902{
Guido van Rossumad4db171998-06-13 13:56:28 +00001903#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001904 FHANDLE tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00001905#endif
Guido van Rossumad4db171998-06-13 13:56:28 +00001906 PyEval_RestoreThread(event_tstate);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001907 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00001908 errorInCmd = 0;
1909#ifndef MS_WINDOWS
1910 tfile = MAKEFHANDLE(fileno(stdin));
Guido van Rossum7bf15641998-05-22 18:28:17 +00001911 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00001912#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001913 while (!errorInCmd && !stdin_ready) {
1914 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00001915#ifdef MS_WINDOWS
1916 if (_kbhit()) {
1917 stdin_ready = 1;
1918 break;
1919 }
1920#endif
1921#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00001922 Py_BEGIN_ALLOW_THREADS
1923 acquire_lock(tcl_lock, 1);
Guido van Rossum00d93061998-05-28 23:06:38 +00001924 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
1925 release_lock(tcl_lock);
1926 if (result == 0)
1927 Sleep(20);
1928 Py_END_ALLOW_THREADS
1929#else
1930 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001931#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001932
1933 if (result < 0)
1934 break;
1935 }
Guido van Rossumad4db171998-06-13 13:56:28 +00001936#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001937 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00001938#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00001939 if (errorInCmd) {
1940 errorInCmd = 0;
1941 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1942 excInCmd = valInCmd = trbInCmd = NULL;
1943 PyErr_Print();
1944 }
Guido van Rossumad4db171998-06-13 13:56:28 +00001945 PyEval_SaveThread();
Barry Warsawfa701a81997-01-16 00:15:11 +00001946 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001947}
Guido van Rossum18468821994-06-20 07:49:28 +00001948
Guido van Rossum00d93061998-05-28 23:06:38 +00001949#endif
1950
Guido van Rossum7bf15641998-05-22 18:28:17 +00001951static void
1952EnableEventHook()
1953{
Guido van Rossum00d93061998-05-28 23:06:38 +00001954#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001955 if (PyOS_InputHook == NULL) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001956 event_tstate = PyThreadState_Get();
Guido van Rossum7bf15641998-05-22 18:28:17 +00001957 PyOS_InputHook = EventHook;
1958 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001959#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001960}
1961
1962static void
1963DisableEventHook()
1964{
Guido van Rossum00d93061998-05-28 23:06:38 +00001965#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001966 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
1967 PyOS_InputHook = NULL;
1968 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001969#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001970}
1971
Barry Warsawfa701a81997-01-16 00:15:11 +00001972
1973/* all errors will be checked in one fell swoop in init_tkinter() */
1974static void
1975ins_long(d, name, val)
1976 PyObject *d;
1977 char *name;
1978 long val;
1979{
1980 PyObject *v = PyInt_FromLong(val);
1981 if (v) {
1982 PyDict_SetItemString(d, name, v);
1983 Py_DECREF(v);
1984 }
1985}
1986static void
1987ins_string(d, name, val)
1988 PyObject *d;
1989 char *name;
1990 char *val;
1991{
1992 PyObject *v = PyString_FromString(val);
1993 if (v) {
1994 PyDict_SetItemString(d, name, v);
1995 Py_DECREF(v);
1996 }
1997}
1998
1999
Guido van Rossum18468821994-06-20 07:49:28 +00002000void
Guido van Rossum35d43371997-08-02 00:09:09 +00002001init_tkinter()
Guido van Rossum18468821994-06-20 07:49:28 +00002002{
Barry Warsawfa701a81997-01-16 00:15:11 +00002003 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002004
Barry Warsawfa701a81997-01-16 00:15:11 +00002005 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002006
2007#ifdef WITH_THREAD
2008 tcl_lock = allocate_lock();
2009#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002010
Barry Warsawfa701a81997-01-16 00:15:11 +00002011 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002012
Barry Warsawfa701a81997-01-16 00:15:11 +00002013 d = PyModule_GetDict(m);
2014 Tkinter_TclError = Py_BuildValue("s", "TclError");
2015 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002016
Guido van Rossum35d43371997-08-02 00:09:09 +00002017 ins_long(d, "READABLE", TCL_READABLE);
2018 ins_long(d, "WRITABLE", TCL_WRITABLE);
2019 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2020 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2021 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2022 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2023 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2024 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2025 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002026 ins_string(d, "TK_VERSION", TK_VERSION);
2027 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002028
Guido van Rossum83551bf1997-09-13 00:44:23 +00002029 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002030
2031 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002032 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2033
Barry Warsawfa701a81997-01-16 00:15:11 +00002034 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002035 return;
2036
Guido van Rossum43ff8681998-07-14 18:02:13 +00002037#if 0
2038 /* This was not a good idea; through <Destroy> bindings,
2039 Tcl_Finalize() may invoke Python code but at that point the
2040 interpreter and thread state have already been destroyed! */
Guido van Rossum26216371998-04-20 18:47:52 +00002041#if TKMAJORMINOR >= 8000
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002042 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002043#endif
Guido van Rossum43ff8681998-07-14 18:02:13 +00002044#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002045
Jack Jansen34cc5c31995-10-31 16:15:12 +00002046#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002047 /*
2048 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2049 ** Most of the initializations in that routine (toolbox init calls and
2050 ** such) have already been done for us, so we only need these.
2051 */
2052#if TKMAJORMINOR >= 8000
2053 tcl_macQdPtr = &qd;
2054#endif
2055
2056 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002057#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002058 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002059#endif /* GENERATINGCFM */
2060#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002061}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002062
Guido van Rossumec22c921996-02-25 04:50:29 +00002063
Barry Warsawfa701a81997-01-16 00:15:11 +00002064
Guido van Rossum9722ad81995-09-22 23:49:28 +00002065#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002066
2067/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002068** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002069*/
2070
Guido van Rossum9722ad81995-09-22 23:49:28 +00002071void
2072panic(char * format, ...)
2073{
Barry Warsawfa701a81997-01-16 00:15:11 +00002074 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002075
Barry Warsawfa701a81997-01-16 00:15:11 +00002076 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002077
Guido van Rossum227cf761998-08-05 13:53:32 +00002078 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002079 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002080
Barry Warsawfa701a81997-01-16 00:15:11 +00002081 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002082
Barry Warsawfa701a81997-01-16 00:15:11 +00002083 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002084}
Jack Jansen40b546d1995-11-14 10:34:45 +00002085
Guido van Rossumec22c921996-02-25 04:50:29 +00002086/*
2087** Pass events to SIOUX before passing them to Tk.
2088*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002089
Guido van Rossumec22c921996-02-25 04:50:29 +00002090static int
2091PyMacConvertEvent(eventPtr)
Barry Warsawfa701a81997-01-16 00:15:11 +00002092 EventRecord *eventPtr;
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002093{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002094 WindowPtr frontwin;
2095 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002096 ** Sioux eats too many events, so we don't pass it everything. We
2097 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002098 ** the Sioux window is frontmost. This means that Tk menus don't work
2099 ** in that case, but at least we can scroll the sioux window.
2100 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2101 ** part of the external interface of Sioux...
2102 */
2103 frontwin = FrontWindow();
2104 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2105 if (SIOUXHandleOneEvent(eventPtr))
2106 return 0; /* Nothing happened to the Tcl event queue */
2107 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002108 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002109}
2110
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002111#if defined(USE_GUSI) && TKMAJORMINOR < 8000
Guido van Rossum290283b1997-06-02 22:16:43 +00002112/*
2113 * For Python we have to override this routine (from TclMacNotify),
2114 * since we use GUSI for our sockets, not Tcl streams. Hence, we have
2115 * to use GUSI select to see whether our socket is ready. Note that
2116 * createfilehandler (above) sets the type to TCL_UNIX_FD for our
2117 * files and sockets.
2118 *
2119 * NOTE: this code was lifted from Tcl 7.6, it may need to be modified
2120 * for other versions. */
2121
2122int
2123Tcl_FileReady(file, mask)
2124 Tcl_File file; /* File handle for a stream. */
2125 int mask; /* OR'ed combination of TCL_READABLE,
2126 * TCL_WRITABLE, and TCL_EXCEPTION:
2127 * indicates conditions caller cares about. */
2128{
2129 int type;
2130 int fd;
2131
2132 fd = (int) Tcl_GetFileInfo(file, &type);
2133
2134 if (type == TCL_MAC_SOCKET) {
2135 return TclMacSocketReady(file, mask);
2136 } else if (type == TCL_MAC_FILE) {
2137 /*
2138 * Under the Macintosh, files are always ready, so we just
2139 * return the mask that was passed in.
2140 */
2141
2142 return mask;
2143 } else if (type == TCL_UNIX_FD) {
2144 fd_set readset, writeset, excset;
2145 struct timeval tv;
2146
2147 FD_ZERO(&readset);
2148 FD_ZERO(&writeset);
2149 FD_ZERO(&excset);
2150
2151 if ( mask & TCL_READABLE ) FD_SET(fd, &readset);
2152 if ( mask & TCL_WRITABLE ) FD_SET(fd, &writeset);
2153 if ( mask & TCL_EXCEPTION ) FD_SET(fd, &excset);
2154
2155 tv.tv_sec = tv.tv_usec = 0;
2156 if ( select(fd+1, &readset, &writeset, &excset, &tv) <= 0 )
2157 return 0;
2158
2159 mask = 0;
2160 if ( FD_ISSET(fd, &readset) ) mask |= TCL_READABLE;
2161 if ( FD_ISSET(fd, &writeset) ) mask |= TCL_WRITABLE;
2162 if ( FD_ISSET(fd, &excset) ) mask |= TCL_EXCEPTION;
2163
2164 return mask;
2165 }
2166
2167 return 0;
2168}
2169#endif /* USE_GUSI */
2170
Guido van Rossumec22c921996-02-25 04:50:29 +00002171#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002172
2173/*
2174** Additional Mac specific code for dealing with shared libraries.
2175*/
2176
2177#include <Resources.h>
2178#include <CodeFragments.h>
2179
2180static int loaded_from_shlib = 0;
2181static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002182
Jack Jansen34cc5c31995-10-31 16:15:12 +00002183/*
2184** If this module is dynamically loaded the following routine should
2185** be the init routine. It takes care of adding the shared library to
2186** the resource-file chain, so that the tk routines can find their
2187** resources.
2188*/
2189OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002190init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002191{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002192 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002193 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002194 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002195 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2196 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002197 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002198 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2199 loaded_from_shlib = 1;
2200 }
2201 return noErr;
2202}
2203
2204/*
2205** Insert the library resources into the search path. Put them after
2206** the resources from the application. Again, we ignore errors.
2207*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002208static
Jack Jansen34cc5c31995-10-31 16:15:12 +00002209mac_addlibresources()
2210{
2211 if ( !loaded_from_shlib )
2212 return;
2213 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2214}
2215
Guido van Rossumec22c921996-02-25 04:50:29 +00002216#endif /* GENERATINGCFM */
2217#endif /* macintosh */