blob: 34360fe077698e4b6a8c2bcc97595c0ce37f5122 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Guido van Rossuma80649b2000-03-28 20:07:05 +000012 Only Tcl/Tk 8.0 and later are supported. Older versions are not
13 supported. (Use Python 1.5.2 if you cannot upgrade your Tcl/Tk
14 libraries.)
15*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
19 - In Tcl_Call(), create Tcl objects from the arguments, possibly using
20 intelligent mappings between Python objects and Tcl objects (e.g. ints,
21 floats and Tcl window pointers could be handled specially).
22
23 - Register a new Tcl type, "Python callable", which can be called more
24 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
25
Guido van Rossum7ffa7611996-08-13 21:10:16 +000026*/
27
Guido van Rossum35d43371997-08-02 00:09:09 +000028
Guido van Rossum9722ad81995-09-22 23:49:28 +000029#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000030#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000031
Guido van Rossum00d93061998-05-28 23:06:38 +000032#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000033#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000034#endif
35
Guido van Rossum2a5119b1998-05-29 01:28:40 +000036#ifdef MS_WINDOWS
37#include <windows.h>
38#endif
39
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000040#ifdef macintosh
41#define MAC_TCL
Guido van Rossum49b56061998-10-01 20:42:43 +000042#endif
43
Guido van Rossum18468821994-06-20 07:49:28 +000044#include <tcl.h>
45#include <tk.h>
46
Guido van Rossum3e819a71997-08-01 19:29:02 +000047#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
48
Guido van Rossuma80649b2000-03-28 20:07:05 +000049#if TKMAJORMINOR < 8000
50#error "Tk older than 8.0 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000051#endif
52
Guido van Rossuma80649b2000-03-28 20:07:05 +000053#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000054/* Sigh, we have to include this to get at the tcl qd pointer */
55#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000056/* And this one we need to clear the menu bar */
57#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000058#endif
59
Guido van Rossuma80649b2000-03-28 20:07:05 +000060#if !defined(MS_WINDOWS)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000061#define HAVE_CREATEFILEHANDLER
62#endif
63
Guido van Rossum00d93061998-05-28 23:06:38 +000064#ifdef HAVE_CREATEFILEHANDLER
65
66/* Tcl_CreateFileHandler() changed several times; these macros deal with the
67 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
68 Unix, only because Jack added it back); when available on Windows, it only
69 applies to sockets. */
70
Guido van Rossum7bf15641998-05-22 18:28:17 +000071#ifdef MS_WINDOWS
72#define FHANDLETYPE TCL_WIN_SOCKET
73#else
74#define FHANDLETYPE TCL_UNIX_FD
75#endif
76
Guido van Rossum00d93061998-05-28 23:06:38 +000077/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
78 which uses this to handle Tcl events while the user is typing commands. */
79
80#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000081#define WAIT_FOR_STDIN
82#endif
83
Guido van Rossum00d93061998-05-28 23:06:38 +000084#endif /* HAVE_CREATEFILEHANDLER */
85
Guido van Rossumad4db171998-06-13 13:56:28 +000086#ifdef MS_WINDOWS
87#include <conio.h>
88#define WAIT_FOR_STDIN
89#endif
90
Guido van Rossum00d93061998-05-28 23:06:38 +000091#ifdef WITH_THREAD
92
93/* The threading situation is complicated. Tcl is not thread-safe, except for
94 Tcl 8.1, which will probably remain in alpha status for another 6 months
95 (and the README says that Tk will probably remain thread-unsafe forever).
96 So we need to use a lock around all uses of Tcl. Previously, the Python
97 interpreter lock was used for this. However, this causes problems when
98 other Python threads need to run while Tcl is blocked waiting for events.
99
100 To solve this problem, a separate lock for Tcl is introduced. Holding it
101 is incompatible with holding Python's interpreter lock. The following four
102 macros manipulate both locks together.
103
104 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
105 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
106 that could call an event handler, or otherwise affect the state of a Tcl
107 interpreter. These assume that the surrounding code has the Python
108 interpreter lock; inside the brackets, the Python interpreter lock has been
109 released and the lock for Tcl has been acquired.
110
Guido van Rossum5e977831998-06-15 14:03:52 +0000111 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
112 (For example, when transferring data from the Tcl interpreter result to a
113 Python string object.) This can be done by using different macros to close
114 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
115 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
116 releases the Tcl lock.
117
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000118 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000119 handlers when the handler needs to use Python. Such event handlers are
120 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000121 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000122 the Python interpreter lock, restoring the appropriate thread state, and
123 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
124 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000125 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000126
127 These locks expand to several statements and brackets; they should not be
128 used in branches of if statements and the like.
129
130*/
131
Guido van Rossum65d5b571998-12-21 19:32:43 +0000132static PyThread_type_lock tcl_lock = 0;
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000133static PyThreadState *tcl_tstate = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000134
135#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000136 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000137 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000138
139#define LEAVE_TCL \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000140 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000141
Guido van Rossum62320c91998-06-15 04:36:09 +0000142#define ENTER_OVERLAP \
143 Py_END_ALLOW_THREADS
144
145#define LEAVE_OVERLAP_TCL \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000146 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000147
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000148#define ENTER_PYTHON \
149 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000150 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000151
152#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000153 { PyThreadState *tstate = PyEval_SaveThread(); \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000154 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Guido van Rossum00d93061998-05-28 23:06:38 +0000155
156#else
157
158#define ENTER_TCL
159#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000160#define ENTER_OVERLAP
161#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000163#define LEAVE_PYTHON
164
165#endif
166
Guido van Rossumec22c921996-02-25 04:50:29 +0000167#ifdef macintosh
168
169/*
170** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000171** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000172*/
173
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000174/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000175#define FREECAST (char *)
176
Guido van Rossumec22c921996-02-25 04:50:29 +0000177#include <Events.h> /* For EventRecord */
178
Fred Drake509d79a2000-07-08 04:04:38 +0000179typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
180void Tcl_MacSetEventProc (TclMacConvertEventPtr procPtr);
181int TkMacConvertEvent (EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000182
Fred Drake509d79a2000-07-08 04:04:38 +0000183staticforward int PyMacConvertEvent (EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000184
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000185#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
186 #pragma import on
187#endif
188
189#include <SIOUX.h>
190extern int SIOUXIsAppWindow(WindowPtr);
191
192#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
193 #pragma import reset
194#endif
Guido van Rossumec22c921996-02-25 04:50:29 +0000195#endif /* macintosh */
196
Guido van Rossum97867b21996-08-08 19:09:53 +0000197#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000198#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000199#endif
200
Guido van Rossum18468821994-06-20 07:49:28 +0000201/**** Tkapp Object Declaration ****/
202
203staticforward PyTypeObject Tkapp_Type;
204
Guido van Rossum00d93061998-05-28 23:06:38 +0000205typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000206 PyObject_HEAD
207 Tcl_Interp *interp;
Guido van Rossum00d93061998-05-28 23:06:38 +0000208} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000209
210#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000211#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
212#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
213
Guido van Rossum35d43371997-08-02 00:09:09 +0000214#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000215(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000216
Barry Warsawfa701a81997-01-16 00:15:11 +0000217
218
Guido van Rossum18468821994-06-20 07:49:28 +0000219/**** Error Handling ****/
220
221static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000222static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000223static int errorInCmd = 0;
224static PyObject *excInCmd;
225static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000226static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000227
Barry Warsawfa701a81997-01-16 00:15:11 +0000228
229
Guido van Rossum18468821994-06-20 07:49:28 +0000230static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000231Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000232{
Barry Warsawfa701a81997-01-16 00:15:11 +0000233 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
234 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000235}
236
Barry Warsawfa701a81997-01-16 00:15:11 +0000237
Barry Warsawfa701a81997-01-16 00:15:11 +0000238
Guido van Rossum18468821994-06-20 07:49:28 +0000239/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000240
241#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000242#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000243
Guido van Rossum00d93061998-05-28 23:06:38 +0000244/* Millisecond sleep() for Unix platforms. */
245
246static void
Fred Drake509d79a2000-07-08 04:04:38 +0000247Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000248{
249 /* XXX Too bad if you don't have select(). */
250 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000251 t.tv_sec = milli/1000;
252 t.tv_usec = (milli%1000) * 1000;
253 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
254}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000255#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000256#endif /* WITH_THREAD */
257
258
Guido van Rossum18468821994-06-20 07:49:28 +0000259static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000260AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000261{
Guido van Rossum35d43371997-08-02 00:09:09 +0000262 if (PyString_Check(value))
263 return PyString_AsString(value);
Barry Warsawfa701a81997-01-16 00:15:11 +0000264 else {
265 PyObject *v = PyObject_Str(value);
266 PyList_Append(tmp, v);
267 Py_DECREF(v);
268 return PyString_AsString(v);
269 }
Guido van Rossum18468821994-06-20 07:49:28 +0000270}
271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
273
Guido van Rossum18468821994-06-20 07:49:28 +0000274#define ARGSZ 64
275
276static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000277Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000278{
Barry Warsawfa701a81997-01-16 00:15:11 +0000279 PyObject *tmp = NULL;
280 char *argvStore[ARGSZ];
281 char **argv = NULL;
282 int fvStore[ARGSZ];
283 int *fv = NULL;
284 int argc = 0, i;
285 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000286
Barry Warsawfa701a81997-01-16 00:15:11 +0000287 if (!(tmp = PyList_New(0)))
288 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000289
Barry Warsawfa701a81997-01-16 00:15:11 +0000290 argv = argvStore;
291 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000292
Barry Warsawfa701a81997-01-16 00:15:11 +0000293 if (args == NULL)
294 argc = 0;
295
296 else if (!PyTuple_Check(args)) {
297 argc = 1;
298 fv[0] = 0;
299 argv[0] = AsString(args, tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000300 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000301 else {
302 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000303
Barry Warsawfa701a81997-01-16 00:15:11 +0000304 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000305 argv = (char **)ckalloc(argc * sizeof(char *));
306 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000307 if (argv == NULL || fv == NULL) {
308 PyErr_NoMemory();
309 goto finally;
310 }
311 }
312
313 for (i = 0; i < argc; i++) {
314 PyObject *v = PyTuple_GetItem(args, i);
315 if (PyTuple_Check(v)) {
316 fv[i] = 1;
317 if (!(argv[i] = Merge(v)))
318 goto finally;
319 }
320 else if (v == Py_None) {
321 argc = i;
322 break;
323 }
324 else {
325 fv[i] = 0;
326 argv[i] = AsString(v, tmp);
327 }
328 }
Guido van Rossum18468821994-06-20 07:49:28 +0000329 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000330 res = Tcl_Merge(argc, argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000331
Barry Warsawfa701a81997-01-16 00:15:11 +0000332 finally:
333 for (i = 0; i < argc; i++)
334 if (fv[i]) {
335 ckfree(argv[i]);
336 }
337 if (argv != argvStore)
338 ckfree(FREECAST argv);
339 if (fv != fvStore)
340 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000341
Barry Warsawfa701a81997-01-16 00:15:11 +0000342 Py_DECREF(tmp);
343 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000344}
345
Barry Warsawfa701a81997-01-16 00:15:11 +0000346
347
Guido van Rossum18468821994-06-20 07:49:28 +0000348static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000349Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000350{
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 int argc;
352 char **argv;
353 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000354
Barry Warsawfa701a81997-01-16 00:15:11 +0000355 if (list == NULL) {
356 Py_INCREF(Py_None);
357 return Py_None;
358 }
Guido van Rossum18468821994-06-20 07:49:28 +0000359
Guido van Rossum00d93061998-05-28 23:06:38 +0000360 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000361 /* Not a list.
362 * Could be a quoted string containing funnies, e.g. {"}.
363 * Return the string itself.
364 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000365 return PyString_FromString(list);
366 }
Guido van Rossum18468821994-06-20 07:49:28 +0000367
Barry Warsawfa701a81997-01-16 00:15:11 +0000368 if (argc == 0)
369 v = PyString_FromString("");
370 else if (argc == 1)
371 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000372 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000373 int i;
374 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000375
Barry Warsawfa701a81997-01-16 00:15:11 +0000376 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000377 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000378 Py_DECREF(v);
379 v = NULL;
380 break;
381 }
382 PyTuple_SetItem(v, i, w);
383 }
384 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000385 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000387}
388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389
390
Guido van Rossum18468821994-06-20 07:49:28 +0000391/**** Tkapp Object ****/
392
393#ifndef WITH_APPINIT
394int
Fred Drake509d79a2000-07-08 04:04:38 +0000395Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000396{
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000398
Barry Warsawfa701a81997-01-16 00:15:11 +0000399 main = Tk_MainWindow(interp);
400 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000401 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000402 return TCL_ERROR;
403 }
404 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000405 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000406 return TCL_ERROR;
407 }
408 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000409}
410#endif /* !WITH_APPINIT */
411
Guido van Rossum18468821994-06-20 07:49:28 +0000412
Barry Warsawfa701a81997-01-16 00:15:11 +0000413
414
415/* Initialize the Tk application; see the `main' function in
416 * `tkMain.c'.
417 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000418
Thomas Wouters58d05102000-07-24 14:43:35 +0000419static void EnableEventHook(void); /* Forward */
420static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000421
Barry Warsawfa701a81997-01-16 00:15:11 +0000422static TkappObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000423Tkapp_New(char *screenName, char *baseName, char *className, int interactive)
Barry Warsawfa701a81997-01-16 00:15:11 +0000424{
425 TkappObject *v;
426 char *argv0;
427
Guido van Rossumb18618d2000-05-03 23:44:39 +0000428 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000429 if (v == NULL)
430 return NULL;
431
432 v->interp = Tcl_CreateInterp();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000433
Guido van Rossuma80649b2000-03-28 20:07:05 +0000434#if defined(macintosh)
435 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000436 ClearMenuBar();
437 TkMacInitMenus(v->interp);
438#endif
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000439 /* Delete the 'exit' command, which can screw things up */
440 Tcl_DeleteCommand(v->interp, "exit");
441
Barry Warsawfa701a81997-01-16 00:15:11 +0000442 if (screenName != NULL)
443 Tcl_SetVar2(v->interp, "env", "DISPLAY",
444 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000445
Barry Warsawfa701a81997-01-16 00:15:11 +0000446 if (interactive)
447 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
448 else
449 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000450
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 /* This is used to get the application class for Tk 4.1 and up */
452 argv0 = (char*)ckalloc(strlen(className) + 1);
453 if (!argv0) {
454 PyErr_NoMemory();
455 Py_DECREF(v);
456 return NULL;
457 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000458
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000460 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000461 argv0[0] = tolower(argv0[0]);
462 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
463 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000464
Barry Warsawfa701a81997-01-16 00:15:11 +0000465 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000466 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000467
Guido van Rossum7bf15641998-05-22 18:28:17 +0000468 EnableEventHook();
469
Barry Warsawfa701a81997-01-16 00:15:11 +0000470 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000471}
472
Barry Warsawfa701a81997-01-16 00:15:11 +0000473
474
Guido van Rossum18468821994-06-20 07:49:28 +0000475/** Tcl Eval **/
476
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000477#if TKMAJORMINOR >= 8001
478#define USING_OBJECTS
479#endif
480
481#ifdef USING_OBJECTS
482
483static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000484AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000485{
486 Tcl_Obj *result;
487
488 if (PyString_Check(value))
489 return Tcl_NewStringObj(PyString_AS_STRING(value),
490 PyString_GET_SIZE(value));
491 else if (PyInt_Check(value))
492 return Tcl_NewLongObj(PyInt_AS_LONG(value));
493 else if (PyFloat_Check(value))
494 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
495 else if (PyTuple_Check(value)) {
496 Tcl_Obj **argv = (Tcl_Obj**)
497 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
498 int i;
499 if(!argv)
500 return 0;
501 for(i=0;i<PyTuple_Size(value);i++)
502 argv[i] = AsObj(PyTuple_GetItem(value,i));
503 result = Tcl_NewListObj(PyTuple_Size(value), argv);
504 ckfree(FREECAST argv);
505 return result;
506 }
507 else if (PyUnicode_Check(value)) {
Guido van Rossum990f5c62000-05-04 15:07:16 +0000508#if TKMAJORMINOR <= 8001
509 /* In Tcl 8.1 we must use UTF-8 */
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000510 PyObject* utf8 = PyUnicode_AsUTF8String (value);
511 if (!utf8)
512 return 0;
Guido van Rossum8823acc2000-04-27 20:14:31 +0000513 result = Tcl_NewStringObj (PyString_AS_STRING (utf8),
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000514 PyString_GET_SIZE (utf8));
Guido van Rossum8823acc2000-04-27 20:14:31 +0000515 Py_DECREF(utf8);
516 return result;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000517#else /* TKMAJORMINOR > 8001 */
518 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
519 if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) {
520 /* XXX Should really test this at compile time */
521 PyErr_SetString(PyExc_SystemError,
522 "Py_UNICODE and Tcl_UniChar differ in size");
523 return 0;
524 }
525 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value),
526 PyUnicode_GET_SIZE(value));
527#endif /* TKMAJORMINOR > 8001 */
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000528 }
529 else {
530 PyObject *v = PyObject_Str(value);
531 if (!v)
532 return 0;
533 result = AsObj(v);
534 Py_DECREF(v);
535 return result;
536 }
537}
538
Guido van Rossum18468821994-06-20 07:49:28 +0000539static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000540Tkapp_Call(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000541{
Guido van Rossum632de272000-03-29 00:19:50 +0000542 Tcl_Obj *objStore[ARGSZ];
543 Tcl_Obj **objv = NULL;
544 int objc = 0, i;
545 PyObject *res = NULL;
546 Tcl_Interp *interp = Tkapp_Interp(self);
547 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
548 int flags = TCL_EVAL_DIRECT;
Guido van Rossum18468821994-06-20 07:49:28 +0000549
Guido van Rossum632de272000-03-29 00:19:50 +0000550 objv = objStore;
Barry Warsawfa701a81997-01-16 00:15:11 +0000551
Guido van Rossum212643f1998-04-29 16:22:14 +0000552 if (args == NULL)
Guido van Rossum632de272000-03-29 00:19:50 +0000553 objc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000554
Guido van Rossum212643f1998-04-29 16:22:14 +0000555 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +0000556 objc = 1;
557 objv[0] = AsObj(args);
558 if (objv[0] == 0)
559 goto finally;
560 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000561 }
562 else {
Guido van Rossum632de272000-03-29 00:19:50 +0000563 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +0000564
Guido van Rossum632de272000-03-29 00:19:50 +0000565 if (objc > ARGSZ) {
566 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
567 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +0000568 PyErr_NoMemory();
569 goto finally;
570 }
571 }
572
Guido van Rossum632de272000-03-29 00:19:50 +0000573 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +0000574 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +0000575 if (v == Py_None) {
576 objc = i;
577 break;
578 }
Guido van Rossum632de272000-03-29 00:19:50 +0000579 objv[i] = AsObj(v);
580 if (!objv[i])
581 goto finally;
582 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000583 }
584 }
Guido van Rossum212643f1998-04-29 16:22:14 +0000585
Guido van Rossum62320c91998-06-15 04:36:09 +0000586 ENTER_TCL
Guido van Rossum632de272000-03-29 00:19:50 +0000587
588 i = Tcl_EvalObjv(interp, objc, objv, flags);
589
Guido van Rossum62320c91998-06-15 04:36:09 +0000590 ENTER_OVERLAP
Guido van Rossum632de272000-03-29 00:19:50 +0000591 if (i == TCL_ERROR)
Guido van Rossum212643f1998-04-29 16:22:14 +0000592 Tkinter_Error(self);
Guido van Rossum990f5c62000-05-04 15:07:16 +0000593 else {
Guido van Rossum632de272000-03-29 00:19:50 +0000594 /* We could request the object result here, but doing
595 so would confuse applications that expect a string. */
Guido van Rossum990f5c62000-05-04 15:07:16 +0000596 char *s = Tcl_GetStringResult(interp);
597 char *p = s;
598 /* If the result contains any bytes with the top bit set,
599 it's UTF-8 and we should decode it to Unicode */
600 while (*p != '\0') {
601 if (*p & 0x80)
602 break;
603 p++;
604 }
605 if (*p == '\0')
606 res = PyString_FromStringAndSize(s, (int)(p-s));
607 else {
608 /* Convert UTF-8 to Unicode string */
609 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +0000610 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
611 if (res == NULL) {
612 PyErr_Clear();
613 res = PyString_FromStringAndSize(s, (int)(p-s));
614 }
Guido van Rossum990f5c62000-05-04 15:07:16 +0000615 }
616 }
Guido van Rossum632de272000-03-29 00:19:50 +0000617
Guido van Rossum62320c91998-06-15 04:36:09 +0000618 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000619
Guido van Rossum212643f1998-04-29 16:22:14 +0000620 finally:
Guido van Rossum632de272000-03-29 00:19:50 +0000621 for (i = 0; i < objc; i++)
622 Tcl_DecrRefCount(objv[i]);
623 if (objv != objStore)
624 ckfree(FREECAST objv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000625 return res;
626}
627
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000628#else /* !USING_OBJECTS */
629
630static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000631Tkapp_Call(PyObject *self, PyObject *args)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000632{
633 /* This is copied from Merge() */
634 PyObject *tmp = NULL;
635 char *argvStore[ARGSZ];
636 char **argv = NULL;
637 int fvStore[ARGSZ];
638 int *fv = NULL;
639 int argc = 0, i;
640 PyObject *res = NULL; /* except this has a different type */
641 Tcl_CmdInfo info; /* and this is added */
642 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
643
644 if (!(tmp = PyList_New(0)))
645 return NULL;
646
647 argv = argvStore;
648 fv = fvStore;
649
650 if (args == NULL)
651 argc = 0;
652
653 else if (!PyTuple_Check(args)) {
654 argc = 1;
655 fv[0] = 0;
656 argv[0] = AsString(args, tmp);
657 }
658 else {
659 argc = PyTuple_Size(args);
660
661 if (argc > ARGSZ) {
662 argv = (char **)ckalloc(argc * sizeof(char *));
663 fv = (int *)ckalloc(argc * sizeof(int));
664 if (argv == NULL || fv == NULL) {
665 PyErr_NoMemory();
666 goto finally;
667 }
668 }
669
670 for (i = 0; i < argc; i++) {
671 PyObject *v = PyTuple_GetItem(args, i);
672 if (PyTuple_Check(v)) {
673 fv[i] = 1;
674 if (!(argv[i] = Merge(v)))
675 goto finally;
676 }
677 else if (v == Py_None) {
678 argc = i;
679 break;
680 }
681 else {
682 fv[i] = 0;
683 argv[i] = AsString(v, tmp);
684 }
685 }
686 }
687 /* End code copied from Merge() */
688
689 /* All this to avoid a call to Tcl_Merge() and the corresponding call
690 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
691 if (Py_VerboseFlag >= 2) {
692 for (i = 0; i < argc; i++)
693 PySys_WriteStderr("%s ", argv[i]);
694 }
695 ENTER_TCL
696 info.proc = NULL;
697 if (argc < 1 ||
698 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
699 info.proc == NULL)
700 {
701 char *cmd;
702 cmd = Tcl_Merge(argc, argv);
703 i = Tcl_Eval(interp, cmd);
704 ckfree(cmd);
705 }
706 else {
707 Tcl_ResetResult(interp);
708 i = (*info.proc)(info.clientData, interp, argc, argv);
709 }
710 ENTER_OVERLAP
711 if (info.proc == NULL && Py_VerboseFlag >= 2)
712 PySys_WriteStderr("... use TclEval ");
713 if (i == TCL_ERROR) {
714 if (Py_VerboseFlag >= 2)
715 PySys_WriteStderr("... error: '%s'\n",
716 interp->result);
717 Tkinter_Error(self);
718 }
719 else {
720 if (Py_VerboseFlag >= 2)
721 PySys_WriteStderr("-> '%s'\n", interp->result);
722 res = PyString_FromString(interp->result);
723 }
724 LEAVE_OVERLAP_TCL
725
726 /* Copied from Merge() again */
727 finally:
728 for (i = 0; i < argc; i++)
729 if (fv[i]) {
730 ckfree(argv[i]);
731 }
732 if (argv != argvStore)
733 ckfree(FREECAST argv);
734 if (fv != fvStore)
735 ckfree(FREECAST fv);
736
737 Py_DECREF(tmp);
738 return res;
739}
740
741#endif /* !USING_OBJECTS */
Barry Warsawfa701a81997-01-16 00:15:11 +0000742
743static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000744Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000745{
Guido van Rossum212643f1998-04-29 16:22:14 +0000746 /* Could do the same here as for Tkapp_Call(), but this is not used
747 much, so I can't be bothered. Unfortunately Tcl doesn't export a
748 way for the user to do what all its Global* variants do (save and
749 reset the scope pointer, call the local version, restore the saved
750 scope pointer). */
751
Guido van Rossum62320c91998-06-15 04:36:09 +0000752 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +0000753 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000754
Guido van Rossum62320c91998-06-15 04:36:09 +0000755 cmd = Merge(args);
Barry Warsawfa701a81997-01-16 00:15:11 +0000756 if (!cmd)
757 PyErr_SetString(Tkinter_TclError, "merge failed");
758
Guido van Rossum00d93061998-05-28 23:06:38 +0000759 else {
760 int err;
761 ENTER_TCL
762 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +0000763 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000764 if (err == TCL_ERROR)
765 res = Tkinter_Error(self);
766 else
767 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +0000768 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000769 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000770
771 if (cmd)
772 ckfree(cmd);
773
774 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000775}
776
777static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000778Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000779{
Barry Warsawfa701a81997-01-16 00:15:11 +0000780 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000781 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000782 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000783
Guido van Rossum43713e52000-02-29 13:59:29 +0000784 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000785 return NULL;
786
Guido van Rossum00d93061998-05-28 23:06:38 +0000787 ENTER_TCL
788 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000789 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000790 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000791 res = Tkinter_Error(self);
792 else
793 res = PyString_FromString(Tkapp_Result(self));
794 LEAVE_OVERLAP_TCL
795 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000796}
797
798static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000799Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000800{
Barry Warsawfa701a81997-01-16 00:15:11 +0000801 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000802 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000803 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +0000804
Guido van Rossum43713e52000-02-29 13:59:29 +0000805 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000806 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000807
Guido van Rossum00d93061998-05-28 23:06:38 +0000808 ENTER_TCL
809 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000810 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000811 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000812 res = Tkinter_Error(self);
813 else
814 res = PyString_FromString(Tkapp_Result(self));
815 LEAVE_OVERLAP_TCL
816 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000817}
818
819static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000820Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000821{
Barry Warsawfa701a81997-01-16 00:15:11 +0000822 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +0000823 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000824 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000825
Guido van Rossum43713e52000-02-29 13:59:29 +0000826 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +0000827 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000828
Guido van Rossum00d93061998-05-28 23:06:38 +0000829 ENTER_TCL
830 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +0000831 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000832 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000833 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +0000834
Guido van Rossum62320c91998-06-15 04:36:09 +0000835 else
836 res = PyString_FromString(Tkapp_Result(self));
837 LEAVE_OVERLAP_TCL
838 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000839}
840
841static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000842Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000843{
Barry Warsawfa701a81997-01-16 00:15:11 +0000844 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000845 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000846 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000847
Guido van Rossum35d43371997-08-02 00:09:09 +0000848 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000849 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000850
Guido van Rossum00d93061998-05-28 23:06:38 +0000851 ENTER_TCL
852 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +0000853 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000854 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000855 res = Tkinter_Error(self);
856 else
857 res = PyString_FromString(Tkapp_Result(self));
858 LEAVE_OVERLAP_TCL
859 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000860}
861
862static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000863Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000864{
Barry Warsawfa701a81997-01-16 00:15:11 +0000865 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +0000866
Guido van Rossum43713e52000-02-29 13:59:29 +0000867 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +0000868 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000869 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000870 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +0000871 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +0000872
Barry Warsawfa701a81997-01-16 00:15:11 +0000873 Py_INCREF(Py_None);
874 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000875}
876
Barry Warsawfa701a81997-01-16 00:15:11 +0000877
878
Guido van Rossum18468821994-06-20 07:49:28 +0000879/** Tcl Variable **/
880
881static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000882SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000883{
Guido van Rossum00d93061998-05-28 23:06:38 +0000884 char *name1, *name2, *ok, *s;
Barry Warsawfa701a81997-01-16 00:15:11 +0000885 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +0000886 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000887
Guido van Rossum62320c91998-06-15 04:36:09 +0000888 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +0000889 if (!tmp)
890 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000891
Guido van Rossum43713e52000-02-29 13:59:29 +0000892 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000893 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +0000894 s = AsString(newValue, tmp);
895 ENTER_TCL
896 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
897 LEAVE_TCL
898 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000899 else {
Guido van Rossum35d43371997-08-02 00:09:09 +0000900 PyErr_Clear();
Guido van Rossum43713e52000-02-29 13:59:29 +0000901 if (PyArg_ParseTuple(args, "ssO:setvar", &name1, &name2, &newValue)) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000902 s = AsString (newValue, tmp);
903 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000904 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
Guido van Rossum00d93061998-05-28 23:06:38 +0000905 s, flags);
906 LEAVE_TCL
907 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000908 else {
Guido van Rossum00d93061998-05-28 23:06:38 +0000909 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +0000910 return NULL;
911 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000912 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000913 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000914
Barry Warsawfa701a81997-01-16 00:15:11 +0000915 if (!ok)
916 return Tkinter_Error(self);
917
918 Py_INCREF(Py_None);
919 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000920}
921
922static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000923Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000924{
Barry Warsawfa701a81997-01-16 00:15:11 +0000925 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000926}
927
928static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000929Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000930{
Barry Warsawfa701a81997-01-16 00:15:11 +0000931 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000932}
933
Barry Warsawfa701a81997-01-16 00:15:11 +0000934
935
Guido van Rossum18468821994-06-20 07:49:28 +0000936static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000937GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000938{
Guido van Rossum35d43371997-08-02 00:09:09 +0000939 char *name1, *name2=NULL, *s;
Guido van Rossum62320c91998-06-15 04:36:09 +0000940 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000941
Guido van Rossum43713e52000-02-29 13:59:29 +0000942 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +0000943 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000944 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000945 if (name2 == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000946 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
Guido van Rossum18468821994-06-20 07:49:28 +0000947
Barry Warsawfa701a81997-01-16 00:15:11 +0000948 else
Guido van Rossum35d43371997-08-02 00:09:09 +0000949 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000950 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000951
Barry Warsawfa701a81997-01-16 00:15:11 +0000952 if (s == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000953 res = Tkinter_Error(self);
954 else
955 res = PyString_FromString(s);
956 LEAVE_OVERLAP_TCL
957 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000958}
959
960static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000961Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000962{
Barry Warsawfa701a81997-01-16 00:15:11 +0000963 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000964}
965
966static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000967Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000968{
Barry Warsawfa701a81997-01-16 00:15:11 +0000969 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000970}
971
Barry Warsawfa701a81997-01-16 00:15:11 +0000972
973
Guido van Rossum18468821994-06-20 07:49:28 +0000974static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000975UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000976{
Guido van Rossum35d43371997-08-02 00:09:09 +0000977 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +0000978 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000979 int code;
Guido van Rossum18468821994-06-20 07:49:28 +0000980
Guido van Rossum43713e52000-02-29 13:59:29 +0000981 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +0000982 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000983 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000984 if (name2 == NULL)
985 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
986
987 else
988 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000989 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000990
Barry Warsawfa701a81997-01-16 00:15:11 +0000991 if (code == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000992 res = Tkinter_Error(self);
993 else {
994 Py_INCREF(Py_None);
995 res = Py_None;
996 }
997 LEAVE_OVERLAP_TCL
998 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000999}
1000
1001static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001002Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001003{
Barry Warsawfa701a81997-01-16 00:15:11 +00001004 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001005}
1006
1007static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001008Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001009{
Barry Warsawfa701a81997-01-16 00:15:11 +00001010 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001011}
1012
Barry Warsawfa701a81997-01-16 00:15:11 +00001013
1014
Guido van Rossum18468821994-06-20 07:49:28 +00001015/** Tcl to Python **/
1016
1017static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001018Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001019{
Barry Warsawfa701a81997-01-16 00:15:11 +00001020 char *s;
1021 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001022
Guido van Rossum43713e52000-02-29 13:59:29 +00001023 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001024 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001025 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001026 return Tkinter_Error(self);
1027 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001028}
1029
1030static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001031Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001032{
Barry Warsawfa701a81997-01-16 00:15:11 +00001033 char *s;
1034 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001035
Guido van Rossum43713e52000-02-29 13:59:29 +00001036 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001037 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001038 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001039 return Tkinter_Error(self);
1040 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001041}
1042
1043static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001044Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001045{
Barry Warsawfa701a81997-01-16 00:15:11 +00001046 char *s;
1047 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001048
Guido van Rossum43713e52000-02-29 13:59:29 +00001049 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001050 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001051 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1052 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001053 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001054}
1055
1056static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001057Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001058{
Barry Warsawfa701a81997-01-16 00:15:11 +00001059 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001060 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001061 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001062
Guido van Rossum43713e52000-02-29 13:59:29 +00001063 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001064 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001065 ENTER_TCL
1066 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001067 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001068 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001069 res = Tkinter_Error(self);
1070 else
1071 res = Py_BuildValue("s", Tkapp_Result(self));
1072 LEAVE_OVERLAP_TCL
1073 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001074}
1075
1076static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001077Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001078{
Barry Warsawfa701a81997-01-16 00:15:11 +00001079 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001080 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001081 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001082 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001083
Guido van Rossum43713e52000-02-29 13:59:29 +00001084 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001085 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001086 ENTER_TCL
1087 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001088 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001089 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001090 res = Tkinter_Error(self);
1091 else
1092 res = Py_BuildValue("l", v);
1093 LEAVE_OVERLAP_TCL
1094 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001095}
1096
1097static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001098Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001099{
Barry Warsawfa701a81997-01-16 00:15:11 +00001100 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001101 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001102 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001103 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001104
Guido van Rossum43713e52000-02-29 13:59:29 +00001105 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001106 return NULL;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001107 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001108 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001109 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001110 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001111 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001112 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001113 res = Tkinter_Error(self);
1114 else
1115 res = Py_BuildValue("d", v);
1116 LEAVE_OVERLAP_TCL
1117 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001118}
1119
1120static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001121Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001122{
Barry Warsawfa701a81997-01-16 00:15:11 +00001123 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001124 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001125 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001126 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001127
Guido van Rossum43713e52000-02-29 13:59:29 +00001128 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001129 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001130 ENTER_TCL
1131 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001132 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001133 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001134 res = Tkinter_Error(self);
1135 else
1136 res = Py_BuildValue("i", v);
1137 LEAVE_OVERLAP_TCL
1138 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001139}
1140
Barry Warsawfa701a81997-01-16 00:15:11 +00001141
1142
Guido van Rossum18468821994-06-20 07:49:28 +00001143static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001144Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001145{
Barry Warsawfa701a81997-01-16 00:15:11 +00001146 char *list;
1147 int argc;
1148 char **argv;
1149 PyObject *v;
1150 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001151
Guido van Rossum43713e52000-02-29 13:59:29 +00001152 if (!PyArg_ParseTuple(args, "s:splitlist", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001153 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001154
Barry Warsawfa701a81997-01-16 00:15:11 +00001155 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1156 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001157
Barry Warsawfa701a81997-01-16 00:15:11 +00001158 if (!(v = PyTuple_New(argc)))
1159 return NULL;
1160
1161 for (i = 0; i < argc; i++) {
1162 PyObject *s = PyString_FromString(argv[i]);
1163 if (!s || PyTuple_SetItem(v, i, s)) {
1164 Py_DECREF(v);
1165 v = NULL;
1166 goto finally;
1167 }
1168 }
Guido van Rossum18468821994-06-20 07:49:28 +00001169
Barry Warsawfa701a81997-01-16 00:15:11 +00001170 finally:
1171 ckfree(FREECAST argv);
1172 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001173}
1174
1175static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001176Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001177{
Barry Warsawfa701a81997-01-16 00:15:11 +00001178 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001179
Guido van Rossum43713e52000-02-29 13:59:29 +00001180 if (!PyArg_ParseTuple(args, "s:split", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001181 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001182 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001183}
1184
1185static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001186Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001187{
Barry Warsawfa701a81997-01-16 00:15:11 +00001188 char *s = Merge(args);
1189 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001190
Barry Warsawfa701a81997-01-16 00:15:11 +00001191 if (s) {
1192 res = PyString_FromString(s);
1193 ckfree(s);
1194 }
1195 else
1196 PyErr_SetString(Tkinter_TclError, "merge failed");
1197
1198 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001199}
1200
Barry Warsawfa701a81997-01-16 00:15:11 +00001201
1202
Guido van Rossum18468821994-06-20 07:49:28 +00001203/** Tcl Command **/
1204
Guido van Rossum00d93061998-05-28 23:06:38 +00001205/* Client data struct */
1206typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001207 PyObject *self;
1208 PyObject *func;
1209} PythonCmd_ClientData;
1210
1211static int
Fred Drake509d79a2000-07-08 04:04:38 +00001212PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001213{
1214 errorInCmd = 1;
1215 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1216 LEAVE_PYTHON
1217 return TCL_ERROR;
1218}
1219
Guido van Rossum18468821994-06-20 07:49:28 +00001220/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001221 * function or method.
1222 */
Guido van Rossum18468821994-06-20 07:49:28 +00001223static int
Fred Drake509d79a2000-07-08 04:04:38 +00001224PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001225{
Guido van Rossum00d93061998-05-28 23:06:38 +00001226 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001227 PyObject *self, *func, *arg, *res, *tmp;
1228 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001229
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001230 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001231
Barry Warsawfa701a81997-01-16 00:15:11 +00001232 /* TBD: no error checking here since we know, via the
1233 * Tkapp_CreateCommand() that the client data is a two-tuple
1234 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001235 self = data->self;
1236 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001237
Barry Warsawfa701a81997-01-16 00:15:11 +00001238 /* Create argument list (argv1, ..., argvN) */
1239 if (!(arg = PyTuple_New(argc - 1)))
1240 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001241
Barry Warsawfa701a81997-01-16 00:15:11 +00001242 for (i = 0; i < (argc - 1); i++) {
1243 PyObject *s = PyString_FromString(argv[i + 1]);
1244 if (!s || PyTuple_SetItem(arg, i, s)) {
1245 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001246 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001247 }
1248 }
1249 res = PyEval_CallObject(func, arg);
1250 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001251
Barry Warsawfa701a81997-01-16 00:15:11 +00001252 if (res == NULL)
1253 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001254
Barry Warsawfa701a81997-01-16 00:15:11 +00001255 if (!(tmp = PyList_New(0))) {
1256 Py_DECREF(res);
1257 return PythonCmd_Error(interp);
1258 }
1259
1260 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1261 Py_DECREF(res);
1262 Py_DECREF(tmp);
1263
Guido van Rossum00d93061998-05-28 23:06:38 +00001264 LEAVE_PYTHON
1265
Barry Warsawfa701a81997-01-16 00:15:11 +00001266 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00001267}
1268
1269static void
Fred Drake509d79a2000-07-08 04:04:38 +00001270PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001271{
Guido van Rossum00d93061998-05-28 23:06:38 +00001272 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1273
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001274 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001275 Py_XDECREF(data->self);
1276 Py_XDECREF(data->func);
1277 PyMem_DEL(data);
1278 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001279}
1280
Barry Warsawfa701a81997-01-16 00:15:11 +00001281
1282
Guido van Rossum18468821994-06-20 07:49:28 +00001283static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001284Tkapp_CreateCommand(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001285{
Guido van Rossum00d93061998-05-28 23:06:38 +00001286 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001287 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001288 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001289 Tcl_Command err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001290
Guido van Rossum43713e52000-02-29 13:59:29 +00001291 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00001292 return NULL;
1293 if (!PyCallable_Check(func)) {
1294 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001295 return NULL;
1296 }
Guido van Rossum18468821994-06-20 07:49:28 +00001297
Guido van Rossum00d93061998-05-28 23:06:38 +00001298 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001299 if (!data)
1300 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001301 Py_XINCREF(self);
1302 Py_XINCREF(func);
1303 data->self = self;
1304 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00001305
Guido van Rossum00d93061998-05-28 23:06:38 +00001306 ENTER_TCL
1307 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1308 (ClientData)data, PythonCmdDelete);
1309 LEAVE_TCL
1310 if (err == NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001311 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001312 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001313 return NULL;
1314 }
Guido van Rossum18468821994-06-20 07:49:28 +00001315
Barry Warsawfa701a81997-01-16 00:15:11 +00001316 Py_INCREF(Py_None);
1317 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001318}
1319
Barry Warsawfa701a81997-01-16 00:15:11 +00001320
1321
Guido van Rossum18468821994-06-20 07:49:28 +00001322static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001323Tkapp_DeleteCommand(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001324{
Barry Warsawfa701a81997-01-16 00:15:11 +00001325 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001326 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001327
Guido van Rossum43713e52000-02-29 13:59:29 +00001328 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001329 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001330 ENTER_TCL
1331 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1332 LEAVE_TCL
1333 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001334 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1335 return NULL;
1336 }
1337 Py_INCREF(Py_None);
1338 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001339}
1340
Barry Warsawfa701a81997-01-16 00:15:11 +00001341
1342
Guido van Rossum00d93061998-05-28 23:06:38 +00001343#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00001344/** File Handler **/
1345
Guido van Rossum00d93061998-05-28 23:06:38 +00001346typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00001347 PyObject *func;
1348 PyObject *file;
1349 int id;
1350 struct _fhcdata *next;
1351} FileHandler_ClientData;
1352
1353static FileHandler_ClientData *HeadFHCD;
1354
1355static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00001356NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00001357{
1358 FileHandler_ClientData *p;
1359 p = PyMem_NEW(FileHandler_ClientData, 1);
1360 if (p != NULL) {
1361 Py_XINCREF(func);
1362 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00001363 p->func = func;
1364 p->file = file;
1365 p->id = id;
1366 p->next = HeadFHCD;
1367 HeadFHCD = p;
1368 }
1369 return p;
1370}
1371
1372static void
Fred Drake509d79a2000-07-08 04:04:38 +00001373DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00001374{
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
Fred Drake509d79a2000-07-08 04:04:38 +00001391FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00001392{
Guido van Rossum00d93061998-05-28 23:06:38 +00001393 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001394 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00001395
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001396 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001397 func = data->func;
1398 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00001399
Barry Warsawfa701a81997-01-16 00:15:11 +00001400 arg = Py_BuildValue("(Oi)", file, (long) mask);
1401 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00001402 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00001403
1404 if (res == NULL) {
1405 errorInCmd = 1;
1406 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1407 }
1408 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001409 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001410}
1411
Guido van Rossum18468821994-06-20 07:49:28 +00001412static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001413Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
1414 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00001415{
Guido van Rossum00d93061998-05-28 23:06:38 +00001416 FileHandler_ClientData *data;
1417 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001418 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00001419
Guido van Rossum43713e52000-02-29 13:59:29 +00001420 if (!PyArg_ParseTuple(args, "OiO:createfilehandler", &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001421 return NULL;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00001422 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00001423 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00001424 return NULL;
1425 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001426 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001427 return NULL;
1428 }
1429
Guido van Rossuma80649b2000-03-28 20:07:05 +00001430 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001431 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 return NULL;
1433
Barry Warsawfa701a81997-01-16 00:15:11 +00001434 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001435 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001436 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00001437 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001438 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001439 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001440}
1441
1442static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001443Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001444{
Barry Warsawfa701a81997-01-16 00:15:11 +00001445 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001446 int tfile;
Guido van Rossum68784361996-05-16 17:17:31 +00001447
Guido van Rossum43713e52000-02-29 13:59:29 +00001448 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00001449 return NULL;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00001450 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00001451 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00001452 return NULL;
1453
Guido van Rossuma80649b2000-03-28 20:07:05 +00001454 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00001455
Barry Warsawfa701a81997-01-16 00:15:11 +00001456 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001457 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001458 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001459 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001460 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001461 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001462}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001463#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00001464
Barry Warsawfa701a81997-01-16 00:15:11 +00001465
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001466/**** Tktt Object (timer token) ****/
1467
1468staticforward PyTypeObject Tktt_Type;
1469
Guido van Rossum00d93061998-05-28 23:06:38 +00001470typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00001471 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00001472 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00001473 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001474} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001475
1476static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001477Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001478{
Barry Warsawfa701a81997-01-16 00:15:11 +00001479 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001480 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001481
Guido van Rossum43713e52000-02-29 13:59:29 +00001482 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00001483 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001484 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001485 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00001486 v->token = NULL;
1487 }
1488 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001489 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001490 Py_DECREF(func);
1491 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00001492 }
1493 Py_INCREF(Py_None);
1494 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001495}
1496
1497static PyMethodDef Tktt_methods[] =
1498{
Guido van Rossum35d43371997-08-02 00:09:09 +00001499 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001500 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001501};
1502
1503static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001504Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001505{
Barry Warsawfa701a81997-01-16 00:15:11 +00001506 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001507
Guido van Rossumb18618d2000-05-03 23:44:39 +00001508 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00001509 if (v == NULL)
1510 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001511
Guido van Rossum00d93061998-05-28 23:06:38 +00001512 Py_INCREF(func);
1513 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001514 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001515
1516 /* Extra reference, deleted when called or when handler is deleted */
1517 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001518 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001519}
1520
1521static void
Fred Drake509d79a2000-07-08 04:04:38 +00001522Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001523{
Guido van Rossum00d93061998-05-28 23:06:38 +00001524 TkttObject *v = (TkttObject *)self;
1525 PyObject *func = v->func;
1526
1527 Py_XDECREF(func);
1528
Guido van Rossumb18618d2000-05-03 23:44:39 +00001529 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001530}
1531
Guido van Rossum597ac201998-05-12 14:36:19 +00001532static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001533Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001534{
Barry Warsawfa701a81997-01-16 00:15:11 +00001535 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00001536 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001537
Fred Drakea44d3532000-06-30 15:01:00 +00001538 sprintf(buf, "<tktimertoken at %p%s>", v,
Barry Warsawfa701a81997-01-16 00:15:11 +00001539 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00001540 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001541}
1542
1543static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001544Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001545{
Barry Warsawfa701a81997-01-16 00:15:11 +00001546 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001547}
1548
1549static PyTypeObject Tktt_Type =
1550{
Guido van Rossum35d43371997-08-02 00:09:09 +00001551 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001552 0, /*ob_size */
1553 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001554 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001555 0, /*tp_itemsize */
1556 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00001557 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00001558 Tktt_GetAttr, /*tp_getattr */
1559 0, /*tp_setattr */
1560 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00001561 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00001562 0, /*tp_as_number */
1563 0, /*tp_as_sequence */
1564 0, /*tp_as_mapping */
1565 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001566};
1567
Barry Warsawfa701a81997-01-16 00:15:11 +00001568
1569
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001570/** Timer Handler **/
1571
1572static void
Fred Drake509d79a2000-07-08 04:04:38 +00001573TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001574{
Guido van Rossum00d93061998-05-28 23:06:38 +00001575 TkttObject *v = (TkttObject *)clientData;
1576 PyObject *func = v->func;
1577 PyObject *res;
1578
1579 if (func == NULL)
1580 return;
1581
1582 v->func = NULL;
1583
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001584 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001585
1586 res = PyEval_CallObject(func, NULL);
1587 Py_DECREF(func);
1588 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001589
Barry Warsawfa701a81997-01-16 00:15:11 +00001590 if (res == NULL) {
1591 errorInCmd = 1;
1592 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1593 }
1594 else
1595 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001596
1597 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001598}
1599
1600static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001601Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001602{
Barry Warsawfa701a81997-01-16 00:15:11 +00001603 int milliseconds;
1604 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001605 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001606
Guido van Rossum43713e52000-02-29 13:59:29 +00001607 if (!PyArg_ParseTuple(args, "iO:createtimerhandler", &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001608 return NULL;
1609 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001610 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001611 return NULL;
1612 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001613 v = Tktt_New(func);
1614 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1615 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001616
Guido van Rossum00d93061998-05-28 23:06:38 +00001617 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001618}
1619
Barry Warsawfa701a81997-01-16 00:15:11 +00001620
Guido van Rossum18468821994-06-20 07:49:28 +00001621/** Event Loop **/
1622
Guido van Rossum18468821994-06-20 07:49:28 +00001623static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001624Tkapp_MainLoop(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Barry Warsawfa701a81997-01-16 00:15:11 +00001626 int threshold = 0;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001627#ifdef WITH_THREAD
1628 PyThreadState *tstate = PyThreadState_Get();
1629#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001630
Guido van Rossum43713e52000-02-29 13:59:29 +00001631 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00001632 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001633
Barry Warsawfa701a81997-01-16 00:15:11 +00001634 quitMainLoop = 0;
1635 while (Tk_GetNumMainWindows() > threshold &&
1636 !quitMainLoop &&
1637 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001638 {
Guido van Rossum35d43371997-08-02 00:09:09 +00001639 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00001640
1641#ifdef WITH_THREAD
Guido van Rossum62320c91998-06-15 04:36:09 +00001642 Py_BEGIN_ALLOW_THREADS
Guido van Rossum65d5b571998-12-21 19:32:43 +00001643 PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001644 tcl_tstate = tstate;
Guido van Rossum35d43371997-08-02 00:09:09 +00001645 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001646 tcl_tstate = NULL;
Guido van Rossum65d5b571998-12-21 19:32:43 +00001647 PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00001648 if (result == 0)
1649 Sleep(20);
Guido van Rossum35d43371997-08-02 00:09:09 +00001650 Py_END_ALLOW_THREADS
Guido van Rossum5b020781997-08-19 01:00:50 +00001651#else
1652 result = Tcl_DoOneEvent(0);
1653#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001654
Guido van Rossum35d43371997-08-02 00:09:09 +00001655 if (PyErr_CheckSignals() != 0)
1656 return NULL;
1657 if (result < 0)
1658 break;
Guido van Rossum18468821994-06-20 07:49:28 +00001659 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001660 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001661
Barry Warsawfa701a81997-01-16 00:15:11 +00001662 if (errorInCmd) {
1663 errorInCmd = 0;
1664 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1665 excInCmd = valInCmd = trbInCmd = NULL;
1666 return NULL;
1667 }
1668 Py_INCREF(Py_None);
1669 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
1672static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001673Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00001674{
Guido van Rossum35d43371997-08-02 00:09:09 +00001675 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00001676 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001677
Guido van Rossum43713e52000-02-29 13:59:29 +00001678 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00001679 return NULL;
1680
Guido van Rossum00d93061998-05-28 23:06:38 +00001681 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001682 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00001683 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001684 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001685}
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
1690
Guido van Rossum43713e52000-02-29 13:59:29 +00001691 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00001692 return NULL;
1693
1694 quitMainLoop = 1;
1695 Py_INCREF(Py_None);
1696 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001697}
1698
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001699static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001700Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001701{
1702
Guido van Rossum43713e52000-02-29 13:59:29 +00001703 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001704 return NULL;
1705
1706 return PyInt_FromLong((long)Tkapp_Interp(self));
1707}
1708
Barry Warsawfa701a81997-01-16 00:15:11 +00001709
1710
Guido van Rossum18468821994-06-20 07:49:28 +00001711/**** Tkapp Method List ****/
1712
1713static PyMethodDef Tkapp_methods[] =
1714{
Guido van Rossum35d43371997-08-02 00:09:09 +00001715 {"call", Tkapp_Call, 0},
1716 {"globalcall", Tkapp_GlobalCall, 0},
1717 {"eval", Tkapp_Eval, 1},
1718 {"globaleval", Tkapp_GlobalEval, 1},
1719 {"evalfile", Tkapp_EvalFile, 1},
1720 {"record", Tkapp_Record, 1},
1721 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1722 {"setvar", Tkapp_SetVar, 1},
1723 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1724 {"getvar", Tkapp_GetVar, 1},
1725 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1726 {"unsetvar", Tkapp_UnsetVar, 1},
1727 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1728 {"getint", Tkapp_GetInt, 1},
1729 {"getdouble", Tkapp_GetDouble, 1},
1730 {"getboolean", Tkapp_GetBoolean, 1},
1731 {"exprstring", Tkapp_ExprString, 1},
1732 {"exprlong", Tkapp_ExprLong, 1},
1733 {"exprdouble", Tkapp_ExprDouble, 1},
1734 {"exprboolean", Tkapp_ExprBoolean, 1},
1735 {"splitlist", Tkapp_SplitList, 1},
1736 {"split", Tkapp_Split, 1},
1737 {"merge", Tkapp_Merge, 0},
1738 {"createcommand", Tkapp_CreateCommand, 1},
1739 {"deletecommand", Tkapp_DeleteCommand, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001740#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001741 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1742 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001743#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001744 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001745 {"mainloop", Tkapp_MainLoop, 1},
1746 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001747 {"quit", Tkapp_Quit, 1},
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001748 {"interpaddr", Tkapp_InterpAddr, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001749 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001750};
1751
Barry Warsawfa701a81997-01-16 00:15:11 +00001752
1753
Guido van Rossum18468821994-06-20 07:49:28 +00001754/**** Tkapp Type Methods ****/
1755
1756static void
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Guido van Rossum00d93061998-05-28 23:06:38 +00001759 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001760 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00001761 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00001762 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001763 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
1766static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001767Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00001768{
Guido van Rossum35d43371997-08-02 00:09:09 +00001769 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00001770}
1771
1772static PyTypeObject Tkapp_Type =
1773{
Guido van Rossum35d43371997-08-02 00:09:09 +00001774 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001775 0, /*ob_size */
1776 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001777 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001778 0, /*tp_itemsize */
1779 Tkapp_Dealloc, /*tp_dealloc */
1780 0, /*tp_print */
1781 Tkapp_GetAttr, /*tp_getattr */
1782 0, /*tp_setattr */
1783 0, /*tp_compare */
1784 0, /*tp_repr */
1785 0, /*tp_as_number */
1786 0, /*tp_as_sequence */
1787 0, /*tp_as_mapping */
1788 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00001789};
1790
Barry Warsawfa701a81997-01-16 00:15:11 +00001791
1792
Guido van Rossum18468821994-06-20 07:49:28 +00001793/**** Tkinter Module ****/
1794
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001795typedef struct {
1796 PyObject* tuple;
1797 int size; /* current size */
1798 int maxsize; /* allocated size */
1799} FlattenContext;
1800
1801static int
1802_bump(FlattenContext* context, int size)
1803{
1804 /* expand tuple to hold (at least) size new items. return true if
1805 successful, false if an exception was raised*/
1806
1807 int maxsize = context->maxsize * 2;
1808
1809 if (maxsize < context->size + size)
1810 maxsize = context->size + size;
1811
1812 context->maxsize = maxsize;
1813
1814 return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
1815}
1816
1817static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001818_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001819{
1820 /* add tuple or list to argument tuple (recursively) */
1821
1822 int i, size;
1823
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001824 if (depth > 1000) {
1825 PyErr_SetString(PyExc_ValueError,"nesting too deep in _flatten");
1826 return 0;
1827 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001828 size = PyList_GET_SIZE(item);
1829 /* preallocate (assume no nesting) */
1830 if (context->size + size > context->maxsize && !_bump(context, size))
1831 return 0;
1832 /* copy items to output tuple */
1833 for (i = 0; i < size; i++) {
1834 PyObject *o = PyList_GET_ITEM(item, i);
1835 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001836 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001837 return 0;
1838 } else if (o != Py_None) {
1839 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1840 return 0;
1841 Py_INCREF(o);
1842 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1843 }
1844 }
1845 } else if (PyTuple_Check(item)) {
1846 /* same, for tuples */
1847 size = PyTuple_GET_SIZE(item);
1848 if (context->size + size > context->maxsize && !_bump(context, size))
1849 return 0;
1850 for (i = 0; i < size; i++) {
1851 PyObject *o = PyTuple_GET_ITEM(item, i);
1852 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001853 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001854 return 0;
1855 } else if (o != Py_None) {
1856 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1857 return 0;
1858 Py_INCREF(o);
1859 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1860 }
1861 }
1862 } else {
1863 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
1864 return 0;
1865 }
1866 return 1;
1867}
1868
1869static PyObject *
1870Tkinter_Flatten(PyObject* self, PyObject* args)
1871{
1872 FlattenContext context;
1873 PyObject* item;
1874
1875 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
1876 return NULL;
1877
Jeremy Hylton03657cf2000-07-12 13:05:33 +00001878 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001879 if (context.maxsize <= 0)
1880 return PyTuple_New(0);
1881
1882 context.tuple = PyTuple_New(context.maxsize);
1883 if (!context.tuple)
1884 return NULL;
1885
1886 context.size = 0;
1887
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001888 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001889 return NULL;
1890
1891 if (_PyTuple_Resize(&context.tuple, context.size, 0))
1892 return NULL;
1893
1894 return context.tuple;
1895}
1896
Guido van Rossum18468821994-06-20 07:49:28 +00001897static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001898Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001899{
Barry Warsawfa701a81997-01-16 00:15:11 +00001900 char *screenName = NULL;
1901 char *baseName = NULL;
1902 char *className = NULL;
1903 int interactive = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001904
Guido van Rossum35d43371997-08-02 00:09:09 +00001905 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00001906 if (baseName != NULL)
1907 baseName++;
1908 else
1909 baseName = Py_GetProgramName();
1910 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00001911
Guido van Rossum43713e52000-02-29 13:59:29 +00001912 if (!PyArg_ParseTuple(args, "|zssi:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00001913 &screenName, &baseName, &className,
1914 &interactive))
1915 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001916
Barry Warsawfa701a81997-01-16 00:15:11 +00001917 return (PyObject *) Tkapp_New(screenName, baseName, className,
1918 interactive);
Guido van Rossum18468821994-06-20 07:49:28 +00001919}
1920
1921static PyMethodDef moduleMethods[] =
1922{
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001923 {"_flatten", Tkinter_Flatten, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001924 {"create", Tkinter_Create, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001925#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001926 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1927 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001928#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001929 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001930 {"mainloop", Tkapp_MainLoop, 1},
1931 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001932 {"quit", Tkapp_Quit, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001933 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001934};
1935
Guido van Rossum7bf15641998-05-22 18:28:17 +00001936#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001937
1938static int stdin_ready = 0;
1939
Guido van Rossumad4db171998-06-13 13:56:28 +00001940#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00001941static void
Fred Drake509d79a2000-07-08 04:04:38 +00001942MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00001943{
1944 stdin_ready = 1;
1945}
Guido van Rossumad4db171998-06-13 13:56:28 +00001946#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001947
Guido van Rossum00d93061998-05-28 23:06:38 +00001948static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00001949
Guido van Rossum18468821994-06-20 07:49:28 +00001950static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001951EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00001952{
Guido van Rossumad4db171998-06-13 13:56:28 +00001953#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00001954 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00001955#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00001956#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00001957 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00001958#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001959 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00001960 errorInCmd = 0;
1961#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00001962 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001963 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00001964#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001965 while (!errorInCmd && !stdin_ready) {
1966 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00001967#ifdef MS_WINDOWS
1968 if (_kbhit()) {
1969 stdin_ready = 1;
1970 break;
1971 }
1972#endif
1973#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00001974 Py_BEGIN_ALLOW_THREADS
Guido van Rossum65d5b571998-12-21 19:32:43 +00001975 PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00001976 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001977
Guido van Rossum00d93061998-05-28 23:06:38 +00001978 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001979
1980 tcl_tstate = NULL;
Guido van Rossum65d5b571998-12-21 19:32:43 +00001981 PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00001982 if (result == 0)
1983 Sleep(20);
1984 Py_END_ALLOW_THREADS
1985#else
1986 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001987#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001988
1989 if (result < 0)
1990 break;
1991 }
Guido van Rossumad4db171998-06-13 13:56:28 +00001992#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00001993 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00001994#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00001995 if (errorInCmd) {
1996 errorInCmd = 0;
1997 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1998 excInCmd = valInCmd = trbInCmd = NULL;
1999 PyErr_Print();
2000 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002001#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002002 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002003#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002004 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002005}
Guido van Rossum18468821994-06-20 07:49:28 +00002006
Guido van Rossum00d93061998-05-28 23:06:38 +00002007#endif
2008
Guido van Rossum7bf15641998-05-22 18:28:17 +00002009static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002010EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002011{
Guido van Rossum00d93061998-05-28 23:06:38 +00002012#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002013 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002014#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002015 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002016#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002017 PyOS_InputHook = EventHook;
2018 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002019#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002020}
2021
2022static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002023DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002024{
Guido van Rossum00d93061998-05-28 23:06:38 +00002025#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002026 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2027 PyOS_InputHook = NULL;
2028 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002029#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002030}
2031
Barry Warsawfa701a81997-01-16 00:15:11 +00002032
2033/* all errors will be checked in one fell swoop in init_tkinter() */
2034static void
Fred Drake509d79a2000-07-08 04:04:38 +00002035ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002036{
2037 PyObject *v = PyInt_FromLong(val);
2038 if (v) {
2039 PyDict_SetItemString(d, name, v);
2040 Py_DECREF(v);
2041 }
2042}
2043static void
Fred Drake509d79a2000-07-08 04:04:38 +00002044ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002045{
2046 PyObject *v = PyString_FromString(val);
2047 if (v) {
2048 PyDict_SetItemString(d, name, v);
2049 Py_DECREF(v);
2050 }
2051}
2052
2053
Guido van Rossum3886bb61998-12-04 18:50:17 +00002054DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002055init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002056{
Barry Warsawfa701a81997-01-16 00:15:11 +00002057 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002058
Barry Warsawfa701a81997-01-16 00:15:11 +00002059 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002060
2061#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002062 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002063#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002064
Barry Warsawfa701a81997-01-16 00:15:11 +00002065 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002066
Barry Warsawfa701a81997-01-16 00:15:11 +00002067 d = PyModule_GetDict(m);
2068 Tkinter_TclError = Py_BuildValue("s", "TclError");
2069 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002070
Guido van Rossum35d43371997-08-02 00:09:09 +00002071 ins_long(d, "READABLE", TCL_READABLE);
2072 ins_long(d, "WRITABLE", TCL_WRITABLE);
2073 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2074 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2075 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2076 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2077 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2078 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2079 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002080 ins_string(d, "TK_VERSION", TK_VERSION);
2081 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002082
Guido van Rossum83551bf1997-09-13 00:44:23 +00002083 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002084
2085 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002086 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2087
Guido van Rossume187b0e2000-03-27 21:46:29 +00002088 /* This helps the dynamic loader; in Unicode aware Tcl versions
2089 it also helps Tcl find its encodings. */
2090 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002091
Barry Warsawfa701a81997-01-16 00:15:11 +00002092 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002093 return;
2094
Guido van Rossum43ff8681998-07-14 18:02:13 +00002095#if 0
2096 /* This was not a good idea; through <Destroy> bindings,
2097 Tcl_Finalize() may invoke Python code but at that point the
2098 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002099 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002100#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002101
Jack Jansen34cc5c31995-10-31 16:15:12 +00002102#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002103 /*
2104 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2105 ** Most of the initializations in that routine (toolbox init calls and
2106 ** such) have already been done for us, so we only need these.
2107 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002108 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002109
2110 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002111#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002112 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002113#endif /* GENERATINGCFM */
2114#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002115}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002116
Guido van Rossumec22c921996-02-25 04:50:29 +00002117
Barry Warsawfa701a81997-01-16 00:15:11 +00002118
Guido van Rossum9722ad81995-09-22 23:49:28 +00002119#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002120
2121/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002122** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002123*/
2124
Guido van Rossum9722ad81995-09-22 23:49:28 +00002125void
2126panic(char * format, ...)
2127{
Barry Warsawfa701a81997-01-16 00:15:11 +00002128 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002129
Barry Warsawfa701a81997-01-16 00:15:11 +00002130 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002131
Guido van Rossum227cf761998-08-05 13:53:32 +00002132 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002133 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002134
Barry Warsawfa701a81997-01-16 00:15:11 +00002135 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002136
Barry Warsawfa701a81997-01-16 00:15:11 +00002137 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002138}
Jack Jansen40b546d1995-11-14 10:34:45 +00002139
Guido van Rossumec22c921996-02-25 04:50:29 +00002140/*
2141** Pass events to SIOUX before passing them to Tk.
2142*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002143
Guido van Rossumec22c921996-02-25 04:50:29 +00002144static int
Fred Drake509d79a2000-07-08 04:04:38 +00002145PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002146{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002147 WindowPtr frontwin;
2148 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002149 ** Sioux eats too many events, so we don't pass it everything. We
2150 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002151 ** the Sioux window is frontmost. This means that Tk menus don't work
2152 ** in that case, but at least we can scroll the sioux window.
2153 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2154 ** part of the external interface of Sioux...
2155 */
2156 frontwin = FrontWindow();
2157 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2158 if (SIOUXHandleOneEvent(eventPtr))
2159 return 0; /* Nothing happened to the Tcl event queue */
2160 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002161 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002162}
2163
Guido van Rossumec22c921996-02-25 04:50:29 +00002164#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002165
2166/*
2167** Additional Mac specific code for dealing with shared libraries.
2168*/
2169
2170#include <Resources.h>
2171#include <CodeFragments.h>
2172
2173static int loaded_from_shlib = 0;
2174static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002175
Jack Jansen34cc5c31995-10-31 16:15:12 +00002176/*
2177** If this module is dynamically loaded the following routine should
2178** be the init routine. It takes care of adding the shared library to
2179** the resource-file chain, so that the tk routines can find their
2180** resources.
2181*/
2182OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002183init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002184{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002185 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002186 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002187 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002188 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2189 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002190 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002191 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2192 loaded_from_shlib = 1;
2193 }
2194 return noErr;
2195}
2196
2197/*
2198** Insert the library resources into the search path. Put them after
2199** the resources from the application. Again, we ignore errors.
2200*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002201static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002202mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002203{
2204 if ( !loaded_from_shlib )
2205 return;
2206 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2207}
2208
Guido van Rossumec22c921996-02-25 04:50:29 +00002209#endif /* GENERATINGCFM */
2210#endif /* macintosh */