blob: 9601f0680f504e5e17aad5309efdc3371ebf6bd0 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
3Copyright 1994-1995 by Stichting Mathematisch Centrum, Amsterdam,
4The Netherlands.
5
6 All Rights Reserved
7
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00008Copyright (c) 2000, BeOpen.com.
9Copyright (c) 1995-2000, Corporation for National Research Initiatives.
10Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
11All rights reserved.
Guido van Rossum845547d1996-06-26 18:26:04 +000012
Guido van Rossumfd71b9e2000-06-30 23:50:40 +000013See the file "Misc/COPYRIGHT" for information on usage and
14redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum845547d1996-06-26 18:26:04 +000015
16******************************************************************/
17
18/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +000019
Guido van Rossum7ffa7611996-08-13 21:10:16 +000020/* TCL/TK VERSION INFO:
21
Guido van Rossuma80649b2000-03-28 20:07:05 +000022 Only Tcl/Tk 8.0 and later are supported. Older versions are not
23 supported. (Use Python 1.5.2 if you cannot upgrade your Tcl/Tk
24 libraries.)
25*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000026
Guido van Rossuma80649b2000-03-28 20:07:05 +000027/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000028
29 - In Tcl_Call(), create Tcl objects from the arguments, possibly using
30 intelligent mappings between Python objects and Tcl objects (e.g. ints,
31 floats and Tcl window pointers could be handled specially).
32
33 - Register a new Tcl type, "Python callable", which can be called more
34 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
35
Guido van Rossum7ffa7611996-08-13 21:10:16 +000036*/
37
Guido van Rossum35d43371997-08-02 00:09:09 +000038
Guido van Rossum9722ad81995-09-22 23:49:28 +000039#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000040#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000041
Guido van Rossum00d93061998-05-28 23:06:38 +000042#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000043#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000044#endif
45
Guido van Rossum2a5119b1998-05-29 01:28:40 +000046#ifdef MS_WINDOWS
47#include <windows.h>
48#endif
49
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000050#ifdef macintosh
51#define MAC_TCL
Guido van Rossum49b56061998-10-01 20:42:43 +000052#endif
53
Guido van Rossum18468821994-06-20 07:49:28 +000054#include <tcl.h>
55#include <tk.h>
56
Guido van Rossum3e819a71997-08-01 19:29:02 +000057#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
58
Guido van Rossuma80649b2000-03-28 20:07:05 +000059#if TKMAJORMINOR < 8000
60#error "Tk older than 8.0 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000061#endif
62
Guido van Rossuma80649b2000-03-28 20:07:05 +000063#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000064/* Sigh, we have to include this to get at the tcl qd pointer */
65#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000066/* And this one we need to clear the menu bar */
67#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +000068#endif
69
Guido van Rossuma80649b2000-03-28 20:07:05 +000070#if !defined(MS_WINDOWS)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000071#define HAVE_CREATEFILEHANDLER
72#endif
73
Guido van Rossum00d93061998-05-28 23:06:38 +000074#ifdef HAVE_CREATEFILEHANDLER
75
76/* Tcl_CreateFileHandler() changed several times; these macros deal with the
77 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
78 Unix, only because Jack added it back); when available on Windows, it only
79 applies to sockets. */
80
Guido van Rossum7bf15641998-05-22 18:28:17 +000081#ifdef MS_WINDOWS
82#define FHANDLETYPE TCL_WIN_SOCKET
83#else
84#define FHANDLETYPE TCL_UNIX_FD
85#endif
86
Guido van Rossum00d93061998-05-28 23:06:38 +000087/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
88 which uses this to handle Tcl events while the user is typing commands. */
89
90#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000091#define WAIT_FOR_STDIN
92#endif
93
Guido van Rossum00d93061998-05-28 23:06:38 +000094#endif /* HAVE_CREATEFILEHANDLER */
95
Guido van Rossumad4db171998-06-13 13:56:28 +000096#ifdef MS_WINDOWS
97#include <conio.h>
98#define WAIT_FOR_STDIN
99#endif
100
Guido van Rossum00d93061998-05-28 23:06:38 +0000101#ifdef WITH_THREAD
102
103/* The threading situation is complicated. Tcl is not thread-safe, except for
104 Tcl 8.1, which will probably remain in alpha status for another 6 months
105 (and the README says that Tk will probably remain thread-unsafe forever).
106 So we need to use a lock around all uses of Tcl. Previously, the Python
107 interpreter lock was used for this. However, this causes problems when
108 other Python threads need to run while Tcl is blocked waiting for events.
109
110 To solve this problem, a separate lock for Tcl is introduced. Holding it
111 is incompatible with holding Python's interpreter lock. The following four
112 macros manipulate both locks together.
113
114 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
115 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
116 that could call an event handler, or otherwise affect the state of a Tcl
117 interpreter. These assume that the surrounding code has the Python
118 interpreter lock; inside the brackets, the Python interpreter lock has been
119 released and the lock for Tcl has been acquired.
120
Guido van Rossum5e977831998-06-15 14:03:52 +0000121 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
122 (For example, when transferring data from the Tcl interpreter result to a
123 Python string object.) This can be done by using different macros to close
124 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
125 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
126 releases the Tcl lock.
127
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000128 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000129 handlers when the handler needs to use Python. Such event handlers are
130 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000131 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000132 the Python interpreter lock, restoring the appropriate thread state, and
133 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
134 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000135 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000136
137 These locks expand to several statements and brackets; they should not be
138 used in branches of if statements and the like.
139
140*/
141
Guido van Rossum65d5b571998-12-21 19:32:43 +0000142static PyThread_type_lock tcl_lock = 0;
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000143static PyThreadState *tcl_tstate = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000144
145#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000146 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000147 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000148
149#define LEAVE_TCL \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000150 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000151
Guido van Rossum62320c91998-06-15 04:36:09 +0000152#define ENTER_OVERLAP \
153 Py_END_ALLOW_THREADS
154
155#define LEAVE_OVERLAP_TCL \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000156 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000157
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000158#define ENTER_PYTHON \
159 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000160 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000161
162#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000163 { PyThreadState *tstate = PyEval_SaveThread(); \
Guido van Rossum65d5b571998-12-21 19:32:43 +0000164 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Guido van Rossum00d93061998-05-28 23:06:38 +0000165
166#else
167
168#define ENTER_TCL
169#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000170#define ENTER_OVERLAP
171#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000172#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000173#define LEAVE_PYTHON
174
175#endif
176
Guido van Rossumec22c921996-02-25 04:50:29 +0000177#ifdef macintosh
178
179/*
180** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000181** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000182*/
183
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000184/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000185#define FREECAST (char *)
186
Guido van Rossumec22c921996-02-25 04:50:29 +0000187#include <Events.h> /* For EventRecord */
188
Fred Drake509d79a2000-07-08 04:04:38 +0000189typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
190void Tcl_MacSetEventProc (TclMacConvertEventPtr procPtr);
191int TkMacConvertEvent (EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000192
Fred Drake509d79a2000-07-08 04:04:38 +0000193staticforward int PyMacConvertEvent (EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000194
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000195#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
196 #pragma import on
197#endif
198
199#include <SIOUX.h>
200extern int SIOUXIsAppWindow(WindowPtr);
201
202#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
203 #pragma import reset
204#endif
Guido van Rossumec22c921996-02-25 04:50:29 +0000205#endif /* macintosh */
206
Guido van Rossum97867b21996-08-08 19:09:53 +0000207#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000208#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000209#endif
210
Guido van Rossum18468821994-06-20 07:49:28 +0000211/**** Tkapp Object Declaration ****/
212
213staticforward PyTypeObject Tkapp_Type;
214
Guido van Rossum00d93061998-05-28 23:06:38 +0000215typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000216 PyObject_HEAD
217 Tcl_Interp *interp;
Guido van Rossum00d93061998-05-28 23:06:38 +0000218} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000219
220#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000221#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
222#define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
223
Guido van Rossum35d43371997-08-02 00:09:09 +0000224#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000225(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000226
Barry Warsawfa701a81997-01-16 00:15:11 +0000227
228
Guido van Rossum18468821994-06-20 07:49:28 +0000229/**** Error Handling ****/
230
231static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000232static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000233static int errorInCmd = 0;
234static PyObject *excInCmd;
235static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000236static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000237
Barry Warsawfa701a81997-01-16 00:15:11 +0000238
239
Guido van Rossum18468821994-06-20 07:49:28 +0000240static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000241Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000242{
Barry Warsawfa701a81997-01-16 00:15:11 +0000243 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
244 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000245}
246
Barry Warsawfa701a81997-01-16 00:15:11 +0000247
Barry Warsawfa701a81997-01-16 00:15:11 +0000248
Guido van Rossum18468821994-06-20 07:49:28 +0000249/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000250
251#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000252#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000253
Guido van Rossum00d93061998-05-28 23:06:38 +0000254/* Millisecond sleep() for Unix platforms. */
255
256static void
Fred Drake509d79a2000-07-08 04:04:38 +0000257Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000258{
259 /* XXX Too bad if you don't have select(). */
260 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000261 t.tv_sec = milli/1000;
262 t.tv_usec = (milli%1000) * 1000;
263 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
264}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000265#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000266#endif /* WITH_THREAD */
267
268
Guido van Rossum18468821994-06-20 07:49:28 +0000269static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000270AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000271{
Guido van Rossum35d43371997-08-02 00:09:09 +0000272 if (PyString_Check(value))
273 return PyString_AsString(value);
Barry Warsawfa701a81997-01-16 00:15:11 +0000274 else {
275 PyObject *v = PyObject_Str(value);
276 PyList_Append(tmp, v);
277 Py_DECREF(v);
278 return PyString_AsString(v);
279 }
Guido van Rossum18468821994-06-20 07:49:28 +0000280}
281
Barry Warsawfa701a81997-01-16 00:15:11 +0000282
283
Guido van Rossum18468821994-06-20 07:49:28 +0000284#define ARGSZ 64
285
286static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000287Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000288{
Barry Warsawfa701a81997-01-16 00:15:11 +0000289 PyObject *tmp = NULL;
290 char *argvStore[ARGSZ];
291 char **argv = NULL;
292 int fvStore[ARGSZ];
293 int *fv = NULL;
294 int argc = 0, i;
295 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000296
Barry Warsawfa701a81997-01-16 00:15:11 +0000297 if (!(tmp = PyList_New(0)))
298 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000299
Barry Warsawfa701a81997-01-16 00:15:11 +0000300 argv = argvStore;
301 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000302
Barry Warsawfa701a81997-01-16 00:15:11 +0000303 if (args == NULL)
304 argc = 0;
305
306 else if (!PyTuple_Check(args)) {
307 argc = 1;
308 fv[0] = 0;
309 argv[0] = AsString(args, tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000310 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000311 else {
312 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000313
Barry Warsawfa701a81997-01-16 00:15:11 +0000314 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000315 argv = (char **)ckalloc(argc * sizeof(char *));
316 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000317 if (argv == NULL || fv == NULL) {
318 PyErr_NoMemory();
319 goto finally;
320 }
321 }
322
323 for (i = 0; i < argc; i++) {
324 PyObject *v = PyTuple_GetItem(args, i);
325 if (PyTuple_Check(v)) {
326 fv[i] = 1;
327 if (!(argv[i] = Merge(v)))
328 goto finally;
329 }
330 else if (v == Py_None) {
331 argc = i;
332 break;
333 }
334 else {
335 fv[i] = 0;
336 argv[i] = AsString(v, tmp);
337 }
338 }
Guido van Rossum18468821994-06-20 07:49:28 +0000339 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000340 res = Tcl_Merge(argc, argv);
Guido van Rossum18468821994-06-20 07:49:28 +0000341
Barry Warsawfa701a81997-01-16 00:15:11 +0000342 finally:
343 for (i = 0; i < argc; i++)
344 if (fv[i]) {
345 ckfree(argv[i]);
346 }
347 if (argv != argvStore)
348 ckfree(FREECAST argv);
349 if (fv != fvStore)
350 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000351
Barry Warsawfa701a81997-01-16 00:15:11 +0000352 Py_DECREF(tmp);
353 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000354}
355
Barry Warsawfa701a81997-01-16 00:15:11 +0000356
357
Guido van Rossum18468821994-06-20 07:49:28 +0000358static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000359Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000360{
Barry Warsawfa701a81997-01-16 00:15:11 +0000361 int argc;
362 char **argv;
363 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000364
Barry Warsawfa701a81997-01-16 00:15:11 +0000365 if (list == NULL) {
366 Py_INCREF(Py_None);
367 return Py_None;
368 }
Guido van Rossum18468821994-06-20 07:49:28 +0000369
Guido van Rossum00d93061998-05-28 23:06:38 +0000370 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 /* Not a list.
372 * Could be a quoted string containing funnies, e.g. {"}.
373 * Return the string itself.
374 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000375 return PyString_FromString(list);
376 }
Guido van Rossum18468821994-06-20 07:49:28 +0000377
Barry Warsawfa701a81997-01-16 00:15:11 +0000378 if (argc == 0)
379 v = PyString_FromString("");
380 else if (argc == 1)
381 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000382 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000383 int i;
384 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000385
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000387 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000388 Py_DECREF(v);
389 v = NULL;
390 break;
391 }
392 PyTuple_SetItem(v, i, w);
393 }
394 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000395 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000396 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000397}
398
Barry Warsawfa701a81997-01-16 00:15:11 +0000399
400
Guido van Rossum18468821994-06-20 07:49:28 +0000401/**** Tkapp Object ****/
402
403#ifndef WITH_APPINIT
404int
Fred Drake509d79a2000-07-08 04:04:38 +0000405Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000406{
Barry Warsawfa701a81997-01-16 00:15:11 +0000407 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000408
Barry Warsawfa701a81997-01-16 00:15:11 +0000409 main = Tk_MainWindow(interp);
410 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000411 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000412 return TCL_ERROR;
413 }
414 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumb41addf1998-05-12 15:02:41 +0000415 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
Barry Warsawfa701a81997-01-16 00:15:11 +0000416 return TCL_ERROR;
417 }
418 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000419}
420#endif /* !WITH_APPINIT */
421
Guido van Rossum18468821994-06-20 07:49:28 +0000422
Barry Warsawfa701a81997-01-16 00:15:11 +0000423
424
425/* Initialize the Tk application; see the `main' function in
426 * `tkMain.c'.
427 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000428
Thomas Wouters58d05102000-07-24 14:43:35 +0000429static void EnableEventHook(void); /* Forward */
430static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000431
Barry Warsawfa701a81997-01-16 00:15:11 +0000432static TkappObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000433Tkapp_New(char *screenName, char *baseName, char *className, int interactive)
Barry Warsawfa701a81997-01-16 00:15:11 +0000434{
435 TkappObject *v;
436 char *argv0;
437
Guido van Rossumb18618d2000-05-03 23:44:39 +0000438 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000439 if (v == NULL)
440 return NULL;
441
442 v->interp = Tcl_CreateInterp();
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000443
Guido van Rossuma80649b2000-03-28 20:07:05 +0000444#if defined(macintosh)
445 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000446 ClearMenuBar();
447 TkMacInitMenus(v->interp);
448#endif
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000449 /* Delete the 'exit' command, which can screw things up */
450 Tcl_DeleteCommand(v->interp, "exit");
451
Barry Warsawfa701a81997-01-16 00:15:11 +0000452 if (screenName != NULL)
453 Tcl_SetVar2(v->interp, "env", "DISPLAY",
454 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000455
Barry Warsawfa701a81997-01-16 00:15:11 +0000456 if (interactive)
457 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
458 else
459 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000460
Barry Warsawfa701a81997-01-16 00:15:11 +0000461 /* This is used to get the application class for Tk 4.1 and up */
462 argv0 = (char*)ckalloc(strlen(className) + 1);
463 if (!argv0) {
464 PyErr_NoMemory();
465 Py_DECREF(v);
466 return NULL;
467 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000468
Barry Warsawfa701a81997-01-16 00:15:11 +0000469 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000470 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000471 argv0[0] = tolower(argv0[0]);
472 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
473 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000474
Barry Warsawfa701a81997-01-16 00:15:11 +0000475 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000476 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000477
Guido van Rossum7bf15641998-05-22 18:28:17 +0000478 EnableEventHook();
479
Barry Warsawfa701a81997-01-16 00:15:11 +0000480 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000481}
482
Barry Warsawfa701a81997-01-16 00:15:11 +0000483
484
Guido van Rossum18468821994-06-20 07:49:28 +0000485/** Tcl Eval **/
486
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000487#if TKMAJORMINOR >= 8001
488#define USING_OBJECTS
489#endif
490
491#ifdef USING_OBJECTS
492
493static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000494AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000495{
496 Tcl_Obj *result;
497
498 if (PyString_Check(value))
499 return Tcl_NewStringObj(PyString_AS_STRING(value),
500 PyString_GET_SIZE(value));
501 else if (PyInt_Check(value))
502 return Tcl_NewLongObj(PyInt_AS_LONG(value));
503 else if (PyFloat_Check(value))
504 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
505 else if (PyTuple_Check(value)) {
506 Tcl_Obj **argv = (Tcl_Obj**)
507 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
508 int i;
509 if(!argv)
510 return 0;
511 for(i=0;i<PyTuple_Size(value);i++)
512 argv[i] = AsObj(PyTuple_GetItem(value,i));
513 result = Tcl_NewListObj(PyTuple_Size(value), argv);
514 ckfree(FREECAST argv);
515 return result;
516 }
517 else if (PyUnicode_Check(value)) {
Guido van Rossum990f5c62000-05-04 15:07:16 +0000518#if TKMAJORMINOR <= 8001
519 /* In Tcl 8.1 we must use UTF-8 */
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000520 PyObject* utf8 = PyUnicode_AsUTF8String (value);
521 if (!utf8)
522 return 0;
Guido van Rossum8823acc2000-04-27 20:14:31 +0000523 result = Tcl_NewStringObj (PyString_AS_STRING (utf8),
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000524 PyString_GET_SIZE (utf8));
Guido van Rossum8823acc2000-04-27 20:14:31 +0000525 Py_DECREF(utf8);
526 return result;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000527#else /* TKMAJORMINOR > 8001 */
528 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
529 if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) {
530 /* XXX Should really test this at compile time */
531 PyErr_SetString(PyExc_SystemError,
532 "Py_UNICODE and Tcl_UniChar differ in size");
533 return 0;
534 }
535 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value),
536 PyUnicode_GET_SIZE(value));
537#endif /* TKMAJORMINOR > 8001 */
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000538 }
539 else {
540 PyObject *v = PyObject_Str(value);
541 if (!v)
542 return 0;
543 result = AsObj(v);
544 Py_DECREF(v);
545 return result;
546 }
547}
548
Guido van Rossum18468821994-06-20 07:49:28 +0000549static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000550Tkapp_Call(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000551{
Guido van Rossum632de272000-03-29 00:19:50 +0000552 Tcl_Obj *objStore[ARGSZ];
553 Tcl_Obj **objv = NULL;
554 int objc = 0, i;
555 PyObject *res = NULL;
556 Tcl_Interp *interp = Tkapp_Interp(self);
557 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
558 int flags = TCL_EVAL_DIRECT;
Guido van Rossum18468821994-06-20 07:49:28 +0000559
Guido van Rossum632de272000-03-29 00:19:50 +0000560 objv = objStore;
Barry Warsawfa701a81997-01-16 00:15:11 +0000561
Guido van Rossum212643f1998-04-29 16:22:14 +0000562 if (args == NULL)
Guido van Rossum632de272000-03-29 00:19:50 +0000563 objc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000564
Guido van Rossum212643f1998-04-29 16:22:14 +0000565 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +0000566 objc = 1;
567 objv[0] = AsObj(args);
568 if (objv[0] == 0)
569 goto finally;
570 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000571 }
572 else {
Guido van Rossum632de272000-03-29 00:19:50 +0000573 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +0000574
Guido van Rossum632de272000-03-29 00:19:50 +0000575 if (objc > ARGSZ) {
576 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
577 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +0000578 PyErr_NoMemory();
579 goto finally;
580 }
581 }
582
Guido van Rossum632de272000-03-29 00:19:50 +0000583 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +0000584 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +0000585 if (v == Py_None) {
586 objc = i;
587 break;
588 }
Guido van Rossum632de272000-03-29 00:19:50 +0000589 objv[i] = AsObj(v);
590 if (!objv[i])
591 goto finally;
592 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +0000593 }
594 }
Guido van Rossum212643f1998-04-29 16:22:14 +0000595
Guido van Rossum62320c91998-06-15 04:36:09 +0000596 ENTER_TCL
Guido van Rossum632de272000-03-29 00:19:50 +0000597
598 i = Tcl_EvalObjv(interp, objc, objv, flags);
599
Guido van Rossum62320c91998-06-15 04:36:09 +0000600 ENTER_OVERLAP
Guido van Rossum632de272000-03-29 00:19:50 +0000601 if (i == TCL_ERROR)
Guido van Rossum212643f1998-04-29 16:22:14 +0000602 Tkinter_Error(self);
Guido van Rossum990f5c62000-05-04 15:07:16 +0000603 else {
Guido van Rossum632de272000-03-29 00:19:50 +0000604 /* We could request the object result here, but doing
605 so would confuse applications that expect a string. */
Guido van Rossum990f5c62000-05-04 15:07:16 +0000606 char *s = Tcl_GetStringResult(interp);
607 char *p = s;
608 /* If the result contains any bytes with the top bit set,
609 it's UTF-8 and we should decode it to Unicode */
610 while (*p != '\0') {
611 if (*p & 0x80)
612 break;
613 p++;
614 }
615 if (*p == '\0')
616 res = PyString_FromStringAndSize(s, (int)(p-s));
617 else {
618 /* Convert UTF-8 to Unicode string */
619 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +0000620 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
621 if (res == NULL) {
622 PyErr_Clear();
623 res = PyString_FromStringAndSize(s, (int)(p-s));
624 }
Guido van Rossum990f5c62000-05-04 15:07:16 +0000625 }
626 }
Guido van Rossum632de272000-03-29 00:19:50 +0000627
Guido van Rossum62320c91998-06-15 04:36:09 +0000628 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000629
Guido van Rossum212643f1998-04-29 16:22:14 +0000630 finally:
Guido van Rossum632de272000-03-29 00:19:50 +0000631 for (i = 0; i < objc; i++)
632 Tcl_DecrRefCount(objv[i]);
633 if (objv != objStore)
634 ckfree(FREECAST objv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000635 return res;
636}
637
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000638#else /* !USING_OBJECTS */
639
640static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000641Tkapp_Call(PyObject *self, PyObject *args)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000642{
643 /* This is copied from Merge() */
644 PyObject *tmp = NULL;
645 char *argvStore[ARGSZ];
646 char **argv = NULL;
647 int fvStore[ARGSZ];
648 int *fv = NULL;
649 int argc = 0, i;
650 PyObject *res = NULL; /* except this has a different type */
651 Tcl_CmdInfo info; /* and this is added */
652 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
653
654 if (!(tmp = PyList_New(0)))
655 return NULL;
656
657 argv = argvStore;
658 fv = fvStore;
659
660 if (args == NULL)
661 argc = 0;
662
663 else if (!PyTuple_Check(args)) {
664 argc = 1;
665 fv[0] = 0;
666 argv[0] = AsString(args, tmp);
667 }
668 else {
669 argc = PyTuple_Size(args);
670
671 if (argc > ARGSZ) {
672 argv = (char **)ckalloc(argc * sizeof(char *));
673 fv = (int *)ckalloc(argc * sizeof(int));
674 if (argv == NULL || fv == NULL) {
675 PyErr_NoMemory();
676 goto finally;
677 }
678 }
679
680 for (i = 0; i < argc; i++) {
681 PyObject *v = PyTuple_GetItem(args, i);
682 if (PyTuple_Check(v)) {
683 fv[i] = 1;
684 if (!(argv[i] = Merge(v)))
685 goto finally;
686 }
687 else if (v == Py_None) {
688 argc = i;
689 break;
690 }
691 else {
692 fv[i] = 0;
693 argv[i] = AsString(v, tmp);
694 }
695 }
696 }
697 /* End code copied from Merge() */
698
699 /* All this to avoid a call to Tcl_Merge() and the corresponding call
700 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
701 if (Py_VerboseFlag >= 2) {
702 for (i = 0; i < argc; i++)
703 PySys_WriteStderr("%s ", argv[i]);
704 }
705 ENTER_TCL
706 info.proc = NULL;
707 if (argc < 1 ||
708 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
709 info.proc == NULL)
710 {
711 char *cmd;
712 cmd = Tcl_Merge(argc, argv);
713 i = Tcl_Eval(interp, cmd);
714 ckfree(cmd);
715 }
716 else {
717 Tcl_ResetResult(interp);
718 i = (*info.proc)(info.clientData, interp, argc, argv);
719 }
720 ENTER_OVERLAP
721 if (info.proc == NULL && Py_VerboseFlag >= 2)
722 PySys_WriteStderr("... use TclEval ");
723 if (i == TCL_ERROR) {
724 if (Py_VerboseFlag >= 2)
725 PySys_WriteStderr("... error: '%s'\n",
726 interp->result);
727 Tkinter_Error(self);
728 }
729 else {
730 if (Py_VerboseFlag >= 2)
731 PySys_WriteStderr("-> '%s'\n", interp->result);
732 res = PyString_FromString(interp->result);
733 }
734 LEAVE_OVERLAP_TCL
735
736 /* Copied from Merge() again */
737 finally:
738 for (i = 0; i < argc; i++)
739 if (fv[i]) {
740 ckfree(argv[i]);
741 }
742 if (argv != argvStore)
743 ckfree(FREECAST argv);
744 if (fv != fvStore)
745 ckfree(FREECAST fv);
746
747 Py_DECREF(tmp);
748 return res;
749}
750
751#endif /* !USING_OBJECTS */
Barry Warsawfa701a81997-01-16 00:15:11 +0000752
753static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000754Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +0000755{
Guido van Rossum212643f1998-04-29 16:22:14 +0000756 /* Could do the same here as for Tkapp_Call(), but this is not used
757 much, so I can't be bothered. Unfortunately Tcl doesn't export a
758 way for the user to do what all its Global* variants do (save and
759 reset the scope pointer, call the local version, restore the saved
760 scope pointer). */
761
Guido van Rossum62320c91998-06-15 04:36:09 +0000762 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +0000763 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000764
Guido van Rossum62320c91998-06-15 04:36:09 +0000765 cmd = Merge(args);
Barry Warsawfa701a81997-01-16 00:15:11 +0000766 if (!cmd)
767 PyErr_SetString(Tkinter_TclError, "merge failed");
768
Guido van Rossum00d93061998-05-28 23:06:38 +0000769 else {
770 int err;
771 ENTER_TCL
772 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +0000773 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000774 if (err == TCL_ERROR)
775 res = Tkinter_Error(self);
776 else
777 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +0000778 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +0000779 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000780
781 if (cmd)
782 ckfree(cmd);
783
784 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000785}
786
787static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000788Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000789{
Barry Warsawfa701a81997-01-16 00:15:11 +0000790 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000791 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000792 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000793
Guido van Rossum43713e52000-02-29 13:59:29 +0000794 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000795 return NULL;
796
Guido van Rossum00d93061998-05-28 23:06:38 +0000797 ENTER_TCL
798 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000799 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000800 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000801 res = Tkinter_Error(self);
802 else
803 res = PyString_FromString(Tkapp_Result(self));
804 LEAVE_OVERLAP_TCL
805 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000806}
807
808static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000809Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000810{
Barry Warsawfa701a81997-01-16 00:15:11 +0000811 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000812 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000813 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +0000814
Guido van Rossum43713e52000-02-29 13:59:29 +0000815 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000816 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000817
Guido van Rossum00d93061998-05-28 23:06:38 +0000818 ENTER_TCL
819 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +0000820 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000821 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000822 res = Tkinter_Error(self);
823 else
824 res = PyString_FromString(Tkapp_Result(self));
825 LEAVE_OVERLAP_TCL
826 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000827}
828
829static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000830Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000831{
Barry Warsawfa701a81997-01-16 00:15:11 +0000832 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +0000833 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000834 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000835
Guido van Rossum43713e52000-02-29 13:59:29 +0000836 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +0000837 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000838
Guido van Rossum00d93061998-05-28 23:06:38 +0000839 ENTER_TCL
840 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +0000841 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000842 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000843 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +0000844
Guido van Rossum62320c91998-06-15 04:36:09 +0000845 else
846 res = PyString_FromString(Tkapp_Result(self));
847 LEAVE_OVERLAP_TCL
848 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000849}
850
851static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000852Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000853{
Barry Warsawfa701a81997-01-16 00:15:11 +0000854 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +0000855 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000856 int err;
Guido van Rossum18468821994-06-20 07:49:28 +0000857
Guido van Rossum35d43371997-08-02 00:09:09 +0000858 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +0000859 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000860
Guido van Rossum00d93061998-05-28 23:06:38 +0000861 ENTER_TCL
862 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +0000863 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +0000864 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +0000865 res = Tkinter_Error(self);
866 else
867 res = PyString_FromString(Tkapp_Result(self));
868 LEAVE_OVERLAP_TCL
869 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000870}
871
872static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000873Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000874{
Barry Warsawfa701a81997-01-16 00:15:11 +0000875 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +0000876
Guido van Rossum43713e52000-02-29 13:59:29 +0000877 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +0000878 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000879 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +0000880 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +0000881 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +0000882
Barry Warsawfa701a81997-01-16 00:15:11 +0000883 Py_INCREF(Py_None);
884 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000885}
886
Barry Warsawfa701a81997-01-16 00:15:11 +0000887
888
Guido van Rossum18468821994-06-20 07:49:28 +0000889/** Tcl Variable **/
890
891static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000892SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000893{
Guido van Rossum00d93061998-05-28 23:06:38 +0000894 char *name1, *name2, *ok, *s;
Barry Warsawfa701a81997-01-16 00:15:11 +0000895 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +0000896 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +0000897
Guido van Rossum62320c91998-06-15 04:36:09 +0000898 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +0000899 if (!tmp)
900 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000901
Guido van Rossum43713e52000-02-29 13:59:29 +0000902 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000903 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +0000904 s = AsString(newValue, tmp);
905 ENTER_TCL
906 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
907 LEAVE_TCL
908 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000909 else {
Guido van Rossum35d43371997-08-02 00:09:09 +0000910 PyErr_Clear();
Guido van Rossum43713e52000-02-29 13:59:29 +0000911 if (PyArg_ParseTuple(args, "ssO:setvar", &name1, &name2, &newValue)) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000912 s = AsString (newValue, tmp);
913 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000914 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
Guido van Rossum00d93061998-05-28 23:06:38 +0000915 s, flags);
916 LEAVE_TCL
917 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000918 else {
Guido van Rossum00d93061998-05-28 23:06:38 +0000919 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +0000920 return NULL;
921 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000922 }
Guido van Rossum35d43371997-08-02 00:09:09 +0000923 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +0000924
Barry Warsawfa701a81997-01-16 00:15:11 +0000925 if (!ok)
926 return Tkinter_Error(self);
927
928 Py_INCREF(Py_None);
929 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +0000930}
931
932static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000933Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000934{
Barry Warsawfa701a81997-01-16 00:15:11 +0000935 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000936}
937
938static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000939Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000940{
Barry Warsawfa701a81997-01-16 00:15:11 +0000941 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000942}
943
Barry Warsawfa701a81997-01-16 00:15:11 +0000944
945
Guido van Rossum18468821994-06-20 07:49:28 +0000946static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000947GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000948{
Guido van Rossum35d43371997-08-02 00:09:09 +0000949 char *name1, *name2=NULL, *s;
Guido van Rossum62320c91998-06-15 04:36:09 +0000950 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000951
Guido van Rossum43713e52000-02-29 13:59:29 +0000952 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +0000953 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000954 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000955 if (name2 == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000956 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
Guido van Rossum18468821994-06-20 07:49:28 +0000957
Barry Warsawfa701a81997-01-16 00:15:11 +0000958 else
Guido van Rossum35d43371997-08-02 00:09:09 +0000959 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000960 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +0000961
Barry Warsawfa701a81997-01-16 00:15:11 +0000962 if (s == NULL)
Guido van Rossum62320c91998-06-15 04:36:09 +0000963 res = Tkinter_Error(self);
964 else
965 res = PyString_FromString(s);
966 LEAVE_OVERLAP_TCL
967 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000968}
969
970static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000971Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000972{
Barry Warsawfa701a81997-01-16 00:15:11 +0000973 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +0000974}
975
976static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000977Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000978{
Barry Warsawfa701a81997-01-16 00:15:11 +0000979 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000980}
981
Barry Warsawfa701a81997-01-16 00:15:11 +0000982
983
Guido van Rossum18468821994-06-20 07:49:28 +0000984static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000985UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +0000986{
Guido van Rossum35d43371997-08-02 00:09:09 +0000987 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +0000988 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000989 int code;
Guido van Rossum18468821994-06-20 07:49:28 +0000990
Guido van Rossum43713e52000-02-29 13:59:29 +0000991 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +0000992 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +0000993 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +0000994 if (name2 == NULL)
995 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
996
997 else
998 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
Guido van Rossum62320c91998-06-15 04:36:09 +0000999 ENTER_OVERLAP
Guido van Rossum18468821994-06-20 07:49:28 +00001000
Barry Warsawfa701a81997-01-16 00:15:11 +00001001 if (code == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001002 res = Tkinter_Error(self);
1003 else {
1004 Py_INCREF(Py_None);
1005 res = Py_None;
1006 }
1007 LEAVE_OVERLAP_TCL
1008 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001009}
1010
1011static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001012Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001013{
Barry Warsawfa701a81997-01-16 00:15:11 +00001014 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001015}
1016
1017static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001018Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001019{
Barry Warsawfa701a81997-01-16 00:15:11 +00001020 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001021}
1022
Barry Warsawfa701a81997-01-16 00:15:11 +00001023
1024
Guido van Rossum18468821994-06-20 07:49:28 +00001025/** Tcl to Python **/
1026
1027static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001028Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001029{
Barry Warsawfa701a81997-01-16 00:15:11 +00001030 char *s;
1031 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001032
Guido van Rossum43713e52000-02-29 13:59:29 +00001033 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001034 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001035 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001036 return Tkinter_Error(self);
1037 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001038}
1039
1040static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001041Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001042{
Barry Warsawfa701a81997-01-16 00:15:11 +00001043 char *s;
1044 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001045
Guido van Rossum43713e52000-02-29 13:59:29 +00001046 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001047 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001048 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001049 return Tkinter_Error(self);
1050 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001051}
1052
1053static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001054Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001055{
Barry Warsawfa701a81997-01-16 00:15:11 +00001056 char *s;
1057 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001058
Guido van Rossum43713e52000-02-29 13:59:29 +00001059 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001060 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001061 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1062 return Tkinter_Error(self);
Barry Warsawfa701a81997-01-16 00:15:11 +00001063 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001064}
1065
1066static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001067Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001068{
Barry Warsawfa701a81997-01-16 00:15:11 +00001069 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001070 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001071 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001072
Guido van Rossum43713e52000-02-29 13:59:29 +00001073 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001074 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001075 ENTER_TCL
1076 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001077 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001078 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001079 res = Tkinter_Error(self);
1080 else
1081 res = Py_BuildValue("s", Tkapp_Result(self));
1082 LEAVE_OVERLAP_TCL
1083 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001084}
1085
1086static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001087Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001088{
Barry Warsawfa701a81997-01-16 00:15:11 +00001089 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001090 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001091 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001092 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001093
Guido van Rossum43713e52000-02-29 13:59:29 +00001094 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001095 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001096 ENTER_TCL
1097 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001098 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001099 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001100 res = Tkinter_Error(self);
1101 else
1102 res = Py_BuildValue("l", v);
1103 LEAVE_OVERLAP_TCL
1104 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001105}
1106
1107static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001108Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001109{
Barry Warsawfa701a81997-01-16 00:15:11 +00001110 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001111 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001112 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001113 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001114
Guido van Rossum43713e52000-02-29 13:59:29 +00001115 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001116 return NULL;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001117 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001118 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001119 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001120 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001121 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001122 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001123 res = Tkinter_Error(self);
1124 else
1125 res = Py_BuildValue("d", v);
1126 LEAVE_OVERLAP_TCL
1127 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001128}
1129
1130static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001131Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001132{
Barry Warsawfa701a81997-01-16 00:15:11 +00001133 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001134 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001135 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001136 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001137
Guido van Rossum43713e52000-02-29 13:59:29 +00001138 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001139 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001140 ENTER_TCL
1141 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001142 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001143 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001144 res = Tkinter_Error(self);
1145 else
1146 res = Py_BuildValue("i", v);
1147 LEAVE_OVERLAP_TCL
1148 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001149}
1150
Barry Warsawfa701a81997-01-16 00:15:11 +00001151
1152
Guido van Rossum18468821994-06-20 07:49:28 +00001153static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001154Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001155{
Barry Warsawfa701a81997-01-16 00:15:11 +00001156 char *list;
1157 int argc;
1158 char **argv;
1159 PyObject *v;
1160 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001161
Guido van Rossum43713e52000-02-29 13:59:29 +00001162 if (!PyArg_ParseTuple(args, "s:splitlist", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001163 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001164
Barry Warsawfa701a81997-01-16 00:15:11 +00001165 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1166 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001167
Barry Warsawfa701a81997-01-16 00:15:11 +00001168 if (!(v = PyTuple_New(argc)))
1169 return NULL;
1170
1171 for (i = 0; i < argc; i++) {
1172 PyObject *s = PyString_FromString(argv[i]);
1173 if (!s || PyTuple_SetItem(v, i, s)) {
1174 Py_DECREF(v);
1175 v = NULL;
1176 goto finally;
1177 }
1178 }
Guido van Rossum18468821994-06-20 07:49:28 +00001179
Barry Warsawfa701a81997-01-16 00:15:11 +00001180 finally:
1181 ckfree(FREECAST argv);
1182 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001183}
1184
1185static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001186Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001187{
Barry Warsawfa701a81997-01-16 00:15:11 +00001188 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001189
Guido van Rossum43713e52000-02-29 13:59:29 +00001190 if (!PyArg_ParseTuple(args, "s:split", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001191 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001192 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001193}
1194
1195static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001196Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001197{
Barry Warsawfa701a81997-01-16 00:15:11 +00001198 char *s = Merge(args);
1199 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001200
Barry Warsawfa701a81997-01-16 00:15:11 +00001201 if (s) {
1202 res = PyString_FromString(s);
1203 ckfree(s);
1204 }
1205 else
1206 PyErr_SetString(Tkinter_TclError, "merge failed");
1207
1208 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001209}
1210
Barry Warsawfa701a81997-01-16 00:15:11 +00001211
1212
Guido van Rossum18468821994-06-20 07:49:28 +00001213/** Tcl Command **/
1214
Guido van Rossum00d93061998-05-28 23:06:38 +00001215/* Client data struct */
1216typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001217 PyObject *self;
1218 PyObject *func;
1219} PythonCmd_ClientData;
1220
1221static int
Fred Drake509d79a2000-07-08 04:04:38 +00001222PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001223{
1224 errorInCmd = 1;
1225 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1226 LEAVE_PYTHON
1227 return TCL_ERROR;
1228}
1229
Guido van Rossum18468821994-06-20 07:49:28 +00001230/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001231 * function or method.
1232 */
Guido van Rossum18468821994-06-20 07:49:28 +00001233static int
Fred Drake509d79a2000-07-08 04:04:38 +00001234PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001235{
Guido van Rossum00d93061998-05-28 23:06:38 +00001236 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001237 PyObject *self, *func, *arg, *res, *tmp;
1238 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001239
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001240 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001241
Barry Warsawfa701a81997-01-16 00:15:11 +00001242 /* TBD: no error checking here since we know, via the
1243 * Tkapp_CreateCommand() that the client data is a two-tuple
1244 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001245 self = data->self;
1246 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001247
Barry Warsawfa701a81997-01-16 00:15:11 +00001248 /* Create argument list (argv1, ..., argvN) */
1249 if (!(arg = PyTuple_New(argc - 1)))
1250 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001251
Barry Warsawfa701a81997-01-16 00:15:11 +00001252 for (i = 0; i < (argc - 1); i++) {
1253 PyObject *s = PyString_FromString(argv[i + 1]);
1254 if (!s || PyTuple_SetItem(arg, i, s)) {
1255 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001256 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001257 }
1258 }
1259 res = PyEval_CallObject(func, arg);
1260 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001261
Barry Warsawfa701a81997-01-16 00:15:11 +00001262 if (res == NULL)
1263 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001264
Barry Warsawfa701a81997-01-16 00:15:11 +00001265 if (!(tmp = PyList_New(0))) {
1266 Py_DECREF(res);
1267 return PythonCmd_Error(interp);
1268 }
1269
1270 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1271 Py_DECREF(res);
1272 Py_DECREF(tmp);
1273
Guido van Rossum00d93061998-05-28 23:06:38 +00001274 LEAVE_PYTHON
1275
Barry Warsawfa701a81997-01-16 00:15:11 +00001276 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +00001277}
1278
1279static void
Fred Drake509d79a2000-07-08 04:04:38 +00001280PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001281{
Guido van Rossum00d93061998-05-28 23:06:38 +00001282 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1283
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001284 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001285 Py_XDECREF(data->self);
1286 Py_XDECREF(data->func);
1287 PyMem_DEL(data);
1288 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001289}
1290
Barry Warsawfa701a81997-01-16 00:15:11 +00001291
1292
Guido van Rossum18468821994-06-20 07:49:28 +00001293static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001294Tkapp_CreateCommand(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001295{
Guido van Rossum00d93061998-05-28 23:06:38 +00001296 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00001297 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00001298 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001299 Tcl_Command err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001300
Guido van Rossum43713e52000-02-29 13:59:29 +00001301 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00001302 return NULL;
1303 if (!PyCallable_Check(func)) {
1304 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00001305 return NULL;
1306 }
Guido van Rossum18468821994-06-20 07:49:28 +00001307
Guido van Rossum00d93061998-05-28 23:06:38 +00001308 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00001309 if (!data)
1310 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001311 Py_XINCREF(self);
1312 Py_XINCREF(func);
1313 data->self = self;
1314 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00001315
Guido van Rossum00d93061998-05-28 23:06:38 +00001316 ENTER_TCL
1317 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1318 (ClientData)data, PythonCmdDelete);
1319 LEAVE_TCL
1320 if (err == NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001321 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00001322 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00001323 return NULL;
1324 }
Guido van Rossum18468821994-06-20 07:49:28 +00001325
Barry Warsawfa701a81997-01-16 00:15:11 +00001326 Py_INCREF(Py_None);
1327 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001328}
1329
Barry Warsawfa701a81997-01-16 00:15:11 +00001330
1331
Guido van Rossum18468821994-06-20 07:49:28 +00001332static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001333Tkapp_DeleteCommand(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001334{
Barry Warsawfa701a81997-01-16 00:15:11 +00001335 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00001336 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001337
Guido van Rossum43713e52000-02-29 13:59:29 +00001338 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001339 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001340 ENTER_TCL
1341 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1342 LEAVE_TCL
1343 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001344 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1345 return NULL;
1346 }
1347 Py_INCREF(Py_None);
1348 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001349}
1350
Barry Warsawfa701a81997-01-16 00:15:11 +00001351
1352
Guido van Rossum00d93061998-05-28 23:06:38 +00001353#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00001354/** File Handler **/
1355
Guido van Rossum00d93061998-05-28 23:06:38 +00001356typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00001357 PyObject *func;
1358 PyObject *file;
1359 int id;
1360 struct _fhcdata *next;
1361} FileHandler_ClientData;
1362
1363static FileHandler_ClientData *HeadFHCD;
1364
1365static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00001366NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00001367{
1368 FileHandler_ClientData *p;
1369 p = PyMem_NEW(FileHandler_ClientData, 1);
1370 if (p != NULL) {
1371 Py_XINCREF(func);
1372 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00001373 p->func = func;
1374 p->file = file;
1375 p->id = id;
1376 p->next = HeadFHCD;
1377 HeadFHCD = p;
1378 }
1379 return p;
1380}
1381
1382static void
Fred Drake509d79a2000-07-08 04:04:38 +00001383DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00001384{
1385 FileHandler_ClientData *p, **pp;
1386
1387 pp = &HeadFHCD;
1388 while ((p = *pp) != NULL) {
1389 if (p->id == id) {
1390 *pp = p->next;
1391 Py_XDECREF(p->func);
1392 Py_XDECREF(p->file);
1393 PyMem_DEL(p);
1394 }
1395 else
1396 pp = &p->next;
1397 }
1398}
1399
Guido van Rossuma597dde1995-01-10 20:56:29 +00001400static void
Fred Drake509d79a2000-07-08 04:04:38 +00001401FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00001402{
Guido van Rossum00d93061998-05-28 23:06:38 +00001403 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001404 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00001405
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001406 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001407 func = data->func;
1408 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00001409
Barry Warsawfa701a81997-01-16 00:15:11 +00001410 arg = Py_BuildValue("(Oi)", file, (long) mask);
1411 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00001412 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00001413
1414 if (res == NULL) {
1415 errorInCmd = 1;
1416 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1417 }
1418 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001419 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00001420}
1421
Guido van Rossum18468821994-06-20 07:49:28 +00001422static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001423Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
1424 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00001425{
Guido van Rossum00d93061998-05-28 23:06:38 +00001426 FileHandler_ClientData *data;
1427 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001428 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00001429
Guido van Rossum43713e52000-02-29 13:59:29 +00001430 if (!PyArg_ParseTuple(args, "OiO:createfilehandler", &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001431 return NULL;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00001432 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00001433 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00001434 return NULL;
1435 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001436 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001437 return NULL;
1438 }
1439
Guido van Rossuma80649b2000-03-28 20:07:05 +00001440 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001441 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001442 return NULL;
1443
Barry Warsawfa701a81997-01-16 00:15:11 +00001444 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001445 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001446 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00001447 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001448 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001449 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001450}
1451
1452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001453Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001454{
Barry Warsawfa701a81997-01-16 00:15:11 +00001455 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00001456 int tfile;
Guido van Rossum68784361996-05-16 17:17:31 +00001457
Guido van Rossum43713e52000-02-29 13:59:29 +00001458 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00001459 return NULL;
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00001460 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00001461 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00001462 return NULL;
1463
Guido van Rossuma80649b2000-03-28 20:07:05 +00001464 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00001465
Barry Warsawfa701a81997-01-16 00:15:11 +00001466 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00001467 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001468 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00001469 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001470 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00001471 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001472}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001473#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00001474
Barry Warsawfa701a81997-01-16 00:15:11 +00001475
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001476/**** Tktt Object (timer token) ****/
1477
1478staticforward PyTypeObject Tktt_Type;
1479
Guido van Rossum00d93061998-05-28 23:06:38 +00001480typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00001481 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00001482 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00001483 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001484} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001485
1486static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001487Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001488{
Barry Warsawfa701a81997-01-16 00:15:11 +00001489 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00001490 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001491
Guido van Rossum43713e52000-02-29 13:59:29 +00001492 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00001493 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001494 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001495 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00001496 v->token = NULL;
1497 }
1498 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001499 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001500 Py_DECREF(func);
1501 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00001502 }
1503 Py_INCREF(Py_None);
1504 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001505}
1506
1507static PyMethodDef Tktt_methods[] =
1508{
Guido van Rossum35d43371997-08-02 00:09:09 +00001509 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001510 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001511};
1512
1513static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001514Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001515{
Barry Warsawfa701a81997-01-16 00:15:11 +00001516 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001517
Guido van Rossumb18618d2000-05-03 23:44:39 +00001518 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00001519 if (v == NULL)
1520 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001521
Guido van Rossum00d93061998-05-28 23:06:38 +00001522 Py_INCREF(func);
1523 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001524 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001525
1526 /* Extra reference, deleted when called or when handler is deleted */
1527 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001528 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001529}
1530
1531static void
Fred Drake509d79a2000-07-08 04:04:38 +00001532Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001533{
Guido van Rossum00d93061998-05-28 23:06:38 +00001534 TkttObject *v = (TkttObject *)self;
1535 PyObject *func = v->func;
1536
1537 Py_XDECREF(func);
1538
Guido van Rossumb18618d2000-05-03 23:44:39 +00001539 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001540}
1541
Guido van Rossum597ac201998-05-12 14:36:19 +00001542static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001543Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001544{
Barry Warsawfa701a81997-01-16 00:15:11 +00001545 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00001546 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001547
Fred Drakea44d3532000-06-30 15:01:00 +00001548 sprintf(buf, "<tktimertoken at %p%s>", v,
Barry Warsawfa701a81997-01-16 00:15:11 +00001549 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00001550 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001551}
1552
1553static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001554Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001555{
Barry Warsawfa701a81997-01-16 00:15:11 +00001556 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001557}
1558
1559static PyTypeObject Tktt_Type =
1560{
Guido van Rossum35d43371997-08-02 00:09:09 +00001561 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001562 0, /*ob_size */
1563 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001564 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001565 0, /*tp_itemsize */
1566 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00001567 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00001568 Tktt_GetAttr, /*tp_getattr */
1569 0, /*tp_setattr */
1570 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00001571 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00001572 0, /*tp_as_number */
1573 0, /*tp_as_sequence */
1574 0, /*tp_as_mapping */
1575 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001576};
1577
Barry Warsawfa701a81997-01-16 00:15:11 +00001578
1579
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001580/** Timer Handler **/
1581
1582static void
Fred Drake509d79a2000-07-08 04:04:38 +00001583TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001584{
Guido van Rossum00d93061998-05-28 23:06:38 +00001585 TkttObject *v = (TkttObject *)clientData;
1586 PyObject *func = v->func;
1587 PyObject *res;
1588
1589 if (func == NULL)
1590 return;
1591
1592 v->func = NULL;
1593
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001594 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001595
1596 res = PyEval_CallObject(func, NULL);
1597 Py_DECREF(func);
1598 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001599
Barry Warsawfa701a81997-01-16 00:15:11 +00001600 if (res == NULL) {
1601 errorInCmd = 1;
1602 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1603 }
1604 else
1605 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00001606
1607 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001608}
1609
1610static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001611Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001612{
Barry Warsawfa701a81997-01-16 00:15:11 +00001613 int milliseconds;
1614 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001615 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001616
Guido van Rossum43713e52000-02-29 13:59:29 +00001617 if (!PyArg_ParseTuple(args, "iO:createtimerhandler", &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 return NULL;
1619 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00001620 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00001621 return NULL;
1622 }
Guido van Rossum00d93061998-05-28 23:06:38 +00001623 v = Tktt_New(func);
1624 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1625 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00001626
Guido van Rossum00d93061998-05-28 23:06:38 +00001627 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001628}
1629
Barry Warsawfa701a81997-01-16 00:15:11 +00001630
Guido van Rossum18468821994-06-20 07:49:28 +00001631/** Event Loop **/
1632
Guido van Rossum18468821994-06-20 07:49:28 +00001633static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001634Tkapp_MainLoop(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001635{
Barry Warsawfa701a81997-01-16 00:15:11 +00001636 int threshold = 0;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001637#ifdef WITH_THREAD
1638 PyThreadState *tstate = PyThreadState_Get();
1639#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00001640
Guido van Rossum43713e52000-02-29 13:59:29 +00001641 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00001642 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001643
Barry Warsawfa701a81997-01-16 00:15:11 +00001644 quitMainLoop = 0;
1645 while (Tk_GetNumMainWindows() > threshold &&
1646 !quitMainLoop &&
1647 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00001648 {
Guido van Rossum35d43371997-08-02 00:09:09 +00001649 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00001650
1651#ifdef WITH_THREAD
Guido van Rossum62320c91998-06-15 04:36:09 +00001652 Py_BEGIN_ALLOW_THREADS
Guido van Rossum65d5b571998-12-21 19:32:43 +00001653 PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001654 tcl_tstate = tstate;
Guido van Rossum35d43371997-08-02 00:09:09 +00001655 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001656 tcl_tstate = NULL;
Guido van Rossum65d5b571998-12-21 19:32:43 +00001657 PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00001658 if (result == 0)
1659 Sleep(20);
Guido van Rossum35d43371997-08-02 00:09:09 +00001660 Py_END_ALLOW_THREADS
Guido van Rossum5b020781997-08-19 01:00:50 +00001661#else
1662 result = Tcl_DoOneEvent(0);
1663#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001664
Guido van Rossum35d43371997-08-02 00:09:09 +00001665 if (PyErr_CheckSignals() != 0)
1666 return NULL;
1667 if (result < 0)
1668 break;
Guido van Rossum18468821994-06-20 07:49:28 +00001669 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001670 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001671
Barry Warsawfa701a81997-01-16 00:15:11 +00001672 if (errorInCmd) {
1673 errorInCmd = 0;
1674 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1675 excInCmd = valInCmd = trbInCmd = NULL;
1676 return NULL;
1677 }
1678 Py_INCREF(Py_None);
1679 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001680}
1681
1682static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001683Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00001684{
Guido van Rossum35d43371997-08-02 00:09:09 +00001685 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00001686 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00001687
Guido van Rossum43713e52000-02-29 13:59:29 +00001688 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00001689 return NULL;
1690
Guido van Rossum00d93061998-05-28 23:06:38 +00001691 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001692 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00001693 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001694 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00001695}
1696
1697static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001698Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001699{
1700
Guido van Rossum43713e52000-02-29 13:59:29 +00001701 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00001702 return NULL;
1703
1704 quitMainLoop = 1;
1705 Py_INCREF(Py_None);
1706 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001709static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001710Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001711{
1712
Guido van Rossum43713e52000-02-29 13:59:29 +00001713 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001714 return NULL;
1715
1716 return PyInt_FromLong((long)Tkapp_Interp(self));
1717}
1718
Barry Warsawfa701a81997-01-16 00:15:11 +00001719
1720
Guido van Rossum18468821994-06-20 07:49:28 +00001721/**** Tkapp Method List ****/
1722
1723static PyMethodDef Tkapp_methods[] =
1724{
Guido van Rossum35d43371997-08-02 00:09:09 +00001725 {"call", Tkapp_Call, 0},
1726 {"globalcall", Tkapp_GlobalCall, 0},
1727 {"eval", Tkapp_Eval, 1},
1728 {"globaleval", Tkapp_GlobalEval, 1},
1729 {"evalfile", Tkapp_EvalFile, 1},
1730 {"record", Tkapp_Record, 1},
1731 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1732 {"setvar", Tkapp_SetVar, 1},
1733 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1734 {"getvar", Tkapp_GetVar, 1},
1735 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1736 {"unsetvar", Tkapp_UnsetVar, 1},
1737 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1738 {"getint", Tkapp_GetInt, 1},
1739 {"getdouble", Tkapp_GetDouble, 1},
1740 {"getboolean", Tkapp_GetBoolean, 1},
1741 {"exprstring", Tkapp_ExprString, 1},
1742 {"exprlong", Tkapp_ExprLong, 1},
1743 {"exprdouble", Tkapp_ExprDouble, 1},
1744 {"exprboolean", Tkapp_ExprBoolean, 1},
1745 {"splitlist", Tkapp_SplitList, 1},
1746 {"split", Tkapp_Split, 1},
1747 {"merge", Tkapp_Merge, 0},
1748 {"createcommand", Tkapp_CreateCommand, 1},
1749 {"deletecommand", Tkapp_DeleteCommand, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001750#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001751 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1752 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001753#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001754 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001755 {"mainloop", Tkapp_MainLoop, 1},
1756 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001757 {"quit", Tkapp_Quit, 1},
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00001758 {"interpaddr", Tkapp_InterpAddr, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001759 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001760};
1761
Barry Warsawfa701a81997-01-16 00:15:11 +00001762
1763
Guido van Rossum18468821994-06-20 07:49:28 +00001764/**** Tkapp Type Methods ****/
1765
1766static void
Fred Drake509d79a2000-07-08 04:04:38 +00001767Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00001768{
Guido van Rossum00d93061998-05-28 23:06:38 +00001769 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001770 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00001771 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00001772 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001773 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00001774}
1775
1776static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001777Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00001778{
Guido van Rossum35d43371997-08-02 00:09:09 +00001779 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00001780}
1781
1782static PyTypeObject Tkapp_Type =
1783{
Guido van Rossum35d43371997-08-02 00:09:09 +00001784 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00001785 0, /*ob_size */
1786 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00001787 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00001788 0, /*tp_itemsize */
1789 Tkapp_Dealloc, /*tp_dealloc */
1790 0, /*tp_print */
1791 Tkapp_GetAttr, /*tp_getattr */
1792 0, /*tp_setattr */
1793 0, /*tp_compare */
1794 0, /*tp_repr */
1795 0, /*tp_as_number */
1796 0, /*tp_as_sequence */
1797 0, /*tp_as_mapping */
1798 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00001799};
1800
Barry Warsawfa701a81997-01-16 00:15:11 +00001801
1802
Guido van Rossum18468821994-06-20 07:49:28 +00001803/**** Tkinter Module ****/
1804
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001805typedef struct {
1806 PyObject* tuple;
1807 int size; /* current size */
1808 int maxsize; /* allocated size */
1809} FlattenContext;
1810
1811static int
1812_bump(FlattenContext* context, int size)
1813{
1814 /* expand tuple to hold (at least) size new items. return true if
1815 successful, false if an exception was raised*/
1816
1817 int maxsize = context->maxsize * 2;
1818
1819 if (maxsize < context->size + size)
1820 maxsize = context->size + size;
1821
1822 context->maxsize = maxsize;
1823
1824 return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
1825}
1826
1827static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001828_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001829{
1830 /* add tuple or list to argument tuple (recursively) */
1831
1832 int i, size;
1833
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001834 if (depth > 1000) {
1835 PyErr_SetString(PyExc_ValueError,"nesting too deep in _flatten");
1836 return 0;
1837 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001838 size = PyList_GET_SIZE(item);
1839 /* preallocate (assume no nesting) */
1840 if (context->size + size > context->maxsize && !_bump(context, size))
1841 return 0;
1842 /* copy items to output tuple */
1843 for (i = 0; i < size; i++) {
1844 PyObject *o = PyList_GET_ITEM(item, i);
1845 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001846 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001847 return 0;
1848 } else if (o != Py_None) {
1849 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1850 return 0;
1851 Py_INCREF(o);
1852 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1853 }
1854 }
1855 } else if (PyTuple_Check(item)) {
1856 /* same, for tuples */
1857 size = PyTuple_GET_SIZE(item);
1858 if (context->size + size > context->maxsize && !_bump(context, size))
1859 return 0;
1860 for (i = 0; i < size; i++) {
1861 PyObject *o = PyTuple_GET_ITEM(item, i);
1862 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001863 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001864 return 0;
1865 } else if (o != Py_None) {
1866 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1867 return 0;
1868 Py_INCREF(o);
1869 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1870 }
1871 }
1872 } else {
1873 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
1874 return 0;
1875 }
1876 return 1;
1877}
1878
1879static PyObject *
1880Tkinter_Flatten(PyObject* self, PyObject* args)
1881{
1882 FlattenContext context;
1883 PyObject* item;
1884
1885 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
1886 return NULL;
1887
Jeremy Hylton03657cf2000-07-12 13:05:33 +00001888 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001889 if (context.maxsize <= 0)
1890 return PyTuple_New(0);
1891
1892 context.tuple = PyTuple_New(context.maxsize);
1893 if (!context.tuple)
1894 return NULL;
1895
1896 context.size = 0;
1897
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00001898 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001899 return NULL;
1900
1901 if (_PyTuple_Resize(&context.tuple, context.size, 0))
1902 return NULL;
1903
1904 return context.tuple;
1905}
1906
Guido van Rossum18468821994-06-20 07:49:28 +00001907static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001908Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001909{
Barry Warsawfa701a81997-01-16 00:15:11 +00001910 char *screenName = NULL;
1911 char *baseName = NULL;
1912 char *className = NULL;
1913 int interactive = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00001914
Guido van Rossum35d43371997-08-02 00:09:09 +00001915 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00001916 if (baseName != NULL)
1917 baseName++;
1918 else
1919 baseName = Py_GetProgramName();
1920 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00001921
Guido van Rossum43713e52000-02-29 13:59:29 +00001922 if (!PyArg_ParseTuple(args, "|zssi:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00001923 &screenName, &baseName, &className,
1924 &interactive))
1925 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001926
Barry Warsawfa701a81997-01-16 00:15:11 +00001927 return (PyObject *) Tkapp_New(screenName, baseName, className,
1928 interactive);
Guido van Rossum18468821994-06-20 07:49:28 +00001929}
1930
1931static PyMethodDef moduleMethods[] =
1932{
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00001933 {"_flatten", Tkinter_Flatten, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001934 {"create", Tkinter_Create, 1},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00001935#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum35d43371997-08-02 00:09:09 +00001936 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1937 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
Guido van Rossum02c04671997-08-07 00:12:22 +00001938#endif
Guido van Rossum35d43371997-08-02 00:09:09 +00001939 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001940 {"mainloop", Tkapp_MainLoop, 1},
1941 {"dooneevent", Tkapp_DoOneEvent, 1},
Guido van Rossum35d43371997-08-02 00:09:09 +00001942 {"quit", Tkapp_Quit, 1},
Barry Warsawfa701a81997-01-16 00:15:11 +00001943 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00001944};
1945
Guido van Rossum7bf15641998-05-22 18:28:17 +00001946#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00001947
1948static int stdin_ready = 0;
1949
Guido van Rossumad4db171998-06-13 13:56:28 +00001950#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00001951static void
Fred Drake509d79a2000-07-08 04:04:38 +00001952MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00001953{
1954 stdin_ready = 1;
1955}
Guido van Rossumad4db171998-06-13 13:56:28 +00001956#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001957
Guido van Rossum00d93061998-05-28 23:06:38 +00001958static PyThreadState *event_tstate = NULL;
Guido van Rossum0e8457c1997-10-07 18:51:41 +00001959
Guido van Rossum18468821994-06-20 07:49:28 +00001960static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001961EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00001962{
Guido van Rossumad4db171998-06-13 13:56:28 +00001963#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00001964 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00001965#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00001966#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00001967 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00001968#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00001969 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00001970 errorInCmd = 0;
1971#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00001972 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001973 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00001974#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001975 while (!errorInCmd && !stdin_ready) {
1976 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00001977#ifdef MS_WINDOWS
1978 if (_kbhit()) {
1979 stdin_ready = 1;
1980 break;
1981 }
1982#endif
1983#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00001984 Py_BEGIN_ALLOW_THREADS
Guido van Rossum65d5b571998-12-21 19:32:43 +00001985 PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00001986 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001987
Guido van Rossum00d93061998-05-28 23:06:38 +00001988 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001989
1990 tcl_tstate = NULL;
Guido van Rossum65d5b571998-12-21 19:32:43 +00001991 PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00001992 if (result == 0)
1993 Sleep(20);
1994 Py_END_ALLOW_THREADS
1995#else
1996 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00001997#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00001998
1999 if (result < 0)
2000 break;
2001 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002002#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002003 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002004#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002005 if (errorInCmd) {
2006 errorInCmd = 0;
2007 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2008 excInCmd = valInCmd = trbInCmd = NULL;
2009 PyErr_Print();
2010 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002011#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002012 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002013#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002014 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002015}
Guido van Rossum18468821994-06-20 07:49:28 +00002016
Guido van Rossum00d93061998-05-28 23:06:38 +00002017#endif
2018
Guido van Rossum7bf15641998-05-22 18:28:17 +00002019static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002020EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002021{
Guido van Rossum00d93061998-05-28 23:06:38 +00002022#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002023 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002024#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002025 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002026#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002027 PyOS_InputHook = EventHook;
2028 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002029#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002030}
2031
2032static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002033DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002034{
Guido van Rossum00d93061998-05-28 23:06:38 +00002035#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002036 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2037 PyOS_InputHook = NULL;
2038 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002039#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002040}
2041
Barry Warsawfa701a81997-01-16 00:15:11 +00002042
2043/* all errors will be checked in one fell swoop in init_tkinter() */
2044static void
Fred Drake509d79a2000-07-08 04:04:38 +00002045ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002046{
2047 PyObject *v = PyInt_FromLong(val);
2048 if (v) {
2049 PyDict_SetItemString(d, name, v);
2050 Py_DECREF(v);
2051 }
2052}
2053static void
Fred Drake509d79a2000-07-08 04:04:38 +00002054ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002055{
2056 PyObject *v = PyString_FromString(val);
2057 if (v) {
2058 PyDict_SetItemString(d, name, v);
2059 Py_DECREF(v);
2060 }
2061}
2062
2063
Guido van Rossum3886bb61998-12-04 18:50:17 +00002064DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002065init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002066{
Barry Warsawfa701a81997-01-16 00:15:11 +00002067 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002068
Barry Warsawfa701a81997-01-16 00:15:11 +00002069 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002070
2071#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002072 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002073#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002074
Barry Warsawfa701a81997-01-16 00:15:11 +00002075 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002076
Barry Warsawfa701a81997-01-16 00:15:11 +00002077 d = PyModule_GetDict(m);
2078 Tkinter_TclError = Py_BuildValue("s", "TclError");
2079 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002080
Guido van Rossum35d43371997-08-02 00:09:09 +00002081 ins_long(d, "READABLE", TCL_READABLE);
2082 ins_long(d, "WRITABLE", TCL_WRITABLE);
2083 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2084 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2085 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2086 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2087 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2088 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2089 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002090 ins_string(d, "TK_VERSION", TK_VERSION);
2091 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002092
Guido van Rossum83551bf1997-09-13 00:44:23 +00002093 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002094
2095 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002096 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2097
Guido van Rossume187b0e2000-03-27 21:46:29 +00002098 /* This helps the dynamic loader; in Unicode aware Tcl versions
2099 it also helps Tcl find its encodings. */
2100 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00002101
Barry Warsawfa701a81997-01-16 00:15:11 +00002102 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002103 return;
2104
Guido van Rossum43ff8681998-07-14 18:02:13 +00002105#if 0
2106 /* This was not a good idea; through <Destroy> bindings,
2107 Tcl_Finalize() may invoke Python code but at that point the
2108 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002109 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002110#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002111
Jack Jansen34cc5c31995-10-31 16:15:12 +00002112#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002113 /*
2114 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2115 ** Most of the initializations in that routine (toolbox init calls and
2116 ** such) have already been done for us, so we only need these.
2117 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002118 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002119
2120 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00002121#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00002122 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00002123#endif /* GENERATINGCFM */
2124#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00002125}
Guido van Rossum9722ad81995-09-22 23:49:28 +00002126
Guido van Rossumec22c921996-02-25 04:50:29 +00002127
Barry Warsawfa701a81997-01-16 00:15:11 +00002128
Guido van Rossum9722ad81995-09-22 23:49:28 +00002129#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002130
2131/*
Guido van Rossumec22c921996-02-25 04:50:29 +00002132** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002133*/
2134
Guido van Rossum9722ad81995-09-22 23:49:28 +00002135void
2136panic(char * format, ...)
2137{
Barry Warsawfa701a81997-01-16 00:15:11 +00002138 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002139
Barry Warsawfa701a81997-01-16 00:15:11 +00002140 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002141
Guido van Rossum227cf761998-08-05 13:53:32 +00002142 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002143 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002144
Barry Warsawfa701a81997-01-16 00:15:11 +00002145 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00002146
Barry Warsawfa701a81997-01-16 00:15:11 +00002147 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00002148}
Jack Jansen40b546d1995-11-14 10:34:45 +00002149
Guido van Rossumec22c921996-02-25 04:50:29 +00002150/*
2151** Pass events to SIOUX before passing them to Tk.
2152*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002153
Guido van Rossumec22c921996-02-25 04:50:29 +00002154static int
Fred Drake509d79a2000-07-08 04:04:38 +00002155PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002156{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002157 WindowPtr frontwin;
2158 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00002159 ** Sioux eats too many events, so we don't pass it everything. We
2160 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00002161 ** the Sioux window is frontmost. This means that Tk menus don't work
2162 ** in that case, but at least we can scroll the sioux window.
2163 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2164 ** part of the external interface of Sioux...
2165 */
2166 frontwin = FrontWindow();
2167 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2168 if (SIOUXHandleOneEvent(eventPtr))
2169 return 0; /* Nothing happened to the Tcl event queue */
2170 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002171 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002172}
2173
Guido van Rossumec22c921996-02-25 04:50:29 +00002174#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002175
2176/*
2177** Additional Mac specific code for dealing with shared libraries.
2178*/
2179
2180#include <Resources.h>
2181#include <CodeFragments.h>
2182
2183static int loaded_from_shlib = 0;
2184static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00002185
Jack Jansen34cc5c31995-10-31 16:15:12 +00002186/*
2187** If this module is dynamically loaded the following routine should
2188** be the init routine. It takes care of adding the shared library to
2189** the resource-file chain, so that the tk routines can find their
2190** resources.
2191*/
2192OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002193init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002194{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00002195 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00002196 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002197 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002198 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2199 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00002200 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00002201 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2202 loaded_from_shlib = 1;
2203 }
2204 return noErr;
2205}
2206
2207/*
2208** Insert the library resources into the search path. Put them after
2209** the resources from the application. Again, we ignore errors.
2210*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00002211static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002212mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00002213{
2214 if ( !loaded_from_shlib )
2215 return;
2216 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2217}
2218
Guido van Rossumec22c921996-02-25 04:50:29 +00002219#endif /* GENERATINGCFM */
2220#endif /* macintosh */