blob: c6c47dbfb55209be8350d4dd9cddf886562ce488 [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
149 By contrast, ENTER_PYTHON(tstate) and LEAVE_PYTHON are used in Tcl event
150 handlers when the handler needs to use Python. Such event handlers are
151 entered while the lock for Tcl is held; the event handler presumably needs
152 to use Python. ENTER_PYTHON(tstate) releases the lock for Tcl and acquires
153 the Python interpreter lock, restoring the appropriate thread state, and
154 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
155 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
156 the code between ENTER_PYTHON(tstate) and LEAVE_PYTHON.
157
158 These locks expand to several statements and brackets; they should not be
159 used in branches of if statements and the like.
160
161*/
162
163static type_lock tcl_lock = 0;
164
165#define ENTER_TCL \
166 Py_BEGIN_ALLOW_THREADS acquire_lock(tcl_lock, 1);
167
168#define LEAVE_TCL \
169 release_lock(tcl_lock); Py_END_ALLOW_THREADS
170
Guido van Rossum62320c91998-06-15 04:36:09 +0000171#define ENTER_OVERLAP \
172 Py_END_ALLOW_THREADS
173
174#define LEAVE_OVERLAP_TCL \
175 release_lock(tcl_lock);
176
Guido van Rossum00d93061998-05-28 23:06:38 +0000177#define ENTER_PYTHON(tstate) \
Guido van Rossum00d93061998-05-28 23:06:38 +0000178 release_lock(tcl_lock); PyEval_RestoreThread((tstate));
179
180#define LEAVE_PYTHON \
181 PyEval_SaveThread(); acquire_lock(tcl_lock, 1);
182
183#else
184
185#define ENTER_TCL
186#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000187#define ENTER_OVERLAP
188#define LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000189#define ENTER_PYTHON(tstate)
190#define LEAVE_PYTHON
191
192#endif
193
Guido van Rossum35d43371997-08-02 00:09:09 +0000194extern int Tk_GetNumMainWindows();
195
Guido van Rossumec22c921996-02-25 04:50:29 +0000196#ifdef macintosh
197
198/*
199** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000200** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000201*/
202
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000203/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000204#define FREECAST (char *)
205
Guido van Rossumec22c921996-02-25 04:50:29 +0000206#include <Events.h> /* For EventRecord */
207
208typedef int (*TclMacConvertEventPtr) Py_PROTO((EventRecord *eventPtr));
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000209/* They changed the name... */
210#if TKMAJORMINOR < 8000
211#define Tcl_MacSetEventProc TclMacSetEventProc
212#endif
213void Tcl_MacSetEventProc Py_PROTO((TclMacConvertEventPtr procPtr));
Guido van Rossumec22c921996-02-25 04:50:29 +0000214int TkMacConvertEvent Py_PROTO((EventRecord *eventPtr));
215
216staticforward int PyMacConvertEvent Py_PROTO((EventRecord *eventPtr));
217
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000218#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
219 #pragma import on
220#endif
221
222#include <SIOUX.h>
223extern int SIOUXIsAppWindow(WindowPtr);
224
225#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
226 #pragma import reset
227#endif
Guido van Rossumec22c921996-02-25 04:50:29 +0000228#endif /* macintosh */
229
Guido van Rossum97867b21996-08-08 19:09:53 +0000230#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000231#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000232#endif
233
Guido van Rossum18468821994-06-20 07:49:28 +0000234/**** Tkapp Object Declaration ****/
235
236staticforward PyTypeObject Tkapp_Type;
237
Guido van Rossum00d93061998-05-28 23:06:38 +0000238typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000239 PyObject_HEAD
240 Tcl_Interp *interp;
Guido van Rossum00d93061998-05-28 23:06:38 +0000241} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000242
243#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000244#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
245#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
246
Guido van Rossum35d43371997-08-02 00:09:09 +0000247#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000248(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000249
Barry Warsawfa701a81997-01-16 00:15:11 +0000250
251
Guido van Rossum18468821994-06-20 07:49:28 +0000252/**** Error Handling ****/
253
254static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000255static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000256static int errorInCmd = 0;
257static PyObject *excInCmd;
258static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000259static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000260
Barry Warsawfa701a81997-01-16 00:15:11 +0000261
262
Guido van Rossum18468821994-06-20 07:49:28 +0000263static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000264Tkinter_Error(v)
265 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000266{
Barry Warsawfa701a81997-01-16 00:15:11 +0000267 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
268 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000269}
270
Barry Warsawfa701a81997-01-16 00:15:11 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
Guido van Rossum18468821994-06-20 07:49:28 +0000273/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000274
275#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000276#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +0000277/* Millisecond sleep() for Unix platforms. */
278
279static void
280Sleep(milli)
281 int milli;
282{
283 /* XXX Too bad if you don't have select(). */
284 struct timeval t;
285 double frac;
286 t.tv_sec = milli/1000;
287 t.tv_usec = (milli%1000) * 1000;
288 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
289}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000290#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000291#endif /* WITH_THREAD */
292
293
Guido van Rossum18468821994-06-20 07:49:28 +0000294static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000295AsString(value, tmp)
296 PyObject *value;
297 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000298{
Guido van Rossum35d43371997-08-02 00:09:09 +0000299 if (PyString_Check(value))
300 return PyString_AsString(value);
Barry Warsawfa701a81997-01-16 00:15:11 +0000301 else {
302 PyObject *v = PyObject_Str(value);
303 PyList_Append(tmp, v);
304 Py_DECREF(v);
305 return PyString_AsString(v);
306 }
Guido van Rossum18468821994-06-20 07:49:28 +0000307}
308
Barry Warsawfa701a81997-01-16 00:15:11 +0000309
310
Guido van Rossum18468821994-06-20 07:49:28 +0000311#define ARGSZ 64
312
313static char *
Barry Warsawfa701a81997-01-16 00:15:11 +0000314Merge(args)
315 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000316{
Barry Warsawfa701a81997-01-16 00:15:11 +0000317 PyObject *tmp = NULL;
318 char *argvStore[ARGSZ];
319 char **argv = NULL;
320 int fvStore[ARGSZ];
321 int *fv = NULL;
322 int argc = 0, i;
323 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000324
Barry Warsawfa701a81997-01-16 00:15:11 +0000325 if (!(tmp = PyList_New(0)))
326 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000327
Barry Warsawfa701a81997-01-16 00:15:11 +0000328 argv = argvStore;
329 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000330
Barry Warsawfa701a81997-01-16 00:15:11 +0000331 if (args == NULL)
332 argc = 0;
333
334 else if (!PyTuple_Check(args)) {
335 argc = 1;
336 fv[0] = 0;
337 argv[0] = AsString(args, tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000338 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000339 else {
340 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000341
Barry Warsawfa701a81997-01-16 00:15:11 +0000342 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000343 argv = (char **)ckalloc(argc * sizeof(char *));
344 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000345 if (argv == NULL || fv == NULL) {
346 PyErr_NoMemory();
347 goto finally;
348 }
349 }
350
351 for (i = 0; i < argc; i++) {
352 PyObject *v = PyTuple_GetItem(args, i);
353 if (PyTuple_Check(v)) {
354 fv[i] = 1;
355 if (!(argv[i] = Merge(v)))
356 goto finally;
357 }
358 else if (v == Py_None) {
359 argc = i;
360 break;
361 }
362 else {
363 fv[i] = 0;
364 argv[i] = AsString(v, tmp);
365 }
366 }
Guido van Rossum18468821994-06-20 07:49:28 +0000367 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000368 res = Tcl_Merge(argc, argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000369
Barry Warsawfa701a81997-01-16 00:15:11 +0000370 finally:
371 for (i = 0; i < argc; i++)
372 if (fv[i]) {
373 ckfree(argv[i]);
374 }
375 if (argv != argvStore)
376 ckfree(FREECAST argv);
377 if (fv != fvStore)
378 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000379
Barry Warsawfa701a81997-01-16 00:15:11 +0000380 Py_DECREF(tmp);
381 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000382}
383
Barry Warsawfa701a81997-01-16 00:15:11 +0000384
385
Guido van Rossum18468821994-06-20 07:49:28 +0000386static PyObject *
Guido van Rossum00d93061998-05-28 23:06:38 +0000387Split(list)
Barry Warsawfa701a81997-01-16 00:15:11 +0000388 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +0000389{
Barry Warsawfa701a81997-01-16 00:15:11 +0000390 int argc;
391 char **argv;
392 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000393
Barry Warsawfa701a81997-01-16 00:15:11 +0000394 if (list == NULL) {
395 Py_INCREF(Py_None);
396 return Py_None;
397 }
Guido van Rossum18468821994-06-20 07:49:28 +0000398
Guido van Rossum00d93061998-05-28 23:06:38 +0000399 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 /* Not a list.
401 * Could be a quoted string containing funnies, e.g. {"}.
402 * Return the string itself.
403 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000404 return PyString_FromString(list);
405 }
Guido van Rossum18468821994-06-20 07:49:28 +0000406
Barry Warsawfa701a81997-01-16 00:15:11 +0000407 if (argc == 0)
408 v = PyString_FromString("");
409 else if (argc == 1)
410 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000411 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000412 int i;
413 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000414
Barry Warsawfa701a81997-01-16 00:15:11 +0000415 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000416 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000417 Py_DECREF(v);
418 v = NULL;
419 break;
420 }
421 PyTuple_SetItem(v, i, w);
422 }
423 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000424 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000425 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000426}
427
Barry Warsawfa701a81997-01-16 00:15:11 +0000428
429
Guido van Rossum18468821994-06-20 07:49:28 +0000430/**** Tkapp Object ****/
431
432#ifndef WITH_APPINIT
433int
Guido van Rossum35d43371997-08-02 00:09:09 +0000434Tcl_AppInit(interp)
Barry Warsawfa701a81997-01-16 00:15:11 +0000435 Tcl_Interp *interp;
Guido van Rossum18468821994-06-20 07:49:28 +0000436{
Barry Warsawfa701a81997-01-16 00:15:11 +0000437 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000438
Barry Warsawfa701a81997-01-16 00:15:11 +0000439 main = Tk_MainWindow(interp);
440 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000441 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000442 return TCL_ERROR;
443 }
444 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000445 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000446 return TCL_ERROR;
447 }
448 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000449}
450#endif /* !WITH_APPINIT */
451
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Barry Warsawfa701a81997-01-16 00:15:11 +0000453
454
455/* Initialize the Tk application; see the `main' function in
456 * `tkMain.c'.
457 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000458
459static void EnableEventHook(); /* Forward */
460static void DisableEventHook(); /* Forward */
461
Barry Warsawfa701a81997-01-16 00:15:11 +0000462static TkappObject *
463Tkapp_New(screenName, baseName, className, interactive)
464 char *screenName;
465 char *baseName;
466 char *className;
467 int interactive;
468{
469 TkappObject *v;
470 char *argv0;
471
472 v = PyObject_NEW(TkappObject, &Tkapp_Type);
473 if (v == NULL)
474 return NULL;
475
476 v->interp = Tcl_CreateInterp();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000477
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000478#if defined(macintosh) && TKMAJORMINOR >= 8000
479 /* This seems to be needed since Tk 8.0 */
480 ClearMenuBar();
481 TkMacInitMenus(v->interp);
482#endif
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000483 /* Delete the 'exit' command, which can screw things up */
484 Tcl_DeleteCommand(v->interp, "exit");
485
Barry Warsawfa701a81997-01-16 00:15:11 +0000486 if (screenName != NULL)
487 Tcl_SetVar2(v->interp, "env", "DISPLAY",
488 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000489
Barry Warsawfa701a81997-01-16 00:15:11 +0000490 if (interactive)
491 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
492 else
493 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000494
Barry Warsawfa701a81997-01-16 00:15:11 +0000495 /* This is used to get the application class for Tk 4.1 and up */
496 argv0 = (char*)ckalloc(strlen(className) + 1);
497 if (!argv0) {
498 PyErr_NoMemory();
499 Py_DECREF(v);
500 return NULL;
501 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000502
Barry Warsawfa701a81997-01-16 00:15:11 +0000503 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000504 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000505 argv0[0] = tolower(argv0[0]);
506 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
507 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000508
Barry Warsawfa701a81997-01-16 00:15:11 +0000509 if (Tcl_AppInit(v->interp) != TCL_OK)
510 return (TkappObject *)Tkinter_Error(v);
511
Guido van Rossum7bf15641998-05-22 18:28:17 +0000512 EnableEventHook();
513
Barry Warsawfa701a81997-01-16 00:15:11 +0000514 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000515}
516
Barry Warsawfa701a81997-01-16 00:15:11 +0000517
518
Guido van Rossum18468821994-06-20 07:49:28 +0000519/** Tcl Eval **/
520
521static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000522Tkapp_Call(self, args)
523 PyObject *self;
524 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000525{
Guido van Rossum212643f1998-04-29 16:22:14 +0000526 /* This is copied from Merge() */
527 PyObject *tmp = NULL;
528 char *argvStore[ARGSZ];
529 char **argv = NULL;
530 int fvStore[ARGSZ];
531 int *fv = NULL;
532 int argc = 0, i;
533 PyObject *res = NULL; /* except this has a different type */
534 Tcl_CmdInfo info; /* and this is added */
535 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
Guido van Rossum18468821994-06-20 07:49:28 +0000536
Guido van Rossum62320c91998-06-15 04:36:09 +0000537 /* and this test */
538 if (Tcl_InterpDeleted(interp)) {
539 PyErr_SetString(Tkinter_TclError, "application is destroyed");
540 return NULL;
541 }
542
Guido van Rossum212643f1998-04-29 16:22:14 +0000543 if (!(tmp = PyList_New(0)))
544 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000545
Guido van Rossum212643f1998-04-29 16:22:14 +0000546 argv = argvStore;
547 fv = fvStore;
Barry Warsawfa701a81997-01-16 00:15:11 +0000548
Guido van Rossum212643f1998-04-29 16:22:14 +0000549 if (args == NULL)
550 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000551
Guido van Rossum212643f1998-04-29 16:22:14 +0000552 else if (!PyTuple_Check(args)) {
553 argc = 1;
554 fv[0] = 0;
555 argv[0] = AsString(args, tmp);
556 }
557 else {
558 argc = PyTuple_Size(args);
559
560 if (argc > ARGSZ) {
561 argv = (char **)ckalloc(argc * sizeof(char *));
562 fv = (int *)ckalloc(argc * sizeof(int));
563 if (argv == NULL || fv == NULL) {
564 PyErr_NoMemory();
565 goto finally;
566 }
567 }
568
569 for (i = 0; i < argc; i++) {
570 PyObject *v = PyTuple_GetItem(args, i);
571 if (PyTuple_Check(v)) {
572 fv[i] = 1;
573 if (!(argv[i] = Merge(v)))
574 goto finally;
575 }
576 else if (v == Py_None) {
577 argc = i;
578 break;
579 }
580 else {
581 fv[i] = 0;
582 argv[i] = AsString(v, tmp);
583 }
584 }
585 }
586 /* End code copied from Merge() */
587
588 /* All this to avoid a call to Tcl_Merge() and the corresponding call
589 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
590 if (Py_VerboseFlag >= 2) {
591 for (i = 0; i < argc; i++)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000592 PySys_WriteStderr("%s ", argv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000593 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000594 ENTER_TCL
595 info.proc = NULL;
Guido van Rossum212643f1998-04-29 16:22:14 +0000596 if (argc < 1 ||
597 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
598 info.proc == NULL)
599 {
600 char *cmd;
Guido van Rossum212643f1998-04-29 16:22:14 +0000601 cmd = Tcl_Merge(argc, argv);
602 i = Tcl_Eval(interp, cmd);
Barry Warsawfa701a81997-01-16 00:15:11 +0000603 ckfree(cmd);
Guido van Rossum212643f1998-04-29 16:22:14 +0000604 }
605 else {
606 Tcl_ResetResult(interp);
607 i = (*info.proc)(info.clientData, interp, argc, argv);
608 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000609 ENTER_OVERLAP
610 if (info.proc == NULL && Py_VerboseFlag >= 2)
611 PySys_WriteStderr("... use TclEval ");
Guido van Rossum212643f1998-04-29 16:22:14 +0000612 if (i == TCL_ERROR) {
613 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000614 PySys_WriteStderr("... error: '%s'\n",
Guido van Rossum212643f1998-04-29 16:22:14 +0000615 interp->result);
616 Tkinter_Error(self);
617 }
618 else {
619 if (Py_VerboseFlag >= 2)
Guido van Rossumb41addf1998-05-12 15:02:41 +0000620 PySys_WriteStderr("-> '%s'\n", interp->result);
Guido van Rossum212643f1998-04-29 16:22:14 +0000621 res = PyString_FromString(interp->result);
622 }
Guido van Rossum62320c91998-06-15 04:36:09 +0000623 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000624
Guido van Rossum212643f1998-04-29 16:22:14 +0000625 /* Copied from Merge() again */
626 finally:
627 for (i = 0; i < argc; i++)
628 if (fv[i]) {
629 ckfree(argv[i]);
630 }
631 if (argv != argvStore)
632 ckfree(FREECAST argv);
633 if (fv != fvStore)
634 ckfree(FREECAST fv);
635
636 Py_DECREF(tmp);
Barry Warsawfa701a81997-01-16 00:15:11 +0000637 return res;
638}
639
640
641static PyObject *
642Tkapp_GlobalCall(self, args)
643 PyObject *self;
644 PyObject *args;
645{
Guido van Rossum212643f1998-04-29 16:22:14 +0000646 /* Could do the same here as for Tkapp_Call(), but this is not used
647 much, so I can't be bothered. Unfortunately Tcl doesn't export a
648 way for the user to do what all its Global* variants do (save and
649 reset the scope pointer, call the local version, restore the saved
650 scope pointer). */
651
Guido van Rossum62320c91998-06-15 04:36:09 +0000652 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +0000653 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000654
Guido van Rossum62320c91998-06-15 04:36:09 +0000655 if (Tcl_InterpDeleted(Tkapp_Interp(self))) {
656 PyErr_SetString(Tkinter_TclError, "application is destroyed");
657 return NULL;
658 }
659
660 cmd = Merge(args);
Barry Warsawfa701a81997-01-16 00:15:11 +0000661 if (!cmd)
662 PyErr_SetString(Tkinter_TclError, "merge failed");
663
Guido van Rossum00d93061998-05-28 23:06:38 +0000664 else {
665 int err;
666 ENTER_TCL
667 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +0000668 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000669 if (err == TCL_ERROR)
670 res = Tkinter_Error(self);
671 else
672 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +0000673 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000674 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000675
676 if (cmd)
677 ckfree(cmd);
678
679 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000680}
681
682static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000683Tkapp_Eval(self, args)
684 PyObject *self;
685 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000686{
Barry Warsawfa701a81997-01-16 00:15:11 +0000687 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000688 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000689 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000690
Guido van Rossum35d43371997-08-02 00:09:09 +0000691 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000692 return NULL;
693
Guido van Rossum62320c91998-06-15 04:36:09 +0000694 if (Tcl_InterpDeleted(Tkapp_Interp(self))) {
695 PyErr_SetString(Tkinter_TclError, "application is destroyed");
696 return NULL;
697 }
698
Guido van Rossum00d93061998-05-28 23:06:38 +0000699 ENTER_TCL
700 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000701 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000702 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000703 res = Tkinter_Error(self);
704 else
705 res = PyString_FromString(Tkapp_Result(self));
706 LEAVE_OVERLAP_TCL
707 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000708}
709
710static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000711Tkapp_GlobalEval(self, args)
712 PyObject *self;
713 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000714{
Barry Warsawfa701a81997-01-16 00:15:11 +0000715 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000716 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000717 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +0000718
719 if (Tcl_InterpDeleted(Tkapp_Interp(self))) {
720 PyErr_SetString(Tkinter_TclError, "application is destroyed");
721 return NULL;
722 }
723
Guido van Rossum35d43371997-08-02 00:09:09 +0000724 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000725 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000726
Guido van Rossum00d93061998-05-28 23:06:38 +0000727 ENTER_TCL
728 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000729 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000730 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000731 res = Tkinter_Error(self);
732 else
733 res = PyString_FromString(Tkapp_Result(self));
734 LEAVE_OVERLAP_TCL
735 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000736}
737
738static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000739Tkapp_EvalFile(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000740 PyObject *self;
741 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000742{
Barry Warsawfa701a81997-01-16 00:15:11 +0000743 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +0000744 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000745 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000746
Guido van Rossum62320c91998-06-15 04:36:09 +0000747 if (Tcl_InterpDeleted(Tkapp_Interp(self))) {
748 PyErr_SetString(Tkinter_TclError, "application is destroyed");
749 return NULL;
750 }
751
Guido van Rossum35d43371997-08-02 00:09:09 +0000752 if (!PyArg_ParseTuple(args, "s", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +0000753 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000754
Guido van Rossum00d93061998-05-28 23:06:38 +0000755 ENTER_TCL
756 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +0000757 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000758 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000759 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +0000760
Guido van Rossum62320c91998-06-15 04:36:09 +0000761 else
762 res = PyString_FromString(Tkapp_Result(self));
763 LEAVE_OVERLAP_TCL
764 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000765}
766
767static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000768Tkapp_Record(self, args)
769 PyObject *self;
770 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000771{
Barry Warsawfa701a81997-01-16 00:15:11 +0000772 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000773 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000774 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000775
Guido van Rossum62320c91998-06-15 04:36:09 +0000776 if (Tcl_InterpDeleted(Tkapp_Interp(self))) {
777 PyErr_SetString(Tkinter_TclError, "application is destroyed");
778 return NULL;
779 }
780
Guido van Rossum35d43371997-08-02 00:09:09 +0000781 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000782 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000783
Guido van Rossum00d93061998-05-28 23:06:38 +0000784 ENTER_TCL
785 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +0000786 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000787 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000788 res = Tkinter_Error(self);
789 else
790 res = PyString_FromString(Tkapp_Result(self));
791 LEAVE_OVERLAP_TCL
792 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000793}
794
795static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000796Tkapp_AddErrorInfo(self, args)
797 PyObject *self;
798 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000799{
Barry Warsawfa701a81997-01-16 00:15:11 +0000800 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +0000801
Guido van Rossum35d43371997-08-02 00:09:09 +0000802 if (!PyArg_ParseTuple(args, "s", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +0000803 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000804 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000805 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +0000806 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +0000807
Barry Warsawfa701a81997-01-16 00:15:11 +0000808 Py_INCREF(Py_None);
809 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000810}
811
Barry Warsawfa701a81997-01-16 00:15:11 +0000812
813
Guido van Rossum18468821994-06-20 07:49:28 +0000814/** Tcl Variable **/
815
816static PyObject *
Barry Warsawfa701a81997-01-16 00:15:11 +0000817SetVar(self, args, flags)
818 PyObject *self;
819 PyObject *args;
820 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000821{
Guido van Rossum00d93061998-05-28 23:06:38 +0000822 char *name1, *name2, *ok, *s;
Barry Warsawfa701a81997-01-16 00:15:11 +0000823 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +0000824 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000825
Guido van Rossum62320c91998-06-15 04:36:09 +0000826 if (Tcl_InterpDeleted(Tkapp_Interp(self))) {
827 PyErr_SetString(Tkinter_TclError, "application is destroyed");
828 return NULL;
829 }
830
831 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +0000832 if (!tmp)
833 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000834
Guido van Rossum00d93061998-05-28 23:06:38 +0000835 if (PyArg_ParseTuple(args, "sO", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000836 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +0000837 s = AsString(newValue, tmp);
838 ENTER_TCL
839 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
840 LEAVE_TCL
841 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000842 else {
Guido van Rossum35d43371997-08-02 00:09:09 +0000843 PyErr_Clear();
Guido van Rossum00d93061998-05-28 23:06:38 +0000844 if (PyArg_ParseTuple(args, "ssO", &name1, &name2, &newValue)) {
845 s = AsString (newValue, tmp);
846 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000847 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
Guido van Rossum00d93061998-05-28 23:06:38 +0000848 s, flags);
849 LEAVE_TCL
850 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000851 else {
Guido van Rossum00d93061998-05-28 23:06:38 +0000852 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +0000853 return NULL;
854 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000855 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000856 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000857
Barry Warsawfa701a81997-01-16 00:15:11 +0000858 if (!ok)
859 return Tkinter_Error(self);
860
861 Py_INCREF(Py_None);
862 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000863}
864
865static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000866Tkapp_SetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000867 PyObject *self;
868 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000869{
Barry Warsawfa701a81997-01-16 00:15:11 +0000870 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000871}
872
873static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000874Tkapp_GlobalSetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000875 PyObject *self;
876 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000877{
Barry Warsawfa701a81997-01-16 00:15:11 +0000878 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000879}
880
Barry Warsawfa701a81997-01-16 00:15:11 +0000881
882
Guido van Rossum18468821994-06-20 07:49:28 +0000883static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000884GetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000885 PyObject *self;
886 PyObject *args;
887 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000888{
Guido van Rossum35d43371997-08-02 00:09:09 +0000889 char *name1, *name2=NULL, *s;
Guido van Rossum62320c91998-06-15 04:36:09 +0000890 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000891
Guido van Rossum35d43371997-08-02 00:09:09 +0000892 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
893 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000894 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000895 if (name2 == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000896 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
Guido van Rossum18468821994-06-20 07:49:28 +0000897
Barry Warsawfa701a81997-01-16 00:15:11 +0000898 else
Guido van Rossum35d43371997-08-02 00:09:09 +0000899 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000900 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000901
Barry Warsawfa701a81997-01-16 00:15:11 +0000902 if (s == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000903 res = Tkinter_Error(self);
904 else
905 res = PyString_FromString(s);
906 LEAVE_OVERLAP_TCL
907 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000908}
909
910static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000911Tkapp_GetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000912 PyObject *self;
913 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000914{
Barry Warsawfa701a81997-01-16 00:15:11 +0000915 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000916}
917
918static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000919Tkapp_GlobalGetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000920 PyObject *self;
921 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000922{
Barry Warsawfa701a81997-01-16 00:15:11 +0000923 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000924}
925
Barry Warsawfa701a81997-01-16 00:15:11 +0000926
927
Guido van Rossum18468821994-06-20 07:49:28 +0000928static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000929UnsetVar(self, args, flags)
Barry Warsawfa701a81997-01-16 00:15:11 +0000930 PyObject *self;
931 PyObject *args;
932 int flags;
Guido van Rossum18468821994-06-20 07:49:28 +0000933{
Guido van Rossum35d43371997-08-02 00:09:09 +0000934 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +0000935 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000936 int code;
Guido van Rossum18468821994-06-20 07:49:28 +0000937
Guido van Rossum35d43371997-08-02 00:09:09 +0000938 if (!PyArg_ParseTuple(args, "s|s", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +0000939 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000940 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000941 if (name2 == NULL)
942 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
943
944 else
945 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000946 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000947
Barry Warsawfa701a81997-01-16 00:15:11 +0000948 if (code == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000949 res = Tkinter_Error(self);
950 else {
951 Py_INCREF(Py_None);
952 res = Py_None;
953 }
954 LEAVE_OVERLAP_TCL
955 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000956}
957
958static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000959Tkapp_UnsetVar(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000960 PyObject *self;
961 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000962{
Barry Warsawfa701a81997-01-16 00:15:11 +0000963 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000964}
965
966static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000967Tkapp_GlobalUnsetVar(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 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000972}
973
Barry Warsawfa701a81997-01-16 00:15:11 +0000974
975
Guido van Rossum18468821994-06-20 07:49:28 +0000976/** Tcl to Python **/
977
978static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000979Tkapp_GetInt(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000980 PyObject *self;
981 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000982{
Barry Warsawfa701a81997-01-16 00:15:11 +0000983 char *s;
984 int v;
Guido van Rossum18468821994-06-20 07:49:28 +0000985
Guido van Rossum35d43371997-08-02 00:09:09 +0000986 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +0000987 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +0000988 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +0000989 return Tkinter_Error(self);
990 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +0000991}
992
993static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +0000994Tkapp_GetDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000995 PyObject *self;
996 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +0000997{
Barry Warsawfa701a81997-01-16 00:15:11 +0000998 char *s;
999 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001000
Guido van Rossum35d43371997-08-02 00:09:09 +00001001 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001002 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001003 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001004 return Tkinter_Error(self);
1005 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001006}
1007
1008static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001009Tkapp_GetBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001010 PyObject *self;
1011 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001012{
Barry Warsawfa701a81997-01-16 00:15:11 +00001013 char *s;
1014 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001015
Guido van Rossum35d43371997-08-02 00:09:09 +00001016 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001017 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001018 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1019 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001020 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001021}
1022
1023static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001024Tkapp_ExprString(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001025 PyObject *self;
1026 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001027{
Barry Warsawfa701a81997-01-16 00:15:11 +00001028 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001029 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001030 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001031
Guido van Rossum35d43371997-08-02 00:09:09 +00001032 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001033 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001034 ENTER_TCL
1035 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001036 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001037 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001038 res = Tkinter_Error(self);
1039 else
1040 res = Py_BuildValue("s", Tkapp_Result(self));
1041 LEAVE_OVERLAP_TCL
1042 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001043}
1044
1045static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001046Tkapp_ExprLong(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001047 PyObject *self;
1048 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001049{
Barry Warsawfa701a81997-01-16 00:15:11 +00001050 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001051 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001052 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001053 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001054
Guido van Rossum35d43371997-08-02 00:09:09 +00001055 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001056 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001057 ENTER_TCL
1058 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001059 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001060 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001061 res = Tkinter_Error(self);
1062 else
1063 res = Py_BuildValue("l", v);
1064 LEAVE_OVERLAP_TCL
1065 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001066}
1067
1068static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001069Tkapp_ExprDouble(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001070 PyObject *self;
1071 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001072{
Barry Warsawfa701a81997-01-16 00:15:11 +00001073 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001074 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001075 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001076 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001077
Guido van Rossum35d43371997-08-02 00:09:09 +00001078 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001079 return NULL;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001080 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001081 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001082 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001083 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001084 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001085 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001086 res = Tkinter_Error(self);
1087 else
1088 res = Py_BuildValue("d", v);
1089 LEAVE_OVERLAP_TCL
1090 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001091}
1092
1093static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001094Tkapp_ExprBoolean(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001095 PyObject *self;
1096 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001097{
Barry Warsawfa701a81997-01-16 00:15:11 +00001098 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001099 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001100 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001101 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001102
Guido van Rossum35d43371997-08-02 00:09:09 +00001103 if (!PyArg_ParseTuple(args, "s", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001104 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001105 ENTER_TCL
1106 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001107 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001108 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001109 res = Tkinter_Error(self);
1110 else
1111 res = Py_BuildValue("i", v);
1112 LEAVE_OVERLAP_TCL
1113 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001114}
1115
Barry Warsawfa701a81997-01-16 00:15:11 +00001116
1117
Guido van Rossum18468821994-06-20 07:49:28 +00001118static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001119Tkapp_SplitList(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001120 PyObject *self;
1121 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001122{
Barry Warsawfa701a81997-01-16 00:15:11 +00001123 char *list;
1124 int argc;
1125 char **argv;
1126 PyObject *v;
1127 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001128
Guido van Rossum35d43371997-08-02 00:09:09 +00001129 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001130 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001131
Barry Warsawfa701a81997-01-16 00:15:11 +00001132 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1133 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001134
Barry Warsawfa701a81997-01-16 00:15:11 +00001135 if (!(v = PyTuple_New(argc)))
1136 return NULL;
1137
1138 for (i = 0; i < argc; i++) {
1139 PyObject *s = PyString_FromString(argv[i]);
1140 if (!s || PyTuple_SetItem(v, i, s)) {
1141 Py_DECREF(v);
1142 v = NULL;
1143 goto finally;
1144 }
1145 }
Guido van Rossum18468821994-06-20 07:49:28 +00001146
Barry Warsawfa701a81997-01-16 00:15:11 +00001147 finally:
1148 ckfree(FREECAST argv);
1149 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001150}
1151
1152static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001153Tkapp_Split(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001154 PyObject *self;
1155 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001156{
Barry Warsawfa701a81997-01-16 00:15:11 +00001157 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001158
Guido van Rossum35d43371997-08-02 00:09:09 +00001159 if (!PyArg_ParseTuple(args, "s", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001160 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001161 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001162}
1163
1164static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001165Tkapp_Merge(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001166 PyObject *self;
1167 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001168{
Barry Warsawfa701a81997-01-16 00:15:11 +00001169 char *s = Merge(args);
1170 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001171
Barry Warsawfa701a81997-01-16 00:15:11 +00001172 if (s) {
1173 res = PyString_FromString(s);
1174 ckfree(s);
1175 }
1176 else
1177 PyErr_SetString(Tkinter_TclError, "merge failed");
1178
1179 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001180}
1181
Barry Warsawfa701a81997-01-16 00:15:11 +00001182
1183
Guido van Rossum18468821994-06-20 07:49:28 +00001184/** Tcl Command **/
1185
Guido van Rossum00d93061998-05-28 23:06:38 +00001186/* Client data struct */
1187typedef struct {
1188 PyThreadState *tstate;
1189 PyObject *self;
1190 PyObject *func;
1191} PythonCmd_ClientData;
1192
1193static int
1194PythonCmd_Error(interp)
1195 Tcl_Interp *interp;
1196{
1197 errorInCmd = 1;
1198 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1199 LEAVE_PYTHON
1200 return TCL_ERROR;
1201}
1202
Guido van Rossum18468821994-06-20 07:49:28 +00001203/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001204 * function or method.
1205 */
Guido van Rossum18468821994-06-20 07:49:28 +00001206static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001207PythonCmd(clientData, interp, argc, argv)
Guido van Rossum00d93061998-05-28 23:06:38 +00001208 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001209 Tcl_Interp *interp;
1210 int argc;
1211 char *argv[];
Guido van Rossum18468821994-06-20 07:49:28 +00001212{
Guido van Rossum00d93061998-05-28 23:06:38 +00001213 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001214 PyObject *self, *func, *arg, *res, *tmp;
1215 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001216
Guido van Rossum00d93061998-05-28 23:06:38 +00001217 /* XXX Should create fresh thread state? */
1218 ENTER_PYTHON(data->tstate)
1219
Barry Warsawfa701a81997-01-16 00:15:11 +00001220 /* TBD: no error checking here since we know, via the
1221 * Tkapp_CreateCommand() that the client data is a two-tuple
1222 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001223 self = data->self;
1224 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001225
Barry Warsawfa701a81997-01-16 00:15:11 +00001226 /* Create argument list (argv1, ..., argvN) */
1227 if (!(arg = PyTuple_New(argc - 1)))
1228 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001229
Barry Warsawfa701a81997-01-16 00:15:11 +00001230 for (i = 0; i < (argc - 1); i++) {
1231 PyObject *s = PyString_FromString(argv[i + 1]);
1232 if (!s || PyTuple_SetItem(arg, i, s)) {
1233 Py_DECREF(arg);
1234 PythonCmd_Error(interp);
1235 }
1236 }
1237 res = PyEval_CallObject(func, arg);
1238 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001239
Barry Warsawfa701a81997-01-16 00:15:11 +00001240 if (res == NULL)
1241 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001242
Barry Warsawfa701a81997-01-16 00:15:11 +00001243 if (!(tmp = PyList_New(0))) {
1244 Py_DECREF(res);
1245 return PythonCmd_Error(interp);
1246 }
1247
1248 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1249 Py_DECREF(res);
1250 Py_DECREF(tmp);
1251
Guido van Rossum00d93061998-05-28 23:06:38 +00001252 LEAVE_PYTHON
1253
Barry Warsawfa701a81997-01-16 00:15:11 +00001254 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00001255}
1256
1257static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001258PythonCmdDelete(clientData)
Guido van Rossum00d93061998-05-28 23:06:38 +00001259 ClientData clientData;
Guido van Rossum18468821994-06-20 07:49:28 +00001260{
Guido van Rossum00d93061998-05-28 23:06:38 +00001261 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1262
1263 ENTER_PYTHON(data->tstate)
1264 Py_XDECREF(data->self);
1265 Py_XDECREF(data->func);
1266 PyMem_DEL(data);
1267 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001268}
1269
Barry Warsawfa701a81997-01-16 00:15:11 +00001270
1271
Guido van Rossum18468821994-06-20 07:49:28 +00001272static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001273Tkapp_CreateCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001274 PyObject *self;
1275 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001276{
Guido van Rossum00d93061998-05-28 23:06:38 +00001277 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001278 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001279 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001280 Tcl_Command err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001281
1282 if (!PyArg_ParseTuple(args, "sO", &cmdName, &func))
1283 return NULL;
1284 if (!PyCallable_Check(func)) {
1285 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001286 return NULL;
1287 }
Guido van Rossum18468821994-06-20 07:49:28 +00001288
Guido van Rossum00d93061998-05-28 23:06:38 +00001289 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001290 if (!data)
1291 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001292 data->tstate = PyThreadState_Get();
1293 Py_XINCREF(self);
1294 Py_XINCREF(func);
1295 data->self = self;
1296 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00001297
Guido van Rossum00d93061998-05-28 23:06:38 +00001298 ENTER_TCL
1299 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1300 (ClientData)data, PythonCmdDelete);
1301 LEAVE_TCL
1302 if (err == NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001303 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001304 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001305 return NULL;
1306 }
Guido van Rossum18468821994-06-20 07:49:28 +00001307
Barry Warsawfa701a81997-01-16 00:15:11 +00001308 Py_INCREF(Py_None);
1309 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001310}
1311
Barry Warsawfa701a81997-01-16 00:15:11 +00001312
1313
Guido van Rossum18468821994-06-20 07:49:28 +00001314static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001315Tkapp_DeleteCommand(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001316 PyObject *self;
1317 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001318{
Barry Warsawfa701a81997-01-16 00:15:11 +00001319 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001320 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001321
Guido van Rossum35d43371997-08-02 00:09:09 +00001322 if (!PyArg_ParseTuple(args, "s", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001323 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001324 ENTER_TCL
1325 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1326 LEAVE_TCL
1327 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001328 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1329 return NULL;
1330 }
1331 Py_INCREF(Py_None);
1332 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001333}
1334
Barry Warsawfa701a81997-01-16 00:15:11 +00001335
1336
Guido van Rossum00d93061998-05-28 23:06:38 +00001337#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00001338/** File Handler **/
1339
Guido van Rossum00d93061998-05-28 23:06:38 +00001340typedef struct _fhcdata {
1341 PyThreadState *tstate;
1342 PyObject *func;
1343 PyObject *file;
1344 int id;
1345 struct _fhcdata *next;
1346} FileHandler_ClientData;
1347
1348static FileHandler_ClientData *HeadFHCD;
1349
1350static FileHandler_ClientData *
1351NewFHCD(func, file, id)
1352 PyObject *func;
1353 PyObject *file;
1354 int id;
1355{
1356 FileHandler_ClientData *p;
1357 p = PyMem_NEW(FileHandler_ClientData, 1);
1358 if (p != NULL) {
1359 Py_XINCREF(func);
1360 Py_XINCREF(file);
1361 p->tstate = PyThreadState_Get();
1362 p->func = func;
1363 p->file = file;
1364 p->id = id;
1365 p->next = HeadFHCD;
1366 HeadFHCD = p;
1367 }
1368 return p;
1369}
1370
1371static void
1372DeleteFHCD(id)
1373 int id;
1374{
1375 FileHandler_ClientData *p, **pp;
1376
1377 pp = &HeadFHCD;
1378 while ((p = *pp) != NULL) {
1379 if (p->id == id) {
1380 *pp = p->next;
1381 Py_XDECREF(p->func);
1382 Py_XDECREF(p->file);
1383 PyMem_DEL(p);
1384 }
1385 else
1386 pp = &p->next;
1387 }
1388}
1389
Guido van Rossuma597dde1995-01-10 20:56:29 +00001390static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001391FileHandler(clientData, mask)
Guido van Rossum00d93061998-05-28 23:06:38 +00001392 ClientData clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001393 int mask;
Guido van Rossum18468821994-06-20 07:49:28 +00001394{
Guido van Rossum00d93061998-05-28 23:06:38 +00001395 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001396 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00001397
Guido van Rossum00d93061998-05-28 23:06:38 +00001398 /* XXX Should create fresh thread state? */
1399 ENTER_PYTHON(data->tstate)
1400 func = data->func;
1401 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00001402
Barry Warsawfa701a81997-01-16 00:15:11 +00001403 arg = Py_BuildValue("(Oi)", file, (long) mask);
1404 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00001405 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00001406
1407 if (res == NULL) {
1408 errorInCmd = 1;
1409 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1410 }
1411 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001412 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001413}
1414
1415static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001416GetFileNo(file)
Barry Warsawfa701a81997-01-16 00:15:11 +00001417 /* Either an int >= 0 or an object with a
1418 *.fileno() method that returns an int >= 0
1419 */
1420 PyObject *file;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001421{
Guido van Rossuma597dde1995-01-10 20:56:29 +00001422 PyObject *meth, *args, *res;
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001423 int id;
1424 if (PyInt_Check(file)) {
1425 id = PyInt_AsLong(file);
1426 if (id < 0)
1427 PyErr_SetString(PyExc_ValueError, "invalid file id");
1428 return id;
1429 }
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001430 args = PyTuple_New(0);
1431 if (args == NULL)
1432 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001433
1434 meth = PyObject_GetAttrString(file, "fileno");
1435 if (meth == NULL) {
1436 Py_DECREF(args);
1437 return -1;
1438 }
1439
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001440 res = PyEval_CallObject(meth, args);
1441 Py_DECREF(args);
1442 Py_DECREF(meth);
1443 if (res == NULL)
1444 return -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001445
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001446 if (PyInt_Check(res))
1447 id = PyInt_AsLong(res);
1448 else
1449 id = -1;
Barry Warsawfa701a81997-01-16 00:15:11 +00001450
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001451 if (id < 0)
1452 PyErr_SetString(PyExc_ValueError,
1453 "invalid fileno() return value");
1454 Py_DECREF(res);
1455 return id;
Guido van Rossum18468821994-06-20 07:49:28 +00001456}
1457
1458static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001459Tkapp_CreateFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001460 PyObject *self;
1461 PyObject *args; /* Is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00001462{
Guido van Rossum00d93061998-05-28 23:06:38 +00001463 FileHandler_ClientData *data;
1464 PyObject *file, *func;
Barry Warsawfa701a81997-01-16 00:15:11 +00001465 int mask, id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001466 FHANDLE tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00001467
Guido van Rossum35d43371997-08-02 00:09:09 +00001468 if (!PyArg_ParseTuple(args, "OiO", &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001469 return NULL;
1470 id = GetFileNo(file);
1471 if (id < 0)
1472 return NULL;
1473 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001474 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001475 return NULL;
1476 }
1477
Guido van Rossum00d93061998-05-28 23:06:38 +00001478 data = NewFHCD(func, file, id);
1479 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001480 return NULL;
1481
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_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
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}
1490
1491static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001492Tkapp_DeleteFileHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001493 PyObject *self;
1494 PyObject *args; /* Args: file */
Guido van Rossum18468821994-06-20 07:49:28 +00001495{
Barry Warsawfa701a81997-01-16 00:15:11 +00001496 PyObject *file;
Guido van Rossum00d93061998-05-28 23:06:38 +00001497 FileHandler_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001498 int id;
Guido van Rossum7bf15641998-05-22 18:28:17 +00001499 FHANDLE tfile;
Guido van Rossum68784361996-05-16 17:17:31 +00001500
Guido van Rossum35d43371997-08-02 00:09:09 +00001501 if (!PyArg_ParseTuple(args, "O", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00001502 return NULL;
1503 id = GetFileNo(file);
1504 if (id < 0)
1505 return NULL;
1506
Guido van Rossum00d93061998-05-28 23:06:38 +00001507 DeleteFHCD(id);
Guido van Rossum18468821994-06-20 07:49:28 +00001508
Guido van Rossum7bf15641998-05-22 18:28:17 +00001509 tfile = MAKEFHANDLE(id);
Barry Warsawfa701a81997-01-16 00:15:11 +00001510 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001511 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001512 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001513 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001514 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001515 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001516}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001517#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00001518
Barry Warsawfa701a81997-01-16 00:15:11 +00001519
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001520/**** Tktt Object (timer token) ****/
1521
1522staticforward PyTypeObject Tktt_Type;
1523
Guido van Rossum00d93061998-05-28 23:06:38 +00001524typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00001525 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00001526 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00001527 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001528 PyThreadState *tstate;
1529} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001530
1531static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001532Tktt_DeleteTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001533 PyObject *self;
1534 PyObject *args;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001535{
Barry Warsawfa701a81997-01-16 00:15:11 +00001536 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001537 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001538
Guido van Rossum35d43371997-08-02 00:09:09 +00001539 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001540 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001541 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001542 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00001543 v->token = NULL;
1544 }
1545 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001546 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001547 Py_DECREF(func);
1548 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00001549 }
1550 Py_INCREF(Py_None);
1551 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001552}
1553
1554static PyMethodDef Tktt_methods[] =
1555{
Guido van Rossum35d43371997-08-02 00:09:09 +00001556 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001557 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001558};
1559
1560static TkttObject *
Guido van Rossum00d93061998-05-28 23:06:38 +00001561Tktt_New(func)
Barry Warsawfa701a81997-01-16 00:15:11 +00001562 PyObject *func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001563{
Barry Warsawfa701a81997-01-16 00:15:11 +00001564 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001565
Barry Warsawfa701a81997-01-16 00:15:11 +00001566 v = PyObject_NEW(TkttObject, &Tktt_Type);
1567 if (v == NULL)
1568 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001569
Guido van Rossum00d93061998-05-28 23:06:38 +00001570 Py_INCREF(func);
1571 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001572 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001573 v->tstate = PyThreadState_Get();
1574
1575 /* Extra reference, deleted when called or when handler is deleted */
1576 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001577 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001578}
1579
1580static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001581Tktt_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001582 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001583{
Guido van Rossum00d93061998-05-28 23:06:38 +00001584 TkttObject *v = (TkttObject *)self;
1585 PyObject *func = v->func;
1586
1587 Py_XDECREF(func);
1588
Guido van Rossum35d43371997-08-02 00:09:09 +00001589 PyMem_DEL(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001590}
1591
Guido van Rossum597ac201998-05-12 14:36:19 +00001592static PyObject *
1593Tktt_Repr(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001594 PyObject *self;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001595{
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00001597 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001598
Guido van Rossum597ac201998-05-12 14:36:19 +00001599 sprintf(buf, "<tktimertoken at 0x%lx%s>", (long)v,
Barry Warsawfa701a81997-01-16 00:15:11 +00001600 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00001601 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001602}
1603
1604static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001605Tktt_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001606 PyObject *self;
1607 char *name;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001608{
Barry Warsawfa701a81997-01-16 00:15:11 +00001609 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001610}
1611
1612static PyTypeObject Tktt_Type =
1613{
Guido van Rossum35d43371997-08-02 00:09:09 +00001614 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001615 0, /*ob_size */
1616 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001617 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 0, /*tp_itemsize */
1619 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00001620 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00001621 Tktt_GetAttr, /*tp_getattr */
1622 0, /*tp_setattr */
1623 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00001624 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00001625 0, /*tp_as_number */
1626 0, /*tp_as_sequence */
1627 0, /*tp_as_mapping */
1628 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001629};
1630
Barry Warsawfa701a81997-01-16 00:15:11 +00001631
1632
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001633/** Timer Handler **/
1634
1635static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001636TimerHandler(clientData)
Barry Warsawfa701a81997-01-16 00:15:11 +00001637 ClientData clientData;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001638{
Guido van Rossum00d93061998-05-28 23:06:38 +00001639 TkttObject *v = (TkttObject *)clientData;
1640 PyObject *func = v->func;
1641 PyObject *res;
1642
1643 if (func == NULL)
1644 return;
1645
1646 v->func = NULL;
1647
1648 ENTER_PYTHON(v->tstate)
1649
1650 res = PyEval_CallObject(func, NULL);
1651 Py_DECREF(func);
1652 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001653
Barry Warsawfa701a81997-01-16 00:15:11 +00001654 if (res == NULL) {
1655 errorInCmd = 1;
1656 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1657 }
1658 else
1659 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001660
1661 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001662}
1663
1664static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001665Tkapp_CreateTimerHandler(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001666 PyObject *self;
1667 PyObject *args; /* Is (milliseconds, func) */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001668{
Barry Warsawfa701a81997-01-16 00:15:11 +00001669 int milliseconds;
1670 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001671 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001672
Guido van Rossum35d43371997-08-02 00:09:09 +00001673 if (!PyArg_ParseTuple(args, "iO", &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001674 return NULL;
1675 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001676 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001677 return NULL;
1678 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001679 v = Tktt_New(func);
1680 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1681 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001682
Guido van Rossum00d93061998-05-28 23:06:38 +00001683 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001684}
1685
Barry Warsawfa701a81997-01-16 00:15:11 +00001686
Guido van Rossum18468821994-06-20 07:49:28 +00001687/** Event Loop **/
1688
Guido van Rossum18468821994-06-20 07:49:28 +00001689static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001690Tkapp_MainLoop(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001691 PyObject *self;
1692 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001693{
Barry Warsawfa701a81997-01-16 00:15:11 +00001694 int threshold = 0;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001695
Barry Warsawfa701a81997-01-16 00:15:11 +00001696 if (!PyArg_ParseTuple(args, "|i", &threshold))
1697 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001698
Barry Warsawfa701a81997-01-16 00:15:11 +00001699 quitMainLoop = 0;
1700 while (Tk_GetNumMainWindows() > threshold &&
1701 !quitMainLoop &&
1702 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001703 {
Guido van Rossum35d43371997-08-02 00:09:09 +00001704 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00001705
1706#ifdef WITH_THREAD
Guido van Rossum62320c91998-06-15 04:36:09 +00001707 Py_BEGIN_ALLOW_THREADS
1708 acquire_lock(tcl_lock, 1);
Guido van Rossum35d43371997-08-02 00:09:09 +00001709 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossum00d93061998-05-28 23:06:38 +00001710 release_lock(tcl_lock);
1711 if (result == 0)
1712 Sleep(20);
Guido van Rossum35d43371997-08-02 00:09:09 +00001713 Py_END_ALLOW_THREADS
Guido van Rossum5b020781997-08-19 01:00:50 +00001714#else
1715 result = Tcl_DoOneEvent(0);
1716#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001717
Guido van Rossum35d43371997-08-02 00:09:09 +00001718 if (PyErr_CheckSignals() != 0)
1719 return NULL;
1720 if (result < 0)
1721 break;
Guido van Rossum18468821994-06-20 07:49:28 +00001722 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001723 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001724
Barry Warsawfa701a81997-01-16 00:15:11 +00001725 if (errorInCmd) {
1726 errorInCmd = 0;
1727 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1728 excInCmd = valInCmd = trbInCmd = NULL;
1729 return NULL;
1730 }
1731 Py_INCREF(Py_None);
1732 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
1735static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001736Tkapp_DoOneEvent(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001737 PyObject *self;
1738 PyObject *args;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001739{
Guido van Rossum35d43371997-08-02 00:09:09 +00001740 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00001741 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001742
Barry Warsawfa701a81997-01-16 00:15:11 +00001743 if (!PyArg_ParseTuple(args, "|i", &flags))
1744 return NULL;
1745
Guido van Rossum00d93061998-05-28 23:06:38 +00001746 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001747 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00001748 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001749 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001750}
1751
1752static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001753Tkapp_Quit(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001754 PyObject *self;
1755 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001756{
1757
Guido van Rossum35d43371997-08-02 00:09:09 +00001758 if (!PyArg_ParseTuple(args, ""))
Barry Warsawfa701a81997-01-16 00:15:11 +00001759 return NULL;
1760
1761 quitMainLoop = 1;
1762 Py_INCREF(Py_None);
1763 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001766static PyObject *
1767Tkapp_InterpAddr(self, args)
1768 PyObject *self;
1769 PyObject *args;
1770{
1771
1772 if (!PyArg_ParseTuple(args, ""))
1773 return NULL;
1774
1775 return PyInt_FromLong((long)Tkapp_Interp(self));
1776}
1777
Barry Warsawfa701a81997-01-16 00:15:11 +00001778
1779
Guido van Rossum18468821994-06-20 07:49:28 +00001780/**** Tkapp Method List ****/
1781
1782static PyMethodDef Tkapp_methods[] =
1783{
Guido van Rossum35d43371997-08-02 00:09:09 +00001784 {"call", Tkapp_Call, 0},
1785 {"globalcall", Tkapp_GlobalCall, 0},
1786 {"eval", Tkapp_Eval, 1},
1787 {"globaleval", Tkapp_GlobalEval, 1},
1788 {"evalfile", Tkapp_EvalFile, 1},
1789 {"record", Tkapp_Record, 1},
1790 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1791 {"setvar", Tkapp_SetVar, 1},
1792 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1793 {"getvar", Tkapp_GetVar, 1},
1794 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1795 {"unsetvar", Tkapp_UnsetVar, 1},
1796 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1797 {"getint", Tkapp_GetInt, 1},
1798 {"getdouble", Tkapp_GetDouble, 1},
1799 {"getboolean", Tkapp_GetBoolean, 1},
1800 {"exprstring", Tkapp_ExprString, 1},
1801 {"exprlong", Tkapp_ExprLong, 1},
1802 {"exprdouble", Tkapp_ExprDouble, 1},
1803 {"exprboolean", Tkapp_ExprBoolean, 1},
1804 {"splitlist", Tkapp_SplitList, 1},
1805 {"split", Tkapp_Split, 1},
1806 {"merge", Tkapp_Merge, 0},
1807 {"createcommand", Tkapp_CreateCommand, 1},
1808 {"deletecommand", Tkapp_DeleteCommand, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001809#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001810 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1811 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001812#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001813 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001814 {"mainloop", Tkapp_MainLoop, 1},
1815 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001816 {"quit", Tkapp_Quit, 1},
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001817 {"interpaddr", Tkapp_InterpAddr, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001818 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001819};
1820
Barry Warsawfa701a81997-01-16 00:15:11 +00001821
1822
Guido van Rossum18468821994-06-20 07:49:28 +00001823/**** Tkapp Type Methods ****/
1824
1825static void
Guido van Rossum35d43371997-08-02 00:09:09 +00001826Tkapp_Dealloc(self)
Barry Warsawfa701a81997-01-16 00:15:11 +00001827 PyObject *self;
Guido van Rossum18468821994-06-20 07:49:28 +00001828{
Guido van Rossum00d93061998-05-28 23:06:38 +00001829 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001830 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00001831 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001832 PyMem_DEL(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001833 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
1836static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001837Tkapp_GetAttr(self, name)
Barry Warsawfa701a81997-01-16 00:15:11 +00001838 PyObject *self;
1839 char *name;
Guido van Rossum18468821994-06-20 07:49:28 +00001840{
Guido van Rossum35d43371997-08-02 00:09:09 +00001841 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00001842}
1843
1844static PyTypeObject Tkapp_Type =
1845{
Guido van Rossum35d43371997-08-02 00:09:09 +00001846 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001847 0, /*ob_size */
1848 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001849 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001850 0, /*tp_itemsize */
1851 Tkapp_Dealloc, /*tp_dealloc */
1852 0, /*tp_print */
1853 Tkapp_GetAttr, /*tp_getattr */
1854 0, /*tp_setattr */
1855 0, /*tp_compare */
1856 0, /*tp_repr */
1857 0, /*tp_as_number */
1858 0, /*tp_as_sequence */
1859 0, /*tp_as_mapping */
1860 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00001861};
1862
Barry Warsawfa701a81997-01-16 00:15:11 +00001863
1864
Guido van Rossum18468821994-06-20 07:49:28 +00001865/**** Tkinter Module ****/
1866
1867static PyObject *
Guido van Rossum35d43371997-08-02 00:09:09 +00001868Tkinter_Create(self, args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001869 PyObject *self;
1870 PyObject *args;
Guido van Rossum18468821994-06-20 07:49:28 +00001871{
Barry Warsawfa701a81997-01-16 00:15:11 +00001872 char *screenName = NULL;
1873 char *baseName = NULL;
1874 char *className = NULL;
1875 int interactive = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001876
Guido van Rossum35d43371997-08-02 00:09:09 +00001877 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 if (baseName != NULL)
1879 baseName++;
1880 else
1881 baseName = Py_GetProgramName();
1882 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00001883
Barry Warsawfa701a81997-01-16 00:15:11 +00001884 if (!PyArg_ParseTuple(args, "|zssi",
1885 &screenName, &baseName, &className,
1886 &interactive))
1887 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001888
Barry Warsawfa701a81997-01-16 00:15:11 +00001889 return (PyObject *) Tkapp_New(screenName, baseName, className,
1890 interactive);
Guido van Rossum18468821994-06-20 07:49:28 +00001891}
1892
1893static PyMethodDef moduleMethods[] =
1894{
Barry Warsawfa701a81997-01-16 00:15:11 +00001895 {"create", Tkinter_Create, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001896#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001897 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1898 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001899#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001900 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001901 {"mainloop", Tkapp_MainLoop, 1},
1902 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001903 {"quit", Tkapp_Quit, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001904 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001905};
1906
Guido van Rossum7bf15641998-05-22 18:28:17 +00001907#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001908
1909static int stdin_ready = 0;
1910
Guido van Rossumad4db171998-06-13 13:56:28 +00001911#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00001912static void
1913MyFileProc(clientData, mask)
1914 void *clientData;
1915 int mask;
1916{
1917 stdin_ready = 1;
1918}
Guido van Rossumad4db171998-06-13 13:56:28 +00001919#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001920
Guido van Rossum00d93061998-05-28 23:06:38 +00001921static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00001922
Guido van Rossum18468821994-06-20 07:49:28 +00001923static int
Guido van Rossum35d43371997-08-02 00:09:09 +00001924EventHook()
Guido van Rossum18468821994-06-20 07:49:28 +00001925{
Guido van Rossumad4db171998-06-13 13:56:28 +00001926#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001927 FHANDLE tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00001928#endif
1929 if (PyThreadState_Swap(NULL) != NULL)
1930 Py_FatalError("EventHook with non-NULL tstate\n");
1931 PyEval_RestoreThread(event_tstate);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001932 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00001933 errorInCmd = 0;
1934#ifndef MS_WINDOWS
1935 tfile = MAKEFHANDLE(fileno(stdin));
Guido van Rossum7bf15641998-05-22 18:28:17 +00001936 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00001937#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001938 while (!errorInCmd && !stdin_ready) {
1939 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00001940#ifdef MS_WINDOWS
1941 if (_kbhit()) {
1942 stdin_ready = 1;
1943 break;
1944 }
1945#endif
1946#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00001947 Py_BEGIN_ALLOW_THREADS
1948 acquire_lock(tcl_lock, 1);
Guido van Rossum00d93061998-05-28 23:06:38 +00001949 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
1950 release_lock(tcl_lock);
1951 if (result == 0)
1952 Sleep(20);
1953 Py_END_ALLOW_THREADS
1954#else
1955 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001956#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001957
1958 if (result < 0)
1959 break;
1960 }
Guido van Rossumad4db171998-06-13 13:56:28 +00001961#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001962 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00001963#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00001964 if (errorInCmd) {
1965 errorInCmd = 0;
1966 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1967 excInCmd = valInCmd = trbInCmd = NULL;
1968 PyErr_Print();
1969 }
Guido van Rossumad4db171998-06-13 13:56:28 +00001970 PyEval_SaveThread();
Barry Warsawfa701a81997-01-16 00:15:11 +00001971 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001972}
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Guido van Rossum00d93061998-05-28 23:06:38 +00001974#endif
1975
Guido van Rossum7bf15641998-05-22 18:28:17 +00001976static void
1977EnableEventHook()
1978{
Guido van Rossum00d93061998-05-28 23:06:38 +00001979#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001980 if (PyOS_InputHook == NULL) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001981 event_tstate = PyThreadState_Get();
Guido van Rossum7bf15641998-05-22 18:28:17 +00001982 PyOS_InputHook = EventHook;
1983 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001984#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001985}
1986
1987static void
1988DisableEventHook()
1989{
Guido van Rossum00d93061998-05-28 23:06:38 +00001990#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001991 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
1992 PyOS_InputHook = NULL;
1993 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001994#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001995}
1996
Barry Warsawfa701a81997-01-16 00:15:11 +00001997
1998/* all errors will be checked in one fell swoop in init_tkinter() */
1999static void
2000ins_long(d, name, val)
2001 PyObject *d;
2002 char *name;
2003 long val;
2004{
2005 PyObject *v = PyInt_FromLong(val);
2006 if (v) {
2007 PyDict_SetItemString(d, name, v);
2008 Py_DECREF(v);
2009 }
2010}
2011static void
2012ins_string(d, name, val)
2013 PyObject *d;
2014 char *name;
2015 char *val;
2016{
2017 PyObject *v = PyString_FromString(val);
2018 if (v) {
2019 PyDict_SetItemString(d, name, v);
2020 Py_DECREF(v);
2021 }
2022}
2023
2024
Guido van Rossum18468821994-06-20 07:49:28 +00002025void
Guido van Rossum35d43371997-08-02 00:09:09 +00002026init_tkinter()
Guido van Rossum18468821994-06-20 07:49:28 +00002027{
Barry Warsawfa701a81997-01-16 00:15:11 +00002028 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002029
Barry Warsawfa701a81997-01-16 00:15:11 +00002030 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002031
2032#ifdef WITH_THREAD
2033 tcl_lock = allocate_lock();
2034#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002035
Barry Warsawfa701a81997-01-16 00:15:11 +00002036 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002037
Barry Warsawfa701a81997-01-16 00:15:11 +00002038 d = PyModule_GetDict(m);
2039 Tkinter_TclError = Py_BuildValue("s", "TclError");
2040 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002041
Guido van Rossum35d43371997-08-02 00:09:09 +00002042 ins_long(d, "READABLE", TCL_READABLE);
2043 ins_long(d, "WRITABLE", TCL_WRITABLE);
2044 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2045 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2046 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2047 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2048 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2049 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2050 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002051 ins_string(d, "TK_VERSION", TK_VERSION);
2052 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002053
Guido van Rossum83551bf1997-09-13 00:44:23 +00002054 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002055
2056 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002057 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2058
Barry Warsawfa701a81997-01-16 00:15:11 +00002059 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002060 return;
2061
Guido van Rossum26216371998-04-20 18:47:52 +00002062#if TKMAJORMINOR >= 8000
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002063 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002064#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002065
Jack Jansen34cc5c31995-10-31 16:15:12 +00002066#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002067 /*
2068 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2069 ** Most of the initializations in that routine (toolbox init calls and
2070 ** such) have already been done for us, so we only need these.
2071 */
2072#if TKMAJORMINOR >= 8000
2073 tcl_macQdPtr = &qd;
2074#endif
2075
2076 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002077#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002078 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002079#endif /* GENERATINGCFM */
2080#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002081}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002082
Guido van Rossumec22c921996-02-25 04:50:29 +00002083
Barry Warsawfa701a81997-01-16 00:15:11 +00002084
Guido van Rossum9722ad81995-09-22 23:49:28 +00002085#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002086
2087/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002088** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002089*/
2090
Guido van Rossum9722ad81995-09-22 23:49:28 +00002091void
2092panic(char * format, ...)
2093{
Barry Warsawfa701a81997-01-16 00:15:11 +00002094 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002095
Barry Warsawfa701a81997-01-16 00:15:11 +00002096 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002097
Guido van Rossumb41addf1998-05-12 15:02:41 +00002098 vPySys_WriteStderr(format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002099 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002100
Barry Warsawfa701a81997-01-16 00:15:11 +00002101 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002102
Barry Warsawfa701a81997-01-16 00:15:11 +00002103 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002104}
Jack Jansen40b546d1995-11-14 10:34:45 +00002105
Guido van Rossumec22c921996-02-25 04:50:29 +00002106/*
2107** Pass events to SIOUX before passing them to Tk.
2108*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002109
Guido van Rossumec22c921996-02-25 04:50:29 +00002110static int
2111PyMacConvertEvent(eventPtr)
Barry Warsawfa701a81997-01-16 00:15:11 +00002112 EventRecord *eventPtr;
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002113{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002114 WindowPtr frontwin;
2115 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002116 ** Sioux eats too many events, so we don't pass it everything. We
2117 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002118 ** the Sioux window is frontmost. This means that Tk menus don't work
2119 ** in that case, but at least we can scroll the sioux window.
2120 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2121 ** part of the external interface of Sioux...
2122 */
2123 frontwin = FrontWindow();
2124 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2125 if (SIOUXHandleOneEvent(eventPtr))
2126 return 0; /* Nothing happened to the Tcl event queue */
2127 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002128 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002129}
2130
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002131#if defined(USE_GUSI) && TKMAJORMINOR < 8000
Guido van Rossum290283b1997-06-02 22:16:43 +00002132/*
2133 * For Python we have to override this routine (from TclMacNotify),
2134 * since we use GUSI for our sockets, not Tcl streams. Hence, we have
2135 * to use GUSI select to see whether our socket is ready. Note that
2136 * createfilehandler (above) sets the type to TCL_UNIX_FD for our
2137 * files and sockets.
2138 *
2139 * NOTE: this code was lifted from Tcl 7.6, it may need to be modified
2140 * for other versions. */
2141
2142int
2143Tcl_FileReady(file, mask)
2144 Tcl_File file; /* File handle for a stream. */
2145 int mask; /* OR'ed combination of TCL_READABLE,
2146 * TCL_WRITABLE, and TCL_EXCEPTION:
2147 * indicates conditions caller cares about. */
2148{
2149 int type;
2150 int fd;
2151
2152 fd = (int) Tcl_GetFileInfo(file, &type);
2153
2154 if (type == TCL_MAC_SOCKET) {
2155 return TclMacSocketReady(file, mask);
2156 } else if (type == TCL_MAC_FILE) {
2157 /*
2158 * Under the Macintosh, files are always ready, so we just
2159 * return the mask that was passed in.
2160 */
2161
2162 return mask;
2163 } else if (type == TCL_UNIX_FD) {
2164 fd_set readset, writeset, excset;
2165 struct timeval tv;
2166
2167 FD_ZERO(&readset);
2168 FD_ZERO(&writeset);
2169 FD_ZERO(&excset);
2170
2171 if ( mask & TCL_READABLE ) FD_SET(fd, &readset);
2172 if ( mask & TCL_WRITABLE ) FD_SET(fd, &writeset);
2173 if ( mask & TCL_EXCEPTION ) FD_SET(fd, &excset);
2174
2175 tv.tv_sec = tv.tv_usec = 0;
2176 if ( select(fd+1, &readset, &writeset, &excset, &tv) <= 0 )
2177 return 0;
2178
2179 mask = 0;
2180 if ( FD_ISSET(fd, &readset) ) mask |= TCL_READABLE;
2181 if ( FD_ISSET(fd, &writeset) ) mask |= TCL_WRITABLE;
2182 if ( FD_ISSET(fd, &excset) ) mask |= TCL_EXCEPTION;
2183
2184 return mask;
2185 }
2186
2187 return 0;
2188}
2189#endif /* USE_GUSI */
2190
Guido van Rossumec22c921996-02-25 04:50:29 +00002191#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002192
2193/*
2194** Additional Mac specific code for dealing with shared libraries.
2195*/
2196
2197#include <Resources.h>
2198#include <CodeFragments.h>
2199
2200static int loaded_from_shlib = 0;
2201static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002202
Jack Jansen34cc5c31995-10-31 16:15:12 +00002203/*
2204** If this module is dynamically loaded the following routine should
2205** be the init routine. It takes care of adding the shared library to
2206** the resource-file chain, so that the tk routines can find their
2207** resources.
2208*/
2209OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002210init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002211{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002212 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002213 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002214 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002215 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2216 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002217 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002218 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2219 loaded_from_shlib = 1;
2220 }
2221 return noErr;
2222}
2223
2224/*
2225** Insert the library resources into the search path. Put them after
2226** the resources from the application. Again, we ignore errors.
2227*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002228static
Jack Jansen34cc5c31995-10-31 16:15:12 +00002229mac_addlibresources()
2230{
2231 if ( !loaded_from_shlib )
2232 return;
2233 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2234}
2235
Guido van Rossumec22c921996-02-25 04:50:29 +00002236#endif /* GENERATINGCFM */
2237#endif /* macintosh */