blob: e6f89531da9a4c57cc3f77752b252d59d9eafc20 [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
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Jason Tishlerbbe89612002-12-31 20:30:46 +000070/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000071#ifndef CONST84_RETURN
72#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000073#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000074#define CONST
75#endif
76
Guido van Rossum3e819a71997-08-01 19:29:02 +000077#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000079#if TKMAJORMINOR < 8002
80#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
101/* Tcl_CreateFileHandler() changed several times; these macros deal with the
102 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
103 Unix, only because Jack added it back); when available on Windows, it only
104 applies to sockets. */
105
Guido van Rossum7bf15641998-05-22 18:28:17 +0000106#ifdef MS_WINDOWS
107#define FHANDLETYPE TCL_WIN_SOCKET
108#else
109#define FHANDLETYPE TCL_UNIX_FD
110#endif
111
Guido van Rossum00d93061998-05-28 23:06:38 +0000112/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
113 which uses this to handle Tcl events while the user is typing commands. */
114
115#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#define WAIT_FOR_STDIN
117#endif
118
Guido van Rossum00d93061998-05-28 23:06:38 +0000119#endif /* HAVE_CREATEFILEHANDLER */
120
Guido van Rossumad4db171998-06-13 13:56:28 +0000121#ifdef MS_WINDOWS
122#include <conio.h>
123#define WAIT_FOR_STDIN
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126#ifdef WITH_THREAD
127
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000128/* The threading situation is complicated. Tcl is not thread-safe, except
129 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000130 So we need to use a lock around all uses of Tcl. Previously, the Python
131 interpreter lock was used for this. However, this causes problems when
132 other Python threads need to run while Tcl is blocked waiting for events.
133
134 To solve this problem, a separate lock for Tcl is introduced. Holding it
135 is incompatible with holding Python's interpreter lock. The following four
136 macros manipulate both locks together.
137
138 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
139 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
140 that could call an event handler, or otherwise affect the state of a Tcl
141 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000142 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000143 released and the lock for Tcl has been acquired.
144
Guido van Rossum5e977831998-06-15 14:03:52 +0000145 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
146 (For example, when transferring data from the Tcl interpreter result to a
147 Python string object.) This can be done by using different macros to close
148 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
149 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
150 releases the Tcl lock.
151
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000152 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 handlers when the handler needs to use Python. Such event handlers are
154 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000155 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000156 the Python interpreter lock, restoring the appropriate thread state, and
157 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
158 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000159 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000160
161 These locks expand to several statements and brackets; they should not be
162 used in branches of if statements and the like.
163
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000164 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
165 only valid in the thread that created it, and all Tk activity must happen in this
166 thread, also. That means that the mainloop must be invoked in the thread that
167 created the interpreter. Invoking commands from other threads is possible;
168 _tkinter will queue an event for the interpreter thread, which will then
169 execute the command and pass back the result. If the main thread is not in the
170 mainloop, and invoking commands causes an exception; if the main loop is running
171 but not processing events, the command invocation will block.
172
173 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
174 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
175 threads. So we use the Tcl TLS API.
176
Guido van Rossum00d93061998-05-28 23:06:38 +0000177*/
178
Guido van Rossum65d5b571998-12-21 19:32:43 +0000179static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180
181#ifdef TCL_THREADS
182static Tcl_ThreadDataKey state_key;
183typedef PyThreadState *ThreadSpecificData;
184#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
185#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000186static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000187#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
189#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000190 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000191 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
193#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000195
Guido van Rossum62320c91998-06-15 04:36:09 +0000196#define ENTER_OVERLAP \
197 Py_END_ALLOW_THREADS
198
199#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000200 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000201
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000202#define ENTER_PYTHON \
203 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
206#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000207 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
209
210#define CHECK_TCL_APPARTMENT \
211 if (((TkappObject *)self)->threaded && \
212 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
213 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
214 return 0; \
215 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000216
217#else
218
219#define ENTER_TCL
220#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000221#define ENTER_OVERLAP
222#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000223#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000224#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000225#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#endif
228
Guido van Rossum97867b21996-08-08 19:09:53 +0000229#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000230#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000231#endif
232
Guido van Rossum18468821994-06-20 07:49:28 +0000233/**** Tkapp Object Declaration ****/
234
Jeremy Hylton938ace62002-07-17 16:30:39 +0000235static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000236
Guido van Rossum00d93061998-05-28 23:06:38 +0000237typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000238 PyObject_HEAD
239 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000240 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000241 int threaded; /* True if tcl_platform[threaded] */
242 Tcl_ThreadId thread_id;
243 int dispatching;
244 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000245 So we cache interesting types here. */
246 Tcl_ObjType *BooleanType;
247 Tcl_ObjType *ByteArrayType;
248 Tcl_ObjType *DoubleType;
249 Tcl_ObjType *IntType;
250 Tcl_ObjType *ListType;
251 Tcl_ObjType *ProcBodyType;
252 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000253} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000254
255#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000256#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000257#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000258
Guido van Rossum35d43371997-08-02 00:09:09 +0000259#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000260(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000261
Barry Warsawfa701a81997-01-16 00:15:11 +0000262
263
Guido van Rossum18468821994-06-20 07:49:28 +0000264/**** Error Handling ****/
265
266static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000267static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000268static int errorInCmd = 0;
269static PyObject *excInCmd;
270static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000271static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000272
Barry Warsawfa701a81997-01-16 00:15:11 +0000273
274
Guido van Rossum18468821994-06-20 07:49:28 +0000275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000276Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000277{
Barry Warsawfa701a81997-01-16 00:15:11 +0000278 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
279 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000280}
281
Barry Warsawfa701a81997-01-16 00:15:11 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Guido van Rossum18468821994-06-20 07:49:28 +0000284/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000285
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000286static int Tkinter_busywaitinterval = 20;
287
Guido van Rossum00d93061998-05-28 23:06:38 +0000288#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000289#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000290
Guido van Rossum00d93061998-05-28 23:06:38 +0000291/* Millisecond sleep() for Unix platforms. */
292
293static void
Fred Drake509d79a2000-07-08 04:04:38 +0000294Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000295{
296 /* XXX Too bad if you don't have select(). */
297 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000298 t.tv_sec = milli/1000;
299 t.tv_usec = (milli%1000) * 1000;
300 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
301}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000302#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000303
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000304/* Wait up to 1s for the mainloop to come up. */
305
306static int
307WaitForMainloop(TkappObject* self)
308{
309 int i;
310 for (i = 0; i < 10; i++) {
311 if (self->dispatching)
312 return 1;
313 Py_BEGIN_ALLOW_THREADS
314 Sleep(100);
315 Py_END_ALLOW_THREADS
316 }
317 if (self->dispatching)
318 return 1;
319 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
320 return 0;
321}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000322#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000323
Guido van Rossum00d93061998-05-28 23:06:38 +0000324
Guido van Rossum18468821994-06-20 07:49:28 +0000325static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000326AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000327{
Guido van Rossum35d43371997-08-02 00:09:09 +0000328 if (PyString_Check(value))
329 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000330#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000331 else if (PyUnicode_Check(value)) {
332 PyObject *v = PyUnicode_AsUTF8String(value);
333 if (v == NULL)
334 return NULL;
335 if (PyList_Append(tmp, v) != 0) {
336 Py_DECREF(v);
337 return NULL;
338 }
339 Py_DECREF(v);
340 return PyString_AsString(v);
341 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000342#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000343 else {
344 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000345 if (v == NULL)
346 return NULL;
347 if (PyList_Append(tmp, v) != 0) {
348 Py_DECREF(v);
349 return NULL;
350 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 Py_DECREF(v);
352 return PyString_AsString(v);
353 }
Guido van Rossum18468821994-06-20 07:49:28 +0000354}
355
Barry Warsawfa701a81997-01-16 00:15:11 +0000356
357
Guido van Rossum18468821994-06-20 07:49:28 +0000358#define ARGSZ 64
359
360static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000361Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000362{
Barry Warsawfa701a81997-01-16 00:15:11 +0000363 PyObject *tmp = NULL;
364 char *argvStore[ARGSZ];
365 char **argv = NULL;
366 int fvStore[ARGSZ];
367 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000368 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000369 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000370
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 if (!(tmp = PyList_New(0)))
372 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000373
Barry Warsawfa701a81997-01-16 00:15:11 +0000374 argv = argvStore;
375 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000376
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 if (args == NULL)
378 argc = 0;
379
380 else if (!PyTuple_Check(args)) {
381 argc = 1;
382 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000383 if (!(argv[0] = AsString(args, tmp)))
384 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000385 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 else {
387 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000390 argv = (char **)ckalloc(argc * sizeof(char *));
391 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000392 if (argv == NULL || fv == NULL) {
393 PyErr_NoMemory();
394 goto finally;
395 }
396 }
397
398 for (i = 0; i < argc; i++) {
399 PyObject *v = PyTuple_GetItem(args, i);
400 if (PyTuple_Check(v)) {
401 fv[i] = 1;
402 if (!(argv[i] = Merge(v)))
403 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000404 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000405 }
406 else if (v == Py_None) {
407 argc = i;
408 break;
409 }
410 else {
411 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 if (!(argv[i] = AsString(v, tmp)))
413 goto finally;
414 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000415 }
416 }
Guido van Rossum18468821994-06-20 07:49:28 +0000417 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000418 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000419 if (res == NULL)
420 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000421
Barry Warsawfa701a81997-01-16 00:15:11 +0000422 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000423 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 if (fv[i]) {
425 ckfree(argv[i]);
426 }
427 if (argv != argvStore)
428 ckfree(FREECAST argv);
429 if (fv != fvStore)
430 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000431
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 Py_DECREF(tmp);
433 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000434}
435
Barry Warsawfa701a81997-01-16 00:15:11 +0000436
437
Guido van Rossum18468821994-06-20 07:49:28 +0000438static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000439Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000440{
Barry Warsawfa701a81997-01-16 00:15:11 +0000441 int argc;
442 char **argv;
443 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000444
Barry Warsawfa701a81997-01-16 00:15:11 +0000445 if (list == NULL) {
446 Py_INCREF(Py_None);
447 return Py_None;
448 }
Guido van Rossum18468821994-06-20 07:49:28 +0000449
Guido van Rossum00d93061998-05-28 23:06:38 +0000450 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 /* Not a list.
452 * Could be a quoted string containing funnies, e.g. {"}.
453 * Return the string itself.
454 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 return PyString_FromString(list);
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Barry Warsawfa701a81997-01-16 00:15:11 +0000458 if (argc == 0)
459 v = PyString_FromString("");
460 else if (argc == 1)
461 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000462 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000463 int i;
464 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000467 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000468 Py_DECREF(v);
469 v = NULL;
470 break;
471 }
472 PyTuple_SetItem(v, i, w);
473 }
474 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000477}
478
Martin v. Löwisffad6332002-11-26 09:28:05 +0000479/* In some cases, Tcl will still return strings that are supposed to be
480 lists. SplitObj walks through a nested tuple, finding string objects that
481 need to be split. */
482
483PyObject *
484SplitObj(PyObject *arg)
485{
486 if (PyTuple_Check(arg)) {
487 int i, size;
488 PyObject *elem, *newelem, *result;
489
490 size = PyTuple_Size(arg);
491 result = NULL;
492 /* Recursively invoke SplitObj for all tuple items.
493 If this does not return a new object, no action is
494 needed. */
495 for(i = 0; i < size; i++) {
496 elem = PyTuple_GetItem(arg, i);
497 newelem = SplitObj(elem);
498 if (!newelem) {
499 Py_XDECREF(result);
500 return NULL;
501 }
502 if (!result) {
503 int k;
504 if (newelem == elem) {
505 Py_DECREF(newelem);
506 continue;
507 }
508 result = PyTuple_New(size);
509 if (!result)
510 return NULL;
511 for(k = 0; k < i; k++) {
512 elem = PyTuple_GetItem(arg, k);
513 Py_INCREF(elem);
514 PyTuple_SetItem(result, k, elem);
515 }
516 }
517 PyTuple_SetItem(result, i, newelem);
518 }
519 if (result)
520 return result;
521 /* Fall through, returning arg. */
522 }
523 else if (PyString_Check(arg)) {
524 int argc;
525 char **argv;
526 char *list = PyString_AsString(arg);
527
528 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
529 Py_INCREF(arg);
530 return arg;
531 }
532 Tcl_Free(FREECAST argv);
533 if (argc > 1)
534 return Split(PyString_AsString(arg));
535 /* Fall through, returning arg. */
536 }
537 Py_INCREF(arg);
538 return arg;
539}
Barry Warsawfa701a81997-01-16 00:15:11 +0000540
541
Guido van Rossum18468821994-06-20 07:49:28 +0000542/**** Tkapp Object ****/
543
544#ifndef WITH_APPINIT
545int
Fred Drake509d79a2000-07-08 04:04:38 +0000546Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000547{
Barry Warsawfa701a81997-01-16 00:15:11 +0000548 Tk_Window main;
Guido van Rossumec22c921996-02-25 04:50:29 +0000549
Barry Warsawfa701a81997-01-16 00:15:11 +0000550 main = Tk_MainWindow(interp);
551 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000552 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000553 return TCL_ERROR;
554 }
555 if (Tk_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000556 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000557 return TCL_ERROR;
558 }
559 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000560}
561#endif /* !WITH_APPINIT */
562
Guido van Rossum18468821994-06-20 07:49:28 +0000563
Barry Warsawfa701a81997-01-16 00:15:11 +0000564
565
566/* Initialize the Tk application; see the `main' function in
567 * `tkMain.c'.
568 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000569
Thomas Wouters58d05102000-07-24 14:43:35 +0000570static void EnableEventHook(void); /* Forward */
571static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000572
Barry Warsawfa701a81997-01-16 00:15:11 +0000573static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000574Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000575 int interactive, int wantobjects)
Barry Warsawfa701a81997-01-16 00:15:11 +0000576{
577 TkappObject *v;
578 char *argv0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000579
Guido van Rossumb18618d2000-05-03 23:44:39 +0000580 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000581 if (v == NULL)
582 return NULL;
583
584 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000585 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000586 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
587 TCL_GLOBAL_ONLY) != NULL;
588 v->thread_id = Tcl_GetCurrentThread();
589 v->dispatching = 0;
590
591#ifndef TCL_THREADS
592 if (v->threaded) {
593 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
594 Py_DECREF(v);
595 return 0;
596 }
597#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000598#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000599 if (v->threaded && tcl_lock) {
600 /* If Tcl is threaded, we don't need the lock. */
601 PyThread_free_lock(tcl_lock);
602 tcl_lock = NULL;
603 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000604#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000605
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000606 v->BooleanType = Tcl_GetObjType("boolean");
607 v->ByteArrayType = Tcl_GetObjType("bytearray");
608 v->DoubleType = Tcl_GetObjType("double");
609 v->IntType = Tcl_GetObjType("int");
610 v->ListType = Tcl_GetObjType("list");
611 v->ProcBodyType = Tcl_GetObjType("procbody");
612 v->StringType = Tcl_GetObjType("string");
613
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000614 /* Delete the 'exit' command, which can screw things up */
615 Tcl_DeleteCommand(v->interp, "exit");
616
Barry Warsawfa701a81997-01-16 00:15:11 +0000617 if (screenName != NULL)
618 Tcl_SetVar2(v->interp, "env", "DISPLAY",
619 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000620
Barry Warsawfa701a81997-01-16 00:15:11 +0000621 if (interactive)
622 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
623 else
624 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000625
Barry Warsawfa701a81997-01-16 00:15:11 +0000626 /* This is used to get the application class for Tk 4.1 and up */
627 argv0 = (char*)ckalloc(strlen(className) + 1);
628 if (!argv0) {
629 PyErr_NoMemory();
630 Py_DECREF(v);
631 return NULL;
632 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000633
Barry Warsawfa701a81997-01-16 00:15:11 +0000634 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000635 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000636 argv0[0] = tolower(argv0[0]);
637 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
638 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000639
Barry Warsawfa701a81997-01-16 00:15:11 +0000640 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000641 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000642
Guido van Rossum7bf15641998-05-22 18:28:17 +0000643 EnableEventHook();
644
Barry Warsawfa701a81997-01-16 00:15:11 +0000645 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000646}
647
Barry Warsawfa701a81997-01-16 00:15:11 +0000648
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000649static void
650Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
651 Tcl_Condition *cond, Tcl_Mutex *mutex)
652{
653 Py_BEGIN_ALLOW_THREADS;
654 Tcl_MutexLock(mutex);
655 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
656 Tcl_ThreadAlert(self->thread_id);
657 Tcl_ConditionWait(cond, mutex, NULL);
658 Tcl_MutexUnlock(mutex);
659 Py_END_ALLOW_THREADS
660}
661
Barry Warsawfa701a81997-01-16 00:15:11 +0000662
Guido van Rossum18468821994-06-20 07:49:28 +0000663/** Tcl Eval **/
664
Martin v. Löwisffad6332002-11-26 09:28:05 +0000665typedef struct {
666 PyObject_HEAD
667 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000668 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000669} PyTclObject;
670
671staticforward PyTypeObject PyTclObject_Type;
672#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
673
674static PyObject *
675newPyTclObject(Tcl_Obj *arg)
676{
677 PyTclObject *self;
678 self = PyObject_New(PyTclObject, &PyTclObject_Type);
679 if (self == NULL)
680 return NULL;
681 Tcl_IncrRefCount(arg);
682 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000683 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000684 return (PyObject*)self;
685}
686
687static void
688PyTclObject_dealloc(PyTclObject *self)
689{
690 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000691 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000692 PyObject_Del(self);
693}
694
695static PyObject *
696PyTclObject_str(PyTclObject *self)
697{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000698 if (self->string && PyString_Check(self->string)) {
699 Py_INCREF(self->string);
700 return self->string;
701 }
702 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000703 return PyString_FromString(Tcl_GetString(self->value));
704}
705
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000706static char*
707PyTclObject_TclString(PyObject *self)
708{
709 return Tcl_GetString(((PyTclObject*)self)->value);
710}
711
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000712/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000713PyDoc_STRVAR(PyTclObject_string__doc__,
714"the string representation of this object, either as string or Unicode");
715
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000716static PyObject *
717PyTclObject_string(PyTclObject *self, void *ignored)
718{
719 char *s;
720 int i, len;
721 if (!self->string) {
722 s = Tcl_GetStringFromObj(self->value, &len);
723 for (i = 0; i < len; i++)
724 if (s[i] & 0x80)
725 break;
726#ifdef Py_USING_UNICODE
727 if (i == len)
728 /* It is an ASCII string. */
729 self->string = PyString_FromStringAndSize(s, len);
730 else {
731 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
732 if (!self->string) {
733 PyErr_Clear();
734 self->string = PyString_FromStringAndSize(s, len);
735 }
736 }
737#else
738 self->string = PyString_FromStringAndSize(s, len);
739#endif
740 if (!self->string)
741 return NULL;
742 }
743 Py_INCREF(self->string);
744 return self->string;
745}
746
747#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000748PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
749
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000750static PyObject *
751PyTclObject_unicode(PyTclObject *self, void *ignored)
752{
753 char *s;
754 int len;
755 if (self->string && PyUnicode_Check(self->string)) {
756 Py_INCREF(self->string);
757 return self->string;
758 }
759 /* XXX Could chache result if it is non-ASCII. */
760 s = Tcl_GetStringFromObj(self->value, &len);
761 return PyUnicode_DecodeUTF8(s, len, "strict");
762}
763#endif
764
Martin v. Löwisffad6332002-11-26 09:28:05 +0000765static PyObject *
766PyTclObject_repr(PyTclObject *self)
767{
768 char buf[50];
769 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
770 self->value->typePtr->name, (int)self->value);
771 return PyString_FromString(buf);
772}
773
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000774static int
775PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
776{
777 int res;
778 res = strcmp(Tcl_GetString(self->value),
779 Tcl_GetString(other->value));
780 if (res < 0) return -1;
781 if (res > 0) return 1;
782 return 0;
783}
784
Martin v. Löwis39195712003-01-04 00:33:13 +0000785PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
786
Martin v. Löwisffad6332002-11-26 09:28:05 +0000787static PyObject*
788get_typename(PyTclObject* obj, void* ignored)
789{
790 return PyString_FromString(obj->value->typePtr->name);
791}
792
Martin v. Löwis39195712003-01-04 00:33:13 +0000793
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000795 {"typename", (getter)get_typename, NULL, get_typename__doc__},
796 {"string", (getter)PyTclObject_string, NULL,
797 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000798 {0},
799};
800
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000801static PyMethodDef PyTclObject_methods[] = {
802 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000803 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000804 {0}
805};
806
Martin v. Löwisffad6332002-11-26 09:28:05 +0000807statichere PyTypeObject PyTclObject_Type = {
808 PyObject_HEAD_INIT(NULL)
809 0, /*ob_size*/
810 "_tkinter.Tcl_Obj", /*tp_name*/
811 sizeof(PyTclObject), /*tp_basicsize*/
812 0, /*tp_itemsize*/
813 /* methods */
814 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
815 0, /*tp_print*/
816 0, /*tp_getattr*/
817 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000818 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000819 (reprfunc)PyTclObject_repr, /*tp_repr*/
820 0, /*tp_as_number*/
821 0, /*tp_as_sequence*/
822 0, /*tp_as_mapping*/
823 0, /*tp_hash*/
824 0, /*tp_call*/
825 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000826 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000827 0, /*tp_setattro*/
828 0, /*tp_as_buffer*/
829 Py_TPFLAGS_DEFAULT, /*tp_flags*/
830 0, /*tp_doc*/
831 0, /*tp_traverse*/
832 0, /*tp_clear*/
833 0, /*tp_richcompare*/
834 0, /*tp_weaklistoffset*/
835 0, /*tp_iter*/
836 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000837 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000838 0, /*tp_members*/
839 PyTclObject_getsetlist, /*tp_getset*/
840 0, /*tp_base*/
841 0, /*tp_dict*/
842 0, /*tp_descr_get*/
843 0, /*tp_descr_set*/
844 0, /*tp_dictoffset*/
845 0, /*tp_init*/
846 0, /*tp_alloc*/
847 0, /*tp_new*/
848 0, /*tp_free*/
849 0, /*tp_is_gc*/
850};
851
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000852static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000853AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000854{
855 Tcl_Obj *result;
856
857 if (PyString_Check(value))
858 return Tcl_NewStringObj(PyString_AS_STRING(value),
859 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000860 else if (PyBool_Check(value))
861 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000862 else if (PyInt_Check(value))
863 return Tcl_NewLongObj(PyInt_AS_LONG(value));
864 else if (PyFloat_Check(value))
865 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
866 else if (PyTuple_Check(value)) {
867 Tcl_Obj **argv = (Tcl_Obj**)
868 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
869 int i;
870 if(!argv)
871 return 0;
872 for(i=0;i<PyTuple_Size(value);i++)
873 argv[i] = AsObj(PyTuple_GetItem(value,i));
874 result = Tcl_NewListObj(PyTuple_Size(value), argv);
875 ckfree(FREECAST argv);
876 return result;
877 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000878#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000879 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000880 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
881 int size = PyUnicode_GET_SIZE(value);
882 /* This #ifdef assumes that Tcl uses UCS-2.
883 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000884#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000885 Tcl_UniChar *outbuf;
886 int i;
887 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
888 if (!outbuf) {
889 PyErr_NoMemory();
890 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000891 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000892 for (i = 0; i < size; i++) {
893 if (inbuf[i] >= 0x10000) {
894 /* Tcl doesn't do UTF-16, yet. */
895 PyErr_SetString(PyExc_ValueError,
896 "unsupported character");
897 ckfree(FREECAST outbuf);
898 return NULL;
899 }
900 outbuf[i] = inbuf[i];
901 }
902 result = Tcl_NewUnicodeObj(outbuf, size);
903 ckfree(FREECAST outbuf);
904 return result;
905#else
906 return Tcl_NewUnicodeObj(inbuf, size);
907#endif
908
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000909 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000910#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000911 else if(PyTclObject_Check(value)) {
912 Tcl_Obj *v = ((PyTclObject*)value)->value;
913 Tcl_IncrRefCount(v);
914 return v;
915 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000916 else {
917 PyObject *v = PyObject_Str(value);
918 if (!v)
919 return 0;
920 result = AsObj(v);
921 Py_DECREF(v);
922 return result;
923 }
924}
925
Martin v. Löwisffad6332002-11-26 09:28:05 +0000926static PyObject*
927FromObj(PyObject* tkapp, Tcl_Obj *value)
928{
929 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000930 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000932 if (value->typePtr == NULL) {
933 /* If the result contains any bytes with the top bit set,
934 it's UTF-8 and we should decode it to Unicode */
935#ifdef Py_USING_UNICODE
936 int i;
937 char *s = value->bytes;
938 int len = value->length;
939 for (i = 0; i < len; i++) {
940 if (value->bytes[i] & 0x80)
941 break;
942 }
943
944 if (i == value->length)
945 result = PyString_FromStringAndSize(s, len);
946 else {
947 /* Convert UTF-8 to Unicode string */
948 result = PyUnicode_DecodeUTF8(s, len, "strict");
949 if (result == NULL) {
950 PyErr_Clear();
951 result = PyString_FromStringAndSize(s, len);
952 }
953 }
954#else
955 res = PyString_FromStringAndSize(value->bytes, value->length);
956#endif
957 return result;
958 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000959
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000960 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000961 result = value->internalRep.longValue ? Py_True : Py_False;
962 Py_INCREF(result);
963 return result;
964 }
965
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000966 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000967 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000968 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000969 return PyString_FromStringAndSize(data, size);
970 }
971
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000972 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000973 return PyFloat_FromDouble(value->internalRep.doubleValue);
974 }
975
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000976 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977 return PyInt_FromLong(value->internalRep.longValue);
978 }
979
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000980 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981 int size;
982 int i, status;
983 PyObject *elem;
984 Tcl_Obj *tcl_elem;
985
986 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
987 if (status == TCL_ERROR)
988 return Tkinter_Error(tkapp);
989 result = PyTuple_New(size);
990 if (!result)
991 return NULL;
992 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000993 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +0000994 value, i, &tcl_elem);
995 if (status == TCL_ERROR) {
996 Py_DECREF(result);
997 return Tkinter_Error(tkapp);
998 }
999 elem = FromObj(tkapp, tcl_elem);
1000 if (!elem) {
1001 Py_DECREF(result);
1002 return NULL;
1003 }
1004 PyTuple_SetItem(result, i, elem);
1005 }
1006 return result;
1007 }
1008
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001009 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001010 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001011 }
1012
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001013 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001015#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016 PyObject *result;
1017 int size;
1018 Tcl_UniChar *input;
1019 Py_UNICODE *output;
1020
1021 size = Tcl_GetCharLength(value);
1022 result = PyUnicode_FromUnicode(NULL, size);
1023 if (!result)
1024 return NULL;
1025 input = Tcl_GetUnicode(value);
1026 output = PyUnicode_AS_UNICODE(result);
1027 while (size--)
1028 *output++ = *input++;
1029 return result;
1030#else
1031 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1032 Tcl_GetCharLength(value));
1033#endif
1034#else
1035 int size;
1036 char *c;
1037 c = Tcl_GetStringFromObj(value, &size);
1038 return PyString_FromStringAndSize(c, size);
1039#endif
1040 }
1041
1042 return newPyTclObject(value);
1043}
1044
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001045/* This mutex synchronizes inter-thread command calls. */
1046
1047TCL_DECLARE_MUTEX(call_mutex)
1048
1049typedef struct Tkapp_CallEvent {
1050 Tcl_Event ev; /* Must be first */
1051 TkappObject *self;
1052 PyObject *args;
1053 int flags;
1054 PyObject **res;
1055 PyObject **exc_type, **exc_value, **exc_tb;
1056 Tcl_Condition done;
1057} Tkapp_CallEvent;
1058
1059void
1060Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001061{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001062 int i;
1063 for (i = 0; i < objc; i++)
1064 Tcl_DecrRefCount(objv[i]);
1065 if (objv != objStore)
1066 ckfree(FREECAST objv);
1067}
Guido van Rossum18468821994-06-20 07:49:28 +00001068
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001069/* Convert Python objects to Tcl objects. This must happen in the
1070 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001071
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072static Tcl_Obj**
1073Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1074{
1075 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001076 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001077 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001078 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001079
Guido van Rossum212643f1998-04-29 16:22:14 +00001080 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001081 objv[0] = AsObj(args);
1082 if (objv[0] == 0)
1083 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001084 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001085 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001086 }
1087 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001088 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001089
Guido van Rossum632de272000-03-29 00:19:50 +00001090 if (objc > ARGSZ) {
1091 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1092 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001093 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001094 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001095 goto finally;
1096 }
1097 }
1098
Guido van Rossum632de272000-03-29 00:19:50 +00001099 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001100 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001101 if (v == Py_None) {
1102 objc = i;
1103 break;
1104 }
Guido van Rossum632de272000-03-29 00:19:50 +00001105 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001106 if (!objv[i]) {
1107 /* Reset objc, so it attempts to clear
1108 objects only up to i. */
1109 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001110 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001111 }
Guido van Rossum632de272000-03-29 00:19:50 +00001112 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001113 }
1114 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001115 *pobjc = objc;
1116 return objv;
1117finally:
1118 Tkapp_CallDeallocArgs(objv, objStore, objc);
1119 return NULL;
1120}
Guido van Rossum212643f1998-04-29 16:22:14 +00001121
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001122/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001123
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124static PyObject*
1125Tkapp_CallResult(TkappObject *self)
1126{
1127 PyObject *res = NULL;
1128 if(self->wantobjects) {
1129 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001130 /* Not sure whether the IncrRef is necessary, but something
1131 may overwrite the interpreter result while we are
1132 converting it. */
1133 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001134 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001135 Tcl_DecrRefCount(value);
1136 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001137 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001138 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001139
Guido van Rossum990f5c62000-05-04 15:07:16 +00001140 /* If the result contains any bytes with the top bit set,
1141 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001142#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001143 while (*p != '\0') {
1144 if (*p & 0x80)
1145 break;
1146 p++;
1147 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001148
Guido van Rossum990f5c62000-05-04 15:07:16 +00001149 if (*p == '\0')
1150 res = PyString_FromStringAndSize(s, (int)(p-s));
1151 else {
1152 /* Convert UTF-8 to Unicode string */
1153 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001154 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1155 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156 PyErr_Clear();
1157 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001158 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001159 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001160#else
1161 p = strchr(p, '\0');
1162 res = PyString_FromStringAndSize(s, (int)(p-s));
1163#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001164 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165 return res;
1166}
Guido van Rossum632de272000-03-29 00:19:50 +00001167
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001168/* Tkapp_CallProc is the event procedure that is executed in the context of
1169 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1170 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001171
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001172static int
1173Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1174{
1175 Tcl_Obj *objStore[ARGSZ];
1176 Tcl_Obj **objv;
1177 int objc;
1178 int i;
1179 ENTER_PYTHON
1180 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1181 if (!objv) {
1182 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1183 *(e->res) = NULL;
1184 }
1185 LEAVE_PYTHON
1186 if (!objv)
1187 goto done;
1188 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1189 ENTER_PYTHON
1190 if (i == TCL_ERROR) {
1191 *(e->res) = NULL;
1192 *(e->exc_type) = NULL;
1193 *(e->exc_tb) = NULL;
1194 *(e->exc_value) = PyObject_CallFunction(
1195 Tkinter_TclError, "s",
1196 Tcl_GetStringResult(e->self->interp));
1197 }
1198 else {
1199 *(e->res) = Tkapp_CallResult(e->self);
1200 }
1201 LEAVE_PYTHON
1202 done:
1203 /* Wake up calling thread. */
1204 Tcl_MutexLock(&call_mutex);
1205 Tcl_ConditionNotify(&e->done);
1206 Tcl_MutexUnlock(&call_mutex);
1207 return 1;
1208}
1209
1210/* This is the main entry point for calling a Tcl command.
1211 It supports three cases, with regard to threading:
1212 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1213 the context of the calling thread.
1214 2. Tcl is threaded, caller of the command is in the interpreter thread:
1215 Execute the command in the calling thread. Since the Tcl lock will
1216 not be used, we can merge that with case 1.
1217 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1218 the interpreter thread. Allocation of Tcl objects needs to occur in the
1219 interpreter thread, so we ship the PyObject* args to the target thread,
1220 and perform processing there. */
1221
1222static PyObject *
1223Tkapp_Call(PyObject *_self, PyObject *args)
1224{
1225 Tcl_Obj *objStore[ARGSZ];
1226 Tcl_Obj **objv = NULL;
1227 int objc, i;
1228 PyObject *res = NULL;
1229 TkappObject *self = (TkappObject*)_self;
1230 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1231 int flags = TCL_EVAL_DIRECT;
1232
Martin v. Löwisa9656492003-03-30 08:44:58 +00001233#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001234 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1235 /* We cannot call the command directly. Instead, we must
1236 marshal the parameters to the interpreter thread. */
1237 Tkapp_CallEvent *ev;
1238 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001239 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001240 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001241 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1242 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1243 ev->self = self;
1244 ev->args = args;
1245 ev->res = &res;
1246 ev->exc_type = &exc_type;
1247 ev->exc_value = &exc_value;
1248 ev->exc_tb = &exc_tb;
1249 ev->done = (Tcl_Condition)0;
1250
1251 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1252
1253 if (res == NULL) {
1254 if (exc_type)
1255 PyErr_Restore(exc_type, exc_value, exc_tb);
1256 else
1257 PyErr_SetObject(Tkinter_TclError, exc_value);
1258 }
1259 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001260 else
1261#endif
1262 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001263
1264 objv = Tkapp_CallArgs(args, objStore, &objc);
1265 if (!objv)
1266 return NULL;
1267
1268 ENTER_TCL
1269
1270 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1271
1272 ENTER_OVERLAP
1273
1274 if (i == TCL_ERROR)
1275 Tkinter_Error(_self);
1276 else
1277 res = Tkapp_CallResult(self);
1278
1279 LEAVE_OVERLAP_TCL
1280
1281 Tkapp_CallDeallocArgs(objv, objStore, objc);
1282 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001283 return res;
1284}
1285
1286
1287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001288Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001289{
Guido van Rossum212643f1998-04-29 16:22:14 +00001290 /* Could do the same here as for Tkapp_Call(), but this is not used
1291 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1292 way for the user to do what all its Global* variants do (save and
1293 reset the scope pointer, call the local version, restore the saved
1294 scope pointer). */
1295
Guido van Rossum62320c91998-06-15 04:36:09 +00001296 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001297 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001298
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299 CHECK_TCL_APPARTMENT;
1300
Guido van Rossum62320c91998-06-15 04:36:09 +00001301 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001302 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001303 int err;
1304 ENTER_TCL
1305 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001306 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001307 if (err == TCL_ERROR)
1308 res = Tkinter_Error(self);
1309 else
1310 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001311 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001312 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001313 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001314
1315 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001316}
1317
1318static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001319Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001320{
Barry Warsawfa701a81997-01-16 00:15:11 +00001321 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001322 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001323 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324
Guido van Rossum43713e52000-02-29 13:59:29 +00001325 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001326 return NULL;
1327
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328 CHECK_TCL_APPARTMENT;
1329
Guido van Rossum00d93061998-05-28 23:06:38 +00001330 ENTER_TCL
1331 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001332 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001333 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001334 res = Tkinter_Error(self);
1335 else
1336 res = PyString_FromString(Tkapp_Result(self));
1337 LEAVE_OVERLAP_TCL
1338 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001339}
1340
1341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001342Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001343{
Barry Warsawfa701a81997-01-16 00:15:11 +00001344 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001345 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001346 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001347
Guido van Rossum43713e52000-02-29 13:59:29 +00001348 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001349 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001350
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001351 CHECK_TCL_APPARTMENT;
1352
Guido van Rossum00d93061998-05-28 23:06:38 +00001353 ENTER_TCL
1354 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001355 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001356 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001357 res = Tkinter_Error(self);
1358 else
1359 res = PyString_FromString(Tkapp_Result(self));
1360 LEAVE_OVERLAP_TCL
1361 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001362}
1363
1364static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001365Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001366{
Barry Warsawfa701a81997-01-16 00:15:11 +00001367 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001368 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001369 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001370
Guido van Rossum43713e52000-02-29 13:59:29 +00001371 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001372 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001373
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001374 CHECK_TCL_APPARTMENT;
1375
Guido van Rossum00d93061998-05-28 23:06:38 +00001376 ENTER_TCL
1377 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001378 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001379 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001380 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001381
Guido van Rossum62320c91998-06-15 04:36:09 +00001382 else
1383 res = PyString_FromString(Tkapp_Result(self));
1384 LEAVE_OVERLAP_TCL
1385 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001386}
1387
1388static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001389Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001390{
Barry Warsawfa701a81997-01-16 00:15:11 +00001391 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001392 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001393 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001394
Guido van Rossum35d43371997-08-02 00:09:09 +00001395 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001396 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001397
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001398 CHECK_TCL_APPARTMENT;
1399
Guido van Rossum00d93061998-05-28 23:06:38 +00001400 ENTER_TCL
1401 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001402 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001403 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001404 res = Tkinter_Error(self);
1405 else
1406 res = PyString_FromString(Tkapp_Result(self));
1407 LEAVE_OVERLAP_TCL
1408 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001409}
1410
1411static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001412Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001413{
Barry Warsawfa701a81997-01-16 00:15:11 +00001414 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001415
Guido van Rossum43713e52000-02-29 13:59:29 +00001416 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001417 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001418 CHECK_TCL_APPARTMENT;
1419
Guido van Rossum00d93061998-05-28 23:06:38 +00001420 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001421 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001422 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001423
Barry Warsawfa701a81997-01-16 00:15:11 +00001424 Py_INCREF(Py_None);
1425 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001426}
1427
Barry Warsawfa701a81997-01-16 00:15:11 +00001428
1429
Guido van Rossum18468821994-06-20 07:49:28 +00001430/** Tcl Variable **/
1431
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001432TCL_DECLARE_MUTEX(var_mutex)
1433
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001434typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001435typedef struct VarEvent {
1436 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001437 PyObject *self;
1438 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001440 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001441 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001442 PyObject **exc_type;
1443 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001445} VarEvent;
1446
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001447static int
1448varname_converter(PyObject *in, void *_out)
1449{
1450 char **out = (char**)_out;
1451 if (PyString_Check(in)) {
1452 *out = PyString_AsString(in);
1453 return 1;
1454 }
1455 if (PyTclObject_Check(in)) {
1456 *out = PyTclObject_TclString(in);
1457 return 1;
1458 }
1459 /* XXX: Should give diagnostics. */
1460 return 0;
1461}
1462
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001463void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001464var_perform(VarEvent *ev)
1465{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001466 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1467 if (!*(ev->res)) {
1468 PyObject *exc, *val, *tb;
1469 PyErr_Fetch(&exc, &val, &tb);
1470 PyErr_NormalizeException(&exc, &val, &tb);
1471 *(ev->exc_type) = exc;
1472 *(ev->exc_val) = val;
1473 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001474 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001475
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476}
1477
1478static int
1479var_proc(VarEvent* ev, int flags)
1480{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001481 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001482 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483 Tcl_MutexLock(&var_mutex);
1484 Tcl_ConditionNotify(&ev->cond);
1485 Tcl_MutexUnlock(&var_mutex);
1486 LEAVE_PYTHON
1487 return 1;
1488}
1489
1490static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001491var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001494#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001496 TkappObject *self = (TkappObject*)_self;
1497 VarEvent *ev;
1498 PyObject *res, *exc_type, *exc_val;
1499
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500 /* The current thread is not the interpreter thread. Marshal
1501 the call to the interpreter thread, then wait for
1502 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001503 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001505
1506 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1507
1508 ev->self = _self;
1509 ev->args = args;
1510 ev->flags = flags;
1511 ev->func = func;
1512 ev->res = &res;
1513 ev->exc_type = &exc_type;
1514 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515 ev->cond = NULL;
1516 ev->ev.proc = (Tcl_EventProc*)var_proc;
1517 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001518 if (!res) {
1519 PyErr_SetObject(exc_type, exc_val);
1520 Py_DECREF(exc_type);
1521 Py_DECREF(exc_val);
1522 return NULL;
1523 }
1524 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001525 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001526#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001527 /* Tcl is not threaded, or this is the interpreter thread. */
1528 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001529}
1530
Guido van Rossum18468821994-06-20 07:49:28 +00001531static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001532SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001533{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001534 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001535 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001536 PyObject *res = NULL;
1537 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001538
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001539 if (PyArg_ParseTuple(args, "O&O:setvar",
1540 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001541 /* XXX Acquire tcl lock??? */
1542 newval = AsObj(newValue);
1543 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001544 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001545 ENTER_TCL
1546 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1547 newval, flags);
1548 ENTER_OVERLAP
1549 if (!ok)
1550 Tkinter_Error(self);
1551 else {
1552 res = Py_None;
1553 Py_INCREF(res);
1554 }
1555 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001556 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001557 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001558 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001559 if (PyArg_ParseTuple(args, "ssO:setvar",
1560 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001561 /* XXX must hold tcl lock already??? */
1562 newval = AsObj(newValue);
1563 ENTER_TCL
1564 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1565 ENTER_OVERLAP
1566 if (!ok)
1567 Tkinter_Error(self);
1568 else {
1569 res = Py_None;
1570 Py_INCREF(res);
1571 }
1572 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001573 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001574 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001575 return NULL;
1576 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001577 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001578 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001579}
1580
1581static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001582Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001583{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001584 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
1587static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001588Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001589{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001590 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001591}
1592
Barry Warsawfa701a81997-01-16 00:15:11 +00001593
1594
Guido van Rossum18468821994-06-20 07:49:28 +00001595static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001596GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001597{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001598 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001599 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001600 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001601
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001602 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1603 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001604 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001605
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001606 ENTER_TCL
1607 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1608 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001609 if (tres == NULL) {
1610 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1611 } else {
1612 if (((TkappObject*)self)->wantobjects) {
1613 res = FromObj(self, tres);
1614 }
1615 else {
1616 res = PyString_FromString(Tcl_GetString(tres));
1617 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001618 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001619 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001620 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001621}
1622
1623static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001624Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001625{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001626 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001627}
1628
1629static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001630Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001631{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001632 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001633}
1634
Barry Warsawfa701a81997-01-16 00:15:11 +00001635
1636
Guido van Rossum18468821994-06-20 07:49:28 +00001637static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001638UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001639{
Guido van Rossum35d43371997-08-02 00:09:09 +00001640 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001641 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001642 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001643
Guido van Rossum43713e52000-02-29 13:59:29 +00001644 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001645 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001646
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001647 ENTER_TCL
1648 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1649 ENTER_OVERLAP
1650 if (code == TCL_ERROR)
1651 res = Tkinter_Error(self);
1652 else {
1653 Py_INCREF(Py_None);
1654 res = Py_None;
1655 }
1656 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001657 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001658}
1659
1660static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001661Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001662{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001663 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001664}
1665
1666static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001667Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001668{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001669 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
Barry Warsawfa701a81997-01-16 00:15:11 +00001672
1673
Guido van Rossum18468821994-06-20 07:49:28 +00001674/** Tcl to Python **/
1675
1676static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001677Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001678{
Barry Warsawfa701a81997-01-16 00:15:11 +00001679 char *s;
1680 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001681
Martin v. Löwisffad6332002-11-26 09:28:05 +00001682 if (PyTuple_Size(args) == 1) {
1683 PyObject* o = PyTuple_GetItem(args, 0);
1684 if (PyInt_Check(o)) {
1685 Py_INCREF(o);
1686 return o;
1687 }
1688 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001689 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001690 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001691 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001692 return Tkinter_Error(self);
1693 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001694}
1695
1696static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001697Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001698{
Barry Warsawfa701a81997-01-16 00:15:11 +00001699 char *s;
1700 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001701
Martin v. Löwisffad6332002-11-26 09:28:05 +00001702 if (PyTuple_Size(args) == 1) {
1703 PyObject *o = PyTuple_GetItem(args, 0);
1704 if (PyFloat_Check(o)) {
1705 Py_INCREF(o);
1706 return o;
1707 }
1708 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001709 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001710 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001711 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001712 return Tkinter_Error(self);
1713 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001714}
1715
1716static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001717Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001718{
Barry Warsawfa701a81997-01-16 00:15:11 +00001719 char *s;
1720 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001721
Martin v. Löwisffad6332002-11-26 09:28:05 +00001722 if (PyTuple_Size(args) == 1) {
1723 PyObject *o = PyTuple_GetItem(args, 0);
1724 if (PyInt_Check(o)) {
1725 Py_INCREF(o);
1726 return o;
1727 }
1728 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001729 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001730 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001731 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1732 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001733 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001734}
1735
1736static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001737Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001738{
Barry Warsawfa701a81997-01-16 00:15:11 +00001739 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001740 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001741 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001742
Guido van Rossum43713e52000-02-29 13:59:29 +00001743 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001744 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001745
1746 CHECK_TCL_APPARTMENT;
1747
Guido van Rossum00d93061998-05-28 23:06:38 +00001748 ENTER_TCL
1749 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001750 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001751 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001752 res = Tkinter_Error(self);
1753 else
1754 res = Py_BuildValue("s", Tkapp_Result(self));
1755 LEAVE_OVERLAP_TCL
1756 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001757}
1758
1759static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001760Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001761{
Barry Warsawfa701a81997-01-16 00:15:11 +00001762 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001763 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001764 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001765 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001766
Guido van Rossum43713e52000-02-29 13:59:29 +00001767 if (!PyArg_ParseTuple(args, "s:exprlong", &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_ExprLong(Tkapp_Interp(self), s, &v);
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("l", v);
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_ExprDouble(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;
Barry Warsawfa701a81997-01-16 00:15:11 +00001788 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001789 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001790
Guido van Rossum43713e52000-02-29 13:59:29 +00001791 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001792 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001793 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001794 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001795 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001796 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001797 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001798 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001799 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001800 res = Tkinter_Error(self);
1801 else
1802 res = Py_BuildValue("d", 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_ExprBoolean(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;
Guido van Rossum00d93061998-05-28 23:06:38 +00001812 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001813 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001814
Guido van Rossum43713e52000-02-29 13:59:29 +00001815 if (!PyArg_ParseTuple(args, "s:exprboolean", &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 Rossum00d93061998-05-28 23:06:38 +00001818 ENTER_TCL
1819 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001820 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001821 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001822 res = Tkinter_Error(self);
1823 else
1824 res = Py_BuildValue("i", v);
1825 LEAVE_OVERLAP_TCL
1826 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001827}
1828
Barry Warsawfa701a81997-01-16 00:15:11 +00001829
1830
Guido van Rossum18468821994-06-20 07:49:28 +00001831static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001832Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001833{
Barry Warsawfa701a81997-01-16 00:15:11 +00001834 char *list;
1835 int argc;
1836 char **argv;
1837 PyObject *v;
1838 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001839
Martin v. Löwisffad6332002-11-26 09:28:05 +00001840 if (PyTuple_Size(args) == 1) {
1841 v = PyTuple_GetItem(args, 0);
1842 if (PyTuple_Check(v)) {
1843 Py_INCREF(v);
1844 return v;
1845 }
1846 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001847 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001848 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001849
Neal Norwitzd1c55102003-05-29 00:17:03 +00001850 if (Tcl_SplitList(Tkapp_Interp(self), list,
1851 &argc, &argv) == TCL_ERROR) {
1852 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001853 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001854 }
Guido van Rossum18468821994-06-20 07:49:28 +00001855
Barry Warsawfa701a81997-01-16 00:15:11 +00001856 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001857 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001858
Barry Warsawfa701a81997-01-16 00:15:11 +00001859 for (i = 0; i < argc; i++) {
1860 PyObject *s = PyString_FromString(argv[i]);
1861 if (!s || PyTuple_SetItem(v, i, s)) {
1862 Py_DECREF(v);
1863 v = NULL;
1864 goto finally;
1865 }
1866 }
Guido van Rossum18468821994-06-20 07:49:28 +00001867
Barry Warsawfa701a81997-01-16 00:15:11 +00001868 finally:
1869 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001870 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001871 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001872}
1873
1874static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001875Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001876{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001877 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001879
Martin v. Löwisffad6332002-11-26 09:28:05 +00001880 if (PyTuple_Size(args) == 1) {
1881 PyObject* o = PyTuple_GetItem(args, 0);
1882 if (PyTuple_Check(o)) {
1883 o = SplitObj(o);
1884 return o;
1885 }
1886 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001887 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001888 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001889 v = Split(list);
1890 PyMem_Free(list);
1891 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001892}
1893
1894static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001895Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001896{
Barry Warsawfa701a81997-01-16 00:15:11 +00001897 char *s = Merge(args);
1898 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001899
Barry Warsawfa701a81997-01-16 00:15:11 +00001900 if (s) {
1901 res = PyString_FromString(s);
1902 ckfree(s);
1903 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001904
1905 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001906}
1907
Barry Warsawfa701a81997-01-16 00:15:11 +00001908
1909
Guido van Rossum18468821994-06-20 07:49:28 +00001910/** Tcl Command **/
1911
Guido van Rossum00d93061998-05-28 23:06:38 +00001912/* Client data struct */
1913typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001914 PyObject *self;
1915 PyObject *func;
1916} PythonCmd_ClientData;
1917
1918static int
Fred Drake509d79a2000-07-08 04:04:38 +00001919PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001920{
1921 errorInCmd = 1;
1922 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1923 LEAVE_PYTHON
1924 return TCL_ERROR;
1925}
1926
Guido van Rossum18468821994-06-20 07:49:28 +00001927/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001928 * function or method.
1929 */
Guido van Rossum18468821994-06-20 07:49:28 +00001930static int
Fred Drake509d79a2000-07-08 04:04:38 +00001931PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001932{
Guido van Rossum00d93061998-05-28 23:06:38 +00001933 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001934 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001935 int i, rv;
1936 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001937
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001938 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001939
Barry Warsawfa701a81997-01-16 00:15:11 +00001940 /* TBD: no error checking here since we know, via the
1941 * Tkapp_CreateCommand() that the client data is a two-tuple
1942 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001943 self = data->self;
1944 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001945
Barry Warsawfa701a81997-01-16 00:15:11 +00001946 /* Create argument list (argv1, ..., argvN) */
1947 if (!(arg = PyTuple_New(argc - 1)))
1948 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001949
Barry Warsawfa701a81997-01-16 00:15:11 +00001950 for (i = 0; i < (argc - 1); i++) {
1951 PyObject *s = PyString_FromString(argv[i + 1]);
1952 if (!s || PyTuple_SetItem(arg, i, s)) {
1953 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001954 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001955 }
1956 }
1957 res = PyEval_CallObject(func, arg);
1958 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001959
Barry Warsawfa701a81997-01-16 00:15:11 +00001960 if (res == NULL)
1961 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001962
Barry Warsawfa701a81997-01-16 00:15:11 +00001963 if (!(tmp = PyList_New(0))) {
1964 Py_DECREF(res);
1965 return PythonCmd_Error(interp);
1966 }
1967
Guido van Rossum2834b972000-10-06 16:58:26 +00001968 s = AsString(res, tmp);
1969 if (s == NULL) {
1970 rv = PythonCmd_Error(interp);
1971 }
1972 else {
1973 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1974 rv = TCL_OK;
1975 }
1976
Barry Warsawfa701a81997-01-16 00:15:11 +00001977 Py_DECREF(res);
1978 Py_DECREF(tmp);
1979
Guido van Rossum00d93061998-05-28 23:06:38 +00001980 LEAVE_PYTHON
1981
Guido van Rossum2834b972000-10-06 16:58:26 +00001982 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001983}
1984
1985static void
Fred Drake509d79a2000-07-08 04:04:38 +00001986PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001987{
Guido van Rossum00d93061998-05-28 23:06:38 +00001988 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1989
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001990 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001991 Py_XDECREF(data->self);
1992 Py_XDECREF(data->func);
1993 PyMem_DEL(data);
1994 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001995}
1996
Barry Warsawfa701a81997-01-16 00:15:11 +00001997
1998
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001999
2000TCL_DECLARE_MUTEX(command_mutex)
2001
2002typedef struct CommandEvent{
2003 Tcl_Event ev;
2004 Tcl_Interp* interp;
2005 char *name;
2006 int create;
2007 int *status;
2008 ClientData *data;
2009 Tcl_Condition done;
2010} CommandEvent;
2011
2012static int
2013Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002014{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002015 if (ev->create)
2016 *ev->status = Tcl_CreateCommand(
2017 ev->interp, ev->name, PythonCmd,
2018 ev->data, PythonCmdDelete) == NULL;
2019 else
2020 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2021 Tcl_MutexLock(&command_mutex);
2022 Tcl_ConditionNotify(&ev->done);
2023 Tcl_MutexUnlock(&command_mutex);
2024 return 1;
2025}
2026
2027static PyObject *
2028Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2029{
2030 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002031 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002032 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002033 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002034 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002035
Guido van Rossum43713e52000-02-29 13:59:29 +00002036 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002037 return NULL;
2038 if (!PyCallable_Check(func)) {
2039 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002040 return NULL;
2041 }
Guido van Rossum18468821994-06-20 07:49:28 +00002042
Martin v. Löwisa9656492003-03-30 08:44:58 +00002043#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002044 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002045 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002046 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002047#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002048
Guido van Rossum00d93061998-05-28 23:06:38 +00002049 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002050 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002051 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002052 Py_XINCREF(self);
2053 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002055 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056
2057 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2058 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2059 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2060 ev->interp = self->interp;
2061 ev->create = 1;
2062 ev->name = cmdName;
2063 ev->data = (ClientData)data;
2064 ev->status = &err;
2065 ev->done = NULL;
2066 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2067 }
2068 else {
2069 ENTER_TCL
2070 err = Tcl_CreateCommand(
2071 Tkapp_Interp(self), cmdName, PythonCmd,
2072 (ClientData)data, PythonCmdDelete) == NULL;
2073 LEAVE_TCL
2074 }
2075 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002076 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002077 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002078 return NULL;
2079 }
Guido van Rossum18468821994-06-20 07:49:28 +00002080
Barry Warsawfa701a81997-01-16 00:15:11 +00002081 Py_INCREF(Py_None);
2082 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002083}
2084
Barry Warsawfa701a81997-01-16 00:15:11 +00002085
2086
Guido van Rossum18468821994-06-20 07:49:28 +00002087static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002088Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002089{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002090 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002091 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002092 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002093
Guido van Rossum43713e52000-02-29 13:59:29 +00002094 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002095 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002096 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2097 CommandEvent *ev;
2098 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2099 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2100 ev->interp = self->interp;
2101 ev->create = 0;
2102 ev->name = cmdName;
2103 ev->status = &err;
2104 ev->done = NULL;
2105 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2106 &command_mutex);
2107 }
2108 else {
2109 ENTER_TCL
2110 err = Tcl_DeleteCommand(self->interp, cmdName);
2111 LEAVE_TCL
2112 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002113 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002114 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2115 return NULL;
2116 }
2117 Py_INCREF(Py_None);
2118 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002119}
2120
Barry Warsawfa701a81997-01-16 00:15:11 +00002121
2122
Guido van Rossum00d93061998-05-28 23:06:38 +00002123#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002124/** File Handler **/
2125
Guido van Rossum00d93061998-05-28 23:06:38 +00002126typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002127 PyObject *func;
2128 PyObject *file;
2129 int id;
2130 struct _fhcdata *next;
2131} FileHandler_ClientData;
2132
2133static FileHandler_ClientData *HeadFHCD;
2134
2135static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002136NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002137{
2138 FileHandler_ClientData *p;
2139 p = PyMem_NEW(FileHandler_ClientData, 1);
2140 if (p != NULL) {
2141 Py_XINCREF(func);
2142 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002143 p->func = func;
2144 p->file = file;
2145 p->id = id;
2146 p->next = HeadFHCD;
2147 HeadFHCD = p;
2148 }
2149 return p;
2150}
2151
2152static void
Fred Drake509d79a2000-07-08 04:04:38 +00002153DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002154{
2155 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002156
2157 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002158 while ((p = *pp) != NULL) {
2159 if (p->id == id) {
2160 *pp = p->next;
2161 Py_XDECREF(p->func);
2162 Py_XDECREF(p->file);
2163 PyMem_DEL(p);
2164 }
2165 else
2166 pp = &p->next;
2167 }
2168}
2169
Guido van Rossuma597dde1995-01-10 20:56:29 +00002170static void
Fred Drake509d79a2000-07-08 04:04:38 +00002171FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002172{
Guido van Rossum00d93061998-05-28 23:06:38 +00002173 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002174 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002175
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002176 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002177 func = data->func;
2178 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002179
Barry Warsawfa701a81997-01-16 00:15:11 +00002180 arg = Py_BuildValue("(Oi)", file, (long) mask);
2181 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002182 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002183
2184 if (res == NULL) {
2185 errorInCmd = 1;
2186 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2187 }
2188 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002189 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002190}
2191
Guido van Rossum18468821994-06-20 07:49:28 +00002192static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002193Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2194 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002195{
Guido van Rossum00d93061998-05-28 23:06:38 +00002196 FileHandler_ClientData *data;
2197 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002198 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002199
Guido van Rossum2834b972000-10-06 16:58:26 +00002200 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2201 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002202 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002203
Martin v. Löwisa9656492003-03-30 08:44:58 +00002204#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002205 if (!self && !tcl_lock) {
2206 /* We don't have the Tcl lock since Tcl is threaded. */
2207 PyErr_SetString(PyExc_RuntimeError,
2208 "_tkinter.createfilehandler not supported "
2209 "for threaded Tcl");
2210 return NULL;
2211 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002212#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002213
2214 if (self) {
2215 CHECK_TCL_APPARTMENT;
2216 }
2217
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002218 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002219 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002220 return NULL;
2221 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002222 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002223 return NULL;
2224 }
2225
Guido van Rossuma80649b2000-03-28 20:07:05 +00002226 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002227 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002228 return NULL;
2229
Barry Warsawfa701a81997-01-16 00:15:11 +00002230 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002231 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002232 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002233 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002234 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002235 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002236}
2237
2238static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002239Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002240{
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002242 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002243
Guido van Rossum43713e52000-02-29 13:59:29 +00002244 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002245 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002246
Martin v. Löwisa9656492003-03-30 08:44:58 +00002247#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002248 if (!self && !tcl_lock) {
2249 /* We don't have the Tcl lock since Tcl is threaded. */
2250 PyErr_SetString(PyExc_RuntimeError,
2251 "_tkinter.deletefilehandler not supported "
2252 "for threaded Tcl");
2253 return NULL;
2254 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002255#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002256
2257 if (self) {
2258 CHECK_TCL_APPARTMENT;
2259 }
2260
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002261 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002262 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002263 return NULL;
2264
Guido van Rossuma80649b2000-03-28 20:07:05 +00002265 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002266
Barry Warsawfa701a81997-01-16 00:15:11 +00002267 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002268 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002269 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002270 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002271 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002272 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002273}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002274#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002275
Barry Warsawfa701a81997-01-16 00:15:11 +00002276
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002277/**** Tktt Object (timer token) ****/
2278
Jeremy Hylton938ace62002-07-17 16:30:39 +00002279static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002280
Guido van Rossum00d93061998-05-28 23:06:38 +00002281typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002283 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002285} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002286
2287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002288Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002289{
Barry Warsawfa701a81997-01-16 00:15:11 +00002290 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002291 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292
Guido van Rossum43713e52000-02-29 13:59:29 +00002293 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002295 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002296 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002297 v->token = NULL;
2298 }
2299 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002300 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002301 Py_DECREF(func);
2302 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002303 }
2304 Py_INCREF(Py_None);
2305 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002306}
2307
2308static PyMethodDef Tktt_methods[] =
2309{
Neal Norwitzb0493252002-03-31 14:44:22 +00002310 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002311 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002312};
2313
2314static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002315Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316{
Barry Warsawfa701a81997-01-16 00:15:11 +00002317 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318
Guido van Rossumb18618d2000-05-03 23:44:39 +00002319 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 if (v == NULL)
2321 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322
Guido van Rossum00d93061998-05-28 23:06:38 +00002323 Py_INCREF(func);
2324 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002325 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002326
2327 /* Extra reference, deleted when called or when handler is deleted */
2328 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002329 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330}
2331
2332static void
Fred Drake509d79a2000-07-08 04:04:38 +00002333Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334{
Guido van Rossum00d93061998-05-28 23:06:38 +00002335 TkttObject *v = (TkttObject *)self;
2336 PyObject *func = v->func;
2337
2338 Py_XDECREF(func);
2339
Guido van Rossumb18618d2000-05-03 23:44:39 +00002340 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341}
2342
Guido van Rossum597ac201998-05-12 14:36:19 +00002343static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002344Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345{
Barry Warsawfa701a81997-01-16 00:15:11 +00002346 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002347 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348
Tim Peters885d4572001-11-28 20:27:42 +00002349 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002350 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002351 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002352}
2353
2354static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002355Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356{
Barry Warsawfa701a81997-01-16 00:15:11 +00002357 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358}
2359
2360static PyTypeObject Tktt_Type =
2361{
Guido van Rossum35d43371997-08-02 00:09:09 +00002362 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002363 0, /*ob_size */
2364 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002365 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002366 0, /*tp_itemsize */
2367 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002368 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002369 Tktt_GetAttr, /*tp_getattr */
2370 0, /*tp_setattr */
2371 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002372 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002373 0, /*tp_as_number */
2374 0, /*tp_as_sequence */
2375 0, /*tp_as_mapping */
2376 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377};
2378
Barry Warsawfa701a81997-01-16 00:15:11 +00002379
2380
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381/** Timer Handler **/
2382
2383static void
Fred Drake509d79a2000-07-08 04:04:38 +00002384TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002385{
Guido van Rossum00d93061998-05-28 23:06:38 +00002386 TkttObject *v = (TkttObject *)clientData;
2387 PyObject *func = v->func;
2388 PyObject *res;
2389
2390 if (func == NULL)
2391 return;
2392
2393 v->func = NULL;
2394
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002395 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002396
2397 res = PyEval_CallObject(func, NULL);
2398 Py_DECREF(func);
2399 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002400
Barry Warsawfa701a81997-01-16 00:15:11 +00002401 if (res == NULL) {
2402 errorInCmd = 1;
2403 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2404 }
2405 else
2406 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002407
2408 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002409}
2410
2411static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002412Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002413{
Barry Warsawfa701a81997-01-16 00:15:11 +00002414 int milliseconds;
2415 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002416 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002417
Guido van Rossum2834b972000-10-06 16:58:26 +00002418 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2419 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002420 return NULL;
2421 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002422 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002423 return NULL;
2424 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002425
Martin v. Löwisa9656492003-03-30 08:44:58 +00002426#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002427 if (!self && !tcl_lock) {
2428 /* We don't have the Tcl lock since Tcl is threaded. */
2429 PyErr_SetString(PyExc_RuntimeError,
2430 "_tkinter.createtimerhandler not supported "
2431 "for threaded Tcl");
2432 return NULL;
2433 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002434#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002435
2436 if (self) {
2437 CHECK_TCL_APPARTMENT;
2438 }
2439
Guido van Rossum00d93061998-05-28 23:06:38 +00002440 v = Tktt_New(func);
2441 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2442 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002443
Guido van Rossum00d93061998-05-28 23:06:38 +00002444 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002445}
2446
Barry Warsawfa701a81997-01-16 00:15:11 +00002447
Guido van Rossum18468821994-06-20 07:49:28 +00002448/** Event Loop **/
2449
Guido van Rossum18468821994-06-20 07:49:28 +00002450static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002451Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002452{
Barry Warsawfa701a81997-01-16 00:15:11 +00002453 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002454 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002455#ifdef WITH_THREAD
2456 PyThreadState *tstate = PyThreadState_Get();
2457#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002458
Guido van Rossum43713e52000-02-29 13:59:29 +00002459 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002460 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002461
Martin v. Löwisa9656492003-03-30 08:44:58 +00002462#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002463 if (!self && !tcl_lock) {
2464 /* We don't have the Tcl lock since Tcl is threaded. */
2465 PyErr_SetString(PyExc_RuntimeError,
2466 "_tkinter.mainloop not supported "
2467 "for threaded Tcl");
2468 return NULL;
2469 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002470#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002471
2472 if (self) {
2473 CHECK_TCL_APPARTMENT;
2474 self->dispatching = 1;
2475 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002476
Barry Warsawfa701a81997-01-16 00:15:11 +00002477 quitMainLoop = 0;
2478 while (Tk_GetNumMainWindows() > threshold &&
2479 !quitMainLoop &&
2480 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002481 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002482 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002483
2484#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002485 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002486 /* Allow other Python threads to run. */
2487 ENTER_TCL
2488 result = Tcl_DoOneEvent(0);
2489 LEAVE_TCL
2490 }
2491 else {
2492 Py_BEGIN_ALLOW_THREADS
2493 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2494 tcl_tstate = tstate;
2495 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2496 tcl_tstate = NULL;
2497 if(tcl_lock)PyThread_release_lock(tcl_lock);
2498 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002499 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002500 Py_END_ALLOW_THREADS
2501 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002502#else
2503 result = Tcl_DoOneEvent(0);
2504#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002505
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002506 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002507 if (self)
2508 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002509 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002510 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002511 if (result < 0)
2512 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002513 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002514 if (self)
2515 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002516 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002517
Barry Warsawfa701a81997-01-16 00:15:11 +00002518 if (errorInCmd) {
2519 errorInCmd = 0;
2520 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2521 excInCmd = valInCmd = trbInCmd = NULL;
2522 return NULL;
2523 }
2524 Py_INCREF(Py_None);
2525 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002526}
2527
2528static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002529Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002530{
Guido van Rossum35d43371997-08-02 00:09:09 +00002531 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002532 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002533
Guido van Rossum43713e52000-02-29 13:59:29 +00002534 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002535 return NULL;
2536
Guido van Rossum00d93061998-05-28 23:06:38 +00002537 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002538 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002539 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002540 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002541}
2542
2543static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002544Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002545{
2546
Guido van Rossum43713e52000-02-29 13:59:29 +00002547 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002548 return NULL;
2549
2550 quitMainLoop = 1;
2551 Py_INCREF(Py_None);
2552 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002553}
2554
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002555static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002556Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002557{
2558
Guido van Rossum43713e52000-02-29 13:59:29 +00002559 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002560 return NULL;
2561
2562 return PyInt_FromLong((long)Tkapp_Interp(self));
2563}
2564
Barry Warsawfa701a81997-01-16 00:15:11 +00002565
Martin v. Löwisffad6332002-11-26 09:28:05 +00002566static PyObject *
2567Tkapp_WantObjects(PyObject *self, PyObject *args)
2568{
2569
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002570 int wantobjects = -1;
2571 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002572 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002573 if (wantobjects == -1)
2574 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002575 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002576
2577 Py_INCREF(Py_None);
2578 return Py_None;
2579}
2580
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002581static PyObject *
2582Tkapp_WillDispatch(PyObject *self, PyObject *args)
2583{
2584
2585 ((TkappObject*)self)->dispatching = 1;
2586
2587 Py_INCREF(Py_None);
2588 return Py_None;
2589}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002590
Barry Warsawfa701a81997-01-16 00:15:11 +00002591
Guido van Rossum18468821994-06-20 07:49:28 +00002592/**** Tkapp Method List ****/
2593
2594static PyMethodDef Tkapp_methods[] =
2595{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002596 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002597 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002598 {"call", Tkapp_Call, METH_OLDARGS},
2599 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2600 {"eval", Tkapp_Eval, METH_VARARGS},
2601 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2602 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2603 {"record", Tkapp_Record, METH_VARARGS},
2604 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2605 {"setvar", Tkapp_SetVar, METH_VARARGS},
2606 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2607 {"getvar", Tkapp_GetVar, METH_VARARGS},
2608 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2609 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2610 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2611 {"getint", Tkapp_GetInt, METH_VARARGS},
2612 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2613 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2614 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2615 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2616 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2617 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2618 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2619 {"split", Tkapp_Split, METH_VARARGS},
2620 {"merge", Tkapp_Merge, METH_OLDARGS},
2621 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2622 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002623#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002624 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2625 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002626#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002627 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2628 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2629 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2630 {"quit", Tkapp_Quit, METH_VARARGS},
2631 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002632 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002633};
2634
Barry Warsawfa701a81997-01-16 00:15:11 +00002635
2636
Guido van Rossum18468821994-06-20 07:49:28 +00002637/**** Tkapp Type Methods ****/
2638
2639static void
Fred Drake509d79a2000-07-08 04:04:38 +00002640Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002641{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002642 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002643 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002644 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002645 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002646 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002647 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002648}
2649
2650static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002651Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002652{
Guido van Rossum35d43371997-08-02 00:09:09 +00002653 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002654}
2655
2656static PyTypeObject Tkapp_Type =
2657{
Guido van Rossum35d43371997-08-02 00:09:09 +00002658 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002659 0, /*ob_size */
2660 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002661 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002662 0, /*tp_itemsize */
2663 Tkapp_Dealloc, /*tp_dealloc */
2664 0, /*tp_print */
2665 Tkapp_GetAttr, /*tp_getattr */
2666 0, /*tp_setattr */
2667 0, /*tp_compare */
2668 0, /*tp_repr */
2669 0, /*tp_as_number */
2670 0, /*tp_as_sequence */
2671 0, /*tp_as_mapping */
2672 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002673};
2674
Barry Warsawfa701a81997-01-16 00:15:11 +00002675
2676
Guido van Rossum18468821994-06-20 07:49:28 +00002677/**** Tkinter Module ****/
2678
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002679typedef struct {
2680 PyObject* tuple;
2681 int size; /* current size */
2682 int maxsize; /* allocated size */
2683} FlattenContext;
2684
2685static int
2686_bump(FlattenContext* context, int size)
2687{
Guido van Rossum2834b972000-10-06 16:58:26 +00002688 /* expand tuple to hold (at least) size new items.
2689 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002690
2691 int maxsize = context->maxsize * 2;
2692
2693 if (maxsize < context->size + size)
2694 maxsize = context->size + size;
2695
2696 context->maxsize = maxsize;
2697
Tim Peters4324aa32001-05-28 22:30:08 +00002698 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002699}
2700
2701static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002702_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002703{
2704 /* add tuple or list to argument tuple (recursively) */
2705
2706 int i, size;
2707
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002708 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002709 PyErr_SetString(PyExc_ValueError,
2710 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002711 return 0;
2712 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002713 size = PyList_GET_SIZE(item);
2714 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002715 if (context->size + size > context->maxsize &&
2716 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002717 return 0;
2718 /* copy items to output tuple */
2719 for (i = 0; i < size; i++) {
2720 PyObject *o = PyList_GET_ITEM(item, i);
2721 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002722 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002723 return 0;
2724 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002725 if (context->size + 1 > context->maxsize &&
2726 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002727 return 0;
2728 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002729 PyTuple_SET_ITEM(context->tuple,
2730 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731 }
2732 }
2733 } else if (PyTuple_Check(item)) {
2734 /* same, for tuples */
2735 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002736 if (context->size + size > context->maxsize &&
2737 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738 return 0;
2739 for (i = 0; i < size; i++) {
2740 PyObject *o = PyTuple_GET_ITEM(item, i);
2741 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002742 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002743 return 0;
2744 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002745 if (context->size + 1 > context->maxsize &&
2746 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002747 return 0;
2748 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002749 PyTuple_SET_ITEM(context->tuple,
2750 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002751 }
2752 }
2753 } else {
2754 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2755 return 0;
2756 }
2757 return 1;
2758}
2759
2760static PyObject *
2761Tkinter_Flatten(PyObject* self, PyObject* args)
2762{
2763 FlattenContext context;
2764 PyObject* item;
2765
2766 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2767 return NULL;
2768
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002769 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002770 if (context.maxsize <= 0)
2771 return PyTuple_New(0);
2772
2773 context.tuple = PyTuple_New(context.maxsize);
2774 if (!context.tuple)
2775 return NULL;
2776
2777 context.size = 0;
2778
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002779 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780 return NULL;
2781
Tim Peters4324aa32001-05-28 22:30:08 +00002782 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002783 return NULL;
2784
2785 return context.tuple;
2786}
2787
Guido van Rossum18468821994-06-20 07:49:28 +00002788static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002789Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002790{
Barry Warsawfa701a81997-01-16 00:15:11 +00002791 char *screenName = NULL;
2792 char *baseName = NULL;
2793 char *className = NULL;
2794 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002795 int wantobjects = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002796
Guido van Rossum35d43371997-08-02 00:09:09 +00002797 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002798 if (baseName != NULL)
2799 baseName++;
2800 else
2801 baseName = Py_GetProgramName();
2802 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002803
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00002804 if (!PyArg_ParseTuple(args, "|zssii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002805 &screenName, &baseName, &className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002806 &interactive, &wantobjects))
Barry Warsawfa701a81997-01-16 00:15:11 +00002807 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002808
Barry Warsawfa701a81997-01-16 00:15:11 +00002809 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002810 interactive, wantobjects);
Guido van Rossum18468821994-06-20 07:49:28 +00002811}
2812
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002813static PyObject *
2814Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2815{
2816 int new_val;
2817 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2818 return NULL;
2819 if (new_val < 0) {
2820 PyErr_SetString(PyExc_ValueError,
2821 "busywaitinterval must be >= 0");
2822 return NULL;
2823 }
2824 Tkinter_busywaitinterval = new_val;
2825 Py_INCREF(Py_None);
2826 return Py_None;
2827}
2828
2829static char setbusywaitinterval_doc[] =
2830"setbusywaitinterval(n) -> None\n\
2831\n\
2832Set the busy-wait interval in milliseconds between successive\n\
2833calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2834It should be set to a divisor of the maximum time between\n\
2835frames in an animation.";
2836
2837static PyObject *
2838Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2839{
2840 return PyInt_FromLong(Tkinter_busywaitinterval);
2841}
2842
2843static char getbusywaitinterval_doc[] =
2844"getbusywaitinterval() -> int\n\
2845\n\
2846Return the current busy-wait interval between successive\n\
2847calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2848
Guido van Rossum18468821994-06-20 07:49:28 +00002849static PyMethodDef moduleMethods[] =
2850{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002851 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2852 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002853#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002854 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2855 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002856#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002857 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2858 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2859 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2860 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002861 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2862 setbusywaitinterval_doc},
2863 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2864 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002865 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002866};
2867
Guido van Rossum7bf15641998-05-22 18:28:17 +00002868#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002869
2870static int stdin_ready = 0;
2871
Guido van Rossumad4db171998-06-13 13:56:28 +00002872#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002873static void
Fred Drake509d79a2000-07-08 04:04:38 +00002874MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002875{
2876 stdin_ready = 1;
2877}
Guido van Rossumad4db171998-06-13 13:56:28 +00002878#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002879
Martin v. Löwisa9656492003-03-30 08:44:58 +00002880#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002881static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002882#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002883
Guido van Rossum18468821994-06-20 07:49:28 +00002884static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002885EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002886{
Guido van Rossumad4db171998-06-13 13:56:28 +00002887#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002888 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002889#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002890#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002891 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002892#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002893 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002894 errorInCmd = 0;
2895#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002896 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002897 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002898#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002899 while (!errorInCmd && !stdin_ready) {
2900 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002901#ifdef MS_WINDOWS
2902 if (_kbhit()) {
2903 stdin_ready = 1;
2904 break;
2905 }
2906#endif
2907#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002908 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002909 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002910 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002911
Guido van Rossum00d93061998-05-28 23:06:38 +00002912 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002913
2914 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002915 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002916 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002917 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002918 Py_END_ALLOW_THREADS
2919#else
2920 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002921#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002922
2923 if (result < 0)
2924 break;
2925 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002926#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002927 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002928#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002929 if (errorInCmd) {
2930 errorInCmd = 0;
2931 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2932 excInCmd = valInCmd = trbInCmd = NULL;
2933 PyErr_Print();
2934 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002935#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002936 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002937#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002938 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002939}
Guido van Rossum18468821994-06-20 07:49:28 +00002940
Guido van Rossum00d93061998-05-28 23:06:38 +00002941#endif
2942
Guido van Rossum7bf15641998-05-22 18:28:17 +00002943static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002944EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002945{
Guido van Rossum00d93061998-05-28 23:06:38 +00002946#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002947 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002948#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002949 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002950#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002951 PyOS_InputHook = EventHook;
2952 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002953#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002954}
2955
2956static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002957DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002958{
Guido van Rossum00d93061998-05-28 23:06:38 +00002959#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002960 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2961 PyOS_InputHook = NULL;
2962 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002963#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002964}
2965
Barry Warsawfa701a81997-01-16 00:15:11 +00002966
2967/* all errors will be checked in one fell swoop in init_tkinter() */
2968static void
Fred Drake509d79a2000-07-08 04:04:38 +00002969ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002970{
2971 PyObject *v = PyInt_FromLong(val);
2972 if (v) {
2973 PyDict_SetItemString(d, name, v);
2974 Py_DECREF(v);
2975 }
2976}
2977static void
Fred Drake509d79a2000-07-08 04:04:38 +00002978ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002979{
2980 PyObject *v = PyString_FromString(val);
2981 if (v) {
2982 PyDict_SetItemString(d, name, v);
2983 Py_DECREF(v);
2984 }
2985}
2986
2987
Mark Hammond62b1ab12002-07-23 06:31:15 +00002988PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002989init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002990{
Barry Warsawfa701a81997-01-16 00:15:11 +00002991 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00002992
Barry Warsawfa701a81997-01-16 00:15:11 +00002993 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00002994
2995#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00002996 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002997#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002998
Barry Warsawfa701a81997-01-16 00:15:11 +00002999 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003000
Barry Warsawfa701a81997-01-16 00:15:11 +00003001 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003002 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003003 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003004
Guido van Rossum35d43371997-08-02 00:09:09 +00003005 ins_long(d, "READABLE", TCL_READABLE);
3006 ins_long(d, "WRITABLE", TCL_WRITABLE);
3007 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3008 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3009 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3010 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3011 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3012 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3013 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003014 ins_string(d, "TK_VERSION", TK_VERSION);
3015 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003016
Guido van Rossum83551bf1997-09-13 00:44:23 +00003017 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003018
3019 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003020 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3021
Martin v. Löwisffad6332002-11-26 09:28:05 +00003022 PyTclObject_Type.ob_type = &PyType_Type;
3023 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003024
3025#ifdef TK_AQUA
3026 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3027 * start waking up. Note that Tcl_FindExecutable will do this, this
3028 * code must be above it! The original warning from
3029 * tkMacOSXAppInit.c is copied below.
3030 *
3031 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3032 * Tcl interpreter for now. It probably should work to do this
3033 * in the other order, but for now it doesn't seem to.
3034 *
3035 */
3036 Tk_MacOSXSetupTkNotifier();
3037#endif
3038
3039
Guido van Rossume187b0e2000-03-27 21:46:29 +00003040 /* This helps the dynamic loader; in Unicode aware Tcl versions
3041 it also helps Tcl find its encodings. */
3042 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003043
Barry Warsawfa701a81997-01-16 00:15:11 +00003044 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003045 return;
3046
Guido van Rossum43ff8681998-07-14 18:02:13 +00003047#if 0
3048 /* This was not a good idea; through <Destroy> bindings,
3049 Tcl_Finalize() may invoke Python code but at that point the
3050 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003051 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003052#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003053
Guido van Rossum18468821994-06-20 07:49:28 +00003054}