blob: 822a0c37f5a8257984f0e490dec7d7645b2ac073 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Guido van Rossumbf0dc9f1996-08-20 20:49:56 +000036#ifdef macintosh
37#define MAC_TCL
Guido van Rossum49b56061998-10-01 20:42:43 +000038#endif
39
Martin v. Löwis39195712003-01-04 00:33:13 +000040/* Allow using this code in Python 2.[12] */
41#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000042#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
45#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000046#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000047#endif
48
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000049#ifndef PyBool_Check
50#define PyBool_Check(o) 0
51#define PyBool_FromLong PyInt_FromLong
52#endif
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Jason Tishlerbbe89612002-12-31 20:30:46 +000074/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000075#ifndef CONST84_RETURN
76#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000077#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000078#define CONST
79#endif
80
Guido van Rossum3e819a71997-08-01 19:29:02 +000081#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
82
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000083#if TKMAJORMINOR < 8002
84#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
90 either UTF-16 or UCS-4. */
91#if TCL_UTF_MAX != 3
92#error "unsupported Tcl configuration"
93#endif
94
Guido van Rossuma80649b2000-03-28 20:07:05 +000095#if defined(macintosh)
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096/* Sigh, we have to include this to get at the tcl qd pointer */
97#include <tkMac.h>
Guido van Rossum2ea1c941998-04-28 16:12:43 +000098/* And this one we need to clear the menu bar */
99#include <Menus.h>
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000100#endif
101
Jack Jansen84c10b12001-07-16 19:32:52 +0000102#if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
103/* Mac has it, but it doesn't really work:-( */
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000104#define HAVE_CREATEFILEHANDLER
105#endif
106
Guido van Rossum00d93061998-05-28 23:06:38 +0000107#ifdef HAVE_CREATEFILEHANDLER
108
109/* Tcl_CreateFileHandler() changed several times; these macros deal with the
110 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
111 Unix, only because Jack added it back); when available on Windows, it only
112 applies to sockets. */
113
Guido van Rossum7bf15641998-05-22 18:28:17 +0000114#ifdef MS_WINDOWS
115#define FHANDLETYPE TCL_WIN_SOCKET
116#else
117#define FHANDLETYPE TCL_UNIX_FD
118#endif
119
Guido van Rossum00d93061998-05-28 23:06:38 +0000120/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
121 which uses this to handle Tcl events while the user is typing commands. */
122
123#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000124#define WAIT_FOR_STDIN
125#endif
126
Guido van Rossum00d93061998-05-28 23:06:38 +0000127#endif /* HAVE_CREATEFILEHANDLER */
128
Guido van Rossumad4db171998-06-13 13:56:28 +0000129#ifdef MS_WINDOWS
130#include <conio.h>
131#define WAIT_FOR_STDIN
132#endif
133
Guido van Rossum00d93061998-05-28 23:06:38 +0000134#ifdef WITH_THREAD
135
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000136/* The threading situation is complicated. Tcl is not thread-safe, except
137 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000138 So we need to use a lock around all uses of Tcl. Previously, the Python
139 interpreter lock was used for this. However, this causes problems when
140 other Python threads need to run while Tcl is blocked waiting for events.
141
142 To solve this problem, a separate lock for Tcl is introduced. Holding it
143 is incompatible with holding Python's interpreter lock. The following four
144 macros manipulate both locks together.
145
146 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
147 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
148 that could call an event handler, or otherwise affect the state of a Tcl
149 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000150 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000151 released and the lock for Tcl has been acquired.
152
Guido van Rossum5e977831998-06-15 14:03:52 +0000153 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
154 (For example, when transferring data from the Tcl interpreter result to a
155 Python string object.) This can be done by using different macros to close
156 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
157 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
158 releases the Tcl lock.
159
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000160 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000161 handlers when the handler needs to use Python. Such event handlers are
162 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000163 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000164 the Python interpreter lock, restoring the appropriate thread state, and
165 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
166 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000167 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000168
169 These locks expand to several statements and brackets; they should not be
170 used in branches of if statements and the like.
171
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000172 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
173 only valid in the thread that created it, and all Tk activity must happen in this
174 thread, also. That means that the mainloop must be invoked in the thread that
175 created the interpreter. Invoking commands from other threads is possible;
176 _tkinter will queue an event for the interpreter thread, which will then
177 execute the command and pass back the result. If the main thread is not in the
178 mainloop, and invoking commands causes an exception; if the main loop is running
179 but not processing events, the command invocation will block.
180
181 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
182 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
183 threads. So we use the Tcl TLS API.
184
Guido van Rossum00d93061998-05-28 23:06:38 +0000185*/
186
Guido van Rossum65d5b571998-12-21 19:32:43 +0000187static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000188
189#ifdef TCL_THREADS
190static Tcl_ThreadDataKey state_key;
191typedef PyThreadState *ThreadSpecificData;
192#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
193#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000194static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000195#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000196
197#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000198 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000199 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000200
201#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000202 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
Guido van Rossum62320c91998-06-15 04:36:09 +0000204#define ENTER_OVERLAP \
205 Py_END_ALLOW_THREADS
206
207#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000209
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000210#define ENTER_PYTHON \
211 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000212 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000213
214#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000215 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000216 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
217
218#define CHECK_TCL_APPARTMENT \
219 if (((TkappObject *)self)->threaded && \
220 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
221 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
222 return 0; \
223 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000224
225#else
226
227#define ENTER_TCL
228#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000229#define ENTER_OVERLAP
230#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000231#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000232#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000233#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000234
235#endif
236
Guido van Rossumec22c921996-02-25 04:50:29 +0000237#ifdef macintosh
238
239/*
240** Additional cruft needed by Tcl/Tk on the Mac.
Guido van Rossum97867b21996-08-08 19:09:53 +0000241** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
Guido van Rossumec22c921996-02-25 04:50:29 +0000242*/
243
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000244/* ckfree() expects a char* */
Guido van Rossum97867b21996-08-08 19:09:53 +0000245#define FREECAST (char *)
246
Guido van Rossumec22c921996-02-25 04:50:29 +0000247#include <Events.h> /* For EventRecord */
248
Fred Drake509d79a2000-07-08 04:04:38 +0000249typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
Guido van Rossum2834b972000-10-06 16:58:26 +0000250void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
251int TkMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000252
Jeremy Hylton938ace62002-07-17 16:30:39 +0000253static int PyMacConvertEvent(EventRecord *eventPtr);
Guido van Rossumec22c921996-02-25 04:50:29 +0000254
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000255#include <SIOUX.h>
256extern int SIOUXIsAppWindow(WindowPtr);
257
Guido van Rossumec22c921996-02-25 04:50:29 +0000258#endif /* macintosh */
259
Guido van Rossum97867b21996-08-08 19:09:53 +0000260#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000261#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000262#endif
263
Guido van Rossum18468821994-06-20 07:49:28 +0000264/**** Tkapp Object Declaration ****/
265
Jeremy Hylton938ace62002-07-17 16:30:39 +0000266static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000267
Guido van Rossum00d93061998-05-28 23:06:38 +0000268typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000269 PyObject_HEAD
270 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000271 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000272 int threaded; /* True if tcl_platform[threaded] */
273 Tcl_ThreadId thread_id;
274 int dispatching;
275 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000276 So we cache interesting types here. */
277 Tcl_ObjType *BooleanType;
278 Tcl_ObjType *ByteArrayType;
279 Tcl_ObjType *DoubleType;
280 Tcl_ObjType *IntType;
281 Tcl_ObjType *ListType;
282 Tcl_ObjType *ProcBodyType;
283 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000284} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000285
286#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000287#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000288#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000289
Guido van Rossum35d43371997-08-02 00:09:09 +0000290#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000291(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000292
Barry Warsawfa701a81997-01-16 00:15:11 +0000293
294
Guido van Rossum18468821994-06-20 07:49:28 +0000295/**** Error Handling ****/
296
297static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000298static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000299static int errorInCmd = 0;
300static PyObject *excInCmd;
301static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000302static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000303
Barry Warsawfa701a81997-01-16 00:15:11 +0000304
305
Guido van Rossum18468821994-06-20 07:49:28 +0000306static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000307Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000308{
Barry Warsawfa701a81997-01-16 00:15:11 +0000309 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
310 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000311}
312
Barry Warsawfa701a81997-01-16 00:15:11 +0000313
Barry Warsawfa701a81997-01-16 00:15:11 +0000314
Guido van Rossum18468821994-06-20 07:49:28 +0000315/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000316
317#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000318#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000319
Guido van Rossum00d93061998-05-28 23:06:38 +0000320/* Millisecond sleep() for Unix platforms. */
321
322static void
Fred Drake509d79a2000-07-08 04:04:38 +0000323Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000324{
325 /* XXX Too bad if you don't have select(). */
326 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000327 t.tv_sec = milli/1000;
328 t.tv_usec = (milli%1000) * 1000;
329 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
330}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000331#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000332
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000333/* Wait up to 1s for the mainloop to come up. */
334
335static int
336WaitForMainloop(TkappObject* self)
337{
338 int i;
339 for (i = 0; i < 10; i++) {
340 if (self->dispatching)
341 return 1;
342 Py_BEGIN_ALLOW_THREADS
343 Sleep(100);
344 Py_END_ALLOW_THREADS
345 }
346 if (self->dispatching)
347 return 1;
348 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
349 return 0;
350}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000351#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000352
Guido van Rossum00d93061998-05-28 23:06:38 +0000353
Guido van Rossum18468821994-06-20 07:49:28 +0000354static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000355AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000356{
Guido van Rossum35d43371997-08-02 00:09:09 +0000357 if (PyString_Check(value))
358 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000359#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000360 else if (PyUnicode_Check(value)) {
361 PyObject *v = PyUnicode_AsUTF8String(value);
362 if (v == NULL)
363 return NULL;
364 if (PyList_Append(tmp, v) != 0) {
365 Py_DECREF(v);
366 return NULL;
367 }
368 Py_DECREF(v);
369 return PyString_AsString(v);
370 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000371#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000372 else {
373 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000374 if (v == NULL)
375 return NULL;
376 if (PyList_Append(tmp, v) != 0) {
377 Py_DECREF(v);
378 return NULL;
379 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000380 Py_DECREF(v);
381 return PyString_AsString(v);
382 }
Guido van Rossum18468821994-06-20 07:49:28 +0000383}
384
Barry Warsawfa701a81997-01-16 00:15:11 +0000385
386
Guido van Rossum18468821994-06-20 07:49:28 +0000387#define ARGSZ 64
388
389static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000390Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000391{
Barry Warsawfa701a81997-01-16 00:15:11 +0000392 PyObject *tmp = NULL;
393 char *argvStore[ARGSZ];
394 char **argv = NULL;
395 int fvStore[ARGSZ];
396 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000397 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000398 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000399
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 if (!(tmp = PyList_New(0)))
401 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000402
Barry Warsawfa701a81997-01-16 00:15:11 +0000403 argv = argvStore;
404 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Barry Warsawfa701a81997-01-16 00:15:11 +0000406 if (args == NULL)
407 argc = 0;
408
409 else if (!PyTuple_Check(args)) {
410 argc = 1;
411 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 if (!(argv[0] = AsString(args, tmp)))
413 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000414 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000415 else {
416 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000417
Barry Warsawfa701a81997-01-16 00:15:11 +0000418 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000419 argv = (char **)ckalloc(argc * sizeof(char *));
420 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000421 if (argv == NULL || fv == NULL) {
422 PyErr_NoMemory();
423 goto finally;
424 }
425 }
426
427 for (i = 0; i < argc; i++) {
428 PyObject *v = PyTuple_GetItem(args, i);
429 if (PyTuple_Check(v)) {
430 fv[i] = 1;
431 if (!(argv[i] = Merge(v)))
432 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000433 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000434 }
435 else if (v == Py_None) {
436 argc = i;
437 break;
438 }
439 else {
440 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000441 if (!(argv[i] = AsString(v, tmp)))
442 goto finally;
443 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000444 }
445 }
Guido van Rossum18468821994-06-20 07:49:28 +0000446 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000447 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000448 if (res == NULL)
449 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000450
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000452 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 if (fv[i]) {
454 ckfree(argv[i]);
455 }
456 if (argv != argvStore)
457 ckfree(FREECAST argv);
458 if (fv != fvStore)
459 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000460
Barry Warsawfa701a81997-01-16 00:15:11 +0000461 Py_DECREF(tmp);
462 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000463}
464
Barry Warsawfa701a81997-01-16 00:15:11 +0000465
466
Guido van Rossum18468821994-06-20 07:49:28 +0000467static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000468Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000469{
Barry Warsawfa701a81997-01-16 00:15:11 +0000470 int argc;
471 char **argv;
472 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Barry Warsawfa701a81997-01-16 00:15:11 +0000474 if (list == NULL) {
475 Py_INCREF(Py_None);
476 return Py_None;
477 }
Guido van Rossum18468821994-06-20 07:49:28 +0000478
Guido van Rossum00d93061998-05-28 23:06:38 +0000479 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000480 /* Not a list.
481 * Could be a quoted string containing funnies, e.g. {"}.
482 * Return the string itself.
483 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000484 return PyString_FromString(list);
485 }
Guido van Rossum18468821994-06-20 07:49:28 +0000486
Barry Warsawfa701a81997-01-16 00:15:11 +0000487 if (argc == 0)
488 v = PyString_FromString("");
489 else if (argc == 1)
490 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000491 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000492 int i;
493 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000494
Barry Warsawfa701a81997-01-16 00:15:11 +0000495 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000496 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000497 Py_DECREF(v);
498 v = NULL;
499 break;
500 }
501 PyTuple_SetItem(v, i, w);
502 }
503 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000504 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000505 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000506}
507
Martin v. Löwisffad6332002-11-26 09:28:05 +0000508/* In some cases, Tcl will still return strings that are supposed to be
509 lists. SplitObj walks through a nested tuple, finding string objects that
510 need to be split. */
511
512PyObject *
513SplitObj(PyObject *arg)
514{
515 if (PyTuple_Check(arg)) {
516 int i, size;
517 PyObject *elem, *newelem, *result;
518
519 size = PyTuple_Size(arg);
520 result = NULL;
521 /* Recursively invoke SplitObj for all tuple items.
522 If this does not return a new object, no action is
523 needed. */
524 for(i = 0; i < size; i++) {
525 elem = PyTuple_GetItem(arg, i);
526 newelem = SplitObj(elem);
527 if (!newelem) {
528 Py_XDECREF(result);
529 return NULL;
530 }
531 if (!result) {
532 int k;
533 if (newelem == elem) {
534 Py_DECREF(newelem);
535 continue;
536 }
537 result = PyTuple_New(size);
538 if (!result)
539 return NULL;
540 for(k = 0; k < i; k++) {
541 elem = PyTuple_GetItem(arg, k);
542 Py_INCREF(elem);
543 PyTuple_SetItem(result, k, elem);
544 }
545 }
546 PyTuple_SetItem(result, i, newelem);
547 }
548 if (result)
549 return result;
550 /* Fall through, returning arg. */
551 }
552 else if (PyString_Check(arg)) {
553 int argc;
554 char **argv;
555 char *list = PyString_AsString(arg);
556
557 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
558 Py_INCREF(arg);
559 return arg;
560 }
561 Tcl_Free(FREECAST argv);
562 if (argc > 1)
563 return Split(PyString_AsString(arg));
564 /* Fall through, returning arg. */
565 }
566 Py_INCREF(arg);
567 return arg;
568}
Barry Warsawfa701a81997-01-16 00:15:11 +0000569
570
Guido van Rossum18468821994-06-20 07:49:28 +0000571/**** Tkapp Object ****/
572
573#ifndef WITH_APPINIT
574int
Fred Drake509d79a2000-07-08 04:04:38 +0000575Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000576{
Barry Warsawfa701a81997-01-16 00:15:11 +0000577 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000578
Barry Warsawfa701a81997-01-16 00:15:11 +0000579 main = Tk_MainWindow(interp);
580 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000581 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000582 return TCL_ERROR;
583 }
584 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000585 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000586 return TCL_ERROR;
587 }
588 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000589}
590#endif /* !WITH_APPINIT */
591
Guido van Rossum18468821994-06-20 07:49:28 +0000592
Barry Warsawfa701a81997-01-16 00:15:11 +0000593
594
595/* Initialize the Tk application; see the `main' function in
596 * `tkMain.c'.
597 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000598
Thomas Wouters58d05102000-07-24 14:43:35 +0000599static void EnableEventHook(void); /* Forward */
600static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000601
Barry Warsawfa701a81997-01-16 00:15:11 +0000602static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000603Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000604 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000605{
606 TkappObject *v;
607 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000608
Guido van Rossumb18618d2000-05-03 23:44:39 +0000609 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000610 if (v == NULL)
611 return NULL;
612
613 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000614 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000615 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
616 TCL_GLOBAL_ONLY) != NULL;
617 v->thread_id = Tcl_GetCurrentThread();
618 v->dispatching = 0;
619
620#ifndef TCL_THREADS
621 if (v->threaded) {
622 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
623 Py_DECREF(v);
624 return 0;
625 }
626#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000627#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000628 if (v->threaded && tcl_lock) {
629 /* If Tcl is threaded, we don't need the lock. */
630 PyThread_free_lock(tcl_lock);
631 tcl_lock = NULL;
632 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000633#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000634
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000635 v->BooleanType = Tcl_GetObjType("boolean");
636 v->ByteArrayType = Tcl_GetObjType("bytearray");
637 v->DoubleType = Tcl_GetObjType("double");
638 v->IntType = Tcl_GetObjType("int");
639 v->ListType = Tcl_GetObjType("list");
640 v->ProcBodyType = Tcl_GetObjType("procbody");
641 v->StringType = Tcl_GetObjType("string");
642
Guido van Rossuma80649b2000-03-28 20:07:05 +0000643#if defined(macintosh)
644 /* This seems to be needed */
Guido van Rossum2ea1c941998-04-28 16:12:43 +0000645 ClearMenuBar();
646 TkMacInitMenus(v->interp);
647#endif
Jack Jansencb852442001-12-09 23:15:56 +0000648
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000649 /* Delete the 'exit' command, which can screw things up */
650 Tcl_DeleteCommand(v->interp, "exit");
651
Barry Warsawfa701a81997-01-16 00:15:11 +0000652 if (screenName != NULL)
653 Tcl_SetVar2(v->interp, "env", "DISPLAY",
654 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000655
Barry Warsawfa701a81997-01-16 00:15:11 +0000656 if (interactive)
657 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
658 else
659 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000660
Barry Warsawfa701a81997-01-16 00:15:11 +0000661 /* This is used to get the application class for Tk 4.1 and up */
662 argv0 = (char*)ckalloc(strlen(className) + 1);
663 if (!argv0) {
664 PyErr_NoMemory();
665 Py_DECREF(v);
666 return NULL;
667 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000668
Barry Warsawfa701a81997-01-16 00:15:11 +0000669 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000670 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000671 argv0[0] = tolower(argv0[0]);
672 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
673 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000674
Barry Warsawfa701a81997-01-16 00:15:11 +0000675 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000676 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000677
Guido van Rossum7bf15641998-05-22 18:28:17 +0000678 EnableEventHook();
679
Barry Warsawfa701a81997-01-16 00:15:11 +0000680 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000681}
682
Barry Warsawfa701a81997-01-16 00:15:11 +0000683
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000684static void
685Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
686 Tcl_Condition *cond, Tcl_Mutex *mutex)
687{
688 Py_BEGIN_ALLOW_THREADS;
689 Tcl_MutexLock(mutex);
690 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
691 Tcl_ThreadAlert(self->thread_id);
692 Tcl_ConditionWait(cond, mutex, NULL);
693 Tcl_MutexUnlock(mutex);
694 Py_END_ALLOW_THREADS
695}
696
Barry Warsawfa701a81997-01-16 00:15:11 +0000697
Guido van Rossum18468821994-06-20 07:49:28 +0000698/** Tcl Eval **/
699
Martin v. Löwisffad6332002-11-26 09:28:05 +0000700typedef struct {
701 PyObject_HEAD
702 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000703 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000704} PyTclObject;
705
706staticforward PyTypeObject PyTclObject_Type;
707#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
708
709static PyObject *
710newPyTclObject(Tcl_Obj *arg)
711{
712 PyTclObject *self;
713 self = PyObject_New(PyTclObject, &PyTclObject_Type);
714 if (self == NULL)
715 return NULL;
716 Tcl_IncrRefCount(arg);
717 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000718 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000719 return (PyObject*)self;
720}
721
722static void
723PyTclObject_dealloc(PyTclObject *self)
724{
725 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000726 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000727 PyObject_Del(self);
728}
729
730static PyObject *
731PyTclObject_str(PyTclObject *self)
732{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000733 if (self->string && PyString_Check(self->string)) {
734 Py_INCREF(self->string);
735 return self->string;
736 }
737 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000738 return PyString_FromString(Tcl_GetString(self->value));
739}
740
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000741/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000742PyDoc_STRVAR(PyTclObject_string__doc__,
743"the string representation of this object, either as string or Unicode");
744
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000745static PyObject *
746PyTclObject_string(PyTclObject *self, void *ignored)
747{
748 char *s;
749 int i, len;
750 if (!self->string) {
751 s = Tcl_GetStringFromObj(self->value, &len);
752 for (i = 0; i < len; i++)
753 if (s[i] & 0x80)
754 break;
755#ifdef Py_USING_UNICODE
756 if (i == len)
757 /* It is an ASCII string. */
758 self->string = PyString_FromStringAndSize(s, len);
759 else {
760 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
761 if (!self->string) {
762 PyErr_Clear();
763 self->string = PyString_FromStringAndSize(s, len);
764 }
765 }
766#else
767 self->string = PyString_FromStringAndSize(s, len);
768#endif
769 if (!self->string)
770 return NULL;
771 }
772 Py_INCREF(self->string);
773 return self->string;
774}
775
776#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000777PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
778
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000779static PyObject *
780PyTclObject_unicode(PyTclObject *self, void *ignored)
781{
782 char *s;
783 int len;
784 if (self->string && PyUnicode_Check(self->string)) {
785 Py_INCREF(self->string);
786 return self->string;
787 }
788 /* XXX Could chache result if it is non-ASCII. */
789 s = Tcl_GetStringFromObj(self->value, &len);
790 return PyUnicode_DecodeUTF8(s, len, "strict");
791}
792#endif
793
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794static PyObject *
795PyTclObject_repr(PyTclObject *self)
796{
797 char buf[50];
798 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
799 self->value->typePtr->name, (int)self->value);
800 return PyString_FromString(buf);
801}
802
Martin v. Löwis39195712003-01-04 00:33:13 +0000803PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
804
Martin v. Löwisffad6332002-11-26 09:28:05 +0000805static PyObject*
806get_typename(PyTclObject* obj, void* ignored)
807{
808 return PyString_FromString(obj->value->typePtr->name);
809}
810
Martin v. Löwis39195712003-01-04 00:33:13 +0000811
Martin v. Löwisffad6332002-11-26 09:28:05 +0000812static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000813 {"typename", (getter)get_typename, NULL, get_typename__doc__},
814 {"string", (getter)PyTclObject_string, NULL,
815 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000816 {0},
817};
818
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000819static PyMethodDef PyTclObject_methods[] = {
820 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000821 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000822 {0}
823};
824
Martin v. Löwisffad6332002-11-26 09:28:05 +0000825statichere PyTypeObject PyTclObject_Type = {
826 PyObject_HEAD_INIT(NULL)
827 0, /*ob_size*/
828 "_tkinter.Tcl_Obj", /*tp_name*/
829 sizeof(PyTclObject), /*tp_basicsize*/
830 0, /*tp_itemsize*/
831 /* methods */
832 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
833 0, /*tp_print*/
834 0, /*tp_getattr*/
835 0, /*tp_setattr*/
836 0, /*tp_compare*/
837 (reprfunc)PyTclObject_repr, /*tp_repr*/
838 0, /*tp_as_number*/
839 0, /*tp_as_sequence*/
840 0, /*tp_as_mapping*/
841 0, /*tp_hash*/
842 0, /*tp_call*/
843 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000844 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000845 0, /*tp_setattro*/
846 0, /*tp_as_buffer*/
847 Py_TPFLAGS_DEFAULT, /*tp_flags*/
848 0, /*tp_doc*/
849 0, /*tp_traverse*/
850 0, /*tp_clear*/
851 0, /*tp_richcompare*/
852 0, /*tp_weaklistoffset*/
853 0, /*tp_iter*/
854 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000855 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000856 0, /*tp_members*/
857 PyTclObject_getsetlist, /*tp_getset*/
858 0, /*tp_base*/
859 0, /*tp_dict*/
860 0, /*tp_descr_get*/
861 0, /*tp_descr_set*/
862 0, /*tp_dictoffset*/
863 0, /*tp_init*/
864 0, /*tp_alloc*/
865 0, /*tp_new*/
866 0, /*tp_free*/
867 0, /*tp_is_gc*/
868};
869
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000870static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000871AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000872{
873 Tcl_Obj *result;
874
875 if (PyString_Check(value))
876 return Tcl_NewStringObj(PyString_AS_STRING(value),
877 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000878 else if (PyBool_Check(value))
879 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000880 else if (PyInt_Check(value))
881 return Tcl_NewLongObj(PyInt_AS_LONG(value));
882 else if (PyFloat_Check(value))
883 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
884 else if (PyTuple_Check(value)) {
885 Tcl_Obj **argv = (Tcl_Obj**)
886 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
887 int i;
888 if(!argv)
889 return 0;
890 for(i=0;i<PyTuple_Size(value);i++)
891 argv[i] = AsObj(PyTuple_GetItem(value,i));
892 result = Tcl_NewListObj(PyTuple_Size(value), argv);
893 ckfree(FREECAST argv);
894 return result;
895 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000896#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000897 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000898 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
899 int size = PyUnicode_GET_SIZE(value);
900 /* This #ifdef assumes that Tcl uses UCS-2.
901 See TCL_UTF_MAX test above. */
902#ifdef Py_UNICODE_WIDE
903 Tcl_UniChar *outbuf;
904 int i;
905 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
906 if (!outbuf) {
907 PyErr_NoMemory();
908 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000909 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000910 for (i = 0; i < size; i++) {
911 if (inbuf[i] >= 0x10000) {
912 /* Tcl doesn't do UTF-16, yet. */
913 PyErr_SetString(PyExc_ValueError,
914 "unsupported character");
915 ckfree(FREECAST outbuf);
916 return NULL;
917 }
918 outbuf[i] = inbuf[i];
919 }
920 result = Tcl_NewUnicodeObj(outbuf, size);
921 ckfree(FREECAST outbuf);
922 return result;
923#else
924 return Tcl_NewUnicodeObj(inbuf, size);
925#endif
926
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000927 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000928#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000929 else if(PyTclObject_Check(value)) {
930 Tcl_Obj *v = ((PyTclObject*)value)->value;
931 Tcl_IncrRefCount(v);
932 return v;
933 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000934 else {
935 PyObject *v = PyObject_Str(value);
936 if (!v)
937 return 0;
938 result = AsObj(v);
939 Py_DECREF(v);
940 return result;
941 }
942}
943
Martin v. Löwisffad6332002-11-26 09:28:05 +0000944static PyObject*
945FromObj(PyObject* tkapp, Tcl_Obj *value)
946{
947 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000948 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000949
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000950 if (value->typePtr == NULL) {
951 /* If the result contains any bytes with the top bit set,
952 it's UTF-8 and we should decode it to Unicode */
953#ifdef Py_USING_UNICODE
954 int i;
955 char *s = value->bytes;
956 int len = value->length;
957 for (i = 0; i < len; i++) {
958 if (value->bytes[i] & 0x80)
959 break;
960 }
961
962 if (i == value->length)
963 result = PyString_FromStringAndSize(s, len);
964 else {
965 /* Convert UTF-8 to Unicode string */
966 result = PyUnicode_DecodeUTF8(s, len, "strict");
967 if (result == NULL) {
968 PyErr_Clear();
969 result = PyString_FromStringAndSize(s, len);
970 }
971 }
972#else
973 res = PyString_FromStringAndSize(value->bytes, value->length);
974#endif
975 return result;
976 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000978 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000979 result = value->internalRep.longValue ? Py_True : Py_False;
980 Py_INCREF(result);
981 return result;
982 }
983
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000984 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000985 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000986 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000987 return PyString_FromStringAndSize(data, size);
988 }
989
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000990 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000991 return PyFloat_FromDouble(value->internalRep.doubleValue);
992 }
993
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000994 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000995 return PyInt_FromLong(value->internalRep.longValue);
996 }
997
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000998 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000999 int size;
1000 int i, status;
1001 PyObject *elem;
1002 Tcl_Obj *tcl_elem;
1003
1004 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1005 if (status == TCL_ERROR)
1006 return Tkinter_Error(tkapp);
1007 result = PyTuple_New(size);
1008 if (!result)
1009 return NULL;
1010 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001011 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001012 value, i, &tcl_elem);
1013 if (status == TCL_ERROR) {
1014 Py_DECREF(result);
1015 return Tkinter_Error(tkapp);
1016 }
1017 elem = FromObj(tkapp, tcl_elem);
1018 if (!elem) {
1019 Py_DECREF(result);
1020 return NULL;
1021 }
1022 PyTuple_SetItem(result, i, elem);
1023 }
1024 return result;
1025 }
1026
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001027 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001028 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001029 }
1030
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001031 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001032#ifdef Py_USING_UNICODE
1033#ifdef Py_UNICODE_WIDE
1034 PyObject *result;
1035 int size;
1036 Tcl_UniChar *input;
1037 Py_UNICODE *output;
1038
1039 size = Tcl_GetCharLength(value);
1040 result = PyUnicode_FromUnicode(NULL, size);
1041 if (!result)
1042 return NULL;
1043 input = Tcl_GetUnicode(value);
1044 output = PyUnicode_AS_UNICODE(result);
1045 while (size--)
1046 *output++ = *input++;
1047 return result;
1048#else
1049 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1050 Tcl_GetCharLength(value));
1051#endif
1052#else
1053 int size;
1054 char *c;
1055 c = Tcl_GetStringFromObj(value, &size);
1056 return PyString_FromStringAndSize(c, size);
1057#endif
1058 }
1059
1060 return newPyTclObject(value);
1061}
1062
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001063/* This mutex synchronizes inter-thread command calls. */
1064
1065TCL_DECLARE_MUTEX(call_mutex)
1066
1067typedef struct Tkapp_CallEvent {
1068 Tcl_Event ev; /* Must be first */
1069 TkappObject *self;
1070 PyObject *args;
1071 int flags;
1072 PyObject **res;
1073 PyObject **exc_type, **exc_value, **exc_tb;
1074 Tcl_Condition done;
1075} Tkapp_CallEvent;
1076
1077void
1078Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001079{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001080 int i;
1081 for (i = 0; i < objc; i++)
1082 Tcl_DecrRefCount(objv[i]);
1083 if (objv != objStore)
1084 ckfree(FREECAST objv);
1085}
Guido van Rossum18468821994-06-20 07:49:28 +00001086
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001087/* Convert Python objects to Tcl objects. This must happen in the
1088 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001089
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001090static Tcl_Obj**
1091Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1092{
1093 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001094 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001095 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001096 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001097
Guido van Rossum212643f1998-04-29 16:22:14 +00001098 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001099 objv[0] = AsObj(args);
1100 if (objv[0] == 0)
1101 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001102 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001103 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001104 }
1105 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001106 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001107
Guido van Rossum632de272000-03-29 00:19:50 +00001108 if (objc > ARGSZ) {
1109 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1110 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001111 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001112 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001113 goto finally;
1114 }
1115 }
1116
Guido van Rossum632de272000-03-29 00:19:50 +00001117 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001118 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001119 if (v == Py_None) {
1120 objc = i;
1121 break;
1122 }
Guido van Rossum632de272000-03-29 00:19:50 +00001123 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001124 if (!objv[i]) {
1125 /* Reset objc, so it attempts to clear
1126 objects only up to i. */
1127 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001128 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001129 }
Guido van Rossum632de272000-03-29 00:19:50 +00001130 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001131 }
1132 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001133 *pobjc = objc;
1134 return objv;
1135finally:
1136 Tkapp_CallDeallocArgs(objv, objStore, objc);
1137 return NULL;
1138}
Guido van Rossum212643f1998-04-29 16:22:14 +00001139
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001140/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001141
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001142static PyObject*
1143Tkapp_CallResult(TkappObject *self)
1144{
1145 PyObject *res = NULL;
1146 if(self->wantobjects) {
1147 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001148 /* Not sure whether the IncrRef is necessary, but something
1149 may overwrite the interpreter result while we are
1150 converting it. */
1151 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001152 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001153 Tcl_DecrRefCount(value);
1154 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001155 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001156 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001157
Guido van Rossum990f5c62000-05-04 15:07:16 +00001158 /* If the result contains any bytes with the top bit set,
1159 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001160#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001161 while (*p != '\0') {
1162 if (*p & 0x80)
1163 break;
1164 p++;
1165 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001166
Guido van Rossum990f5c62000-05-04 15:07:16 +00001167 if (*p == '\0')
1168 res = PyString_FromStringAndSize(s, (int)(p-s));
1169 else {
1170 /* Convert UTF-8 to Unicode string */
1171 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001172 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1173 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001174 PyErr_Clear();
1175 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001176 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001177 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001178#else
1179 p = strchr(p, '\0');
1180 res = PyString_FromStringAndSize(s, (int)(p-s));
1181#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001182 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001183 return res;
1184}
Guido van Rossum632de272000-03-29 00:19:50 +00001185
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001186/* Tkapp_CallProc is the event procedure that is executed in the context of
1187 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1188 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001189
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190static int
1191Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1192{
1193 Tcl_Obj *objStore[ARGSZ];
1194 Tcl_Obj **objv;
1195 int objc;
1196 int i;
1197 ENTER_PYTHON
1198 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1199 if (!objv) {
1200 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1201 *(e->res) = NULL;
1202 }
1203 LEAVE_PYTHON
1204 if (!objv)
1205 goto done;
1206 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1207 ENTER_PYTHON
1208 if (i == TCL_ERROR) {
1209 *(e->res) = NULL;
1210 *(e->exc_type) = NULL;
1211 *(e->exc_tb) = NULL;
1212 *(e->exc_value) = PyObject_CallFunction(
1213 Tkinter_TclError, "s",
1214 Tcl_GetStringResult(e->self->interp));
1215 }
1216 else {
1217 *(e->res) = Tkapp_CallResult(e->self);
1218 }
1219 LEAVE_PYTHON
1220 done:
1221 /* Wake up calling thread. */
1222 Tcl_MutexLock(&call_mutex);
1223 Tcl_ConditionNotify(&e->done);
1224 Tcl_MutexUnlock(&call_mutex);
1225 return 1;
1226}
1227
1228/* This is the main entry point for calling a Tcl command.
1229 It supports three cases, with regard to threading:
1230 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1231 the context of the calling thread.
1232 2. Tcl is threaded, caller of the command is in the interpreter thread:
1233 Execute the command in the calling thread. Since the Tcl lock will
1234 not be used, we can merge that with case 1.
1235 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1236 the interpreter thread. Allocation of Tcl objects needs to occur in the
1237 interpreter thread, so we ship the PyObject* args to the target thread,
1238 and perform processing there. */
1239
1240static PyObject *
1241Tkapp_Call(PyObject *_self, PyObject *args)
1242{
1243 Tcl_Obj *objStore[ARGSZ];
1244 Tcl_Obj **objv = NULL;
1245 int objc, i;
1246 PyObject *res = NULL;
1247 TkappObject *self = (TkappObject*)_self;
1248 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1249 int flags = TCL_EVAL_DIRECT;
1250
Martin v. Löwisa9656492003-03-30 08:44:58 +00001251#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1253 /* We cannot call the command directly. Instead, we must
1254 marshal the parameters to the interpreter thread. */
1255 Tkapp_CallEvent *ev;
1256 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001257 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001258 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001259 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1260 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1261 ev->self = self;
1262 ev->args = args;
1263 ev->res = &res;
1264 ev->exc_type = &exc_type;
1265 ev->exc_value = &exc_value;
1266 ev->exc_tb = &exc_tb;
1267 ev->done = (Tcl_Condition)0;
1268
1269 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1270
1271 if (res == NULL) {
1272 if (exc_type)
1273 PyErr_Restore(exc_type, exc_value, exc_tb);
1274 else
1275 PyErr_SetObject(Tkinter_TclError, exc_value);
1276 }
1277 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001278 else
1279#endif
1280 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281
1282 objv = Tkapp_CallArgs(args, objStore, &objc);
1283 if (!objv)
1284 return NULL;
1285
1286 ENTER_TCL
1287
1288 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1289
1290 ENTER_OVERLAP
1291
1292 if (i == TCL_ERROR)
1293 Tkinter_Error(_self);
1294 else
1295 res = Tkapp_CallResult(self);
1296
1297 LEAVE_OVERLAP_TCL
1298
1299 Tkapp_CallDeallocArgs(objv, objStore, objc);
1300 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001301 return res;
1302}
1303
1304
1305static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001306Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001307{
Guido van Rossum212643f1998-04-29 16:22:14 +00001308 /* Could do the same here as for Tkapp_Call(), but this is not used
1309 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1310 way for the user to do what all its Global* variants do (save and
1311 reset the scope pointer, call the local version, restore the saved
1312 scope pointer). */
1313
Guido van Rossum62320c91998-06-15 04:36:09 +00001314 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001315 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001316
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317 CHECK_TCL_APPARTMENT;
1318
Guido van Rossum62320c91998-06-15 04:36:09 +00001319 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001320 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001321 int err;
1322 ENTER_TCL
1323 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001324 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001325 if (err == TCL_ERROR)
1326 res = Tkinter_Error(self);
1327 else
1328 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001329 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001330 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001331 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001332
1333 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001334}
1335
1336static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001337Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001338{
Barry Warsawfa701a81997-01-16 00:15:11 +00001339 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001340 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001341 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342
Guido van Rossum43713e52000-02-29 13:59:29 +00001343 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001344 return NULL;
1345
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001346 CHECK_TCL_APPARTMENT;
1347
Guido van Rossum00d93061998-05-28 23:06:38 +00001348 ENTER_TCL
1349 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001350 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001351 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001352 res = Tkinter_Error(self);
1353 else
1354 res = PyString_FromString(Tkapp_Result(self));
1355 LEAVE_OVERLAP_TCL
1356 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001357}
1358
1359static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001360Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001361{
Barry Warsawfa701a81997-01-16 00:15:11 +00001362 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001363 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001365
Guido van Rossum43713e52000-02-29 13:59:29 +00001366 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001367 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001368
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369 CHECK_TCL_APPARTMENT;
1370
Guido van Rossum00d93061998-05-28 23:06:38 +00001371 ENTER_TCL
1372 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001374 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001375 res = Tkinter_Error(self);
1376 else
1377 res = PyString_FromString(Tkapp_Result(self));
1378 LEAVE_OVERLAP_TCL
1379 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001380}
1381
1382static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001383Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001384{
Barry Warsawfa701a81997-01-16 00:15:11 +00001385 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001386 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001388
Guido van Rossum43713e52000-02-29 13:59:29 +00001389 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001390 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001391
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392 CHECK_TCL_APPARTMENT;
1393
Guido van Rossum00d93061998-05-28 23:06:38 +00001394 ENTER_TCL
1395 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001397 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001398 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001399
Guido van Rossum62320c91998-06-15 04:36:09 +00001400 else
1401 res = PyString_FromString(Tkapp_Result(self));
1402 LEAVE_OVERLAP_TCL
1403 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001404}
1405
1406static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001407Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001408{
Barry Warsawfa701a81997-01-16 00:15:11 +00001409 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001410 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001411 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001412
Guido van Rossum35d43371997-08-02 00:09:09 +00001413 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001414 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001415
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001416 CHECK_TCL_APPARTMENT;
1417
Guido van Rossum00d93061998-05-28 23:06:38 +00001418 ENTER_TCL
1419 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001420 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001421 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001422 res = Tkinter_Error(self);
1423 else
1424 res = PyString_FromString(Tkapp_Result(self));
1425 LEAVE_OVERLAP_TCL
1426 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001427}
1428
1429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001430Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001431{
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001433
Guido van Rossum43713e52000-02-29 13:59:29 +00001434 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001435 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001436 CHECK_TCL_APPARTMENT;
1437
Guido van Rossum00d93061998-05-28 23:06:38 +00001438 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001439 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001440 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001441
Barry Warsawfa701a81997-01-16 00:15:11 +00001442 Py_INCREF(Py_None);
1443 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001444}
1445
Barry Warsawfa701a81997-01-16 00:15:11 +00001446
1447
Guido van Rossum18468821994-06-20 07:49:28 +00001448/** Tcl Variable **/
1449
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001450TCL_DECLARE_MUTEX(var_mutex)
1451
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001452typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
1453typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
1454typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455typedef struct VarEvent {
1456 Tcl_Event ev; /* must be first */
1457 TkappObject *self;
1458 char* arg1;
1459 char* arg2;
1460 char* arg3;
1461 int flags;
1462 EventFunc1 func1;
1463 EventFunc2 func2;
1464 EventFunc3 func3;
1465 PyObject **res;
1466 PyObject **exc;
1467 Tcl_Condition cond;
1468 int coderesult;
1469} VarEvent;
1470
1471static const char*
1472var_perform(VarEvent *ev)
1473{
1474 if (!ev->arg2 && !ev->arg2)
1475 return ev->func1(ev->self->interp, ev->arg1, ev->flags);
1476 if (!ev->arg3)
1477 return ev->func2(ev->self->interp, ev->arg1,
1478 ev->arg2, ev->flags);
1479 return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
1480 ev->arg3, ev->flags);
1481}
1482
1483static void
1484var_fill_result(VarEvent *ev, const char* res)
1485{
1486 if (ev->coderesult) {
1487 if ((int)res != TCL_ERROR) {
1488 Py_INCREF(Py_None);
1489 *(ev->res) = Py_None;
1490 return;
1491 }
1492 }
1493 else if (res) {
1494 *(ev->res) = PyString_FromString(res);
1495 return;
1496 }
1497
1498 *(ev->res) = NULL;
1499 *(ev->exc) = PyObject_CallFunction(
1500 Tkinter_TclError, "s",
1501 Tcl_GetStringResult(ev->self->interp));
1502
1503}
1504
1505static int
1506var_proc(VarEvent* ev, int flags)
1507{
1508 const char *result = var_perform(ev);
1509 ENTER_PYTHON
1510 var_fill_result(ev, result);
1511 Tcl_MutexLock(&var_mutex);
1512 Tcl_ConditionNotify(&ev->cond);
1513 Tcl_MutexUnlock(&var_mutex);
1514 LEAVE_PYTHON
1515 return 1;
1516}
1517
1518static PyObject*
1519var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
1520 EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
1521 int coderesult)
1522{
1523 VarEvent _ev;
1524 TkappObject *self = (TkappObject*)_self;
1525 VarEvent *ev = self->threaded ?
1526 (VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
1527 PyObject *res, *exc;
1528
1529 ev->self = self;
1530 ev->arg1 = arg1;
1531 ev->arg2 = arg2;
1532 ev->arg3 = arg3;
1533 ev->flags = flags;
1534 ev->func1 = func1;
1535 ev->func2 = func2;
1536 ev->func3 = func3;
1537 ev->coderesult = coderesult;
1538 ev->res = &res;
1539 ev->exc = &exc;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001540#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1542 /* The current thread is not the interpreter thread. Marshal
1543 the call to the interpreter thread, then wait for
1544 completion. */
1545
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001546 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001547 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548 ev->cond = NULL;
1549 ev->ev.proc = (Tcl_EventProc*)var_proc;
1550 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1551 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001552 else
1553#endif
1554 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001555 /* Tcl is not threaded, or this is the interpreter thread. To
1556 perform the call, we must hold the TCL lock. To receive the
1557 results, we must also hold the Python lock. */
1558 const char *result;
1559 ENTER_TCL
1560 result = var_perform(ev);
1561 ENTER_OVERLAP
1562 var_fill_result(ev, result);
1563 LEAVE_OVERLAP_TCL
1564 }
1565 if (!res) {
1566 PyErr_SetObject(Tkinter_TclError, exc);
1567 return NULL;
1568 }
1569 return res;
1570}
1571
1572static PyObject*
1573var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
Martin v. Löwis5b177f12002-12-30 18:14:15 +00001574 int (*func1)(Tcl_Interp*, CONST char*, int),
1575 int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
1576 int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001577{
1578 return var_invoke(_self, arg1, arg2, arg3, flags,
1579 (EventFunc1)func1, (EventFunc2)func2,
1580 (EventFunc3)func3, 1);
1581}
1582
Guido van Rossum18468821994-06-20 07:49:28 +00001583static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001584SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001585{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001586 char *name1, *name2, *s;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001587 PyObject *res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001588 PyObject *newValue;
Guido van Rossum62320c91998-06-15 04:36:09 +00001589 PyObject *tmp;
Guido van Rossum18468821994-06-20 07:49:28 +00001590
Guido van Rossum62320c91998-06-15 04:36:09 +00001591 tmp = PyList_New(0);
Barry Warsawfa701a81997-01-16 00:15:11 +00001592 if (!tmp)
1593 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001594
Guido van Rossum43713e52000-02-29 13:59:29 +00001595 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 /* XXX Merge? */
Guido van Rossum00d93061998-05-28 23:06:38 +00001597 s = AsString(newValue, tmp);
Guido van Rossum2834b972000-10-06 16:58:26 +00001598 if (s == NULL)
1599 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001600 res = var_invoke(self, name1, s, NULL, flags,
1601 NULL, Tcl_SetVar, NULL, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001602 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001603 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001604 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001605 if (PyArg_ParseTuple(args, "ssO:setvar",
1606 &name1, &name2, &newValue)) {
1607 s = AsString(newValue, tmp);
1608 if (s == NULL)
1609 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001610 res = var_invoke(self, name1, name2, s, flags,
1611 NULL, NULL, Tcl_SetVar2, 0);
Guido van Rossum00d93061998-05-28 23:06:38 +00001612 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001613 else {
Guido van Rossum00d93061998-05-28 23:06:38 +00001614 Py_DECREF(tmp);
Guido van Rossum35d43371997-08-02 00:09:09 +00001615 return NULL;
1616 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001617 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001618 Py_DECREF(tmp);
Guido van Rossum18468821994-06-20 07:49:28 +00001619
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001620 if (!res)
1621 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001622
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001623 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001624 Py_INCREF(Py_None);
1625 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001626}
1627
1628static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001629Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001630{
Barry Warsawfa701a81997-01-16 00:15:11 +00001631 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001632}
1633
1634static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001635Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001636{
Barry Warsawfa701a81997-01-16 00:15:11 +00001637 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001638}
1639
Barry Warsawfa701a81997-01-16 00:15:11 +00001640
1641
Guido van Rossum18468821994-06-20 07:49:28 +00001642static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001643GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001644{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001645 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001646 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001647
Guido van Rossum43713e52000-02-29 13:59:29 +00001648 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001649 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001650
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001651 res = var_invoke(self, name1, name2, NULL, flags,
1652 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
Guido van Rossum62320c91998-06-15 04:36:09 +00001653 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001654}
1655
1656static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001657Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001658{
Barry Warsawfa701a81997-01-16 00:15:11 +00001659 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001660}
1661
1662static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001663Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001664{
Barry Warsawfa701a81997-01-16 00:15:11 +00001665 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001666}
1667
Barry Warsawfa701a81997-01-16 00:15:11 +00001668
1669
Guido van Rossum18468821994-06-20 07:49:28 +00001670static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001671UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001672{
Guido van Rossum35d43371997-08-02 00:09:09 +00001673 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001674 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001675
Guido van Rossum43713e52000-02-29 13:59:29 +00001676 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001677 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001678
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001679 res = var_invoke2(self, name1, name2, NULL, flags,
1680 Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001681 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001682}
1683
1684static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001685Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001686{
Barry Warsawfa701a81997-01-16 00:15:11 +00001687 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001688}
1689
1690static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001691Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001692{
Barry Warsawfa701a81997-01-16 00:15:11 +00001693 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001694}
1695
Barry Warsawfa701a81997-01-16 00:15:11 +00001696
1697
Guido van Rossum18468821994-06-20 07:49:28 +00001698/** Tcl to Python **/
1699
1700static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001701Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001702{
Barry Warsawfa701a81997-01-16 00:15:11 +00001703 char *s;
1704 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001705
Martin v. Löwisffad6332002-11-26 09:28:05 +00001706 if (PyTuple_Size(args) == 1) {
1707 PyObject* o = PyTuple_GetItem(args, 0);
1708 if (PyInt_Check(o)) {
1709 Py_INCREF(o);
1710 return o;
1711 }
1712 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001713 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001714 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001715 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001716 return Tkinter_Error(self);
1717 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001718}
1719
1720static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001721Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001722{
Barry Warsawfa701a81997-01-16 00:15:11 +00001723 char *s;
1724 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001725
Martin v. Löwisffad6332002-11-26 09:28:05 +00001726 if (PyTuple_Size(args) == 1) {
1727 PyObject *o = PyTuple_GetItem(args, 0);
1728 if (PyFloat_Check(o)) {
1729 Py_INCREF(o);
1730 return o;
1731 }
1732 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001733 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001734 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001735 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001736 return Tkinter_Error(self);
1737 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001738}
1739
1740static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001741Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001742{
Barry Warsawfa701a81997-01-16 00:15:11 +00001743 char *s;
1744 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001745
Martin v. Löwisffad6332002-11-26 09:28:05 +00001746 if (PyTuple_Size(args) == 1) {
1747 PyObject *o = PyTuple_GetItem(args, 0);
1748 if (PyInt_Check(o)) {
1749 Py_INCREF(o);
1750 return o;
1751 }
1752 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001753 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001754 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001755 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1756 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001757 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001758}
1759
1760static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001761Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001762{
Barry Warsawfa701a81997-01-16 00:15:11 +00001763 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001764 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001765 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001766
Guido van Rossum43713e52000-02-29 13:59:29 +00001767 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001768 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001769
1770 CHECK_TCL_APPARTMENT;
1771
Guido van Rossum00d93061998-05-28 23:06:38 +00001772 ENTER_TCL
1773 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001774 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001775 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001776 res = Tkinter_Error(self);
1777 else
1778 res = Py_BuildValue("s", Tkapp_Result(self));
1779 LEAVE_OVERLAP_TCL
1780 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001781}
1782
1783static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001784Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001785{
Barry Warsawfa701a81997-01-16 00:15:11 +00001786 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001787 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001788 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001789 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001790
Guido van Rossum43713e52000-02-29 13:59:29 +00001791 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001792 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001793
1794 CHECK_TCL_APPARTMENT;
1795
Guido van Rossum00d93061998-05-28 23:06:38 +00001796 ENTER_TCL
1797 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001798 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001799 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001800 res = Tkinter_Error(self);
1801 else
1802 res = Py_BuildValue("l", v);
1803 LEAVE_OVERLAP_TCL
1804 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001805}
1806
1807static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001808Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001809{
Barry Warsawfa701a81997-01-16 00:15:11 +00001810 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001811 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001812 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001813 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001814
Guido van Rossum43713e52000-02-29 13:59:29 +00001815 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001816 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001817 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001818 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001819 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001820 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001821 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001822 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001823 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001824 res = Tkinter_Error(self);
1825 else
1826 res = Py_BuildValue("d", v);
1827 LEAVE_OVERLAP_TCL
1828 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001829}
1830
1831static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001832Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001833{
Barry Warsawfa701a81997-01-16 00:15:11 +00001834 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001835 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001836 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001837 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001838
Guido van Rossum43713e52000-02-29 13:59:29 +00001839 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001840 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001841 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001842 ENTER_TCL
1843 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001844 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001845 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001846 res = Tkinter_Error(self);
1847 else
1848 res = Py_BuildValue("i", v);
1849 LEAVE_OVERLAP_TCL
1850 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001851}
1852
Barry Warsawfa701a81997-01-16 00:15:11 +00001853
1854
Guido van Rossum18468821994-06-20 07:49:28 +00001855static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001856Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001857{
Barry Warsawfa701a81997-01-16 00:15:11 +00001858 char *list;
1859 int argc;
1860 char **argv;
1861 PyObject *v;
1862 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001863
Martin v. Löwisffad6332002-11-26 09:28:05 +00001864 if (PyTuple_Size(args) == 1) {
1865 v = PyTuple_GetItem(args, 0);
1866 if (PyTuple_Check(v)) {
1867 Py_INCREF(v);
1868 return v;
1869 }
1870 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001871 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001872 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001873
Barry Warsawfa701a81997-01-16 00:15:11 +00001874 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1875 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001876
Barry Warsawfa701a81997-01-16 00:15:11 +00001877 if (!(v = PyTuple_New(argc)))
1878 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880 for (i = 0; i < argc; i++) {
1881 PyObject *s = PyString_FromString(argv[i]);
1882 if (!s || PyTuple_SetItem(v, i, s)) {
1883 Py_DECREF(v);
1884 v = NULL;
1885 goto finally;
1886 }
1887 }
Guido van Rossum18468821994-06-20 07:49:28 +00001888
Barry Warsawfa701a81997-01-16 00:15:11 +00001889 finally:
1890 ckfree(FREECAST argv);
1891 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001892}
1893
1894static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001895Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001896{
Barry Warsawfa701a81997-01-16 00:15:11 +00001897 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001898
Martin v. Löwisffad6332002-11-26 09:28:05 +00001899 if (PyTuple_Size(args) == 1) {
1900 PyObject* o = PyTuple_GetItem(args, 0);
1901 if (PyTuple_Check(o)) {
1902 o = SplitObj(o);
1903 return o;
1904 }
1905 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001906 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001907 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001908 return Split(list);
Guido van Rossum18468821994-06-20 07:49:28 +00001909}
1910
1911static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001912Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001913{
Barry Warsawfa701a81997-01-16 00:15:11 +00001914 char *s = Merge(args);
1915 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001916
Barry Warsawfa701a81997-01-16 00:15:11 +00001917 if (s) {
1918 res = PyString_FromString(s);
1919 ckfree(s);
1920 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001921
1922 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001923}
1924
Barry Warsawfa701a81997-01-16 00:15:11 +00001925
1926
Guido van Rossum18468821994-06-20 07:49:28 +00001927/** Tcl Command **/
1928
Guido van Rossum00d93061998-05-28 23:06:38 +00001929/* Client data struct */
1930typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001931 PyObject *self;
1932 PyObject *func;
1933} PythonCmd_ClientData;
1934
1935static int
Fred Drake509d79a2000-07-08 04:04:38 +00001936PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001937{
1938 errorInCmd = 1;
1939 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1940 LEAVE_PYTHON
1941 return TCL_ERROR;
1942}
1943
Guido van Rossum18468821994-06-20 07:49:28 +00001944/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001945 * function or method.
1946 */
Guido van Rossum18468821994-06-20 07:49:28 +00001947static int
Fred Drake509d79a2000-07-08 04:04:38 +00001948PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001949{
Guido van Rossum00d93061998-05-28 23:06:38 +00001950 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001951 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001952 int i, rv;
1953 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001954
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001955 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001956
Barry Warsawfa701a81997-01-16 00:15:11 +00001957 /* TBD: no error checking here since we know, via the
1958 * Tkapp_CreateCommand() that the client data is a two-tuple
1959 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001960 self = data->self;
1961 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001962
Barry Warsawfa701a81997-01-16 00:15:11 +00001963 /* Create argument list (argv1, ..., argvN) */
1964 if (!(arg = PyTuple_New(argc - 1)))
1965 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001966
Barry Warsawfa701a81997-01-16 00:15:11 +00001967 for (i = 0; i < (argc - 1); i++) {
1968 PyObject *s = PyString_FromString(argv[i + 1]);
1969 if (!s || PyTuple_SetItem(arg, i, s)) {
1970 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001971 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001972 }
1973 }
1974 res = PyEval_CallObject(func, arg);
1975 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001976
Barry Warsawfa701a81997-01-16 00:15:11 +00001977 if (res == NULL)
1978 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001979
Barry Warsawfa701a81997-01-16 00:15:11 +00001980 if (!(tmp = PyList_New(0))) {
1981 Py_DECREF(res);
1982 return PythonCmd_Error(interp);
1983 }
1984
Guido van Rossum2834b972000-10-06 16:58:26 +00001985 s = AsString(res, tmp);
1986 if (s == NULL) {
1987 rv = PythonCmd_Error(interp);
1988 }
1989 else {
1990 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1991 rv = TCL_OK;
1992 }
1993
Barry Warsawfa701a81997-01-16 00:15:11 +00001994 Py_DECREF(res);
1995 Py_DECREF(tmp);
1996
Guido van Rossum00d93061998-05-28 23:06:38 +00001997 LEAVE_PYTHON
1998
Guido van Rossum2834b972000-10-06 16:58:26 +00001999 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002000}
2001
2002static void
Fred Drake509d79a2000-07-08 04:04:38 +00002003PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002004{
Guido van Rossum00d93061998-05-28 23:06:38 +00002005 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2006
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002007 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002008 Py_XDECREF(data->self);
2009 Py_XDECREF(data->func);
2010 PyMem_DEL(data);
2011 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002012}
2013
Barry Warsawfa701a81997-01-16 00:15:11 +00002014
2015
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002016
2017TCL_DECLARE_MUTEX(command_mutex)
2018
2019typedef struct CommandEvent{
2020 Tcl_Event ev;
2021 Tcl_Interp* interp;
2022 char *name;
2023 int create;
2024 int *status;
2025 ClientData *data;
2026 Tcl_Condition done;
2027} CommandEvent;
2028
2029static int
2030Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002031{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002032 if (ev->create)
2033 *ev->status = Tcl_CreateCommand(
2034 ev->interp, ev->name, PythonCmd,
2035 ev->data, PythonCmdDelete) == NULL;
2036 else
2037 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2038 Tcl_MutexLock(&command_mutex);
2039 Tcl_ConditionNotify(&ev->done);
2040 Tcl_MutexUnlock(&command_mutex);
2041 return 1;
2042}
2043
2044static PyObject *
2045Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2046{
2047 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002048 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002049 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002050 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002051 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002052
Guido van Rossum43713e52000-02-29 13:59:29 +00002053 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002054 return NULL;
2055 if (!PyCallable_Check(func)) {
2056 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002057 return NULL;
2058 }
Guido van Rossum18468821994-06-20 07:49:28 +00002059
Martin v. Löwisa9656492003-03-30 08:44:58 +00002060#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002061 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002062 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002063 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002064#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002065
Guido van Rossum00d93061998-05-28 23:06:38 +00002066 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002067 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002068 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002069 Py_XINCREF(self);
2070 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002071 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002072 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002073
2074 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2075 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2076 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2077 ev->interp = self->interp;
2078 ev->create = 1;
2079 ev->name = cmdName;
2080 ev->data = (ClientData)data;
2081 ev->status = &err;
2082 ev->done = NULL;
2083 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2084 }
2085 else {
2086 ENTER_TCL
2087 err = Tcl_CreateCommand(
2088 Tkapp_Interp(self), cmdName, PythonCmd,
2089 (ClientData)data, PythonCmdDelete) == NULL;
2090 LEAVE_TCL
2091 }
2092 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002093 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002094 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002095 return NULL;
2096 }
Guido van Rossum18468821994-06-20 07:49:28 +00002097
Barry Warsawfa701a81997-01-16 00:15:11 +00002098 Py_INCREF(Py_None);
2099 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002100}
2101
Barry Warsawfa701a81997-01-16 00:15:11 +00002102
2103
Guido van Rossum18468821994-06-20 07:49:28 +00002104static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002105Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002106{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002108 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002109 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002110
Guido van Rossum43713e52000-02-29 13:59:29 +00002111 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002112 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002113 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2114 CommandEvent *ev;
2115 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2116 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2117 ev->interp = self->interp;
2118 ev->create = 0;
2119 ev->name = cmdName;
2120 ev->status = &err;
2121 ev->done = NULL;
2122 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2123 &command_mutex);
2124 }
2125 else {
2126 ENTER_TCL
2127 err = Tcl_DeleteCommand(self->interp, cmdName);
2128 LEAVE_TCL
2129 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002130 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002131 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2132 return NULL;
2133 }
2134 Py_INCREF(Py_None);
2135 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002136}
2137
Barry Warsawfa701a81997-01-16 00:15:11 +00002138
2139
Guido van Rossum00d93061998-05-28 23:06:38 +00002140#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002141/** File Handler **/
2142
Guido van Rossum00d93061998-05-28 23:06:38 +00002143typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002144 PyObject *func;
2145 PyObject *file;
2146 int id;
2147 struct _fhcdata *next;
2148} FileHandler_ClientData;
2149
2150static FileHandler_ClientData *HeadFHCD;
2151
2152static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002153NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002154{
2155 FileHandler_ClientData *p;
2156 p = PyMem_NEW(FileHandler_ClientData, 1);
2157 if (p != NULL) {
2158 Py_XINCREF(func);
2159 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002160 p->func = func;
2161 p->file = file;
2162 p->id = id;
2163 p->next = HeadFHCD;
2164 HeadFHCD = p;
2165 }
2166 return p;
2167}
2168
2169static void
Fred Drake509d79a2000-07-08 04:04:38 +00002170DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002171{
2172 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002173
2174 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002175 while ((p = *pp) != NULL) {
2176 if (p->id == id) {
2177 *pp = p->next;
2178 Py_XDECREF(p->func);
2179 Py_XDECREF(p->file);
2180 PyMem_DEL(p);
2181 }
2182 else
2183 pp = &p->next;
2184 }
2185}
2186
Guido van Rossuma597dde1995-01-10 20:56:29 +00002187static void
Fred Drake509d79a2000-07-08 04:04:38 +00002188FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002189{
Guido van Rossum00d93061998-05-28 23:06:38 +00002190 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002191 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002192
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002193 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002194 func = data->func;
2195 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002196
Barry Warsawfa701a81997-01-16 00:15:11 +00002197 arg = Py_BuildValue("(Oi)", file, (long) mask);
2198 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002199 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002200
2201 if (res == NULL) {
2202 errorInCmd = 1;
2203 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2204 }
2205 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002206 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002207}
2208
Guido van Rossum18468821994-06-20 07:49:28 +00002209static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002210Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2211 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002212{
Guido van Rossum00d93061998-05-28 23:06:38 +00002213 FileHandler_ClientData *data;
2214 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002215 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002216
Guido van Rossum2834b972000-10-06 16:58:26 +00002217 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2218 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002219 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002220
Martin v. Löwisa9656492003-03-30 08:44:58 +00002221#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002222 if (!self && !tcl_lock) {
2223 /* We don't have the Tcl lock since Tcl is threaded. */
2224 PyErr_SetString(PyExc_RuntimeError,
2225 "_tkinter.createfilehandler not supported "
2226 "for threaded Tcl");
2227 return NULL;
2228 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002229#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002230
2231 if (self) {
2232 CHECK_TCL_APPARTMENT;
2233 }
2234
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002235 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002236 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002237 return NULL;
2238 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002239 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002240 return NULL;
2241 }
2242
Guido van Rossuma80649b2000-03-28 20:07:05 +00002243 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002244 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002245 return NULL;
2246
Barry Warsawfa701a81997-01-16 00:15:11 +00002247 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002248 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002249 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002250 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002251 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002252 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002253}
2254
2255static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002256Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002257{
Barry Warsawfa701a81997-01-16 00:15:11 +00002258 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002259 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002260
Guido van Rossum43713e52000-02-29 13:59:29 +00002261 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002262 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002263
Martin v. Löwisa9656492003-03-30 08:44:58 +00002264#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002265 if (!self && !tcl_lock) {
2266 /* We don't have the Tcl lock since Tcl is threaded. */
2267 PyErr_SetString(PyExc_RuntimeError,
2268 "_tkinter.deletefilehandler not supported "
2269 "for threaded Tcl");
2270 return NULL;
2271 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002272#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002273
2274 if (self) {
2275 CHECK_TCL_APPARTMENT;
2276 }
2277
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002278 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002279 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002280 return NULL;
2281
Guido van Rossuma80649b2000-03-28 20:07:05 +00002282 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002283
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002285 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002287 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002288 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002289 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002290}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002291#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002292
Barry Warsawfa701a81997-01-16 00:15:11 +00002293
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002294/**** Tktt Object (timer token) ****/
2295
Jeremy Hylton938ace62002-07-17 16:30:39 +00002296static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002297
Guido van Rossum00d93061998-05-28 23:06:38 +00002298typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002300 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002301 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002302} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002303
2304static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002305Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002306{
Barry Warsawfa701a81997-01-16 00:15:11 +00002307 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002308 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002309
Guido van Rossum43713e52000-02-29 13:59:29 +00002310 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002311 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002312 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002313 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002314 v->token = NULL;
2315 }
2316 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002317 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002318 Py_DECREF(func);
2319 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 }
2321 Py_INCREF(Py_None);
2322 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002323}
2324
2325static PyMethodDef Tktt_methods[] =
2326{
Neal Norwitzb0493252002-03-31 14:44:22 +00002327 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002328 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329};
2330
2331static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002332Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333{
Barry Warsawfa701a81997-01-16 00:15:11 +00002334 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002335
Guido van Rossumb18618d2000-05-03 23:44:39 +00002336 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002337 if (v == NULL)
2338 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339
Guido van Rossum00d93061998-05-28 23:06:38 +00002340 Py_INCREF(func);
2341 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002342 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002343
2344 /* Extra reference, deleted when called or when handler is deleted */
2345 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002346 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347}
2348
2349static void
Fred Drake509d79a2000-07-08 04:04:38 +00002350Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351{
Guido van Rossum00d93061998-05-28 23:06:38 +00002352 TkttObject *v = (TkttObject *)self;
2353 PyObject *func = v->func;
2354
2355 Py_XDECREF(func);
2356
Guido van Rossumb18618d2000-05-03 23:44:39 +00002357 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358}
2359
Guido van Rossum597ac201998-05-12 14:36:19 +00002360static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002361Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002362{
Barry Warsawfa701a81997-01-16 00:15:11 +00002363 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002364 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002365
Tim Peters885d4572001-11-28 20:27:42 +00002366 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002367 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002368 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002369}
2370
2371static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002372Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373{
Barry Warsawfa701a81997-01-16 00:15:11 +00002374 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375}
2376
2377static PyTypeObject Tktt_Type =
2378{
Guido van Rossum35d43371997-08-02 00:09:09 +00002379 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002380 0, /*ob_size */
2381 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002382 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002383 0, /*tp_itemsize */
2384 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002385 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002386 Tktt_GetAttr, /*tp_getattr */
2387 0, /*tp_setattr */
2388 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002389 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002390 0, /*tp_as_number */
2391 0, /*tp_as_sequence */
2392 0, /*tp_as_mapping */
2393 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002394};
2395
Barry Warsawfa701a81997-01-16 00:15:11 +00002396
2397
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002398/** Timer Handler **/
2399
2400static void
Fred Drake509d79a2000-07-08 04:04:38 +00002401TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402{
Guido van Rossum00d93061998-05-28 23:06:38 +00002403 TkttObject *v = (TkttObject *)clientData;
2404 PyObject *func = v->func;
2405 PyObject *res;
2406
2407 if (func == NULL)
2408 return;
2409
2410 v->func = NULL;
2411
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002412 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002413
2414 res = PyEval_CallObject(func, NULL);
2415 Py_DECREF(func);
2416 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002417
Barry Warsawfa701a81997-01-16 00:15:11 +00002418 if (res == NULL) {
2419 errorInCmd = 1;
2420 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2421 }
2422 else
2423 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002424
2425 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002426}
2427
2428static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002429Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002430{
Barry Warsawfa701a81997-01-16 00:15:11 +00002431 int milliseconds;
2432 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002433 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434
Guido van Rossum2834b972000-10-06 16:58:26 +00002435 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2436 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002437 return NULL;
2438 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002439 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002440 return NULL;
2441 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002442
Martin v. Löwisa9656492003-03-30 08:44:58 +00002443#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002444 if (!self && !tcl_lock) {
2445 /* We don't have the Tcl lock since Tcl is threaded. */
2446 PyErr_SetString(PyExc_RuntimeError,
2447 "_tkinter.createtimerhandler not supported "
2448 "for threaded Tcl");
2449 return NULL;
2450 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002451#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002452
2453 if (self) {
2454 CHECK_TCL_APPARTMENT;
2455 }
2456
Guido van Rossum00d93061998-05-28 23:06:38 +00002457 v = Tktt_New(func);
2458 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2459 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002460
Guido van Rossum00d93061998-05-28 23:06:38 +00002461 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002462}
2463
Barry Warsawfa701a81997-01-16 00:15:11 +00002464
Guido van Rossum18468821994-06-20 07:49:28 +00002465/** Event Loop **/
2466
Guido van Rossum18468821994-06-20 07:49:28 +00002467static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002468Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002469{
Barry Warsawfa701a81997-01-16 00:15:11 +00002470 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002471 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002472#ifdef WITH_THREAD
2473 PyThreadState *tstate = PyThreadState_Get();
2474#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002475
Guido van Rossum43713e52000-02-29 13:59:29 +00002476 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002477 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002478
Martin v. Löwisa9656492003-03-30 08:44:58 +00002479#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002480 if (!self && !tcl_lock) {
2481 /* We don't have the Tcl lock since Tcl is threaded. */
2482 PyErr_SetString(PyExc_RuntimeError,
2483 "_tkinter.mainloop not supported "
2484 "for threaded Tcl");
2485 return NULL;
2486 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002487#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002488
2489 if (self) {
2490 CHECK_TCL_APPARTMENT;
2491 self->dispatching = 1;
2492 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002493
Barry Warsawfa701a81997-01-16 00:15:11 +00002494 quitMainLoop = 0;
2495 while (Tk_GetNumMainWindows() > threshold &&
2496 !quitMainLoop &&
2497 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002498 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002499 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002500
2501#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002502 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002503 /* Allow other Python threads to run. */
2504 ENTER_TCL
2505 result = Tcl_DoOneEvent(0);
2506 LEAVE_TCL
2507 }
2508 else {
2509 Py_BEGIN_ALLOW_THREADS
2510 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2511 tcl_tstate = tstate;
2512 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2513 tcl_tstate = NULL;
2514 if(tcl_lock)PyThread_release_lock(tcl_lock);
2515 if (result == 0)
2516 Sleep(20);
2517 Py_END_ALLOW_THREADS
2518 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002519#else
2520 result = Tcl_DoOneEvent(0);
2521#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002522
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002523 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002524 if (self)
2525 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002526 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002527 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002528 if (result < 0)
2529 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002530 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002531 if (self)
2532 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002533 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002534
Barry Warsawfa701a81997-01-16 00:15:11 +00002535 if (errorInCmd) {
2536 errorInCmd = 0;
2537 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2538 excInCmd = valInCmd = trbInCmd = NULL;
2539 return NULL;
2540 }
2541 Py_INCREF(Py_None);
2542 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002543}
2544
2545static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002546Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002547{
Guido van Rossum35d43371997-08-02 00:09:09 +00002548 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002549 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002550
Guido van Rossum43713e52000-02-29 13:59:29 +00002551 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002552 return NULL;
2553
Guido van Rossum00d93061998-05-28 23:06:38 +00002554 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002555 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002556 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002557 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002558}
2559
2560static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002561Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002562{
2563
Guido van Rossum43713e52000-02-29 13:59:29 +00002564 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002565 return NULL;
2566
2567 quitMainLoop = 1;
2568 Py_INCREF(Py_None);
2569 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002570}
2571
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002572static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002573Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002574{
2575
Guido van Rossum43713e52000-02-29 13:59:29 +00002576 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002577 return NULL;
2578
2579 return PyInt_FromLong((long)Tkapp_Interp(self));
2580}
2581
Barry Warsawfa701a81997-01-16 00:15:11 +00002582
Martin v. Löwisffad6332002-11-26 09:28:05 +00002583static PyObject *
2584Tkapp_WantObjects(PyObject *self, PyObject *args)
2585{
2586
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002587 int wantobjects;
2588 if (!PyArg_ParseTuple(args, "i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002589 return NULL;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002590 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002591
2592 Py_INCREF(Py_None);
2593 return Py_None;
2594}
2595
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002596static PyObject *
2597Tkapp_WillDispatch(PyObject *self, PyObject *args)
2598{
2599
2600 ((TkappObject*)self)->dispatching = 1;
2601
2602 Py_INCREF(Py_None);
2603 return Py_None;
2604}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002605
Barry Warsawfa701a81997-01-16 00:15:11 +00002606
Guido van Rossum18468821994-06-20 07:49:28 +00002607/**** Tkapp Method List ****/
2608
2609static PyMethodDef Tkapp_methods[] =
2610{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002611 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002612 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002613 {"call", Tkapp_Call, METH_OLDARGS},
2614 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2615 {"eval", Tkapp_Eval, METH_VARARGS},
2616 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2617 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2618 {"record", Tkapp_Record, METH_VARARGS},
2619 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2620 {"setvar", Tkapp_SetVar, METH_VARARGS},
2621 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2622 {"getvar", Tkapp_GetVar, METH_VARARGS},
2623 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2624 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2625 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2626 {"getint", Tkapp_GetInt, METH_VARARGS},
2627 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2628 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2629 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2630 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2631 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2632 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2633 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2634 {"split", Tkapp_Split, METH_VARARGS},
2635 {"merge", Tkapp_Merge, METH_OLDARGS},
2636 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2637 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002638#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002639 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2640 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002641#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002642 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2643 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2644 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2645 {"quit", Tkapp_Quit, METH_VARARGS},
2646 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002647 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002648};
2649
Barry Warsawfa701a81997-01-16 00:15:11 +00002650
2651
Guido van Rossum18468821994-06-20 07:49:28 +00002652/**** Tkapp Type Methods ****/
2653
2654static void
Fred Drake509d79a2000-07-08 04:04:38 +00002655Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002656{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002657 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002658 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002659 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002660 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002661 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002662 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002663}
2664
2665static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002666Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002667{
Guido van Rossum35d43371997-08-02 00:09:09 +00002668 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002669}
2670
2671static PyTypeObject Tkapp_Type =
2672{
Guido van Rossum35d43371997-08-02 00:09:09 +00002673 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002674 0, /*ob_size */
2675 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002676 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002677 0, /*tp_itemsize */
2678 Tkapp_Dealloc, /*tp_dealloc */
2679 0, /*tp_print */
2680 Tkapp_GetAttr, /*tp_getattr */
2681 0, /*tp_setattr */
2682 0, /*tp_compare */
2683 0, /*tp_repr */
2684 0, /*tp_as_number */
2685 0, /*tp_as_sequence */
2686 0, /*tp_as_mapping */
2687 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002688};
2689
Barry Warsawfa701a81997-01-16 00:15:11 +00002690
2691
Guido van Rossum18468821994-06-20 07:49:28 +00002692/**** Tkinter Module ****/
2693
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002694typedef struct {
2695 PyObject* tuple;
2696 int size; /* current size */
2697 int maxsize; /* allocated size */
2698} FlattenContext;
2699
2700static int
2701_bump(FlattenContext* context, int size)
2702{
Guido van Rossum2834b972000-10-06 16:58:26 +00002703 /* expand tuple to hold (at least) size new items.
2704 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002705
2706 int maxsize = context->maxsize * 2;
2707
2708 if (maxsize < context->size + size)
2709 maxsize = context->size + size;
2710
2711 context->maxsize = maxsize;
2712
Tim Peters4324aa32001-05-28 22:30:08 +00002713 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002714}
2715
2716static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002717_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002718{
2719 /* add tuple or list to argument tuple (recursively) */
2720
2721 int i, size;
2722
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002723 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002724 PyErr_SetString(PyExc_ValueError,
2725 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002726 return 0;
2727 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002728 size = PyList_GET_SIZE(item);
2729 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002730 if (context->size + size > context->maxsize &&
2731 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002732 return 0;
2733 /* copy items to output tuple */
2734 for (i = 0; i < size; i++) {
2735 PyObject *o = PyList_GET_ITEM(item, i);
2736 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002737 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738 return 0;
2739 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002740 if (context->size + 1 > context->maxsize &&
2741 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002742 return 0;
2743 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002744 PyTuple_SET_ITEM(context->tuple,
2745 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002746 }
2747 }
2748 } else if (PyTuple_Check(item)) {
2749 /* same, for tuples */
2750 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002751 if (context->size + size > context->maxsize &&
2752 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002753 return 0;
2754 for (i = 0; i < size; i++) {
2755 PyObject *o = PyTuple_GET_ITEM(item, i);
2756 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002757 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002758 return 0;
2759 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002760 if (context->size + 1 > context->maxsize &&
2761 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002762 return 0;
2763 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002764 PyTuple_SET_ITEM(context->tuple,
2765 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002766 }
2767 }
2768 } else {
2769 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2770 return 0;
2771 }
2772 return 1;
2773}
2774
2775static PyObject *
2776Tkinter_Flatten(PyObject* self, PyObject* args)
2777{
2778 FlattenContext context;
2779 PyObject* item;
2780
2781 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2782 return NULL;
2783
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002784 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785 if (context.maxsize <= 0)
2786 return PyTuple_New(0);
2787
2788 context.tuple = PyTuple_New(context.maxsize);
2789 if (!context.tuple)
2790 return NULL;
2791
2792 context.size = 0;
2793
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002794 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002795 return NULL;
2796
Tim Peters4324aa32001-05-28 22:30:08 +00002797 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002798 return NULL;
2799
2800 return context.tuple;
2801}
2802
Guido van Rossum18468821994-06-20 07:49:28 +00002803static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002804Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002805{
Barry Warsawfa701a81997-01-16 00:15:11 +00002806 char *screenName = NULL;
2807 char *baseName = NULL;
2808 char *className = NULL;
2809 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002810 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002811
Guido van Rossum35d43371997-08-02 00:09:09 +00002812 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002813 if (baseName != NULL)
2814 baseName++;
2815 else
2816 baseName = Py_GetProgramName();
2817 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002818
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002819 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002820 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002821 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002822 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002823
Barry Warsawfa701a81997-01-16 00:15:11 +00002824 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002825 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002826}
2827
2828static PyMethodDef moduleMethods[] =
2829{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002830 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2831 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002832#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002833 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2834 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002835#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002836 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2837 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2838 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2839 {"quit", Tkapp_Quit, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002840 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002841};
2842
Guido van Rossum7bf15641998-05-22 18:28:17 +00002843#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002844
2845static int stdin_ready = 0;
2846
Guido van Rossumad4db171998-06-13 13:56:28 +00002847#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002848static void
Fred Drake509d79a2000-07-08 04:04:38 +00002849MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002850{
2851 stdin_ready = 1;
2852}
Guido van Rossumad4db171998-06-13 13:56:28 +00002853#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002854
Martin v. Löwisa9656492003-03-30 08:44:58 +00002855#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002856static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002857#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002858
Guido van Rossum18468821994-06-20 07:49:28 +00002859static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002860EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002861{
Guido van Rossumad4db171998-06-13 13:56:28 +00002862#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002863 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002864#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002865#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002866 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002867#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002868 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002869 errorInCmd = 0;
2870#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002871 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002872 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002873#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002874 while (!errorInCmd && !stdin_ready) {
2875 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002876#ifdef MS_WINDOWS
2877 if (_kbhit()) {
2878 stdin_ready = 1;
2879 break;
2880 }
2881#endif
2882#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002883 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002884 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002885 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002886
Guido van Rossum00d93061998-05-28 23:06:38 +00002887 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002888
2889 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002890 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002891 if (result == 0)
2892 Sleep(20);
2893 Py_END_ALLOW_THREADS
2894#else
2895 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002896#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002897
2898 if (result < 0)
2899 break;
2900 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002901#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002902 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002903#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002904 if (errorInCmd) {
2905 errorInCmd = 0;
2906 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2907 excInCmd = valInCmd = trbInCmd = NULL;
2908 PyErr_Print();
2909 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002910#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002911 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002912#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002913 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002914}
Guido van Rossum18468821994-06-20 07:49:28 +00002915
Guido van Rossum00d93061998-05-28 23:06:38 +00002916#endif
2917
Guido van Rossum7bf15641998-05-22 18:28:17 +00002918static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002919EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002920{
Guido van Rossum00d93061998-05-28 23:06:38 +00002921#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002922 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002923#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002924 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002925#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002926 PyOS_InputHook = EventHook;
2927 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002928#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002929}
2930
2931static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002932DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002933{
Guido van Rossum00d93061998-05-28 23:06:38 +00002934#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002935 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2936 PyOS_InputHook = NULL;
2937 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002938#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002939}
2940
Barry Warsawfa701a81997-01-16 00:15:11 +00002941
2942/* all errors will be checked in one fell swoop in init_tkinter() */
2943static void
Fred Drake509d79a2000-07-08 04:04:38 +00002944ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002945{
2946 PyObject *v = PyInt_FromLong(val);
2947 if (v) {
2948 PyDict_SetItemString(d, name, v);
2949 Py_DECREF(v);
2950 }
2951}
2952static void
Fred Drake509d79a2000-07-08 04:04:38 +00002953ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002954{
2955 PyObject *v = PyString_FromString(val);
2956 if (v) {
2957 PyDict_SetItemString(d, name, v);
2958 Py_DECREF(v);
2959 }
2960}
2961
2962
Mark Hammond62b1ab12002-07-23 06:31:15 +00002963PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002964init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002965{
Barry Warsawfa701a81997-01-16 00:15:11 +00002966 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002967
Barry Warsawfa701a81997-01-16 00:15:11 +00002968 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002969
2970#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002971 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002972#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002973
Barry Warsawfa701a81997-01-16 00:15:11 +00002974 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00002975
Barry Warsawfa701a81997-01-16 00:15:11 +00002976 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00002977 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00002978 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002979
Guido van Rossum35d43371997-08-02 00:09:09 +00002980 ins_long(d, "READABLE", TCL_READABLE);
2981 ins_long(d, "WRITABLE", TCL_WRITABLE);
2982 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2983 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2984 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2985 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2986 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2987 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2988 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00002989 ins_string(d, "TK_VERSION", TK_VERSION);
2990 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002991
Guido van Rossum83551bf1997-09-13 00:44:23 +00002992 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002993
2994 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002995 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2996
Martin v. Löwisffad6332002-11-26 09:28:05 +00002997 PyTclObject_Type.ob_type = &PyType_Type;
2998 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002999
3000#ifdef TK_AQUA
3001 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3002 * start waking up. Note that Tcl_FindExecutable will do this, this
3003 * code must be above it! The original warning from
3004 * tkMacOSXAppInit.c is copied below.
3005 *
3006 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3007 * Tcl interpreter for now. It probably should work to do this
3008 * in the other order, but for now it doesn't seem to.
3009 *
3010 */
3011 Tk_MacOSXSetupTkNotifier();
3012#endif
3013
3014
Guido van Rossume187b0e2000-03-27 21:46:29 +00003015 /* This helps the dynamic loader; in Unicode aware Tcl versions
3016 it also helps Tcl find its encodings. */
3017 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003018
Barry Warsawfa701a81997-01-16 00:15:11 +00003019 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003020 return;
3021
Guido van Rossum43ff8681998-07-14 18:02:13 +00003022#if 0
3023 /* This was not a good idea; through <Destroy> bindings,
3024 Tcl_Finalize() may invoke Python code but at that point the
3025 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003026 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003027#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003028
Jack Jansen34cc5c31995-10-31 16:15:12 +00003029#ifdef macintosh
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003030 /*
3031 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
3032 ** Most of the initializations in that routine (toolbox init calls and
3033 ** such) have already been done for us, so we only need these.
3034 */
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003035 tcl_macQdPtr = &qd;
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003036
3037 Tcl_MacSetEventProc(PyMacConvertEvent);
Guido van Rossumec22c921996-02-25 04:50:29 +00003038#if GENERATINGCFM
Barry Warsawfa701a81997-01-16 00:15:11 +00003039 mac_addlibresources();
Guido van Rossumec22c921996-02-25 04:50:29 +00003040#endif /* GENERATINGCFM */
3041#endif /* macintosh */
Guido van Rossum18468821994-06-20 07:49:28 +00003042}
Guido van Rossum9722ad81995-09-22 23:49:28 +00003043
Guido van Rossumec22c921996-02-25 04:50:29 +00003044
Barry Warsawfa701a81997-01-16 00:15:11 +00003045
Guido van Rossum9722ad81995-09-22 23:49:28 +00003046#ifdef macintosh
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003047
3048/*
Guido van Rossumec22c921996-02-25 04:50:29 +00003049** Anyone who embeds Tcl/Tk on the Mac must define panic().
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003050*/
3051
Guido van Rossum9722ad81995-09-22 23:49:28 +00003052void
3053panic(char * format, ...)
3054{
Barry Warsawfa701a81997-01-16 00:15:11 +00003055 va_list varg;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003056
Barry Warsawfa701a81997-01-16 00:15:11 +00003057 va_start(varg, format);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003058
Guido van Rossum227cf761998-08-05 13:53:32 +00003059 vfprintf(stderr, format, varg);
Barry Warsawfa701a81997-01-16 00:15:11 +00003060 (void) fflush(stderr);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003061
Barry Warsawfa701a81997-01-16 00:15:11 +00003062 va_end(varg);
Guido van Rossum9722ad81995-09-22 23:49:28 +00003063
Barry Warsawfa701a81997-01-16 00:15:11 +00003064 Py_FatalError("Tcl/Tk panic");
Guido van Rossum9722ad81995-09-22 23:49:28 +00003065}
Jack Jansen40b546d1995-11-14 10:34:45 +00003066
Guido van Rossumec22c921996-02-25 04:50:29 +00003067/*
3068** Pass events to SIOUX before passing them to Tk.
3069*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003070
Guido van Rossumec22c921996-02-25 04:50:29 +00003071static int
Fred Drake509d79a2000-07-08 04:04:38 +00003072PyMacConvertEvent(EventRecord *eventPtr)
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003073{
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003074 WindowPtr frontwin;
3075 /*
Guido van Rossum00d93061998-05-28 23:06:38 +00003076 ** Sioux eats too many events, so we don't pass it everything. We
3077 ** always pass update events to Sioux, and we only pass other events if
Guido van Rossum2ea1c941998-04-28 16:12:43 +00003078 ** the Sioux window is frontmost. This means that Tk menus don't work
3079 ** in that case, but at least we can scroll the sioux window.
3080 ** Note that the SIOUXIsAppWindow() routine we use here is not really
3081 ** part of the external interface of Sioux...
3082 */
3083 frontwin = FrontWindow();
3084 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
3085 if (SIOUXHandleOneEvent(eventPtr))
3086 return 0; /* Nothing happened to the Tcl event queue */
3087 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003088 return TkMacConvertEvent(eventPtr);
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003089}
3090
Guido van Rossumec22c921996-02-25 04:50:29 +00003091#if GENERATINGCFM
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003092
3093/*
3094** Additional Mac specific code for dealing with shared libraries.
3095*/
3096
3097#include <Resources.h>
3098#include <CodeFragments.h>
3099
3100static int loaded_from_shlib = 0;
3101static FSSpec library_fss;
Guido van Rossum9722ad81995-09-22 23:49:28 +00003102
Jack Jansen34cc5c31995-10-31 16:15:12 +00003103/*
3104** If this module is dynamically loaded the following routine should
3105** be the init routine. It takes care of adding the shared library to
3106** the resource-file chain, so that the tk routines can find their
3107** resources.
3108*/
3109OSErr pascal
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003110init_tkinter_shlib(CFragInitBlockPtr data)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003111{
Guido van Rossumc9970ee1996-08-26 14:37:15 +00003112 __initialize();
Jack Jansen34cc5c31995-10-31 16:15:12 +00003113 if ( data == nil ) return noErr;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003114 if ( data->fragLocator.where == kDataForkCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003115 library_fss = *data->fragLocator.u.onDisk.fileSpec;
3116 loaded_from_shlib = 1;
Guido van Rossum8ec9e631997-04-29 15:49:04 +00003117 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
Jack Jansen34cc5c31995-10-31 16:15:12 +00003118 library_fss = *data->fragLocator.u.inSegs.fileSpec;
3119 loaded_from_shlib = 1;
3120 }
3121 return noErr;
3122}
3123
3124/*
3125** Insert the library resources into the search path. Put them after
3126** the resources from the application. Again, we ignore errors.
3127*/
Guido van Rossumdfd428d1996-02-25 04:46:40 +00003128static
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003129mac_addlibresources(void)
Jack Jansen34cc5c31995-10-31 16:15:12 +00003130{
3131 if ( !loaded_from_shlib )
3132 return;
3133 (void)FSpOpenResFile(&library_fss, fsRdPerm);
3134}
3135
Guido van Rossumec22c921996-02-25 04:50:29 +00003136#endif /* GENERATINGCFM */
3137#endif /* macintosh */