blob: f619032ea890468809849b9728f62c7d3b6ed195 [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 Rossum541f2411998-08-13 13:29:22 +0000284#include "mytime.h"
285
Guido van Rossum00d93061998-05-28 23:06:38 +0000286/* Millisecond sleep() for Unix platforms. */
287
288static void
289Sleep(milli)
290 int milli;
291{
292 /* XXX Too bad if you don't have select(). */
293 struct timeval t;
294 double frac;
295 t.tv_sec = milli/1000;
296 t.tv_usec = (milli%1000) * 1000;
297 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
298}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000299#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000300#endif /* WITH_THREAD */
301
302
Guido van Rossum18468821994-06-20 07:49:28 +0000303static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000304AsString(value, tmp)
305 PyObject *value;
306 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000307{
Guido van Rossum35d43371997-08-02 00:09:09 +0000308 if (PyString_Check(value))
309 return PyString_AsString(value);
Barry Warsawfa701a81997-01-16 00:15:11 +0000310 else {
311 PyObject *v = PyObject_Str(value);
312 PyList_Append(tmp, v);
313 Py_DECREF(v);
314 return PyString_AsString(v);
315 }
Guido van Rossum18468821994-06-20 07:49:28 +0000316}
317
Barry Warsawfa701a81997-01-16 00:15:11 +0000318
319
Guido van Rossum18468821994-06-20 07:49:28 +0000320#define ARGSZ 64
321
322static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000323Merge(args)
324 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000325{
Barry Warsawfa701a81997-01-16 00:15:11 +0000326 PyObject *tmp = NULL;
327 char *argvStore[ARGSZ];
328 char **argv = NULL;
329 int fvStore[ARGSZ];
330 int *fv = NULL;
331 int argc = 0, i;
332 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000333
Barry Warsawfa701a81997-01-16 00:15:11 +0000334 if (!(tmp = PyList_New(0)))
335 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000336
Barry Warsawfa701a81997-01-16 00:15:11 +0000337 argv = argvStore;
338 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000339
Barry Warsawfa701a81997-01-16 00:15:11 +0000340 if (args == NULL)
341 argc = 0;
342
343 else if (!PyTuple_Check(args)) {
344 argc = 1;
345 fv[0] = 0;
346 argv[0] = AsString(args, tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000347 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000348 else {
349 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000350
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000352 argv = (char **)ckalloc(argc * sizeof(char *));
353 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000354 if (argv == NULL || fv == NULL) {
355 PyErr_NoMemory();
356 goto finally;
357 }
358 }
359
360 for (i = 0; i < argc; i++) {
361 PyObject *v = PyTuple_GetItem(args, i);
362 if (PyTuple_Check(v)) {
363 fv[i] = 1;
364 if (!(argv[i] = Merge(v)))
365 goto finally;
366 }
367 else if (v == Py_None) {
368 argc = i;
369 break;
370 }
371 else {
372 fv[i] = 0;
373 argv[i] = AsString(v, tmp);
374 }
375 }
Guido van Rossum18468821994-06-20 07:49:28 +0000376 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 res = Tcl_Merge(argc, argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 finally:
380 for (i = 0; i < argc; i++)
381 if (fv[i]) {
382 ckfree(argv[i]);
383 }
384 if (argv != argvStore)
385 ckfree(FREECAST argv);
386 if (fv != fvStore)
387 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389 Py_DECREF(tmp);
390 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000391}
392
Barry Warsawfa701a81997-01-16 00:15:11 +0000393
394
Guido van Rossum18468821994-06-20 07:49:28 +0000395static PyObject *
Guido van Rossum00d93061998-05-28 23:06:38 +0000396Split(list)
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +0000398{
Barry Warsawfa701a81997-01-16 00:15:11 +0000399 int argc;
400 char **argv;
401 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000402
Barry Warsawfa701a81997-01-16 00:15:11 +0000403 if (list == NULL) {
404 Py_INCREF(Py_None);
405 return Py_None;
406 }
Guido van Rossum18468821994-06-20 07:49:28 +0000407
Guido van Rossum00d93061998-05-28 23:06:38 +0000408 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000409 /* Not a list.
410 * Could be a quoted string containing funnies, e.g. {"}.
411 * Return the string itself.
412 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 return PyString_FromString(list);
414 }
Guido van Rossum18468821994-06-20 07:49:28 +0000415
Barry Warsawfa701a81997-01-16 00:15:11 +0000416 if (argc == 0)
417 v = PyString_FromString("");
418 else if (argc == 1)
419 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000420 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000421 int i;
422 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000423
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000425 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000426 Py_DECREF(v);
427 v = NULL;
428 break;
429 }
430 PyTuple_SetItem(v, i, w);
431 }
432 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000433 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000434 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000435}
436
Barry Warsawfa701a81997-01-16 00:15:11 +0000437
438
Guido van Rossum18468821994-06-20 07:49:28 +0000439/**** Tkapp Object ****/
440
441#ifndef WITH_APPINIT
442int
Guido van Rossum35d43371997-08-02 00:09:09 +0000443Tcl_AppInit(interp)
Barry Warsawfa701a81997-01-16 00:15:11 +0000444 Tcl_Interp *interp;
Guido van Rossum18468821994-06-20 07:49:28 +0000445{
Barry Warsawfa701a81997-01-16 00:15:11 +0000446 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000447
Barry Warsawfa701a81997-01-16 00:15:11 +0000448 main = Tk_MainWindow(interp);
449 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000450 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 return TCL_ERROR;
452 }
453 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000454 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 return TCL_ERROR;
456 }
457 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000458}
459#endif /* !WITH_APPINIT */
460
Guido van Rossum18468821994-06-20 07:49:28 +0000461
Barry Warsawfa701a81997-01-16 00:15:11 +0000462
463
464/* Initialize the Tk application; see the `main' function in
465 * `tkMain.c'.
466 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000467
468static void EnableEventHook(); /* Forward */
469static void DisableEventHook(); /* Forward */
470
Barry Warsawfa701a81997-01-16 00:15:11 +0000471static TkappObject *
472Tkapp_New(screenName, baseName, className, interactive)
473 char *screenName;
474 char *baseName;
475 char *className;
476 int interactive;
477{
478 TkappObject *v;
479 char *argv0;
480
481 v = PyObject_NEW(TkappObject, &Tkapp_Type);
482 if (v == NULL)
483 return NULL;
484
485 v->interp = Tcl_CreateInterp();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000486
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000487#if defined(macintosh) && TKMAJORMINOR >= 8000
488 /* This seems to be needed since Tk 8.0 */
489 ClearMenuBar();
490 TkMacInitMenus(v->interp);
491#endif
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000492 /* Delete the 'exit' command, which can screw things up */
493 Tcl_DeleteCommand(v->interp, "exit");
494
Barry Warsawfa701a81997-01-16 00:15:11 +0000495 if (screenName != NULL)
496 Tcl_SetVar2(v->interp, "env", "DISPLAY",
497 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000498
Barry Warsawfa701a81997-01-16 00:15:11 +0000499 if (interactive)
500 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
501 else
502 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000503
Barry Warsawfa701a81997-01-16 00:15:11 +0000504 /* This is used to get the application class for Tk 4.1 and up */
505 argv0 = (char*)ckalloc(strlen(className) + 1);
506 if (!argv0) {
507 PyErr_NoMemory();
508 Py_DECREF(v);
509 return NULL;
510 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000511
Barry Warsawfa701a81997-01-16 00:15:11 +0000512 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000513 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000514 argv0[0] = tolower(argv0[0]);
515 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
516 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000517
Barry Warsawfa701a81997-01-16 00:15:11 +0000518 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000519 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000520
Guido van Rossum7bf15641998-05-22 18:28:17 +0000521 EnableEventHook();
522
Barry Warsawfa701a81997-01-16 00:15:11 +0000523 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000524}
525
Barry Warsawfa701a81997-01-16 00:15:11 +0000526
527
Guido van Rossum18468821994-06-20 07:49:28 +0000528/** Tcl Eval **/
529
530static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000531Tkapp_Call(self, args)
532 PyObject *self;
533 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000534{
Guido van Rossum212643f1998-04-29 16:22:14 +0000535 /* This is copied from Merge() */
536 PyObject *tmp = NULL;
537 char *argvStore[ARGSZ];
538 char **argv = NULL;
539 int fvStore[ARGSZ];
540 int *fv = NULL;
541 int argc = 0, i;
542 PyObject *res = NULL; /* except this has a different type */
543 Tcl_CmdInfo info; /* and this is added */
544 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
Guido van Rossum18468821994-06-20 07:49:28 +0000545
Guido van Rossum212643f1998-04-29 16:22:14 +0000546 if (!(tmp = PyList_New(0)))
547 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000548
Guido van Rossum212643f1998-04-29 16:22:14 +0000549 argv = argvStore;
550 fv = fvStore;
Barry Warsawfa701a81997-01-16 00:15:11 +0000551
Guido van Rossum212643f1998-04-29 16:22:14 +0000552 if (args == NULL)
553 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000554
Guido van Rossum212643f1998-04-29 16:22:14 +0000555 else if (!PyTuple_Check(args)) {
556 argc = 1;
557 fv[0] = 0;
558 argv[0] = AsString(args, tmp);
559 }
560 else {
561 argc = PyTuple_Size(args);
562
563 if (argc > ARGSZ) {
564 argv = (char **)ckalloc(argc * sizeof(char *));
565 fv = (int *)ckalloc(argc * sizeof(int));
566 if (argv == NULL || fv == NULL) {
567 PyErr_NoMemory();
568 goto finally;
569 }
570 }
571
572 for (i = 0; i < argc; i++) {
573 PyObject *v = PyTuple_GetItem(args, i);
574 if (PyTuple_Check(v)) {
575 fv[i] = 1;
576 if (!(argv[i] = Merge(v)))
577 goto finally;
578 }
579 else if (v == Py_None) {
580 argc = i;
581 break;
582 }
583 else {
584 fv[i] = 0;
585 argv[i] = AsString(v, tmp);
586 }
587 }
588 }
589 /* End code copied from Merge() */
590
591 /* All this to avoid a call to Tcl_Merge() and the corresponding call
592 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
593 if (Py_VerboseFlag >= 2) {
594 for (i = 0; i < argc; i++)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000595 PySys_WriteStderr("%s ", argv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000596 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000597 ENTER_TCL
598 info.proc = NULL;
Guido van Rossum212643f1998-04-29 16:22:14 +0000599 if (argc < 1 ||
600 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
601 info.proc == NULL)
602 {
603 char *cmd;
Guido van Rossum212643f1998-04-29 16:22:14 +0000604 cmd = Tcl_Merge(argc, argv);
605 i = Tcl_Eval(interp, cmd);
Barry Warsawfa701a81997-01-16 00:15:11 +0000606 ckfree(cmd);
Guido van Rossum212643f1998-04-29 16:22:14 +0000607 }
608 else {
609 Tcl_ResetResult(interp);
610 i = (*info.proc)(info.clientData, interp, argc, argv);
611 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000612 ENTER_OVERLAP
613 if (info.proc == NULL && Py_VerboseFlag >= 2)
614 PySys_WriteStderr("... use TclEval ");
Guido van Rossum212643f1998-04-29 16:22:14 +0000615 if (i == TCL_ERROR) {
616 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000617 PySys_WriteStderr("... error: '%s'\n",
Guido van Rossum212643f1998-04-29 16:22:14 +0000618 interp->result);
619 Tkinter_Error(self);
620 }
621 else {
622 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000623 PySys_WriteStderr("-> '%s'\n", interp->result);
Guido van Rossum212643f1998-04-29 16:22:14 +0000624 res = PyString_FromString(interp->result);
625 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000626 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000627
Guido van Rossum212643f1998-04-29 16:22:14 +0000628 /* Copied from Merge() again */
629 finally:
630 for (i = 0; i < argc; i++)
631 if (fv[i]) {
632 ckfree(argv[i]);
633 }
634 if (argv != argvStore)
635 ckfree(FREECAST argv);
636 if (fv != fvStore)
637 ckfree(FREECAST fv);
638
639 Py_DECREF(tmp);
Barry Warsawfa701a81997-01-16 00:15:11 +0000640 return res;
641}
642
643
644static PyObject *
645Tkapp_GlobalCall(self, args)
646 PyObject *self;
647 PyObject *args;
648{
Guido van Rossum212643f1998-04-29 16:22:14 +0000649 /* Could do the same here as for Tkapp_Call(), but this is not used
650 much, so I can't be bothered. Unfortunately Tcl doesn't export a
651 way for the user to do what all its Global* variants do (save and
652 reset the scope pointer, call the local version, restore the saved
653 scope pointer). */
654
Guido van Rossum62320c91998-06-15 04:36:09 +0000655 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +0000656 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000657
Guido van Rossum62320c91998-06-15 04:36:09 +0000658 cmd = Merge(args);
Barry Warsawfa701a81997-01-16 00:15:11 +0000659 if (!cmd)
660 PyErr_SetString(Tkinter_TclError, "merge failed");
661
Guido van Rossum00d93061998-05-28 23:06:38 +0000662 else {
663 int err;
664 ENTER_TCL
665 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +0000666 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000667 if (err == TCL_ERROR)
668 res = Tkinter_Error(self);
669 else
670 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +0000671 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000672 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000673
674 if (cmd)
675 ckfree(cmd);
676
677 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000678}
679
680static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000681Tkapp_Eval(self, args)
682 PyObject *self;
683 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000684{
Barry Warsawfa701a81997-01-16 00:15:11 +0000685 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000686 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000687 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000688
Guido van Rossum35d43371997-08-02 00:09:09 +0000689 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000690 return NULL;
691
Guido van Rossum00d93061998-05-28 23:06:38 +0000692 ENTER_TCL
693 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000694 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000695 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000696 res = Tkinter_Error(self);
697 else
698 res = PyString_FromString(Tkapp_Result(self));
699 LEAVE_OVERLAP_TCL
700 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000701}
702
703static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000704Tkapp_GlobalEval(self, args)
705 PyObject *self;
706 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000707{
Barry Warsawfa701a81997-01-16 00:15:11 +0000708 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000709 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000710 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +0000711
Guido van Rossum35d43371997-08-02 00:09:09 +0000712 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000713 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000714
Guido van Rossum00d93061998-05-28 23:06:38 +0000715 ENTER_TCL
716 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000717 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000718 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000719 res = Tkinter_Error(self);
720 else
721 res = PyString_FromString(Tkapp_Result(self));
722 LEAVE_OVERLAP_TCL
723 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000724}
725
726static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000727Tkapp_EvalFile(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000728 PyObject *self;
729 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000730{
Barry Warsawfa701a81997-01-16 00:15:11 +0000731 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +0000732 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000733 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000734
Guido van Rossum35d43371997-08-02 00:09:09 +0000735 if (!PyArg_ParseTuple(args, "s", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +0000736 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000737
Guido van Rossum00d93061998-05-28 23:06:38 +0000738 ENTER_TCL
739 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +0000740 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000741 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000742 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +0000743
Guido van Rossum62320c91998-06-15 04:36:09 +0000744 else
745 res = PyString_FromString(Tkapp_Result(self));
746 LEAVE_OVERLAP_TCL
747 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000748}
749
750static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000751Tkapp_Record(self, args)
752 PyObject *self;
753 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000754{
Barry Warsawfa701a81997-01-16 00:15:11 +0000755 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000756 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000757 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000758
Guido van Rossum35d43371997-08-02 00:09:09 +0000759 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000760 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000761
Guido van Rossum00d93061998-05-28 23:06:38 +0000762 ENTER_TCL
763 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +0000764 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000765 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000766 res = Tkinter_Error(self);
767 else
768 res = PyString_FromString(Tkapp_Result(self));
769 LEAVE_OVERLAP_TCL
770 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000771}
772
773static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000774Tkapp_AddErrorInfo(self, args)
775 PyObject *self;
776 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000777{
Barry Warsawfa701a81997-01-16 00:15:11 +0000778 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +0000779
Guido van Rossum35d43371997-08-02 00:09:09 +0000780 if (!PyArg_ParseTuple(args, "s", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +0000781 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000782 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000783 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +0000784 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +0000785
Barry Warsawfa701a81997-01-16 00:15:11 +0000786 Py_INCREF(Py_None);
787 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000788}
789
Barry Warsawfa701a81997-01-16 00:15:11 +0000790
791
Guido van Rossum18468821994-06-20 07:49:28 +0000792/** Tcl Variable **/
793
794static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000795SetVar(self, args, flags)
796 PyObject *self;
797 PyObject *args;
798 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000799{
Guido van Rossum00d93061998-05-28 23:06:38 +0000800 char *name1, *name2, *ok, *s;
Barry Warsawfa701a81997-01-16 00:15:11 +0000801 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +0000802 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000803
Guido van Rossum62320c91998-06-15 04:36:09 +0000804 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +0000805 if (!tmp)
806 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000807
Guido van Rossum00d93061998-05-28 23:06:38 +0000808 if (PyArg_ParseTuple(args, "sO", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000809 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +0000810 s = AsString(newValue, tmp);
811 ENTER_TCL
812 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
813 LEAVE_TCL
814 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000815 else {
Guido van Rossum35d43371997-08-02 00:09:09 +0000816 PyErr_Clear();
Guido van Rossum00d93061998-05-28 23:06:38 +0000817 if (PyArg_ParseTuple(args, "ssO", &name1, &name2, &newValue)) {
818 s = AsString (newValue, tmp);
819 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000820 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
Guido van Rossum00d93061998-05-28 23:06:38 +0000821 s, flags);
822 LEAVE_TCL
823 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000824 else {
Guido van Rossum00d93061998-05-28 23:06:38 +0000825 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +0000826 return NULL;
827 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000828 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000829 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000830
Barry Warsawfa701a81997-01-16 00:15:11 +0000831 if (!ok)
832 return Tkinter_Error(self);
833
834 Py_INCREF(Py_None);
835 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000836}
837
838static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000839Tkapp_SetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000840 PyObject *self;
841 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000842{
Barry Warsawfa701a81997-01-16 00:15:11 +0000843 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000844}
845
846static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000847Tkapp_GlobalSetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000848 PyObject *self;
849 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000850{
Barry Warsawfa701a81997-01-16 00:15:11 +0000851 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000852}
853
Barry Warsawfa701a81997-01-16 00:15:11 +0000854
855
Guido van Rossum18468821994-06-20 07:49:28 +0000856static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000857GetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000858 PyObject *self;
859 PyObject *args;
860 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000861{
Guido van Rossum35d43371997-08-02 00:09:09 +0000862 char *name1, *name2=NULL, *s;
Guido van Rossum62320c91998-06-15 04:36:09 +0000863 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000864
Guido van Rossum35d43371997-08-02 00:09:09 +0000865 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
866 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000867 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000868 if (name2 == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000869 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
Guido van Rossum18468821994-06-20 07:49:28 +0000870
Barry Warsawfa701a81997-01-16 00:15:11 +0000871 else
Guido van Rossum35d43371997-08-02 00:09:09 +0000872 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000873 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000874
Barry Warsawfa701a81997-01-16 00:15:11 +0000875 if (s == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000876 res = Tkinter_Error(self);
877 else
878 res = PyString_FromString(s);
879 LEAVE_OVERLAP_TCL
880 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000881}
882
883static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000884Tkapp_GetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000885 PyObject *self;
886 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000887{
Barry Warsawfa701a81997-01-16 00:15:11 +0000888 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000889}
890
891static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000892Tkapp_GlobalGetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000893 PyObject *self;
894 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000895{
Barry Warsawfa701a81997-01-16 00:15:11 +0000896 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000897}
898
Barry Warsawfa701a81997-01-16 00:15:11 +0000899
900
Guido van Rossum18468821994-06-20 07:49:28 +0000901static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000902UnsetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000903 PyObject *self;
904 PyObject *args;
905 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000906{
Guido van Rossum35d43371997-08-02 00:09:09 +0000907 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +0000908 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000909 int code;
Guido van Rossum18468821994-06-20 07:49:28 +0000910
Guido van Rossum35d43371997-08-02 00:09:09 +0000911 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +0000912 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000913 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000914 if (name2 == NULL)
915 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
916
917 else
918 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000919 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000920
Barry Warsawfa701a81997-01-16 00:15:11 +0000921 if (code == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000922 res = Tkinter_Error(self);
923 else {
924 Py_INCREF(Py_None);
925 res = Py_None;
926 }
927 LEAVE_OVERLAP_TCL
928 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000929}
930
931static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000932Tkapp_UnsetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000933 PyObject *self;
934 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000935{
Barry Warsawfa701a81997-01-16 00:15:11 +0000936 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000937}
938
939static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000940Tkapp_GlobalUnsetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000941 PyObject *self;
942 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000943{
Barry Warsawfa701a81997-01-16 00:15:11 +0000944 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000945}
946
Barry Warsawfa701a81997-01-16 00:15:11 +0000947
948
Guido van Rossum18468821994-06-20 07:49:28 +0000949/** Tcl to Python **/
950
951static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000952Tkapp_GetInt(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000953 PyObject *self;
954 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000955{
Barry Warsawfa701a81997-01-16 00:15:11 +0000956 char *s;
957 int v;
Guido van Rossum18468821994-06-20 07:49:28 +0000958
Guido van Rossum35d43371997-08-02 00:09:09 +0000959 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000960 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000961 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +0000962 return Tkinter_Error(self);
963 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000964}
965
966static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000967Tkapp_GetDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000968 PyObject *self;
969 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000970{
Barry Warsawfa701a81997-01-16 00:15:11 +0000971 char *s;
972 double v;
Guido van Rossum18468821994-06-20 07:49:28 +0000973
Guido van Rossum35d43371997-08-02 00:09:09 +0000974 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000975 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000976 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +0000977 return Tkinter_Error(self);
978 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000979}
980
981static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000982Tkapp_GetBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000983 PyObject *self;
984 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000985{
Barry Warsawfa701a81997-01-16 00:15:11 +0000986 char *s;
987 int v;
Guido van Rossum18468821994-06-20 07:49:28 +0000988
Guido van Rossum35d43371997-08-02 00:09:09 +0000989 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000990 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000991 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
992 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +0000993 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000994}
995
996static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000997Tkapp_ExprString(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000998 PyObject *self;
999 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001000{
Barry Warsawfa701a81997-01-16 00:15:11 +00001001 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001002 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001003 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001004
Guido van Rossum35d43371997-08-02 00:09:09 +00001005 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001006 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001007 ENTER_TCL
1008 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001009 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001010 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001011 res = Tkinter_Error(self);
1012 else
1013 res = Py_BuildValue("s", Tkapp_Result(self));
1014 LEAVE_OVERLAP_TCL
1015 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001016}
1017
1018static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001019Tkapp_ExprLong(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001020 PyObject *self;
1021 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001022{
Barry Warsawfa701a81997-01-16 00:15:11 +00001023 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001024 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001025 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001026 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001027
Guido van Rossum35d43371997-08-02 00:09:09 +00001028 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001029 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001030 ENTER_TCL
1031 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001032 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001033 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001034 res = Tkinter_Error(self);
1035 else
1036 res = Py_BuildValue("l", v);
1037 LEAVE_OVERLAP_TCL
1038 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001039}
1040
1041static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001042Tkapp_ExprDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001043 PyObject *self;
1044 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001045{
Barry Warsawfa701a81997-01-16 00:15:11 +00001046 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001047 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001048 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001049 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001050
Guido van Rossum35d43371997-08-02 00:09:09 +00001051 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001052 return NULL;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001053 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001054 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001055 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001056 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001057 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001058 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001059 res = Tkinter_Error(self);
1060 else
1061 res = Py_BuildValue("d", v);
1062 LEAVE_OVERLAP_TCL
1063 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001064}
1065
1066static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001067Tkapp_ExprBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001068 PyObject *self;
1069 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001070{
Barry Warsawfa701a81997-01-16 00:15:11 +00001071 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001072 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001073 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001074 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001075
Guido van Rossum35d43371997-08-02 00:09:09 +00001076 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001077 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001078 ENTER_TCL
1079 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001080 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001081 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001082 res = Tkinter_Error(self);
1083 else
1084 res = Py_BuildValue("i", v);
1085 LEAVE_OVERLAP_TCL
1086 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001087}
1088
Barry Warsawfa701a81997-01-16 00:15:11 +00001089
1090
Guido van Rossum18468821994-06-20 07:49:28 +00001091static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001092Tkapp_SplitList(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001093 PyObject *self;
1094 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001095{
Barry Warsawfa701a81997-01-16 00:15:11 +00001096 char *list;
1097 int argc;
1098 char **argv;
1099 PyObject *v;
1100 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001101
Guido van Rossum35d43371997-08-02 00:09:09 +00001102 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001103 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001104
Barry Warsawfa701a81997-01-16 00:15:11 +00001105 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1106 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001107
Barry Warsawfa701a81997-01-16 00:15:11 +00001108 if (!(v = PyTuple_New(argc)))
1109 return NULL;
1110
1111 for (i = 0; i < argc; i++) {
1112 PyObject *s = PyString_FromString(argv[i]);
1113 if (!s || PyTuple_SetItem(v, i, s)) {
1114 Py_DECREF(v);
1115 v = NULL;
1116 goto finally;
1117 }
1118 }
Guido van Rossum18468821994-06-20 07:49:28 +00001119
Barry Warsawfa701a81997-01-16 00:15:11 +00001120 finally:
1121 ckfree(FREECAST argv);
1122 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001123}
1124
1125static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001126Tkapp_Split(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001127 PyObject *self;
1128 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001129{
Barry Warsawfa701a81997-01-16 00:15:11 +00001130 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001131
Guido van Rossum35d43371997-08-02 00:09:09 +00001132 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001133 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001134 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001135}
1136
1137static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001138Tkapp_Merge(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001139 PyObject *self;
1140 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001141{
Barry Warsawfa701a81997-01-16 00:15:11 +00001142 char *s = Merge(args);
1143 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001144
Barry Warsawfa701a81997-01-16 00:15:11 +00001145 if (s) {
1146 res = PyString_FromString(s);
1147 ckfree(s);
1148 }
1149 else
1150 PyErr_SetString(Tkinter_TclError, "merge failed");
1151
1152 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001153}
1154
Barry Warsawfa701a81997-01-16 00:15:11 +00001155
1156
Guido van Rossum18468821994-06-20 07:49:28 +00001157/** Tcl Command **/
1158
Guido van Rossum00d93061998-05-28 23:06:38 +00001159/* Client data struct */
1160typedef struct {
1161 PyThreadState *tstate;
1162 PyObject *self;
1163 PyObject *func;
1164} PythonCmd_ClientData;
1165
1166static int
1167PythonCmd_Error(interp)
1168 Tcl_Interp *interp;
1169{
1170 errorInCmd = 1;
1171 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1172 LEAVE_PYTHON
1173 return TCL_ERROR;
1174}
1175
Guido van Rossum18468821994-06-20 07:49:28 +00001176/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001177 * function or method.
1178 */
Guido van Rossum18468821994-06-20 07:49:28 +00001179static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001180PythonCmd(clientData, interp, argc, argv)
Guido van Rossum00d93061998-05-28 23:06:38 +00001181 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001182 Tcl_Interp *interp;
1183 int argc;
1184 char *argv[];
Guido van Rossum18468821994-06-20 07:49:28 +00001185{
Guido van Rossum00d93061998-05-28 23:06:38 +00001186 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001187 PyObject *self, *func, *arg, *res, *tmp;
1188 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001189
Guido van Rossum00d93061998-05-28 23:06:38 +00001190 /* XXX Should create fresh thread state? */
1191 ENTER_PYTHON(data->tstate)
1192
Barry Warsawfa701a81997-01-16 00:15:11 +00001193 /* TBD: no error checking here since we know, via the
1194 * Tkapp_CreateCommand() that the client data is a two-tuple
1195 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001196 self = data->self;
1197 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001198
Barry Warsawfa701a81997-01-16 00:15:11 +00001199 /* Create argument list (argv1, ..., argvN) */
1200 if (!(arg = PyTuple_New(argc - 1)))
1201 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001202
Barry Warsawfa701a81997-01-16 00:15:11 +00001203 for (i = 0; i < (argc - 1); i++) {
1204 PyObject *s = PyString_FromString(argv[i + 1]);
1205 if (!s || PyTuple_SetItem(arg, i, s)) {
1206 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001207 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001208 }
1209 }
1210 res = PyEval_CallObject(func, arg);
1211 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001212
Barry Warsawfa701a81997-01-16 00:15:11 +00001213 if (res == NULL)
1214 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001215
Barry Warsawfa701a81997-01-16 00:15:11 +00001216 if (!(tmp = PyList_New(0))) {
1217 Py_DECREF(res);
1218 return PythonCmd_Error(interp);
1219 }
1220
1221 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1222 Py_DECREF(res);
1223 Py_DECREF(tmp);
1224
Guido van Rossum00d93061998-05-28 23:06:38 +00001225 LEAVE_PYTHON
1226
Barry Warsawfa701a81997-01-16 00:15:11 +00001227 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00001228}
1229
1230static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001231PythonCmdDelete(clientData)
Guido van Rossum00d93061998-05-28 23:06:38 +00001232 ClientData clientData;
Guido van Rossum18468821994-06-20 07:49:28 +00001233{
Guido van Rossum00d93061998-05-28 23:06:38 +00001234 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1235
1236 ENTER_PYTHON(data->tstate)
1237 Py_XDECREF(data->self);
1238 Py_XDECREF(data->func);
1239 PyMem_DEL(data);
1240 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001241}
1242
Barry Warsawfa701a81997-01-16 00:15:11 +00001243
1244
Guido van Rossum18468821994-06-20 07:49:28 +00001245static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001246Tkapp_CreateCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001247 PyObject *self;
1248 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001249{
Guido van Rossum00d93061998-05-28 23:06:38 +00001250 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001251 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001252 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001253 Tcl_Command err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001254
1255 if (!PyArg_ParseTuple(args, "sO", &cmdName, &func))
1256 return NULL;
1257 if (!PyCallable_Check(func)) {
1258 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001259 return NULL;
1260 }
Guido van Rossum18468821994-06-20 07:49:28 +00001261
Guido van Rossum00d93061998-05-28 23:06:38 +00001262 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001263 if (!data)
1264 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001265 data->tstate = PyThreadState_Get();
1266 Py_XINCREF(self);
1267 Py_XINCREF(func);
1268 data->self = self;
1269 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00001270
Guido van Rossum00d93061998-05-28 23:06:38 +00001271 ENTER_TCL
1272 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1273 (ClientData)data, PythonCmdDelete);
1274 LEAVE_TCL
1275 if (err == NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001276 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001277 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001278 return NULL;
1279 }
Guido van Rossum18468821994-06-20 07:49:28 +00001280
Barry Warsawfa701a81997-01-16 00:15:11 +00001281 Py_INCREF(Py_None);
1282 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001283}
1284
Barry Warsawfa701a81997-01-16 00:15:11 +00001285
1286
Guido van Rossum18468821994-06-20 07:49:28 +00001287static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001288Tkapp_DeleteCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001289 PyObject *self;
1290 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001291{
Barry Warsawfa701a81997-01-16 00:15:11 +00001292 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001293 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001294
Guido van Rossum35d43371997-08-02 00:09:09 +00001295 if (!PyArg_ParseTuple(args, "s", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001296 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001297 ENTER_TCL
1298 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1299 LEAVE_TCL
1300 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001301 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1302 return NULL;
1303 }
1304 Py_INCREF(Py_None);
1305 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001306}
1307
Barry Warsawfa701a81997-01-16 00:15:11 +00001308
1309
Guido van Rossum00d93061998-05-28 23:06:38 +00001310#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00001311/** File Handler **/
1312
Guido van Rossum00d93061998-05-28 23:06:38 +00001313typedef struct _fhcdata {
1314 PyThreadState *tstate;
1315 PyObject *func;
1316 PyObject *file;
1317 int id;
1318 struct _fhcdata *next;
1319} FileHandler_ClientData;
1320
1321static FileHandler_ClientData *HeadFHCD;
1322
1323static FileHandler_ClientData *
1324NewFHCD(func, file, id)
1325 PyObject *func;
1326 PyObject *file;
1327 int id;
1328{
1329 FileHandler_ClientData *p;
1330 p = PyMem_NEW(FileHandler_ClientData, 1);
1331 if (p != NULL) {
1332 Py_XINCREF(func);
1333 Py_XINCREF(file);
1334 p->tstate = PyThreadState_Get();
1335 p->func = func;
1336 p->file = file;
1337 p->id = id;
1338 p->next = HeadFHCD;
1339 HeadFHCD = p;
1340 }
1341 return p;
1342}
1343
1344static void
1345DeleteFHCD(id)
1346 int id;
1347{
1348 FileHandler_ClientData *p, **pp;
1349
1350 pp = &HeadFHCD;
1351 while ((p = *pp) != NULL) {
1352 if (p->id == id) {
1353 *pp = p->next;
1354 Py_XDECREF(p->func);
1355 Py_XDECREF(p->file);
1356 PyMem_DEL(p);
1357 }
1358 else
1359 pp = &p->next;
1360 }
1361}
1362
Guido van Rossuma597dde1995-01-10 20:56:29 +00001363static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001364FileHandler(clientData, mask)
Guido van Rossum00d93061998-05-28 23:06:38 +00001365 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001366 int mask;
Guido van Rossum18468821994-06-20 07:49:28 +00001367{
Guido van Rossum00d93061998-05-28 23:06:38 +00001368 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001369 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00001370
Guido van Rossum00d93061998-05-28 23:06:38 +00001371 /* XXX Should create fresh thread state? */
1372 ENTER_PYTHON(data->tstate)
1373 func = data->func;
1374 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00001375
Barry Warsawfa701a81997-01-16 00:15:11 +00001376 arg = Py_BuildValue("(Oi)", file, (long) mask);
1377 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00001378 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00001379
1380 if (res == NULL) {
1381 errorInCmd = 1;
1382 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1383 }
1384 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001385 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001386}
1387
1388static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001389GetFileNo(file)
Barry Warsawfa701a81997-01-16 00:15:11 +00001390 /* Either an int >= 0 or an object with a
1391 *.fileno() method that returns an int >= 0
1392 */
1393 PyObject *file;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001394{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001395 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001396 int id;
1397 if (PyInt_Check(file)) {
1398 id = PyInt_AsLong(file);
1399 if (id < 0)
1400 PyErr_SetString(PyExc_ValueError, "invalid file id");
1401 return id;
1402 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001403 args = PyTuple_New(0);
1404 if (args == NULL)
1405 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001406
1407 meth = PyObject_GetAttrString(file, "fileno");
1408 if (meth == NULL) {
1409 Py_DECREF(args);
1410 return -1;
1411 }
1412
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001413 res = PyEval_CallObject(meth, args);
1414 Py_DECREF(args);
1415 Py_DECREF(meth);
1416 if (res == NULL)
1417 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001418
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001419 if (PyInt_Check(res))
1420 id = PyInt_AsLong(res);
1421 else
1422 id = -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001423
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001424 if (id < 0)
1425 PyErr_SetString(PyExc_ValueError,
1426 "invalid fileno() return value");
1427 Py_DECREF(res);
1428 return id;
Guido van Rossum18468821994-06-20 07:49:28 +00001429}
1430
1431static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001432Tkapp_CreateFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001433 PyObject *self;
1434 PyObject *args; /* Is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00001435{
Guido van Rossum00d93061998-05-28 23:06:38 +00001436 FileHandler_ClientData *data;
1437 PyObject *file, *func;
Barry Warsawfa701a81997-01-16 00:15:11 +00001438 int mask, id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001439 FHANDLE tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00001440
Guido van Rossum35d43371997-08-02 00:09:09 +00001441 if (!PyArg_ParseTuple(args, "OiO", &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001442 return NULL;
1443 id = GetFileNo(file);
1444 if (id < 0)
1445 return NULL;
1446 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001447 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001448 return NULL;
1449 }
1450
Guido van Rossum00d93061998-05-28 23:06:38 +00001451 data = NewFHCD(func, file, id);
1452 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001453 return NULL;
1454
Guido van Rossum7bf15641998-05-22 18:28:17 +00001455 tfile = MAKEFHANDLE(id);
Barry Warsawfa701a81997-01-16 00:15:11 +00001456 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001457 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001458 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00001459 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001460 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001461 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001462}
1463
1464static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001465Tkapp_DeleteFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001466 PyObject *self;
1467 PyObject *args; /* Args: file */
Guido van Rossum18468821994-06-20 07:49:28 +00001468{
Barry Warsawfa701a81997-01-16 00:15:11 +00001469 PyObject *file;
Guido van Rossum00d93061998-05-28 23:06:38 +00001470 FileHandler_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001471 int id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001472 FHANDLE tfile;
Guido van Rossum68784361996-05-16 17:17:31 +00001473
Guido van Rossum35d43371997-08-02 00:09:09 +00001474 if (!PyArg_ParseTuple(args, "O", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00001475 return NULL;
1476 id = GetFileNo(file);
1477 if (id < 0)
1478 return NULL;
1479
Guido van Rossum00d93061998-05-28 23:06:38 +00001480 DeleteFHCD(id);
Guido van Rossum18468821994-06-20 07:49:28 +00001481
Guido van Rossum7bf15641998-05-22 18:28:17 +00001482 tfile = MAKEFHANDLE(id);
Barry Warsawfa701a81997-01-16 00:15:11 +00001483 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001484 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001485 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001486 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001487 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001488 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001489}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001490#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00001491
Barry Warsawfa701a81997-01-16 00:15:11 +00001492
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001493/**** Tktt Object (timer token) ****/
1494
1495staticforward PyTypeObject Tktt_Type;
1496
Guido van Rossum00d93061998-05-28 23:06:38 +00001497typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00001498 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00001499 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00001500 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001501 PyThreadState *tstate;
1502} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001503
1504static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001505Tktt_DeleteTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001506 PyObject *self;
1507 PyObject *args;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001508{
Barry Warsawfa701a81997-01-16 00:15:11 +00001509 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001510 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001511
Guido van Rossum35d43371997-08-02 00:09:09 +00001512 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001513 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001514 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001515 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00001516 v->token = NULL;
1517 }
1518 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001519 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001520 Py_DECREF(func);
1521 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00001522 }
1523 Py_INCREF(Py_None);
1524 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001525}
1526
1527static PyMethodDef Tktt_methods[] =
1528{
Guido van Rossum35d43371997-08-02 00:09:09 +00001529 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001530 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001531};
1532
1533static TkttObject *
Guido van Rossum00d93061998-05-28 23:06:38 +00001534Tktt_New(func)
Barry Warsawfa701a81997-01-16 00:15:11 +00001535 PyObject *func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001536{
Barry Warsawfa701a81997-01-16 00:15:11 +00001537 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001538
Barry Warsawfa701a81997-01-16 00:15:11 +00001539 v = PyObject_NEW(TkttObject, &Tktt_Type);
1540 if (v == NULL)
1541 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001542
Guido van Rossum00d93061998-05-28 23:06:38 +00001543 Py_INCREF(func);
1544 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001545 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001546 v->tstate = PyThreadState_Get();
1547
1548 /* Extra reference, deleted when called or when handler is deleted */
1549 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001550 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001551}
1552
1553static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001554Tktt_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001555 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001556{
Guido van Rossum00d93061998-05-28 23:06:38 +00001557 TkttObject *v = (TkttObject *)self;
1558 PyObject *func = v->func;
1559
1560 Py_XDECREF(func);
1561
Guido van Rossum35d43371997-08-02 00:09:09 +00001562 PyMem_DEL(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001563}
1564
Guido van Rossum597ac201998-05-12 14:36:19 +00001565static PyObject *
1566Tktt_Repr(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001567 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001568{
Barry Warsawfa701a81997-01-16 00:15:11 +00001569 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00001570 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001571
Guido van Rossum597ac201998-05-12 14:36:19 +00001572 sprintf(buf, "<tktimertoken at 0x%lx%s>", (long)v,
Barry Warsawfa701a81997-01-16 00:15:11 +00001573 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00001574 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001575}
1576
1577static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001578Tktt_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001579 PyObject *self;
1580 char *name;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001581{
Barry Warsawfa701a81997-01-16 00:15:11 +00001582 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001583}
1584
1585static PyTypeObject Tktt_Type =
1586{
Guido van Rossum35d43371997-08-02 00:09:09 +00001587 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001588 0, /*ob_size */
1589 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001590 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001591 0, /*tp_itemsize */
1592 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00001593 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00001594 Tktt_GetAttr, /*tp_getattr */
1595 0, /*tp_setattr */
1596 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00001597 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00001598 0, /*tp_as_number */
1599 0, /*tp_as_sequence */
1600 0, /*tp_as_mapping */
1601 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001602};
1603
Barry Warsawfa701a81997-01-16 00:15:11 +00001604
1605
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001606/** Timer Handler **/
1607
1608static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001609TimerHandler(clientData)
Barry Warsawfa701a81997-01-16 00:15:11 +00001610 ClientData clientData;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001611{
Guido van Rossum00d93061998-05-28 23:06:38 +00001612 TkttObject *v = (TkttObject *)clientData;
1613 PyObject *func = v->func;
1614 PyObject *res;
1615
1616 if (func == NULL)
1617 return;
1618
1619 v->func = NULL;
1620
1621 ENTER_PYTHON(v->tstate)
1622
1623 res = PyEval_CallObject(func, NULL);
1624 Py_DECREF(func);
1625 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001626
Barry Warsawfa701a81997-01-16 00:15:11 +00001627 if (res == NULL) {
1628 errorInCmd = 1;
1629 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1630 }
1631 else
1632 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001633
1634 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001635}
1636
1637static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001638Tkapp_CreateTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001639 PyObject *self;
1640 PyObject *args; /* Is (milliseconds, func) */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001641{
Barry Warsawfa701a81997-01-16 00:15:11 +00001642 int milliseconds;
1643 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001644 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001645
Guido van Rossum35d43371997-08-02 00:09:09 +00001646 if (!PyArg_ParseTuple(args, "iO", &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001647 return NULL;
1648 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001649 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001650 return NULL;
1651 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001652 v = Tktt_New(func);
1653 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1654 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001655
Guido van Rossum00d93061998-05-28 23:06:38 +00001656 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001657}
1658
Barry Warsawfa701a81997-01-16 00:15:11 +00001659
Guido van Rossum18468821994-06-20 07:49:28 +00001660/** Event Loop **/
1661
Guido van Rossum18468821994-06-20 07:49:28 +00001662static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001663Tkapp_MainLoop(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001664 PyObject *self;
1665 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001666{
Barry Warsawfa701a81997-01-16 00:15:11 +00001667 int threshold = 0;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001668
Barry Warsawfa701a81997-01-16 00:15:11 +00001669 if (!PyArg_ParseTuple(args, "|i", &threshold))
1670 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001671
Barry Warsawfa701a81997-01-16 00:15:11 +00001672 quitMainLoop = 0;
1673 while (Tk_GetNumMainWindows() > threshold &&
1674 !quitMainLoop &&
1675 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001676 {
Guido van Rossum35d43371997-08-02 00:09:09 +00001677 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00001678
1679#ifdef WITH_THREAD
Guido van Rossum62320c91998-06-15 04:36:09 +00001680 Py_BEGIN_ALLOW_THREADS
1681 acquire_lock(tcl_lock, 1);
Guido van Rossum35d43371997-08-02 00:09:09 +00001682 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossum00d93061998-05-28 23:06:38 +00001683 release_lock(tcl_lock);
1684 if (result == 0)
1685 Sleep(20);
Guido van Rossum35d43371997-08-02 00:09:09 +00001686 Py_END_ALLOW_THREADS
Guido van Rossum5b020781997-08-19 01:00:50 +00001687#else
1688 result = Tcl_DoOneEvent(0);
1689#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001690
Guido van Rossum35d43371997-08-02 00:09:09 +00001691 if (PyErr_CheckSignals() != 0)
1692 return NULL;
1693 if (result < 0)
1694 break;
Guido van Rossum18468821994-06-20 07:49:28 +00001695 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001696 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001697
Barry Warsawfa701a81997-01-16 00:15:11 +00001698 if (errorInCmd) {
1699 errorInCmd = 0;
1700 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1701 excInCmd = valInCmd = trbInCmd = NULL;
1702 return NULL;
1703 }
1704 Py_INCREF(Py_None);
1705 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001706}
1707
1708static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001709Tkapp_DoOneEvent(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001710 PyObject *self;
1711 PyObject *args;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001712{
Guido van Rossum35d43371997-08-02 00:09:09 +00001713 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00001714 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001715
Barry Warsawfa701a81997-01-16 00:15:11 +00001716 if (!PyArg_ParseTuple(args, "|i", &flags))
1717 return NULL;
1718
Guido van Rossum00d93061998-05-28 23:06:38 +00001719 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001720 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00001721 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001722 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001723}
1724
1725static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001726Tkapp_Quit(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001727 PyObject *self;
1728 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
1730
Guido van Rossum35d43371997-08-02 00:09:09 +00001731 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001732 return NULL;
1733
1734 quitMainLoop = 1;
1735 Py_INCREF(Py_None);
1736 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001737}
1738
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001739static PyObject *
1740Tkapp_InterpAddr(self, args)
1741 PyObject *self;
1742 PyObject *args;
1743{
1744
1745 if (!PyArg_ParseTuple(args, ""))
1746 return NULL;
1747
1748 return PyInt_FromLong((long)Tkapp_Interp(self));
1749}
1750
Barry Warsawfa701a81997-01-16 00:15:11 +00001751
1752
Guido van Rossum18468821994-06-20 07:49:28 +00001753/**** Tkapp Method List ****/
1754
1755static PyMethodDef Tkapp_methods[] =
1756{
Guido van Rossum35d43371997-08-02 00:09:09 +00001757 {"call", Tkapp_Call, 0},
1758 {"globalcall", Tkapp_GlobalCall, 0},
1759 {"eval", Tkapp_Eval, 1},
1760 {"globaleval", Tkapp_GlobalEval, 1},
1761 {"evalfile", Tkapp_EvalFile, 1},
1762 {"record", Tkapp_Record, 1},
1763 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1764 {"setvar", Tkapp_SetVar, 1},
1765 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1766 {"getvar", Tkapp_GetVar, 1},
1767 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1768 {"unsetvar", Tkapp_UnsetVar, 1},
1769 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1770 {"getint", Tkapp_GetInt, 1},
1771 {"getdouble", Tkapp_GetDouble, 1},
1772 {"getboolean", Tkapp_GetBoolean, 1},
1773 {"exprstring", Tkapp_ExprString, 1},
1774 {"exprlong", Tkapp_ExprLong, 1},
1775 {"exprdouble", Tkapp_ExprDouble, 1},
1776 {"exprboolean", Tkapp_ExprBoolean, 1},
1777 {"splitlist", Tkapp_SplitList, 1},
1778 {"split", Tkapp_Split, 1},
1779 {"merge", Tkapp_Merge, 0},
1780 {"createcommand", Tkapp_CreateCommand, 1},
1781 {"deletecommand", Tkapp_DeleteCommand, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001782#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001783 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1784 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001785#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001786 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001787 {"mainloop", Tkapp_MainLoop, 1},
1788 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001789 {"quit", Tkapp_Quit, 1},
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001790 {"interpaddr", Tkapp_InterpAddr, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001791 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001792};
1793
Barry Warsawfa701a81997-01-16 00:15:11 +00001794
1795
Guido van Rossum18468821994-06-20 07:49:28 +00001796/**** Tkapp Type Methods ****/
1797
1798static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001799Tkapp_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001800 PyObject *self;
Guido van Rossum18468821994-06-20 07:49:28 +00001801{
Guido van Rossum00d93061998-05-28 23:06:38 +00001802 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001803 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00001804 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001805 PyMem_DEL(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001806 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00001807}
1808
1809static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001810Tkapp_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001811 PyObject *self;
1812 char *name;
Guido van Rossum18468821994-06-20 07:49:28 +00001813{
Guido van Rossum35d43371997-08-02 00:09:09 +00001814 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00001815}
1816
1817static PyTypeObject Tkapp_Type =
1818{
Guido van Rossum35d43371997-08-02 00:09:09 +00001819 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001820 0, /*ob_size */
1821 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001822 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001823 0, /*tp_itemsize */
1824 Tkapp_Dealloc, /*tp_dealloc */
1825 0, /*tp_print */
1826 Tkapp_GetAttr, /*tp_getattr */
1827 0, /*tp_setattr */
1828 0, /*tp_compare */
1829 0, /*tp_repr */
1830 0, /*tp_as_number */
1831 0, /*tp_as_sequence */
1832 0, /*tp_as_mapping */
1833 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00001834};
1835
Barry Warsawfa701a81997-01-16 00:15:11 +00001836
1837
Guido van Rossum18468821994-06-20 07:49:28 +00001838/**** Tkinter Module ****/
1839
1840static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001841Tkinter_Create(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001842 PyObject *self;
1843 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001844{
Barry Warsawfa701a81997-01-16 00:15:11 +00001845 char *screenName = NULL;
1846 char *baseName = NULL;
1847 char *className = NULL;
1848 int interactive = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001849
Guido van Rossum35d43371997-08-02 00:09:09 +00001850 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00001851 if (baseName != NULL)
1852 baseName++;
1853 else
1854 baseName = Py_GetProgramName();
1855 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00001856
Barry Warsawfa701a81997-01-16 00:15:11 +00001857 if (!PyArg_ParseTuple(args, "|zssi",
1858 &screenName, &baseName, &className,
1859 &interactive))
1860 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001861
Barry Warsawfa701a81997-01-16 00:15:11 +00001862 return (PyObject *) Tkapp_New(screenName, baseName, className,
1863 interactive);
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
1866static PyMethodDef moduleMethods[] =
1867{
Barry Warsawfa701a81997-01-16 00:15:11 +00001868 {"create", Tkinter_Create, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001869#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001870 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1871 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001872#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001873 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001874 {"mainloop", Tkapp_MainLoop, 1},
1875 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001876 {"quit", Tkapp_Quit, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001877 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001878};
1879
Guido van Rossum7bf15641998-05-22 18:28:17 +00001880#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001881
1882static int stdin_ready = 0;
1883
Guido van Rossumad4db171998-06-13 13:56:28 +00001884#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00001885static void
1886MyFileProc(clientData, mask)
1887 void *clientData;
1888 int mask;
1889{
1890 stdin_ready = 1;
1891}
Guido van Rossumad4db171998-06-13 13:56:28 +00001892#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001893
Guido van Rossum00d93061998-05-28 23:06:38 +00001894static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00001895
Guido van Rossum18468821994-06-20 07:49:28 +00001896static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001897EventHook()
Guido van Rossum18468821994-06-20 07:49:28 +00001898{
Guido van Rossumad4db171998-06-13 13:56:28 +00001899#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001900 FHANDLE tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00001901#endif
Guido van Rossumad4db171998-06-13 13:56:28 +00001902 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 */