blob: 8a09dd6d680e47218f4bbaab416d752a710efe84 [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
62#include "thread.h"
63#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 Rossum18468821994-06-20 07:49:28 +000074#include <tcl.h>
75#include <tk.h>
76
Guido van Rossum3e819a71997-08-01 19:29:02 +000077#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78
Guido van Rossum00d93061998-05-28 23:06:38 +000079#if TKMAJORMINOR < 4001
80 #error "Tk 4.0 or 3.x are not supported -- use 4.1 or higher"
81#endif
82
Guido van Rossum0d2390c1997-08-14 19:57:07 +000083#if TKMAJORMINOR >= 8000 && defined(macintosh)
84/* Sigh, we have to include this to get at the tcl qd pointer */
85#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000086/* And this one we need to clear the menu bar */
87#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000088#endif
89
Guido van Rossumb0105441997-10-08 15:25:37 +000090#if TKMAJORMINOR < 8000 || !defined(MS_WINDOWS)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000091#define HAVE_CREATEFILEHANDLER
92#endif
93
Guido van Rossum00d93061998-05-28 23:06:38 +000094#ifdef HAVE_CREATEFILEHANDLER
95
96/* Tcl_CreateFileHandler() changed several times; these macros deal with the
97 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
98 Unix, only because Jack added it back); when available on Windows, it only
99 applies to sockets. */
100
Guido van Rossum7bf15641998-05-22 18:28:17 +0000101#ifdef MS_WINDOWS
102#define FHANDLETYPE TCL_WIN_SOCKET
103#else
104#define FHANDLETYPE TCL_UNIX_FD
105#endif
106
107#if TKMAJORMINOR < 8000
108#define FHANDLE Tcl_File
109#define MAKEFHANDLE(fd) Tcl_GetFile((ClientData)(fd), FHANDLETYPE)
110#else
111#define FHANDLE int
112#define MAKEFHANDLE(fd) (fd)
113#endif
114
Guido van Rossum00d93061998-05-28 23:06:38 +0000115/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
116 which uses this to handle Tcl events while the user is typing commands. */
117
118#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000119#define WAIT_FOR_STDIN
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122#endif /* HAVE_CREATEFILEHANDLER */
123
Guido van Rossumad4db171998-06-13 13:56:28 +0000124#ifdef MS_WINDOWS
125#include <conio.h>
126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#ifdef WITH_THREAD
130
131/* The threading situation is complicated. Tcl is not thread-safe, except for
132 Tcl 8.1, which will probably remain in alpha status for another 6 months
133 (and the README says that Tk will probably remain thread-unsafe forever).
134 So we need to use a lock around all uses of Tcl. Previously, the Python
135 interpreter lock was used for this. However, this causes problems when
136 other Python threads need to run while Tcl is blocked waiting for events.
137
138 To solve this problem, a separate lock for Tcl is introduced. Holding it
139 is incompatible with holding Python's interpreter lock. The following four
140 macros manipulate both locks together.
141
142 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
143 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
144 that could call an event handler, or otherwise affect the state of a Tcl
145 interpreter. These assume that the surrounding code has the Python
146 interpreter lock; inside the brackets, the Python interpreter lock has been
147 released and the lock for Tcl has been acquired.
148
Guido van Rossum5e977831998-06-15 14:03:52 +0000149 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
150 (For example, when transferring data from the Tcl interpreter result to a
151 Python string object.) This can be done by using different macros to close
152 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
153 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
154 releases the Tcl lock.
155
Guido van Rossum00d93061998-05-28 23:06:38 +0000156 By contrast, ENTER_PYTHON(tstate) and LEAVE_PYTHON are used in Tcl event
157 handlers when the handler needs to use Python. Such event handlers are
158 entered while the lock for Tcl is held; the event handler presumably needs
159 to use Python. ENTER_PYTHON(tstate) releases the lock for Tcl and acquires
160 the Python interpreter lock, restoring the appropriate thread state, and
161 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
162 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
163 the code between ENTER_PYTHON(tstate) and LEAVE_PYTHON.
164
165 These locks expand to several statements and brackets; they should not be
166 used in branches of if statements and the like.
167
168*/
169
170static type_lock tcl_lock = 0;
171
172#define ENTER_TCL \
173 Py_BEGIN_ALLOW_THREADS acquire_lock(tcl_lock, 1);
174
175#define LEAVE_TCL \
176 release_lock(tcl_lock); Py_END_ALLOW_THREADS
177
Guido van Rossum62320c91998-06-15 04:36:09 +0000178#define ENTER_OVERLAP \
179 Py_END_ALLOW_THREADS
180
181#define LEAVE_OVERLAP_TCL \
182 release_lock(tcl_lock);
183
Guido van Rossum00d93061998-05-28 23:06:38 +0000184#define ENTER_PYTHON(tstate) \
Guido van Rossum00d93061998-05-28 23:06:38 +0000185 release_lock(tcl_lock); PyEval_RestoreThread((tstate));
186
187#define LEAVE_PYTHON \
188 PyEval_SaveThread(); acquire_lock(tcl_lock, 1);
189
190#else
191
192#define ENTER_TCL
193#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000194#define ENTER_OVERLAP
195#define LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000196#define ENTER_PYTHON(tstate)
197#define LEAVE_PYTHON
198
199#endif
200
Guido van Rossum35d43371997-08-02 00:09:09 +0000201extern int Tk_GetNumMainWindows();
202
Guido van Rossumec22c921996-02-25 04:50:29 +0000203#ifdef macintosh
204
205/*
206** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000207** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000208*/
209
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000210/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000211#define FREECAST (char *)
212
Guido van Rossumec22c921996-02-25 04:50:29 +0000213#include <Events.h> /* For EventRecord */
214
215typedef int (*TclMacConvertEventPtr) Py_PROTO((EventRecord *eventPtr));
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000216/* They changed the name... */
217#if TKMAJORMINOR < 8000
218#define Tcl_MacSetEventProc TclMacSetEventProc
219#endif
220void Tcl_MacSetEventProc Py_PROTO((TclMacConvertEventPtr procPtr));
Guido van Rossumec22c921996-02-25 04:50:29 +0000221int TkMacConvertEvent Py_PROTO((EventRecord *eventPtr));
222
223staticforward int PyMacConvertEvent Py_PROTO((EventRecord *eventPtr));
224
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000225#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
226 #pragma import on
227#endif
228
229#include <SIOUX.h>
230extern int SIOUXIsAppWindow(WindowPtr);
231
232#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
233 #pragma import reset
234#endif
Guido van Rossumec22c921996-02-25 04:50:29 +0000235#endif /* macintosh */
236
Guido van Rossum97867b21996-08-08 19:09:53 +0000237#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000238#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#endif
240
Guido van Rossum18468821994-06-20 07:49:28 +0000241/**** Tkapp Object Declaration ****/
242
243staticforward PyTypeObject Tkapp_Type;
244
Guido van Rossum00d93061998-05-28 23:06:38 +0000245typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000246 PyObject_HEAD
247 Tcl_Interp *interp;
Guido van Rossum00d93061998-05-28 23:06:38 +0000248} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000249
250#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000251#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
252#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
253
Guido van Rossum35d43371997-08-02 00:09:09 +0000254#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000255(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Barry Warsawfa701a81997-01-16 00:15:11 +0000257
258
Guido van Rossum18468821994-06-20 07:49:28 +0000259/**** Error Handling ****/
260
261static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000262static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000263static int errorInCmd = 0;
264static PyObject *excInCmd;
265static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000266static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000267
Barry Warsawfa701a81997-01-16 00:15:11 +0000268
269
Guido van Rossum18468821994-06-20 07:49:28 +0000270static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000271Tkinter_Error(v)
272 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000273{
Barry Warsawfa701a81997-01-16 00:15:11 +0000274 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
275 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000276}
277
Barry Warsawfa701a81997-01-16 00:15:11 +0000278
Barry Warsawfa701a81997-01-16 00:15:11 +0000279
Guido van Rossum18468821994-06-20 07:49:28 +0000280/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000281
282#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000283#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +0000284/* Millisecond sleep() for Unix platforms. */
285
286static void
287Sleep(milli)
288 int milli;
289{
290 /* XXX Too bad if you don't have select(). */
291 struct timeval t;
292 double frac;
293 t.tv_sec = milli/1000;
294 t.tv_usec = (milli%1000) * 1000;
295 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
296}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000297#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000298#endif /* WITH_THREAD */
299
300
Guido van Rossum18468821994-06-20 07:49:28 +0000301static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000302AsString(value, tmp)
303 PyObject *value;
304 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000305{
Guido van Rossum35d43371997-08-02 00:09:09 +0000306 if (PyString_Check(value))
307 return PyString_AsString(value);
Barry Warsawfa701a81997-01-16 00:15:11 +0000308 else {
309 PyObject *v = PyObject_Str(value);
310 PyList_Append(tmp, v);
311 Py_DECREF(v);
312 return PyString_AsString(v);
313 }
Guido van Rossum18468821994-06-20 07:49:28 +0000314}
315
Barry Warsawfa701a81997-01-16 00:15:11 +0000316
317
Guido van Rossum18468821994-06-20 07:49:28 +0000318#define ARGSZ 64
319
320static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000321Merge(args)
322 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000323{
Barry Warsawfa701a81997-01-16 00:15:11 +0000324 PyObject *tmp = NULL;
325 char *argvStore[ARGSZ];
326 char **argv = NULL;
327 int fvStore[ARGSZ];
328 int *fv = NULL;
329 int argc = 0, i;
330 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000331
Barry Warsawfa701a81997-01-16 00:15:11 +0000332 if (!(tmp = PyList_New(0)))
333 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000334
Barry Warsawfa701a81997-01-16 00:15:11 +0000335 argv = argvStore;
336 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000337
Barry Warsawfa701a81997-01-16 00:15:11 +0000338 if (args == NULL)
339 argc = 0;
340
341 else if (!PyTuple_Check(args)) {
342 argc = 1;
343 fv[0] = 0;
344 argv[0] = AsString(args, tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000345 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000346 else {
347 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000348
Barry Warsawfa701a81997-01-16 00:15:11 +0000349 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000350 argv = (char **)ckalloc(argc * sizeof(char *));
351 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000352 if (argv == NULL || fv == NULL) {
353 PyErr_NoMemory();
354 goto finally;
355 }
356 }
357
358 for (i = 0; i < argc; i++) {
359 PyObject *v = PyTuple_GetItem(args, i);
360 if (PyTuple_Check(v)) {
361 fv[i] = 1;
362 if (!(argv[i] = Merge(v)))
363 goto finally;
364 }
365 else if (v == Py_None) {
366 argc = i;
367 break;
368 }
369 else {
370 fv[i] = 0;
371 argv[i] = AsString(v, tmp);
372 }
373 }
Guido van Rossum18468821994-06-20 07:49:28 +0000374 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000375 res = Tcl_Merge(argc, argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000376
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 finally:
378 for (i = 0; i < argc; i++)
379 if (fv[i]) {
380 ckfree(argv[i]);
381 }
382 if (argv != argvStore)
383 ckfree(FREECAST argv);
384 if (fv != fvStore)
385 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Barry Warsawfa701a81997-01-16 00:15:11 +0000387 Py_DECREF(tmp);
388 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000389}
390
Barry Warsawfa701a81997-01-16 00:15:11 +0000391
392
Guido van Rossum18468821994-06-20 07:49:28 +0000393static PyObject *
Guido van Rossum00d93061998-05-28 23:06:38 +0000394Split(list)
Barry Warsawfa701a81997-01-16 00:15:11 +0000395 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +0000396{
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 int argc;
398 char **argv;
399 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000400
Barry Warsawfa701a81997-01-16 00:15:11 +0000401 if (list == NULL) {
402 Py_INCREF(Py_None);
403 return Py_None;
404 }
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Guido van Rossum00d93061998-05-28 23:06:38 +0000406 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000407 /* Not a list.
408 * Could be a quoted string containing funnies, e.g. {"}.
409 * Return the string itself.
410 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000411 return PyString_FromString(list);
412 }
Guido van Rossum18468821994-06-20 07:49:28 +0000413
Barry Warsawfa701a81997-01-16 00:15:11 +0000414 if (argc == 0)
415 v = PyString_FromString("");
416 else if (argc == 1)
417 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000418 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000419 int i;
420 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000421
Barry Warsawfa701a81997-01-16 00:15:11 +0000422 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000423 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 Py_DECREF(v);
425 v = NULL;
426 break;
427 }
428 PyTuple_SetItem(v, i, w);
429 }
430 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000431 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000433}
434
Barry Warsawfa701a81997-01-16 00:15:11 +0000435
436
Guido van Rossum18468821994-06-20 07:49:28 +0000437/**** Tkapp Object ****/
438
439#ifndef WITH_APPINIT
440int
Guido van Rossum35d43371997-08-02 00:09:09 +0000441Tcl_AppInit(interp)
Barry Warsawfa701a81997-01-16 00:15:11 +0000442 Tcl_Interp *interp;
Guido van Rossum18468821994-06-20 07:49:28 +0000443{
Barry Warsawfa701a81997-01-16 00:15:11 +0000444 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000445
Barry Warsawfa701a81997-01-16 00:15:11 +0000446 main = Tk_MainWindow(interp);
447 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000448 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000449 return TCL_ERROR;
450 }
451 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000452 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 return TCL_ERROR;
454 }
455 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000456}
457#endif /* !WITH_APPINIT */
458
Guido van Rossum18468821994-06-20 07:49:28 +0000459
Barry Warsawfa701a81997-01-16 00:15:11 +0000460
461
462/* Initialize the Tk application; see the `main' function in
463 * `tkMain.c'.
464 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000465
466static void EnableEventHook(); /* Forward */
467static void DisableEventHook(); /* Forward */
468
Barry Warsawfa701a81997-01-16 00:15:11 +0000469static TkappObject *
470Tkapp_New(screenName, baseName, className, interactive)
471 char *screenName;
472 char *baseName;
473 char *className;
474 int interactive;
475{
476 TkappObject *v;
477 char *argv0;
478
479 v = PyObject_NEW(TkappObject, &Tkapp_Type);
480 if (v == NULL)
481 return NULL;
482
483 v->interp = Tcl_CreateInterp();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000484
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000485#if defined(macintosh) && TKMAJORMINOR >= 8000
486 /* This seems to be needed since Tk 8.0 */
487 ClearMenuBar();
488 TkMacInitMenus(v->interp);
489#endif
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000490 /* Delete the 'exit' command, which can screw things up */
491 Tcl_DeleteCommand(v->interp, "exit");
492
Barry Warsawfa701a81997-01-16 00:15:11 +0000493 if (screenName != NULL)
494 Tcl_SetVar2(v->interp, "env", "DISPLAY",
495 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000496
Barry Warsawfa701a81997-01-16 00:15:11 +0000497 if (interactive)
498 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
499 else
500 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000501
Barry Warsawfa701a81997-01-16 00:15:11 +0000502 /* This is used to get the application class for Tk 4.1 and up */
503 argv0 = (char*)ckalloc(strlen(className) + 1);
504 if (!argv0) {
505 PyErr_NoMemory();
506 Py_DECREF(v);
507 return NULL;
508 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000509
Barry Warsawfa701a81997-01-16 00:15:11 +0000510 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000511 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000512 argv0[0] = tolower(argv0[0]);
513 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
514 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000515
Barry Warsawfa701a81997-01-16 00:15:11 +0000516 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000517 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000518
Guido van Rossum7bf15641998-05-22 18:28:17 +0000519 EnableEventHook();
520
Barry Warsawfa701a81997-01-16 00:15:11 +0000521 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000522}
523
Barry Warsawfa701a81997-01-16 00:15:11 +0000524
525
Guido van Rossum18468821994-06-20 07:49:28 +0000526/** Tcl Eval **/
527
528static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000529Tkapp_Call(self, args)
530 PyObject *self;
531 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000532{
Guido van Rossum212643f1998-04-29 16:22:14 +0000533 /* This is copied from Merge() */
534 PyObject *tmp = NULL;
535 char *argvStore[ARGSZ];
536 char **argv = NULL;
537 int fvStore[ARGSZ];
538 int *fv = NULL;
539 int argc = 0, i;
540 PyObject *res = NULL; /* except this has a different type */
541 Tcl_CmdInfo info; /* and this is added */
542 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
Guido van Rossum18468821994-06-20 07:49:28 +0000543
Guido van Rossum212643f1998-04-29 16:22:14 +0000544 if (!(tmp = PyList_New(0)))
545 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000546
Guido van Rossum212643f1998-04-29 16:22:14 +0000547 argv = argvStore;
548 fv = fvStore;
Barry Warsawfa701a81997-01-16 00:15:11 +0000549
Guido van Rossum212643f1998-04-29 16:22:14 +0000550 if (args == NULL)
551 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000552
Guido van Rossum212643f1998-04-29 16:22:14 +0000553 else if (!PyTuple_Check(args)) {
554 argc = 1;
555 fv[0] = 0;
556 argv[0] = AsString(args, tmp);
557 }
558 else {
559 argc = PyTuple_Size(args);
560
561 if (argc > ARGSZ) {
562 argv = (char **)ckalloc(argc * sizeof(char *));
563 fv = (int *)ckalloc(argc * sizeof(int));
564 if (argv == NULL || fv == NULL) {
565 PyErr_NoMemory();
566 goto finally;
567 }
568 }
569
570 for (i = 0; i < argc; i++) {
571 PyObject *v = PyTuple_GetItem(args, i);
572 if (PyTuple_Check(v)) {
573 fv[i] = 1;
574 if (!(argv[i] = Merge(v)))
575 goto finally;
576 }
577 else if (v == Py_None) {
578 argc = i;
579 break;
580 }
581 else {
582 fv[i] = 0;
583 argv[i] = AsString(v, tmp);
584 }
585 }
586 }
587 /* End code copied from Merge() */
588
589 /* All this to avoid a call to Tcl_Merge() and the corresponding call
590 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
591 if (Py_VerboseFlag >= 2) {
592 for (i = 0; i < argc; i++)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000593 PySys_WriteStderr("%s ", argv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000594 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000595 ENTER_TCL
596 info.proc = NULL;
Guido van Rossum212643f1998-04-29 16:22:14 +0000597 if (argc < 1 ||
598 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
599 info.proc == NULL)
600 {
601 char *cmd;
Guido van Rossum212643f1998-04-29 16:22:14 +0000602 cmd = Tcl_Merge(argc, argv);
603 i = Tcl_Eval(interp, cmd);
Barry Warsawfa701a81997-01-16 00:15:11 +0000604 ckfree(cmd);
Guido van Rossum212643f1998-04-29 16:22:14 +0000605 }
606 else {
607 Tcl_ResetResult(interp);
608 i = (*info.proc)(info.clientData, interp, argc, argv);
609 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000610 ENTER_OVERLAP
611 if (info.proc == NULL && Py_VerboseFlag >= 2)
612 PySys_WriteStderr("... use TclEval ");
Guido van Rossum212643f1998-04-29 16:22:14 +0000613 if (i == TCL_ERROR) {
614 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000615 PySys_WriteStderr("... error: '%s'\n",
Guido van Rossum212643f1998-04-29 16:22:14 +0000616 interp->result);
617 Tkinter_Error(self);
618 }
619 else {
620 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000621 PySys_WriteStderr("-> '%s'\n", interp->result);
Guido van Rossum212643f1998-04-29 16:22:14 +0000622 res = PyString_FromString(interp->result);
623 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000624 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000625
Guido van Rossum212643f1998-04-29 16:22:14 +0000626 /* Copied from Merge() again */
627 finally:
628 for (i = 0; i < argc; i++)
629 if (fv[i]) {
630 ckfree(argv[i]);
631 }
632 if (argv != argvStore)
633 ckfree(FREECAST argv);
634 if (fv != fvStore)
635 ckfree(FREECAST fv);
636
637 Py_DECREF(tmp);
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 return res;
639}
640
641
642static PyObject *
643Tkapp_GlobalCall(self, args)
644 PyObject *self;
645 PyObject *args;
646{
Guido van Rossum212643f1998-04-29 16:22:14 +0000647 /* Could do the same here as for Tkapp_Call(), but this is not used
648 much, so I can't be bothered. Unfortunately Tcl doesn't export a
649 way for the user to do what all its Global* variants do (save and
650 reset the scope pointer, call the local version, restore the saved
651 scope pointer). */
652
Guido van Rossum62320c91998-06-15 04:36:09 +0000653 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +0000654 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000655
Guido van Rossum62320c91998-06-15 04:36:09 +0000656 cmd = Merge(args);
Barry Warsawfa701a81997-01-16 00:15:11 +0000657 if (!cmd)
658 PyErr_SetString(Tkinter_TclError, "merge failed");
659
Guido van Rossum00d93061998-05-28 23:06:38 +0000660 else {
661 int err;
662 ENTER_TCL
663 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +0000664 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000665 if (err == TCL_ERROR)
666 res = Tkinter_Error(self);
667 else
668 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +0000669 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000670 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000671
672 if (cmd)
673 ckfree(cmd);
674
675 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000676}
677
678static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000679Tkapp_Eval(self, args)
680 PyObject *self;
681 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000682{
Barry Warsawfa701a81997-01-16 00:15:11 +0000683 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000684 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000685 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000686
Guido van Rossum35d43371997-08-02 00:09:09 +0000687 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000688 return NULL;
689
Guido van Rossum00d93061998-05-28 23:06:38 +0000690 ENTER_TCL
691 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000692 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000693 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000694 res = Tkinter_Error(self);
695 else
696 res = PyString_FromString(Tkapp_Result(self));
697 LEAVE_OVERLAP_TCL
698 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000699}
700
701static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000702Tkapp_GlobalEval(self, args)
703 PyObject *self;
704 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000705{
Barry Warsawfa701a81997-01-16 00:15:11 +0000706 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000707 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000708 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +0000709
Guido van Rossum35d43371997-08-02 00:09:09 +0000710 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000711 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000712
Guido van Rossum00d93061998-05-28 23:06:38 +0000713 ENTER_TCL
714 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000715 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000716 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000717 res = Tkinter_Error(self);
718 else
719 res = PyString_FromString(Tkapp_Result(self));
720 LEAVE_OVERLAP_TCL
721 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000722}
723
724static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000725Tkapp_EvalFile(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000726 PyObject *self;
727 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000728{
Barry Warsawfa701a81997-01-16 00:15:11 +0000729 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +0000730 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000731 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000732
Guido van Rossum35d43371997-08-02 00:09:09 +0000733 if (!PyArg_ParseTuple(args, "s", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +0000734 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000735
Guido van Rossum00d93061998-05-28 23:06:38 +0000736 ENTER_TCL
737 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +0000738 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000739 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000740 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +0000741
Guido van Rossum62320c91998-06-15 04:36:09 +0000742 else
743 res = PyString_FromString(Tkapp_Result(self));
744 LEAVE_OVERLAP_TCL
745 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000746}
747
748static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000749Tkapp_Record(self, args)
750 PyObject *self;
751 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000752{
Barry Warsawfa701a81997-01-16 00:15:11 +0000753 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000754 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000755 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000756
Guido van Rossum35d43371997-08-02 00:09:09 +0000757 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000758 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000759
Guido van Rossum00d93061998-05-28 23:06:38 +0000760 ENTER_TCL
761 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +0000762 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000763 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000764 res = Tkinter_Error(self);
765 else
766 res = PyString_FromString(Tkapp_Result(self));
767 LEAVE_OVERLAP_TCL
768 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000769}
770
771static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000772Tkapp_AddErrorInfo(self, args)
773 PyObject *self;
774 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000775{
Barry Warsawfa701a81997-01-16 00:15:11 +0000776 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +0000777
Guido van Rossum35d43371997-08-02 00:09:09 +0000778 if (!PyArg_ParseTuple(args, "s", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +0000779 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000780 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000781 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +0000782 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +0000783
Barry Warsawfa701a81997-01-16 00:15:11 +0000784 Py_INCREF(Py_None);
785 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000786}
787
Barry Warsawfa701a81997-01-16 00:15:11 +0000788
789
Guido van Rossum18468821994-06-20 07:49:28 +0000790/** Tcl Variable **/
791
792static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000793SetVar(self, args, flags)
794 PyObject *self;
795 PyObject *args;
796 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000797{
Guido van Rossum00d93061998-05-28 23:06:38 +0000798 char *name1, *name2, *ok, *s;
Barry Warsawfa701a81997-01-16 00:15:11 +0000799 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +0000800 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000801
Guido van Rossum62320c91998-06-15 04:36:09 +0000802 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +0000803 if (!tmp)
804 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000805
Guido van Rossum00d93061998-05-28 23:06:38 +0000806 if (PyArg_ParseTuple(args, "sO", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000807 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +0000808 s = AsString(newValue, tmp);
809 ENTER_TCL
810 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
811 LEAVE_TCL
812 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000813 else {
Guido van Rossum35d43371997-08-02 00:09:09 +0000814 PyErr_Clear();
Guido van Rossum00d93061998-05-28 23:06:38 +0000815 if (PyArg_ParseTuple(args, "ssO", &name1, &name2, &newValue)) {
816 s = AsString (newValue, tmp);
817 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000818 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
Guido van Rossum00d93061998-05-28 23:06:38 +0000819 s, flags);
820 LEAVE_TCL
821 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000822 else {
Guido van Rossum00d93061998-05-28 23:06:38 +0000823 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +0000824 return NULL;
825 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000826 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000827 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000828
Barry Warsawfa701a81997-01-16 00:15:11 +0000829 if (!ok)
830 return Tkinter_Error(self);
831
832 Py_INCREF(Py_None);
833 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000834}
835
836static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000837Tkapp_SetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000838 PyObject *self;
839 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000840{
Barry Warsawfa701a81997-01-16 00:15:11 +0000841 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000842}
843
844static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000845Tkapp_GlobalSetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000846 PyObject *self;
847 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000848{
Barry Warsawfa701a81997-01-16 00:15:11 +0000849 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000850}
851
Barry Warsawfa701a81997-01-16 00:15:11 +0000852
853
Guido van Rossum18468821994-06-20 07:49:28 +0000854static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000855GetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000856 PyObject *self;
857 PyObject *args;
858 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000859{
Guido van Rossum35d43371997-08-02 00:09:09 +0000860 char *name1, *name2=NULL, *s;
Guido van Rossum62320c91998-06-15 04:36:09 +0000861 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000862
Guido van Rossum35d43371997-08-02 00:09:09 +0000863 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
864 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000865 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000866 if (name2 == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000867 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
Guido van Rossum18468821994-06-20 07:49:28 +0000868
Barry Warsawfa701a81997-01-16 00:15:11 +0000869 else
Guido van Rossum35d43371997-08-02 00:09:09 +0000870 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000871 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000872
Barry Warsawfa701a81997-01-16 00:15:11 +0000873 if (s == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000874 res = Tkinter_Error(self);
875 else
876 res = PyString_FromString(s);
877 LEAVE_OVERLAP_TCL
878 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000879}
880
881static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000882Tkapp_GetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000883 PyObject *self;
884 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000885{
Barry Warsawfa701a81997-01-16 00:15:11 +0000886 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000887}
888
889static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000890Tkapp_GlobalGetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000891 PyObject *self;
892 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000893{
Barry Warsawfa701a81997-01-16 00:15:11 +0000894 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000895}
896
Barry Warsawfa701a81997-01-16 00:15:11 +0000897
898
Guido van Rossum18468821994-06-20 07:49:28 +0000899static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000900UnsetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000901 PyObject *self;
902 PyObject *args;
903 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000904{
Guido van Rossum35d43371997-08-02 00:09:09 +0000905 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +0000906 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000907 int code;
Guido van Rossum18468821994-06-20 07:49:28 +0000908
Guido van Rossum35d43371997-08-02 00:09:09 +0000909 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +0000910 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000911 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000912 if (name2 == NULL)
913 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
914
915 else
916 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000917 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000918
Barry Warsawfa701a81997-01-16 00:15:11 +0000919 if (code == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000920 res = Tkinter_Error(self);
921 else {
922 Py_INCREF(Py_None);
923 res = Py_None;
924 }
925 LEAVE_OVERLAP_TCL
926 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000927}
928
929static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000930Tkapp_UnsetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000931 PyObject *self;
932 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000933{
Barry Warsawfa701a81997-01-16 00:15:11 +0000934 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000935}
936
937static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000938Tkapp_GlobalUnsetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000939 PyObject *self;
940 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000941{
Barry Warsawfa701a81997-01-16 00:15:11 +0000942 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000943}
944
Barry Warsawfa701a81997-01-16 00:15:11 +0000945
946
Guido van Rossum18468821994-06-20 07:49:28 +0000947/** Tcl to Python **/
948
949static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000950Tkapp_GetInt(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000951 PyObject *self;
952 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000953{
Barry Warsawfa701a81997-01-16 00:15:11 +0000954 char *s;
955 int v;
Guido van Rossum18468821994-06-20 07:49:28 +0000956
Guido van Rossum35d43371997-08-02 00:09:09 +0000957 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000958 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000959 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +0000960 return Tkinter_Error(self);
961 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000962}
963
964static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000965Tkapp_GetDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000966 PyObject *self;
967 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000968{
Barry Warsawfa701a81997-01-16 00:15:11 +0000969 char *s;
970 double v;
Guido van Rossum18468821994-06-20 07:49:28 +0000971
Guido van Rossum35d43371997-08-02 00:09:09 +0000972 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000973 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000974 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +0000975 return Tkinter_Error(self);
976 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000977}
978
979static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000980Tkapp_GetBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000981 PyObject *self;
982 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000983{
Barry Warsawfa701a81997-01-16 00:15:11 +0000984 char *s;
985 int v;
Guido van Rossum18468821994-06-20 07:49:28 +0000986
Guido van Rossum35d43371997-08-02 00:09:09 +0000987 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000988 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000989 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
990 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +0000991 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000992}
993
994static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000995Tkapp_ExprString(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000996 PyObject *self;
997 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000998{
Barry Warsawfa701a81997-01-16 00:15:11 +0000999 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001000 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001001 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001002
Guido van Rossum35d43371997-08-02 00:09:09 +00001003 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001004 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001005 ENTER_TCL
1006 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001007 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001008 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001009 res = Tkinter_Error(self);
1010 else
1011 res = Py_BuildValue("s", Tkapp_Result(self));
1012 LEAVE_OVERLAP_TCL
1013 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001014}
1015
1016static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001017Tkapp_ExprLong(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001018 PyObject *self;
1019 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001020{
Barry Warsawfa701a81997-01-16 00:15:11 +00001021 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001022 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001023 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001024 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001025
Guido van Rossum35d43371997-08-02 00:09:09 +00001026 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001027 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001028 ENTER_TCL
1029 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001030 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001031 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001032 res = Tkinter_Error(self);
1033 else
1034 res = Py_BuildValue("l", v);
1035 LEAVE_OVERLAP_TCL
1036 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001037}
1038
1039static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001040Tkapp_ExprDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001041 PyObject *self;
1042 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001043{
Barry Warsawfa701a81997-01-16 00:15:11 +00001044 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001045 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001046 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001047 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001048
Guido van Rossum35d43371997-08-02 00:09:09 +00001049 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001050 return NULL;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001051 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001052 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001053 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001054 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001055 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001056 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001057 res = Tkinter_Error(self);
1058 else
1059 res = Py_BuildValue("d", v);
1060 LEAVE_OVERLAP_TCL
1061 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001062}
1063
1064static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001065Tkapp_ExprBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001066 PyObject *self;
1067 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001068{
Barry Warsawfa701a81997-01-16 00:15:11 +00001069 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001070 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001071 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001072 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001073
Guido van Rossum35d43371997-08-02 00:09:09 +00001074 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001075 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001076 ENTER_TCL
1077 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001078 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001079 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001080 res = Tkinter_Error(self);
1081 else
1082 res = Py_BuildValue("i", v);
1083 LEAVE_OVERLAP_TCL
1084 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001085}
1086
Barry Warsawfa701a81997-01-16 00:15:11 +00001087
1088
Guido van Rossum18468821994-06-20 07:49:28 +00001089static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001090Tkapp_SplitList(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001091 PyObject *self;
1092 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001093{
Barry Warsawfa701a81997-01-16 00:15:11 +00001094 char *list;
1095 int argc;
1096 char **argv;
1097 PyObject *v;
1098 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001099
Guido van Rossum35d43371997-08-02 00:09:09 +00001100 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001101 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001102
Barry Warsawfa701a81997-01-16 00:15:11 +00001103 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1104 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001105
Barry Warsawfa701a81997-01-16 00:15:11 +00001106 if (!(v = PyTuple_New(argc)))
1107 return NULL;
1108
1109 for (i = 0; i < argc; i++) {
1110 PyObject *s = PyString_FromString(argv[i]);
1111 if (!s || PyTuple_SetItem(v, i, s)) {
1112 Py_DECREF(v);
1113 v = NULL;
1114 goto finally;
1115 }
1116 }
Guido van Rossum18468821994-06-20 07:49:28 +00001117
Barry Warsawfa701a81997-01-16 00:15:11 +00001118 finally:
1119 ckfree(FREECAST argv);
1120 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001121}
1122
1123static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001124Tkapp_Split(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001125 PyObject *self;
1126 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001127{
Barry Warsawfa701a81997-01-16 00:15:11 +00001128 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001129
Guido van Rossum35d43371997-08-02 00:09:09 +00001130 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001131 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001132 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001133}
1134
1135static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001136Tkapp_Merge(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001137 PyObject *self;
1138 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001139{
Barry Warsawfa701a81997-01-16 00:15:11 +00001140 char *s = Merge(args);
1141 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001142
Barry Warsawfa701a81997-01-16 00:15:11 +00001143 if (s) {
1144 res = PyString_FromString(s);
1145 ckfree(s);
1146 }
1147 else
1148 PyErr_SetString(Tkinter_TclError, "merge failed");
1149
1150 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001151}
1152
Barry Warsawfa701a81997-01-16 00:15:11 +00001153
1154
Guido van Rossum18468821994-06-20 07:49:28 +00001155/** Tcl Command **/
1156
Guido van Rossum00d93061998-05-28 23:06:38 +00001157/* Client data struct */
1158typedef struct {
1159 PyThreadState *tstate;
1160 PyObject *self;
1161 PyObject *func;
1162} PythonCmd_ClientData;
1163
1164static int
1165PythonCmd_Error(interp)
1166 Tcl_Interp *interp;
1167{
1168 errorInCmd = 1;
1169 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1170 LEAVE_PYTHON
1171 return TCL_ERROR;
1172}
1173
Guido van Rossum18468821994-06-20 07:49:28 +00001174/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001175 * function or method.
1176 */
Guido van Rossum18468821994-06-20 07:49:28 +00001177static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001178PythonCmd(clientData, interp, argc, argv)
Guido van Rossum00d93061998-05-28 23:06:38 +00001179 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001180 Tcl_Interp *interp;
1181 int argc;
1182 char *argv[];
Guido van Rossum18468821994-06-20 07:49:28 +00001183{
Guido van Rossum00d93061998-05-28 23:06:38 +00001184 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001185 PyObject *self, *func, *arg, *res, *tmp;
1186 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001187
Guido van Rossum00d93061998-05-28 23:06:38 +00001188 /* XXX Should create fresh thread state? */
1189 ENTER_PYTHON(data->tstate)
1190
Barry Warsawfa701a81997-01-16 00:15:11 +00001191 /* TBD: no error checking here since we know, via the
1192 * Tkapp_CreateCommand() that the client data is a two-tuple
1193 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001194 self = data->self;
1195 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001196
Barry Warsawfa701a81997-01-16 00:15:11 +00001197 /* Create argument list (argv1, ..., argvN) */
1198 if (!(arg = PyTuple_New(argc - 1)))
1199 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001200
Barry Warsawfa701a81997-01-16 00:15:11 +00001201 for (i = 0; i < (argc - 1); i++) {
1202 PyObject *s = PyString_FromString(argv[i + 1]);
1203 if (!s || PyTuple_SetItem(arg, i, s)) {
1204 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001205 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001206 }
1207 }
1208 res = PyEval_CallObject(func, arg);
1209 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001210
Barry Warsawfa701a81997-01-16 00:15:11 +00001211 if (res == NULL)
1212 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001213
Barry Warsawfa701a81997-01-16 00:15:11 +00001214 if (!(tmp = PyList_New(0))) {
1215 Py_DECREF(res);
1216 return PythonCmd_Error(interp);
1217 }
1218
1219 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1220 Py_DECREF(res);
1221 Py_DECREF(tmp);
1222
Guido van Rossum00d93061998-05-28 23:06:38 +00001223 LEAVE_PYTHON
1224
Barry Warsawfa701a81997-01-16 00:15:11 +00001225 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00001226}
1227
1228static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001229PythonCmdDelete(clientData)
Guido van Rossum00d93061998-05-28 23:06:38 +00001230 ClientData clientData;
Guido van Rossum18468821994-06-20 07:49:28 +00001231{
Guido van Rossum00d93061998-05-28 23:06:38 +00001232 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1233
1234 ENTER_PYTHON(data->tstate)
1235 Py_XDECREF(data->self);
1236 Py_XDECREF(data->func);
1237 PyMem_DEL(data);
1238 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001239}
1240
Barry Warsawfa701a81997-01-16 00:15:11 +00001241
1242
Guido van Rossum18468821994-06-20 07:49:28 +00001243static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001244Tkapp_CreateCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001245 PyObject *self;
1246 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001247{
Guido van Rossum00d93061998-05-28 23:06:38 +00001248 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001249 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001250 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001251 Tcl_Command err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001252
1253 if (!PyArg_ParseTuple(args, "sO", &cmdName, &func))
1254 return NULL;
1255 if (!PyCallable_Check(func)) {
1256 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001257 return NULL;
1258 }
Guido van Rossum18468821994-06-20 07:49:28 +00001259
Guido van Rossum00d93061998-05-28 23:06:38 +00001260 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001261 if (!data)
1262 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001263 data->tstate = PyThreadState_Get();
1264 Py_XINCREF(self);
1265 Py_XINCREF(func);
1266 data->self = self;
1267 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00001268
Guido van Rossum00d93061998-05-28 23:06:38 +00001269 ENTER_TCL
1270 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1271 (ClientData)data, PythonCmdDelete);
1272 LEAVE_TCL
1273 if (err == NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001274 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001275 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001276 return NULL;
1277 }
Guido van Rossum18468821994-06-20 07:49:28 +00001278
Barry Warsawfa701a81997-01-16 00:15:11 +00001279 Py_INCREF(Py_None);
1280 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001281}
1282
Barry Warsawfa701a81997-01-16 00:15:11 +00001283
1284
Guido van Rossum18468821994-06-20 07:49:28 +00001285static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001286Tkapp_DeleteCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001287 PyObject *self;
1288 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001289{
Barry Warsawfa701a81997-01-16 00:15:11 +00001290 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001291 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001292
Guido van Rossum35d43371997-08-02 00:09:09 +00001293 if (!PyArg_ParseTuple(args, "s", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001294 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001295 ENTER_TCL
1296 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1297 LEAVE_TCL
1298 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001299 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1300 return NULL;
1301 }
1302 Py_INCREF(Py_None);
1303 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001304}
1305
Barry Warsawfa701a81997-01-16 00:15:11 +00001306
1307
Guido van Rossum00d93061998-05-28 23:06:38 +00001308#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00001309/** File Handler **/
1310
Guido van Rossum00d93061998-05-28 23:06:38 +00001311typedef struct _fhcdata {
1312 PyThreadState *tstate;
1313 PyObject *func;
1314 PyObject *file;
1315 int id;
1316 struct _fhcdata *next;
1317} FileHandler_ClientData;
1318
1319static FileHandler_ClientData *HeadFHCD;
1320
1321static FileHandler_ClientData *
1322NewFHCD(func, file, id)
1323 PyObject *func;
1324 PyObject *file;
1325 int id;
1326{
1327 FileHandler_ClientData *p;
1328 p = PyMem_NEW(FileHandler_ClientData, 1);
1329 if (p != NULL) {
1330 Py_XINCREF(func);
1331 Py_XINCREF(file);
1332 p->tstate = PyThreadState_Get();
1333 p->func = func;
1334 p->file = file;
1335 p->id = id;
1336 p->next = HeadFHCD;
1337 HeadFHCD = p;
1338 }
1339 return p;
1340}
1341
1342static void
1343DeleteFHCD(id)
1344 int id;
1345{
1346 FileHandler_ClientData *p, **pp;
1347
1348 pp = &HeadFHCD;
1349 while ((p = *pp) != NULL) {
1350 if (p->id == id) {
1351 *pp = p->next;
1352 Py_XDECREF(p->func);
1353 Py_XDECREF(p->file);
1354 PyMem_DEL(p);
1355 }
1356 else
1357 pp = &p->next;
1358 }
1359}
1360
Guido van Rossuma597dde1995-01-10 20:56:29 +00001361static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001362FileHandler(clientData, mask)
Guido van Rossum00d93061998-05-28 23:06:38 +00001363 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001364 int mask;
Guido van Rossum18468821994-06-20 07:49:28 +00001365{
Guido van Rossum00d93061998-05-28 23:06:38 +00001366 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001367 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00001368
Guido van Rossum00d93061998-05-28 23:06:38 +00001369 /* XXX Should create fresh thread state? */
1370 ENTER_PYTHON(data->tstate)
1371 func = data->func;
1372 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00001373
Barry Warsawfa701a81997-01-16 00:15:11 +00001374 arg = Py_BuildValue("(Oi)", file, (long) mask);
1375 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00001376 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00001377
1378 if (res == NULL) {
1379 errorInCmd = 1;
1380 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1381 }
1382 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001383 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001384}
1385
1386static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001387GetFileNo(file)
Barry Warsawfa701a81997-01-16 00:15:11 +00001388 /* Either an int >= 0 or an object with a
1389 *.fileno() method that returns an int >= 0
1390 */
1391 PyObject *file;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001392{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001393 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001394 int id;
1395 if (PyInt_Check(file)) {
1396 id = PyInt_AsLong(file);
1397 if (id < 0)
1398 PyErr_SetString(PyExc_ValueError, "invalid file id");
1399 return id;
1400 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001401 args = PyTuple_New(0);
1402 if (args == NULL)
1403 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001404
1405 meth = PyObject_GetAttrString(file, "fileno");
1406 if (meth == NULL) {
1407 Py_DECREF(args);
1408 return -1;
1409 }
1410
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001411 res = PyEval_CallObject(meth, args);
1412 Py_DECREF(args);
1413 Py_DECREF(meth);
1414 if (res == NULL)
1415 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001416
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001417 if (PyInt_Check(res))
1418 id = PyInt_AsLong(res);
1419 else
1420 id = -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001421
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001422 if (id < 0)
1423 PyErr_SetString(PyExc_ValueError,
1424 "invalid fileno() return value");
1425 Py_DECREF(res);
1426 return id;
Guido van Rossum18468821994-06-20 07:49:28 +00001427}
1428
1429static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001430Tkapp_CreateFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001431 PyObject *self;
1432 PyObject *args; /* Is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00001433{
Guido van Rossum00d93061998-05-28 23:06:38 +00001434 FileHandler_ClientData *data;
1435 PyObject *file, *func;
Barry Warsawfa701a81997-01-16 00:15:11 +00001436 int mask, id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001437 FHANDLE tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00001438
Guido van Rossum35d43371997-08-02 00:09:09 +00001439 if (!PyArg_ParseTuple(args, "OiO", &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001440 return NULL;
1441 id = GetFileNo(file);
1442 if (id < 0)
1443 return NULL;
1444 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001445 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001446 return NULL;
1447 }
1448
Guido van Rossum00d93061998-05-28 23:06:38 +00001449 data = NewFHCD(func, file, id);
1450 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001451 return NULL;
1452
Guido van Rossum7bf15641998-05-22 18:28:17 +00001453 tfile = MAKEFHANDLE(id);
Barry Warsawfa701a81997-01-16 00:15:11 +00001454 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001455 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001456 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00001457 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001458 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001459 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001460}
1461
1462static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001463Tkapp_DeleteFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001464 PyObject *self;
1465 PyObject *args; /* Args: file */
Guido van Rossum18468821994-06-20 07:49:28 +00001466{
Barry Warsawfa701a81997-01-16 00:15:11 +00001467 PyObject *file;
Guido van Rossum00d93061998-05-28 23:06:38 +00001468 FileHandler_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001469 int id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001470 FHANDLE tfile;
Guido van Rossum68784361996-05-16 17:17:31 +00001471
Guido van Rossum35d43371997-08-02 00:09:09 +00001472 if (!PyArg_ParseTuple(args, "O", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00001473 return NULL;
1474 id = GetFileNo(file);
1475 if (id < 0)
1476 return NULL;
1477
Guido van Rossum00d93061998-05-28 23:06:38 +00001478 DeleteFHCD(id);
Guido van Rossum18468821994-06-20 07:49:28 +00001479
Guido van Rossum7bf15641998-05-22 18:28:17 +00001480 tfile = MAKEFHANDLE(id);
Barry Warsawfa701a81997-01-16 00:15:11 +00001481 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001482 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001483 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001484 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001485 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001486 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001487}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001488#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00001489
Barry Warsawfa701a81997-01-16 00:15:11 +00001490
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001491/**** Tktt Object (timer token) ****/
1492
1493staticforward PyTypeObject Tktt_Type;
1494
Guido van Rossum00d93061998-05-28 23:06:38 +00001495typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00001496 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00001497 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00001498 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001499 PyThreadState *tstate;
1500} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001501
1502static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001503Tktt_DeleteTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001504 PyObject *self;
1505 PyObject *args;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001506{
Barry Warsawfa701a81997-01-16 00:15:11 +00001507 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001508 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001509
Guido van Rossum35d43371997-08-02 00:09:09 +00001510 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001511 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001512 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001513 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00001514 v->token = NULL;
1515 }
1516 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001517 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001518 Py_DECREF(func);
1519 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00001520 }
1521 Py_INCREF(Py_None);
1522 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001523}
1524
1525static PyMethodDef Tktt_methods[] =
1526{
Guido van Rossum35d43371997-08-02 00:09:09 +00001527 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001528 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001529};
1530
1531static TkttObject *
Guido van Rossum00d93061998-05-28 23:06:38 +00001532Tktt_New(func)
Barry Warsawfa701a81997-01-16 00:15:11 +00001533 PyObject *func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001534{
Barry Warsawfa701a81997-01-16 00:15:11 +00001535 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001536
Barry Warsawfa701a81997-01-16 00:15:11 +00001537 v = PyObject_NEW(TkttObject, &Tktt_Type);
1538 if (v == NULL)
1539 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001540
Guido van Rossum00d93061998-05-28 23:06:38 +00001541 Py_INCREF(func);
1542 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001543 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001544 v->tstate = PyThreadState_Get();
1545
1546 /* Extra reference, deleted when called or when handler is deleted */
1547 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001548 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001549}
1550
1551static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001552Tktt_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001553 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001554{
Guido van Rossum00d93061998-05-28 23:06:38 +00001555 TkttObject *v = (TkttObject *)self;
1556 PyObject *func = v->func;
1557
1558 Py_XDECREF(func);
1559
Guido van Rossum35d43371997-08-02 00:09:09 +00001560 PyMem_DEL(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001561}
1562
Guido van Rossum597ac201998-05-12 14:36:19 +00001563static PyObject *
1564Tktt_Repr(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001565 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001566{
Barry Warsawfa701a81997-01-16 00:15:11 +00001567 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00001568 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001569
Guido van Rossum597ac201998-05-12 14:36:19 +00001570 sprintf(buf, "<tktimertoken at 0x%lx%s>", (long)v,
Barry Warsawfa701a81997-01-16 00:15:11 +00001571 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00001572 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001573}
1574
1575static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001576Tktt_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001577 PyObject *self;
1578 char *name;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001579{
Barry Warsawfa701a81997-01-16 00:15:11 +00001580 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001581}
1582
1583static PyTypeObject Tktt_Type =
1584{
Guido van Rossum35d43371997-08-02 00:09:09 +00001585 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001586 0, /*ob_size */
1587 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001588 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001589 0, /*tp_itemsize */
1590 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00001591 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00001592 Tktt_GetAttr, /*tp_getattr */
1593 0, /*tp_setattr */
1594 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00001595 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 0, /*tp_as_number */
1597 0, /*tp_as_sequence */
1598 0, /*tp_as_mapping */
1599 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001600};
1601
Barry Warsawfa701a81997-01-16 00:15:11 +00001602
1603
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001604/** Timer Handler **/
1605
1606static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001607TimerHandler(clientData)
Barry Warsawfa701a81997-01-16 00:15:11 +00001608 ClientData clientData;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001609{
Guido van Rossum00d93061998-05-28 23:06:38 +00001610 TkttObject *v = (TkttObject *)clientData;
1611 PyObject *func = v->func;
1612 PyObject *res;
1613
1614 if (func == NULL)
1615 return;
1616
1617 v->func = NULL;
1618
1619 ENTER_PYTHON(v->tstate)
1620
1621 res = PyEval_CallObject(func, NULL);
1622 Py_DECREF(func);
1623 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001624
Barry Warsawfa701a81997-01-16 00:15:11 +00001625 if (res == NULL) {
1626 errorInCmd = 1;
1627 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1628 }
1629 else
1630 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001631
1632 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001633}
1634
1635static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001636Tkapp_CreateTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001637 PyObject *self;
1638 PyObject *args; /* Is (milliseconds, func) */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001639{
Barry Warsawfa701a81997-01-16 00:15:11 +00001640 int milliseconds;
1641 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001642 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001643
Guido van Rossum35d43371997-08-02 00:09:09 +00001644 if (!PyArg_ParseTuple(args, "iO", &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001645 return NULL;
1646 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001647 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001648 return NULL;
1649 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001650 v = Tktt_New(func);
1651 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1652 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001653
Guido van Rossum00d93061998-05-28 23:06:38 +00001654 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001655}
1656
Barry Warsawfa701a81997-01-16 00:15:11 +00001657
Guido van Rossum18468821994-06-20 07:49:28 +00001658/** Event Loop **/
1659
Guido van Rossum18468821994-06-20 07:49:28 +00001660static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001661Tkapp_MainLoop(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001662 PyObject *self;
1663 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001664{
Barry Warsawfa701a81997-01-16 00:15:11 +00001665 int threshold = 0;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001666
Barry Warsawfa701a81997-01-16 00:15:11 +00001667 if (!PyArg_ParseTuple(args, "|i", &threshold))
1668 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001669
Barry Warsawfa701a81997-01-16 00:15:11 +00001670 quitMainLoop = 0;
1671 while (Tk_GetNumMainWindows() > threshold &&
1672 !quitMainLoop &&
1673 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001674 {
Guido van Rossum35d43371997-08-02 00:09:09 +00001675 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00001676
1677#ifdef WITH_THREAD
Guido van Rossum62320c91998-06-15 04:36:09 +00001678 Py_BEGIN_ALLOW_THREADS
1679 acquire_lock(tcl_lock, 1);
Guido van Rossum35d43371997-08-02 00:09:09 +00001680 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossum00d93061998-05-28 23:06:38 +00001681 release_lock(tcl_lock);
1682 if (result == 0)
1683 Sleep(20);
Guido van Rossum35d43371997-08-02 00:09:09 +00001684 Py_END_ALLOW_THREADS
Guido van Rossum5b020781997-08-19 01:00:50 +00001685#else
1686 result = Tcl_DoOneEvent(0);
1687#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001688
Guido van Rossum35d43371997-08-02 00:09:09 +00001689 if (PyErr_CheckSignals() != 0)
1690 return NULL;
1691 if (result < 0)
1692 break;
Guido van Rossum18468821994-06-20 07:49:28 +00001693 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001694 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001695
Barry Warsawfa701a81997-01-16 00:15:11 +00001696 if (errorInCmd) {
1697 errorInCmd = 0;
1698 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1699 excInCmd = valInCmd = trbInCmd = NULL;
1700 return NULL;
1701 }
1702 Py_INCREF(Py_None);
1703 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001704}
1705
1706static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001707Tkapp_DoOneEvent(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001708 PyObject *self;
1709 PyObject *args;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001710{
Guido van Rossum35d43371997-08-02 00:09:09 +00001711 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00001712 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001713
Barry Warsawfa701a81997-01-16 00:15:11 +00001714 if (!PyArg_ParseTuple(args, "|i", &flags))
1715 return NULL;
1716
Guido van Rossum00d93061998-05-28 23:06:38 +00001717 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001718 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00001719 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001720 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001721}
1722
1723static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001724Tkapp_Quit(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001725 PyObject *self;
1726 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001727{
1728
Guido van Rossum35d43371997-08-02 00:09:09 +00001729 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001730 return NULL;
1731
1732 quitMainLoop = 1;
1733 Py_INCREF(Py_None);
1734 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001735}
1736
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001737static PyObject *
1738Tkapp_InterpAddr(self, args)
1739 PyObject *self;
1740 PyObject *args;
1741{
1742
1743 if (!PyArg_ParseTuple(args, ""))
1744 return NULL;
1745
1746 return PyInt_FromLong((long)Tkapp_Interp(self));
1747}
1748
Barry Warsawfa701a81997-01-16 00:15:11 +00001749
1750
Guido van Rossum18468821994-06-20 07:49:28 +00001751/**** Tkapp Method List ****/
1752
1753static PyMethodDef Tkapp_methods[] =
1754{
Guido van Rossum35d43371997-08-02 00:09:09 +00001755 {"call", Tkapp_Call, 0},
1756 {"globalcall", Tkapp_GlobalCall, 0},
1757 {"eval", Tkapp_Eval, 1},
1758 {"globaleval", Tkapp_GlobalEval, 1},
1759 {"evalfile", Tkapp_EvalFile, 1},
1760 {"record", Tkapp_Record, 1},
1761 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1762 {"setvar", Tkapp_SetVar, 1},
1763 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1764 {"getvar", Tkapp_GetVar, 1},
1765 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1766 {"unsetvar", Tkapp_UnsetVar, 1},
1767 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1768 {"getint", Tkapp_GetInt, 1},
1769 {"getdouble", Tkapp_GetDouble, 1},
1770 {"getboolean", Tkapp_GetBoolean, 1},
1771 {"exprstring", Tkapp_ExprString, 1},
1772 {"exprlong", Tkapp_ExprLong, 1},
1773 {"exprdouble", Tkapp_ExprDouble, 1},
1774 {"exprboolean", Tkapp_ExprBoolean, 1},
1775 {"splitlist", Tkapp_SplitList, 1},
1776 {"split", Tkapp_Split, 1},
1777 {"merge", Tkapp_Merge, 0},
1778 {"createcommand", Tkapp_CreateCommand, 1},
1779 {"deletecommand", Tkapp_DeleteCommand, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001780#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001781 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1782 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001783#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001784 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001785 {"mainloop", Tkapp_MainLoop, 1},
1786 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001787 {"quit", Tkapp_Quit, 1},
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001788 {"interpaddr", Tkapp_InterpAddr, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001789 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001790};
1791
Barry Warsawfa701a81997-01-16 00:15:11 +00001792
1793
Guido van Rossum18468821994-06-20 07:49:28 +00001794/**** Tkapp Type Methods ****/
1795
1796static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001797Tkapp_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001798 PyObject *self;
Guido van Rossum18468821994-06-20 07:49:28 +00001799{
Guido van Rossum00d93061998-05-28 23:06:38 +00001800 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001801 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00001802 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001803 PyMem_DEL(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001804 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00001805}
1806
1807static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001808Tkapp_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001809 PyObject *self;
1810 char *name;
Guido van Rossum18468821994-06-20 07:49:28 +00001811{
Guido van Rossum35d43371997-08-02 00:09:09 +00001812 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00001813}
1814
1815static PyTypeObject Tkapp_Type =
1816{
Guido van Rossum35d43371997-08-02 00:09:09 +00001817 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001818 0, /*ob_size */
1819 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001820 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001821 0, /*tp_itemsize */
1822 Tkapp_Dealloc, /*tp_dealloc */
1823 0, /*tp_print */
1824 Tkapp_GetAttr, /*tp_getattr */
1825 0, /*tp_setattr */
1826 0, /*tp_compare */
1827 0, /*tp_repr */
1828 0, /*tp_as_number */
1829 0, /*tp_as_sequence */
1830 0, /*tp_as_mapping */
1831 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00001832};
1833
Barry Warsawfa701a81997-01-16 00:15:11 +00001834
1835
Guido van Rossum18468821994-06-20 07:49:28 +00001836/**** Tkinter Module ****/
1837
1838static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001839Tkinter_Create(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001840 PyObject *self;
1841 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001842{
Barry Warsawfa701a81997-01-16 00:15:11 +00001843 char *screenName = NULL;
1844 char *baseName = NULL;
1845 char *className = NULL;
1846 int interactive = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001847
Guido van Rossum35d43371997-08-02 00:09:09 +00001848 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00001849 if (baseName != NULL)
1850 baseName++;
1851 else
1852 baseName = Py_GetProgramName();
1853 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00001854
Barry Warsawfa701a81997-01-16 00:15:11 +00001855 if (!PyArg_ParseTuple(args, "|zssi",
1856 &screenName, &baseName, &className,
1857 &interactive))
1858 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001859
Barry Warsawfa701a81997-01-16 00:15:11 +00001860 return (PyObject *) Tkapp_New(screenName, baseName, className,
1861 interactive);
Guido van Rossum18468821994-06-20 07:49:28 +00001862}
1863
1864static PyMethodDef moduleMethods[] =
1865{
Barry Warsawfa701a81997-01-16 00:15:11 +00001866 {"create", Tkinter_Create, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001867#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001868 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1869 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001870#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001871 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001872 {"mainloop", Tkapp_MainLoop, 1},
1873 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001874 {"quit", Tkapp_Quit, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001875 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001876};
1877
Guido van Rossum7bf15641998-05-22 18:28:17 +00001878#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001879
1880static int stdin_ready = 0;
1881
Guido van Rossumad4db171998-06-13 13:56:28 +00001882#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00001883static void
1884MyFileProc(clientData, mask)
1885 void *clientData;
1886 int mask;
1887{
1888 stdin_ready = 1;
1889}
Guido van Rossumad4db171998-06-13 13:56:28 +00001890#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001891
Guido van Rossum00d93061998-05-28 23:06:38 +00001892static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00001893
Guido van Rossum18468821994-06-20 07:49:28 +00001894static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001895EventHook()
Guido van Rossum18468821994-06-20 07:49:28 +00001896{
Guido van Rossumad4db171998-06-13 13:56:28 +00001897#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001898 FHANDLE tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00001899#endif
1900 if (PyThreadState_Swap(NULL) != NULL)
1901 Py_FatalError("EventHook with non-NULL tstate\n");
1902 PyEval_RestoreThread(event_tstate);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001903 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00001904 errorInCmd = 0;
1905#ifndef MS_WINDOWS
1906 tfile = MAKEFHANDLE(fileno(stdin));
Guido van Rossum7bf15641998-05-22 18:28:17 +00001907 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00001908#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001909 while (!errorInCmd && !stdin_ready) {
1910 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00001911#ifdef MS_WINDOWS
1912 if (_kbhit()) {
1913 stdin_ready = 1;
1914 break;
1915 }
1916#endif
1917#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00001918 Py_BEGIN_ALLOW_THREADS
1919 acquire_lock(tcl_lock, 1);
Guido van Rossum00d93061998-05-28 23:06:38 +00001920 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
1921 release_lock(tcl_lock);
1922 if (result == 0)
1923 Sleep(20);
1924 Py_END_ALLOW_THREADS
1925#else
1926 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001927#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001928
1929 if (result < 0)
1930 break;
1931 }
Guido van Rossumad4db171998-06-13 13:56:28 +00001932#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001933 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00001934#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00001935 if (errorInCmd) {
1936 errorInCmd = 0;
1937 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1938 excInCmd = valInCmd = trbInCmd = NULL;
1939 PyErr_Print();
1940 }
Guido van Rossumad4db171998-06-13 13:56:28 +00001941 PyEval_SaveThread();
Barry Warsawfa701a81997-01-16 00:15:11 +00001942 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001943}
Guido van Rossum18468821994-06-20 07:49:28 +00001944
Guido van Rossum00d93061998-05-28 23:06:38 +00001945#endif
1946
Guido van Rossum7bf15641998-05-22 18:28:17 +00001947static void
1948EnableEventHook()
1949{
Guido van Rossum00d93061998-05-28 23:06:38 +00001950#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001951 if (PyOS_InputHook == NULL) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001952 event_tstate = PyThreadState_Get();
Guido van Rossum7bf15641998-05-22 18:28:17 +00001953 PyOS_InputHook = EventHook;
1954 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001955#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001956}
1957
1958static void
1959DisableEventHook()
1960{
Guido van Rossum00d93061998-05-28 23:06:38 +00001961#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001962 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
1963 PyOS_InputHook = NULL;
1964 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001965#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001966}
1967
Barry Warsawfa701a81997-01-16 00:15:11 +00001968
1969/* all errors will be checked in one fell swoop in init_tkinter() */
1970static void
1971ins_long(d, name, val)
1972 PyObject *d;
1973 char *name;
1974 long val;
1975{
1976 PyObject *v = PyInt_FromLong(val);
1977 if (v) {
1978 PyDict_SetItemString(d, name, v);
1979 Py_DECREF(v);
1980 }
1981}
1982static void
1983ins_string(d, name, val)
1984 PyObject *d;
1985 char *name;
1986 char *val;
1987{
1988 PyObject *v = PyString_FromString(val);
1989 if (v) {
1990 PyDict_SetItemString(d, name, v);
1991 Py_DECREF(v);
1992 }
1993}
1994
1995
Guido van Rossum18468821994-06-20 07:49:28 +00001996void
Guido van Rossum35d43371997-08-02 00:09:09 +00001997init_tkinter()
Guido van Rossum18468821994-06-20 07:49:28 +00001998{
Barry Warsawfa701a81997-01-16 00:15:11 +00001999 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002000
Barry Warsawfa701a81997-01-16 00:15:11 +00002001 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002002
2003#ifdef WITH_THREAD
2004 tcl_lock = allocate_lock();
2005#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002006
Barry Warsawfa701a81997-01-16 00:15:11 +00002007 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002008
Barry Warsawfa701a81997-01-16 00:15:11 +00002009 d = PyModule_GetDict(m);
2010 Tkinter_TclError = Py_BuildValue("s", "TclError");
2011 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002012
Guido van Rossum35d43371997-08-02 00:09:09 +00002013 ins_long(d, "READABLE", TCL_READABLE);
2014 ins_long(d, "WRITABLE", TCL_WRITABLE);
2015 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2016 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2017 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2018 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2019 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2020 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2021 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002022 ins_string(d, "TK_VERSION", TK_VERSION);
2023 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002024
Guido van Rossum83551bf1997-09-13 00:44:23 +00002025 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002026
2027 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002028 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2029
Barry Warsawfa701a81997-01-16 00:15:11 +00002030 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002031 return;
2032
Guido van Rossum43ff8681998-07-14 18:02:13 +00002033#if 0
2034 /* This was not a good idea; through <Destroy> bindings,
2035 Tcl_Finalize() may invoke Python code but at that point the
2036 interpreter and thread state have already been destroyed! */
Guido van Rossum26216371998-04-20 18:47:52 +00002037#if TKMAJORMINOR >= 8000
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002038 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002039#endif
Guido van Rossum43ff8681998-07-14 18:02:13 +00002040#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002041
Jack Jansen34cc5c31995-10-31 16:15:12 +00002042#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002043 /*
2044 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2045 ** Most of the initializations in that routine (toolbox init calls and
2046 ** such) have already been done for us, so we only need these.
2047 */
2048#if TKMAJORMINOR >= 8000
2049 tcl_macQdPtr = &qd;
2050#endif
2051
2052 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002053#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002054 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002055#endif /* GENERATINGCFM */
2056#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002057}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002058
Guido van Rossumec22c921996-02-25 04:50:29 +00002059
Barry Warsawfa701a81997-01-16 00:15:11 +00002060
Guido van Rossum9722ad81995-09-22 23:49:28 +00002061#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002062
2063/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002064** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002065*/
2066
Guido van Rossum9722ad81995-09-22 23:49:28 +00002067void
2068panic(char * format, ...)
2069{
Barry Warsawfa701a81997-01-16 00:15:11 +00002070 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002071
Barry Warsawfa701a81997-01-16 00:15:11 +00002072 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002073
Guido van Rossum227cf761998-08-05 13:53:32 +00002074 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002075 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002076
Barry Warsawfa701a81997-01-16 00:15:11 +00002077 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002078
Barry Warsawfa701a81997-01-16 00:15:11 +00002079 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002080}
Jack Jansen40b546d1995-11-14 10:34:45 +00002081
Guido van Rossumec22c921996-02-25 04:50:29 +00002082/*
2083** Pass events to SIOUX before passing them to Tk.
2084*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002085
Guido van Rossumec22c921996-02-25 04:50:29 +00002086static int
2087PyMacConvertEvent(eventPtr)
Barry Warsawfa701a81997-01-16 00:15:11 +00002088 EventRecord *eventPtr;
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002089{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002090 WindowPtr frontwin;
2091 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002092 ** Sioux eats too many events, so we don't pass it everything. We
2093 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002094 ** the Sioux window is frontmost. This means that Tk menus don't work
2095 ** in that case, but at least we can scroll the sioux window.
2096 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2097 ** part of the external interface of Sioux...
2098 */
2099 frontwin = FrontWindow();
2100 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2101 if (SIOUXHandleOneEvent(eventPtr))
2102 return 0; /* Nothing happened to the Tcl event queue */
2103 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002104 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002105}
2106
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002107#if defined(USE_GUSI) && TKMAJORMINOR < 8000
Guido van Rossum290283b1997-06-02 22:16:43 +00002108/*
2109 * For Python we have to override this routine (from TclMacNotify),
2110 * since we use GUSI for our sockets, not Tcl streams. Hence, we have
2111 * to use GUSI select to see whether our socket is ready. Note that
2112 * createfilehandler (above) sets the type to TCL_UNIX_FD for our
2113 * files and sockets.
2114 *
2115 * NOTE: this code was lifted from Tcl 7.6, it may need to be modified
2116 * for other versions. */
2117
2118int
2119Tcl_FileReady(file, mask)
2120 Tcl_File file; /* File handle for a stream. */
2121 int mask; /* OR'ed combination of TCL_READABLE,
2122 * TCL_WRITABLE, and TCL_EXCEPTION:
2123 * indicates conditions caller cares about. */
2124{
2125 int type;
2126 int fd;
2127
2128 fd = (int) Tcl_GetFileInfo(file, &type);
2129
2130 if (type == TCL_MAC_SOCKET) {
2131 return TclMacSocketReady(file, mask);
2132 } else if (type == TCL_MAC_FILE) {
2133 /*
2134 * Under the Macintosh, files are always ready, so we just
2135 * return the mask that was passed in.
2136 */
2137
2138 return mask;
2139 } else if (type == TCL_UNIX_FD) {
2140 fd_set readset, writeset, excset;
2141 struct timeval tv;
2142
2143 FD_ZERO(&readset);
2144 FD_ZERO(&writeset);
2145 FD_ZERO(&excset);
2146
2147 if ( mask & TCL_READABLE ) FD_SET(fd, &readset);
2148 if ( mask & TCL_WRITABLE ) FD_SET(fd, &writeset);
2149 if ( mask & TCL_EXCEPTION ) FD_SET(fd, &excset);
2150
2151 tv.tv_sec = tv.tv_usec = 0;
2152 if ( select(fd+1, &readset, &writeset, &excset, &tv) <= 0 )
2153 return 0;
2154
2155 mask = 0;
2156 if ( FD_ISSET(fd, &readset) ) mask |= TCL_READABLE;
2157 if ( FD_ISSET(fd, &writeset) ) mask |= TCL_WRITABLE;
2158 if ( FD_ISSET(fd, &excset) ) mask |= TCL_EXCEPTION;
2159
2160 return mask;
2161 }
2162
2163 return 0;
2164}
2165#endif /* USE_GUSI */
2166
Guido van Rossumec22c921996-02-25 04:50:29 +00002167#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002168
2169/*
2170** Additional Mac specific code for dealing with shared libraries.
2171*/
2172
2173#include <Resources.h>
2174#include <CodeFragments.h>
2175
2176static int loaded_from_shlib = 0;
2177static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002178
Jack Jansen34cc5c31995-10-31 16:15:12 +00002179/*
2180** If this module is dynamically loaded the following routine should
2181** be the init routine. It takes care of adding the shared library to
2182** the resource-file chain, so that the tk routines can find their
2183** resources.
2184*/
2185OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002186init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002187{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002188 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002189 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002190 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002191 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2192 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002193 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002194 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2195 loaded_from_shlib = 1;
2196 }
2197 return noErr;
2198}
2199
2200/*
2201** Insert the library resources into the search path. Put them after
2202** the resources from the application. Again, we ignore errors.
2203*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002204static
Jack Jansen34cc5c31995-10-31 16:15:12 +00002205mac_addlibresources()
2206{
2207 if ( !loaded_from_shlib )
2208 return;
2209 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2210}
2211
Guido van Rossumec22c921996-02-25 04:50:29 +00002212#endif /* GENERATINGCFM */
2213#endif /* macintosh */