blob: 852bde4a1134869594b5bda0c6320e235f1e9e01 [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;
David Aschere2b4b322004-02-18 05:59:53 +0000549 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000550
Barry Warsawfa701a81997-01-16 00:15:11 +0000551 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 }
David Aschere2b4b322004-02-18 05:59:53 +0000555 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
556 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
557 main = Tk_MainWindow(interp);
558 if (Tk_Init(interp) == TCL_ERROR) {
559 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
560 return TCL_ERROR;
561 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000562 }
563 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000564}
565#endif /* !WITH_APPINIT */
566
Guido van Rossum18468821994-06-20 07:49:28 +0000567
Barry Warsawfa701a81997-01-16 00:15:11 +0000568
569
570/* Initialize the Tk application; see the `main' function in
571 * `tkMain.c'.
572 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000573
Thomas Wouters58d05102000-07-24 14:43:35 +0000574static void EnableEventHook(void); /* Forward */
575static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000576
Barry Warsawfa701a81997-01-16 00:15:11 +0000577static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000578Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000579 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000580{
581 TkappObject *v;
582 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000583
Guido van Rossumb18618d2000-05-03 23:44:39 +0000584 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000585 if (v == NULL)
586 return NULL;
587
588 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000589 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000590 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
591 TCL_GLOBAL_ONLY) != NULL;
592 v->thread_id = Tcl_GetCurrentThread();
593 v->dispatching = 0;
594
595#ifndef TCL_THREADS
596 if (v->threaded) {
597 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
598 Py_DECREF(v);
599 return 0;
600 }
601#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000602#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000603 if (v->threaded && tcl_lock) {
604 /* If Tcl is threaded, we don't need the lock. */
605 PyThread_free_lock(tcl_lock);
606 tcl_lock = NULL;
607 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000608#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000609
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000610 v->BooleanType = Tcl_GetObjType("boolean");
611 v->ByteArrayType = Tcl_GetObjType("bytearray");
612 v->DoubleType = Tcl_GetObjType("double");
613 v->IntType = Tcl_GetObjType("int");
614 v->ListType = Tcl_GetObjType("list");
615 v->ProcBodyType = Tcl_GetObjType("procbody");
616 v->StringType = Tcl_GetObjType("string");
617
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000618 /* Delete the 'exit' command, which can screw things up */
619 Tcl_DeleteCommand(v->interp, "exit");
620
Barry Warsawfa701a81997-01-16 00:15:11 +0000621 if (screenName != NULL)
622 Tcl_SetVar2(v->interp, "env", "DISPLAY",
623 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000624
Barry Warsawfa701a81997-01-16 00:15:11 +0000625 if (interactive)
626 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
627 else
628 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000629
Barry Warsawfa701a81997-01-16 00:15:11 +0000630 /* This is used to get the application class for Tk 4.1 and up */
631 argv0 = (char*)ckalloc(strlen(className) + 1);
632 if (!argv0) {
633 PyErr_NoMemory();
634 Py_DECREF(v);
635 return NULL;
636 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000637
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000639 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000640 argv0[0] = tolower(argv0[0]);
641 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
642 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000643
David Aschere2b4b322004-02-18 05:59:53 +0000644 if (! wantTk) {
645 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
646 }
647
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000648 /* some initial arguments need to be in argv */
649 if (sync || use) {
Tim Peters51fa3b72004-08-04 02:16:48 +0000650 char *args;
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000651 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000652
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000653 if (sync)
654 len += sizeof "-sync";
655 if (use)
656 len += strlen(use) + sizeof "-use ";
657
Tim Peters51fa3b72004-08-04 02:16:48 +0000658 args = (char*)ckalloc(len);
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659 if (!args) {
660 PyErr_NoMemory();
661 Py_DECREF(v);
662 return NULL;
663 }
664
665 args[0] = '\0';
666 if (sync)
667 strcat(args, "-sync");
668 if (use) {
669 if (sync)
670 strcat(args, " ");
671 strcat(args, "-use ");
672 strcat(args, use);
673 }
674
675 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
676 ckfree(args);
677 }
678
Barry Warsawfa701a81997-01-16 00:15:11 +0000679 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000680 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000681
Guido van Rossum7bf15641998-05-22 18:28:17 +0000682 EnableEventHook();
683
Barry Warsawfa701a81997-01-16 00:15:11 +0000684 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000685}
686
Barry Warsawfa701a81997-01-16 00:15:11 +0000687
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000688static void
689Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
690 Tcl_Condition *cond, Tcl_Mutex *mutex)
691{
692 Py_BEGIN_ALLOW_THREADS;
693 Tcl_MutexLock(mutex);
694 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
695 Tcl_ThreadAlert(self->thread_id);
696 Tcl_ConditionWait(cond, mutex, NULL);
697 Tcl_MutexUnlock(mutex);
698 Py_END_ALLOW_THREADS
699}
700
Barry Warsawfa701a81997-01-16 00:15:11 +0000701
Guido van Rossum18468821994-06-20 07:49:28 +0000702/** Tcl Eval **/
703
Martin v. Löwisffad6332002-11-26 09:28:05 +0000704typedef struct {
705 PyObject_HEAD
706 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000707 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000708} PyTclObject;
709
710staticforward PyTypeObject PyTclObject_Type;
711#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
712
713static PyObject *
714newPyTclObject(Tcl_Obj *arg)
715{
716 PyTclObject *self;
717 self = PyObject_New(PyTclObject, &PyTclObject_Type);
718 if (self == NULL)
719 return NULL;
720 Tcl_IncrRefCount(arg);
721 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000722 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000723 return (PyObject*)self;
724}
725
726static void
727PyTclObject_dealloc(PyTclObject *self)
728{
729 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000730 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000731 PyObject_Del(self);
732}
733
734static PyObject *
735PyTclObject_str(PyTclObject *self)
736{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000737 if (self->string && PyString_Check(self->string)) {
738 Py_INCREF(self->string);
739 return self->string;
740 }
741 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742 return PyString_FromString(Tcl_GetString(self->value));
743}
744
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000745static char*
746PyTclObject_TclString(PyObject *self)
747{
748 return Tcl_GetString(((PyTclObject*)self)->value);
749}
750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000752PyDoc_STRVAR(PyTclObject_string__doc__,
753"the string representation of this object, either as string or Unicode");
754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755static PyObject *
756PyTclObject_string(PyTclObject *self, void *ignored)
757{
758 char *s;
759 int i, len;
760 if (!self->string) {
761 s = Tcl_GetStringFromObj(self->value, &len);
762 for (i = 0; i < len; i++)
763 if (s[i] & 0x80)
764 break;
765#ifdef Py_USING_UNICODE
766 if (i == len)
767 /* It is an ASCII string. */
768 self->string = PyString_FromStringAndSize(s, len);
769 else {
770 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
771 if (!self->string) {
772 PyErr_Clear();
773 self->string = PyString_FromStringAndSize(s, len);
774 }
775 }
776#else
777 self->string = PyString_FromStringAndSize(s, len);
778#endif
779 if (!self->string)
780 return NULL;
781 }
782 Py_INCREF(self->string);
783 return self->string;
784}
785
786#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000787PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
788
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000789static PyObject *
790PyTclObject_unicode(PyTclObject *self, void *ignored)
791{
792 char *s;
793 int len;
794 if (self->string && PyUnicode_Check(self->string)) {
795 Py_INCREF(self->string);
796 return self->string;
797 }
798 /* XXX Could chache result if it is non-ASCII. */
799 s = Tcl_GetStringFromObj(self->value, &len);
800 return PyUnicode_DecodeUTF8(s, len, "strict");
801}
802#endif
803
Martin v. Löwisffad6332002-11-26 09:28:05 +0000804static PyObject *
805PyTclObject_repr(PyTclObject *self)
806{
807 char buf[50];
808 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
809 self->value->typePtr->name, (int)self->value);
810 return PyString_FromString(buf);
811}
812
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000813static int
814PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
815{
816 int res;
817 res = strcmp(Tcl_GetString(self->value),
818 Tcl_GetString(other->value));
819 if (res < 0) return -1;
820 if (res > 0) return 1;
821 return 0;
822}
823
Martin v. Löwis39195712003-01-04 00:33:13 +0000824PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
825
Martin v. Löwisffad6332002-11-26 09:28:05 +0000826static PyObject*
827get_typename(PyTclObject* obj, void* ignored)
828{
829 return PyString_FromString(obj->value->typePtr->name);
830}
831
Martin v. Löwis39195712003-01-04 00:33:13 +0000832
Martin v. Löwisffad6332002-11-26 09:28:05 +0000833static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000834 {"typename", (getter)get_typename, NULL, get_typename__doc__},
835 {"string", (getter)PyTclObject_string, NULL,
836 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837 {0},
838};
839
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000840static PyMethodDef PyTclObject_methods[] = {
841 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000842 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000843 {0}
844};
845
Martin v. Löwisffad6332002-11-26 09:28:05 +0000846statichere PyTypeObject PyTclObject_Type = {
847 PyObject_HEAD_INIT(NULL)
848 0, /*ob_size*/
849 "_tkinter.Tcl_Obj", /*tp_name*/
850 sizeof(PyTclObject), /*tp_basicsize*/
851 0, /*tp_itemsize*/
852 /* methods */
853 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
854 0, /*tp_print*/
855 0, /*tp_getattr*/
856 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000857 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858 (reprfunc)PyTclObject_repr, /*tp_repr*/
859 0, /*tp_as_number*/
860 0, /*tp_as_sequence*/
861 0, /*tp_as_mapping*/
862 0, /*tp_hash*/
863 0, /*tp_call*/
864 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000865 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000866 0, /*tp_setattro*/
867 0, /*tp_as_buffer*/
868 Py_TPFLAGS_DEFAULT, /*tp_flags*/
869 0, /*tp_doc*/
870 0, /*tp_traverse*/
871 0, /*tp_clear*/
872 0, /*tp_richcompare*/
873 0, /*tp_weaklistoffset*/
874 0, /*tp_iter*/
875 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000876 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000877 0, /*tp_members*/
878 PyTclObject_getsetlist, /*tp_getset*/
879 0, /*tp_base*/
880 0, /*tp_dict*/
881 0, /*tp_descr_get*/
882 0, /*tp_descr_set*/
883 0, /*tp_dictoffset*/
884 0, /*tp_init*/
885 0, /*tp_alloc*/
886 0, /*tp_new*/
887 0, /*tp_free*/
888 0, /*tp_is_gc*/
889};
890
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000891static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000892AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000893{
894 Tcl_Obj *result;
895
896 if (PyString_Check(value))
897 return Tcl_NewStringObj(PyString_AS_STRING(value),
898 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000899 else if (PyBool_Check(value))
900 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000901 else if (PyInt_Check(value))
902 return Tcl_NewLongObj(PyInt_AS_LONG(value));
903 else if (PyFloat_Check(value))
904 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
905 else if (PyTuple_Check(value)) {
906 Tcl_Obj **argv = (Tcl_Obj**)
907 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
908 int i;
909 if(!argv)
910 return 0;
911 for(i=0;i<PyTuple_Size(value);i++)
912 argv[i] = AsObj(PyTuple_GetItem(value,i));
913 result = Tcl_NewListObj(PyTuple_Size(value), argv);
914 ckfree(FREECAST argv);
915 return result;
916 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000917#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000918 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000919 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
920 int size = PyUnicode_GET_SIZE(value);
921 /* This #ifdef assumes that Tcl uses UCS-2.
922 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000923#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000924 Tcl_UniChar *outbuf;
925 int i;
926 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
927 if (!outbuf) {
928 PyErr_NoMemory();
929 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000930 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000931 for (i = 0; i < size; i++) {
932 if (inbuf[i] >= 0x10000) {
933 /* Tcl doesn't do UTF-16, yet. */
934 PyErr_SetString(PyExc_ValueError,
935 "unsupported character");
936 ckfree(FREECAST outbuf);
937 return NULL;
938 }
939 outbuf[i] = inbuf[i];
940 }
941 result = Tcl_NewUnicodeObj(outbuf, size);
942 ckfree(FREECAST outbuf);
943 return result;
944#else
945 return Tcl_NewUnicodeObj(inbuf, size);
946#endif
947
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000948 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000949#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000950 else if(PyTclObject_Check(value)) {
951 Tcl_Obj *v = ((PyTclObject*)value)->value;
952 Tcl_IncrRefCount(v);
953 return v;
954 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000955 else {
956 PyObject *v = PyObject_Str(value);
957 if (!v)
958 return 0;
959 result = AsObj(v);
960 Py_DECREF(v);
961 return result;
962 }
963}
964
Martin v. Löwisffad6332002-11-26 09:28:05 +0000965static PyObject*
966FromObj(PyObject* tkapp, Tcl_Obj *value)
967{
968 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000969 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000970
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000971 if (value->typePtr == NULL) {
972 /* If the result contains any bytes with the top bit set,
973 it's UTF-8 and we should decode it to Unicode */
974#ifdef Py_USING_UNICODE
975 int i;
976 char *s = value->bytes;
977 int len = value->length;
978 for (i = 0; i < len; i++) {
979 if (value->bytes[i] & 0x80)
980 break;
981 }
982
983 if (i == value->length)
984 result = PyString_FromStringAndSize(s, len);
985 else {
986 /* Convert UTF-8 to Unicode string */
987 result = PyUnicode_DecodeUTF8(s, len, "strict");
988 if (result == NULL) {
989 PyErr_Clear();
990 result = PyString_FromStringAndSize(s, len);
991 }
992 }
993#else
994 res = PyString_FromStringAndSize(value->bytes, value->length);
995#endif
996 return result;
997 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000999 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001000 result = value->internalRep.longValue ? Py_True : Py_False;
1001 Py_INCREF(result);
1002 return result;
1003 }
1004
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001005 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001006 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001007 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008 return PyString_FromStringAndSize(data, size);
1009 }
1010
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001011 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001012 return PyFloat_FromDouble(value->internalRep.doubleValue);
1013 }
1014
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001015 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016 return PyInt_FromLong(value->internalRep.longValue);
1017 }
1018
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001019 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001020 int size;
1021 int i, status;
1022 PyObject *elem;
1023 Tcl_Obj *tcl_elem;
1024
1025 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1026 if (status == TCL_ERROR)
1027 return Tkinter_Error(tkapp);
1028 result = PyTuple_New(size);
1029 if (!result)
1030 return NULL;
1031 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001032 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033 value, i, &tcl_elem);
1034 if (status == TCL_ERROR) {
1035 Py_DECREF(result);
1036 return Tkinter_Error(tkapp);
1037 }
1038 elem = FromObj(tkapp, tcl_elem);
1039 if (!elem) {
1040 Py_DECREF(result);
1041 return NULL;
1042 }
1043 PyTuple_SetItem(result, i, elem);
1044 }
1045 return result;
1046 }
1047
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001048 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001049 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050 }
1051
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001052 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001053#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001054#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055 PyObject *result;
1056 int size;
1057 Tcl_UniChar *input;
1058 Py_UNICODE *output;
1059
1060 size = Tcl_GetCharLength(value);
1061 result = PyUnicode_FromUnicode(NULL, size);
1062 if (!result)
1063 return NULL;
1064 input = Tcl_GetUnicode(value);
1065 output = PyUnicode_AS_UNICODE(result);
1066 while (size--)
1067 *output++ = *input++;
1068 return result;
1069#else
1070 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1071 Tcl_GetCharLength(value));
1072#endif
1073#else
1074 int size;
1075 char *c;
1076 c = Tcl_GetStringFromObj(value, &size);
1077 return PyString_FromStringAndSize(c, size);
1078#endif
1079 }
1080
1081 return newPyTclObject(value);
1082}
1083
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084/* This mutex synchronizes inter-thread command calls. */
1085
1086TCL_DECLARE_MUTEX(call_mutex)
1087
1088typedef struct Tkapp_CallEvent {
1089 Tcl_Event ev; /* Must be first */
1090 TkappObject *self;
1091 PyObject *args;
1092 int flags;
1093 PyObject **res;
1094 PyObject **exc_type, **exc_value, **exc_tb;
1095 Tcl_Condition done;
1096} Tkapp_CallEvent;
1097
1098void
1099Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001100{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001101 int i;
1102 for (i = 0; i < objc; i++)
1103 Tcl_DecrRefCount(objv[i]);
1104 if (objv != objStore)
1105 ckfree(FREECAST objv);
1106}
Guido van Rossum18468821994-06-20 07:49:28 +00001107
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001108/* Convert Python objects to Tcl objects. This must happen in the
1109 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001110
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001111static Tcl_Obj**
1112Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1113{
1114 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001115 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001116 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001117 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001118
Guido van Rossum212643f1998-04-29 16:22:14 +00001119 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001120 objv[0] = AsObj(args);
1121 if (objv[0] == 0)
1122 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001123 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001124 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001125 }
1126 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001127 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001128
Guido van Rossum632de272000-03-29 00:19:50 +00001129 if (objc > ARGSZ) {
1130 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1131 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001132 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001133 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001134 goto finally;
1135 }
1136 }
1137
Guido van Rossum632de272000-03-29 00:19:50 +00001138 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001139 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001140 if (v == Py_None) {
1141 objc = i;
1142 break;
1143 }
Guido van Rossum632de272000-03-29 00:19:50 +00001144 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001145 if (!objv[i]) {
1146 /* Reset objc, so it attempts to clear
1147 objects only up to i. */
1148 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001149 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001150 }
Guido van Rossum632de272000-03-29 00:19:50 +00001151 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001152 }
1153 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154 *pobjc = objc;
1155 return objv;
1156finally:
1157 Tkapp_CallDeallocArgs(objv, objStore, objc);
1158 return NULL;
1159}
Guido van Rossum212643f1998-04-29 16:22:14 +00001160
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001161/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001162
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163static PyObject*
1164Tkapp_CallResult(TkappObject *self)
1165{
1166 PyObject *res = NULL;
1167 if(self->wantobjects) {
1168 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001169 /* Not sure whether the IncrRef is necessary, but something
1170 may overwrite the interpreter result while we are
1171 converting it. */
1172 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001174 Tcl_DecrRefCount(value);
1175 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001176 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001177 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001178
Guido van Rossum990f5c62000-05-04 15:07:16 +00001179 /* If the result contains any bytes with the top bit set,
1180 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001181#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001182 while (*p != '\0') {
1183 if (*p & 0x80)
1184 break;
1185 p++;
1186 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001187
Guido van Rossum990f5c62000-05-04 15:07:16 +00001188 if (*p == '\0')
1189 res = PyString_FromStringAndSize(s, (int)(p-s));
1190 else {
1191 /* Convert UTF-8 to Unicode string */
1192 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001193 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1194 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001195 PyErr_Clear();
1196 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001197 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001198 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001199#else
1200 p = strchr(p, '\0');
1201 res = PyString_FromStringAndSize(s, (int)(p-s));
1202#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001203 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001204 return res;
1205}
Guido van Rossum632de272000-03-29 00:19:50 +00001206
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001207/* Tkapp_CallProc is the event procedure that is executed in the context of
1208 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1209 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001210
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211static int
1212Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1213{
1214 Tcl_Obj *objStore[ARGSZ];
1215 Tcl_Obj **objv;
1216 int objc;
1217 int i;
1218 ENTER_PYTHON
1219 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1220 if (!objv) {
1221 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1222 *(e->res) = NULL;
1223 }
1224 LEAVE_PYTHON
1225 if (!objv)
1226 goto done;
1227 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1228 ENTER_PYTHON
1229 if (i == TCL_ERROR) {
1230 *(e->res) = NULL;
1231 *(e->exc_type) = NULL;
1232 *(e->exc_tb) = NULL;
1233 *(e->exc_value) = PyObject_CallFunction(
1234 Tkinter_TclError, "s",
1235 Tcl_GetStringResult(e->self->interp));
1236 }
1237 else {
1238 *(e->res) = Tkapp_CallResult(e->self);
1239 }
1240 LEAVE_PYTHON
1241 done:
1242 /* Wake up calling thread. */
1243 Tcl_MutexLock(&call_mutex);
1244 Tcl_ConditionNotify(&e->done);
1245 Tcl_MutexUnlock(&call_mutex);
1246 return 1;
1247}
1248
1249/* This is the main entry point for calling a Tcl command.
1250 It supports three cases, with regard to threading:
1251 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1252 the context of the calling thread.
1253 2. Tcl is threaded, caller of the command is in the interpreter thread:
1254 Execute the command in the calling thread. Since the Tcl lock will
1255 not be used, we can merge that with case 1.
1256 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1257 the interpreter thread. Allocation of Tcl objects needs to occur in the
1258 interpreter thread, so we ship the PyObject* args to the target thread,
1259 and perform processing there. */
1260
1261static PyObject *
1262Tkapp_Call(PyObject *_self, PyObject *args)
1263{
1264 Tcl_Obj *objStore[ARGSZ];
1265 Tcl_Obj **objv = NULL;
1266 int objc, i;
1267 PyObject *res = NULL;
1268 TkappObject *self = (TkappObject*)_self;
1269 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1270 int flags = TCL_EVAL_DIRECT;
1271
Martin v. Löwisa9656492003-03-30 08:44:58 +00001272#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001273 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1274 /* We cannot call the command directly. Instead, we must
1275 marshal the parameters to the interpreter thread. */
1276 Tkapp_CallEvent *ev;
1277 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001278 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001280 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1281 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1282 ev->self = self;
1283 ev->args = args;
1284 ev->res = &res;
1285 ev->exc_type = &exc_type;
1286 ev->exc_value = &exc_value;
1287 ev->exc_tb = &exc_tb;
1288 ev->done = (Tcl_Condition)0;
1289
1290 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1291
1292 if (res == NULL) {
1293 if (exc_type)
1294 PyErr_Restore(exc_type, exc_value, exc_tb);
1295 else
1296 PyErr_SetObject(Tkinter_TclError, exc_value);
1297 }
1298 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001299 else
1300#endif
1301 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302
1303 objv = Tkapp_CallArgs(args, objStore, &objc);
1304 if (!objv)
1305 return NULL;
1306
1307 ENTER_TCL
1308
1309 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1310
1311 ENTER_OVERLAP
1312
1313 if (i == TCL_ERROR)
1314 Tkinter_Error(_self);
1315 else
1316 res = Tkapp_CallResult(self);
1317
1318 LEAVE_OVERLAP_TCL
1319
1320 Tkapp_CallDeallocArgs(objv, objStore, objc);
1321 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001322 return res;
1323}
1324
1325
1326static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001327Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001328{
Guido van Rossum212643f1998-04-29 16:22:14 +00001329 /* Could do the same here as for Tkapp_Call(), but this is not used
1330 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1331 way for the user to do what all its Global* variants do (save and
1332 reset the scope pointer, call the local version, restore the saved
1333 scope pointer). */
1334
Guido van Rossum62320c91998-06-15 04:36:09 +00001335 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001336 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001337
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338 CHECK_TCL_APPARTMENT;
1339
Guido van Rossum62320c91998-06-15 04:36:09 +00001340 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001341 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001342 int err;
1343 ENTER_TCL
1344 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001345 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001346 if (err == TCL_ERROR)
1347 res = Tkinter_Error(self);
1348 else
1349 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001350 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001351 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001352 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001353
1354 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001355}
1356
1357static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001358Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001359{
Barry Warsawfa701a81997-01-16 00:15:11 +00001360 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001361 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001362 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001363
Guido van Rossum43713e52000-02-29 13:59:29 +00001364 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001365 return NULL;
1366
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001367 CHECK_TCL_APPARTMENT;
1368
Guido van Rossum00d93061998-05-28 23:06:38 +00001369 ENTER_TCL
1370 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001371 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001372 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 res = Tkinter_Error(self);
1374 else
1375 res = PyString_FromString(Tkapp_Result(self));
1376 LEAVE_OVERLAP_TCL
1377 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001378}
1379
1380static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001381Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001382{
Barry Warsawfa701a81997-01-16 00:15:11 +00001383 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001384 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001385 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001386
Guido van Rossum43713e52000-02-29 13:59:29 +00001387 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001388 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001389
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390 CHECK_TCL_APPARTMENT;
1391
Guido van Rossum00d93061998-05-28 23:06:38 +00001392 ENTER_TCL
1393 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001394 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001395 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 res = Tkinter_Error(self);
1397 else
1398 res = PyString_FromString(Tkapp_Result(self));
1399 LEAVE_OVERLAP_TCL
1400 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001401}
1402
1403static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001404Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001405{
Barry Warsawfa701a81997-01-16 00:15:11 +00001406 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001407 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001408 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001409
Guido van Rossum43713e52000-02-29 13:59:29 +00001410 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001411 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001412
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413 CHECK_TCL_APPARTMENT;
1414
Guido van Rossum00d93061998-05-28 23:06:38 +00001415 ENTER_TCL
1416 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001417 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001418 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001419 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001420
Guido van Rossum62320c91998-06-15 04:36:09 +00001421 else
1422 res = PyString_FromString(Tkapp_Result(self));
1423 LEAVE_OVERLAP_TCL
1424 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001425}
1426
1427static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001428Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001429{
Barry Warsawfa701a81997-01-16 00:15:11 +00001430 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001431 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001432 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001433
Guido van Rossum35d43371997-08-02 00:09:09 +00001434 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001435 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001436
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001437 CHECK_TCL_APPARTMENT;
1438
Guido van Rossum00d93061998-05-28 23:06:38 +00001439 ENTER_TCL
1440 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001441 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001442 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001443 res = Tkinter_Error(self);
1444 else
1445 res = PyString_FromString(Tkapp_Result(self));
1446 LEAVE_OVERLAP_TCL
1447 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001448}
1449
1450static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001451Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001452{
Barry Warsawfa701a81997-01-16 00:15:11 +00001453 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001454
Guido van Rossum43713e52000-02-29 13:59:29 +00001455 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001456 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457 CHECK_TCL_APPARTMENT;
1458
Guido van Rossum00d93061998-05-28 23:06:38 +00001459 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001460 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001461 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001462
Barry Warsawfa701a81997-01-16 00:15:11 +00001463 Py_INCREF(Py_None);
1464 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001465}
1466
Barry Warsawfa701a81997-01-16 00:15:11 +00001467
1468
Guido van Rossum18468821994-06-20 07:49:28 +00001469/** Tcl Variable **/
1470
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471TCL_DECLARE_MUTEX(var_mutex)
1472
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001473typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001474typedef struct VarEvent {
1475 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001476 PyObject *self;
1477 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001478 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001479 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001481 PyObject **exc_type;
1482 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484} VarEvent;
1485
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001486static int
1487varname_converter(PyObject *in, void *_out)
1488{
1489 char **out = (char**)_out;
1490 if (PyString_Check(in)) {
1491 *out = PyString_AsString(in);
1492 return 1;
1493 }
1494 if (PyTclObject_Check(in)) {
1495 *out = PyTclObject_TclString(in);
1496 return 1;
1497 }
1498 /* XXX: Should give diagnostics. */
1499 return 0;
1500}
1501
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001502void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503var_perform(VarEvent *ev)
1504{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001505 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1506 if (!*(ev->res)) {
1507 PyObject *exc, *val, *tb;
1508 PyErr_Fetch(&exc, &val, &tb);
1509 PyErr_NormalizeException(&exc, &val, &tb);
1510 *(ev->exc_type) = exc;
1511 *(ev->exc_val) = val;
1512 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001514
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515}
1516
1517static int
1518var_proc(VarEvent* ev, int flags)
1519{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001521 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001522 Tcl_MutexLock(&var_mutex);
1523 Tcl_ConditionNotify(&ev->cond);
1524 Tcl_MutexUnlock(&var_mutex);
1525 LEAVE_PYTHON
1526 return 1;
1527}
1528
1529static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001530var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001531{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001533#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001535 TkappObject *self = (TkappObject*)_self;
1536 VarEvent *ev;
1537 PyObject *res, *exc_type, *exc_val;
1538
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001539 /* The current thread is not the interpreter thread. Marshal
1540 the call to the interpreter thread, then wait for
1541 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001542 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001543 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001544
1545 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1546
1547 ev->self = _self;
1548 ev->args = args;
1549 ev->flags = flags;
1550 ev->func = func;
1551 ev->res = &res;
1552 ev->exc_type = &exc_type;
1553 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554 ev->cond = NULL;
1555 ev->ev.proc = (Tcl_EventProc*)var_proc;
1556 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001557 if (!res) {
1558 PyErr_SetObject(exc_type, exc_val);
1559 Py_DECREF(exc_type);
1560 Py_DECREF(exc_val);
1561 return NULL;
1562 }
1563 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001564 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001565#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001566 /* Tcl is not threaded, or this is the interpreter thread. */
1567 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001568}
1569
Guido van Rossum18468821994-06-20 07:49:28 +00001570static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001571SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001572{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001573 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001574 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001575 PyObject *res = NULL;
1576 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001577
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001578 if (PyArg_ParseTuple(args, "O&O:setvar",
1579 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001580 /* XXX Acquire tcl lock??? */
1581 newval = AsObj(newValue);
1582 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001583 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001584 ENTER_TCL
1585 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1586 newval, flags);
1587 ENTER_OVERLAP
1588 if (!ok)
1589 Tkinter_Error(self);
1590 else {
1591 res = Py_None;
1592 Py_INCREF(res);
1593 }
1594 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001595 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001597 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001598 if (PyArg_ParseTuple(args, "ssO:setvar",
1599 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001600 /* XXX must hold tcl lock already??? */
1601 newval = AsObj(newValue);
1602 ENTER_TCL
1603 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1604 ENTER_OVERLAP
1605 if (!ok)
1606 Tkinter_Error(self);
1607 else {
1608 res = Py_None;
1609 Py_INCREF(res);
1610 }
1611 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001612 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001613 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001614 return NULL;
1615 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001616 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001617 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001618}
1619
1620static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001621Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001622{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001623 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001624}
1625
1626static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001627Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001628{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001629 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001630}
1631
Barry Warsawfa701a81997-01-16 00:15:11 +00001632
1633
Guido van Rossum18468821994-06-20 07:49:28 +00001634static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001635GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001636{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001637 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001638 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001639 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001640
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001641 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1642 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001643 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001645 ENTER_TCL
1646 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1647 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001648 if (tres == NULL) {
1649 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1650 } else {
1651 if (((TkappObject*)self)->wantobjects) {
1652 res = FromObj(self, tres);
1653 }
1654 else {
1655 res = PyString_FromString(Tcl_GetString(tres));
1656 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001657 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001658 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001659 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001660}
1661
1662static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001663Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001664{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001665 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001666}
1667
1668static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001669Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001670{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001671 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001672}
1673
Barry Warsawfa701a81997-01-16 00:15:11 +00001674
1675
Guido van Rossum18468821994-06-20 07:49:28 +00001676static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001677UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001678{
Guido van Rossum35d43371997-08-02 00:09:09 +00001679 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001680 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001681 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001682
Guido van Rossum43713e52000-02-29 13:59:29 +00001683 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001684 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001685
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001686 ENTER_TCL
1687 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1688 ENTER_OVERLAP
1689 if (code == TCL_ERROR)
1690 res = Tkinter_Error(self);
1691 else {
1692 Py_INCREF(Py_None);
1693 res = Py_None;
1694 }
1695 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001696 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001697}
1698
1699static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001700Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001701{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001702 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001703}
1704
1705static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001706Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001707{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001708 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
Barry Warsawfa701a81997-01-16 00:15:11 +00001711
1712
Guido van Rossum18468821994-06-20 07:49:28 +00001713/** Tcl to Python **/
1714
1715static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001716Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001717{
Barry Warsawfa701a81997-01-16 00:15:11 +00001718 char *s;
1719 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001720
Martin v. Löwisffad6332002-11-26 09:28:05 +00001721 if (PyTuple_Size(args) == 1) {
1722 PyObject* o = PyTuple_GetItem(args, 0);
1723 if (PyInt_Check(o)) {
1724 Py_INCREF(o);
1725 return o;
1726 }
1727 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001728 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001729 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001730 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 return Tkinter_Error(self);
1732 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
1735static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001736Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001737{
Barry Warsawfa701a81997-01-16 00:15:11 +00001738 char *s;
1739 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001740
Martin v. Löwisffad6332002-11-26 09:28:05 +00001741 if (PyTuple_Size(args) == 1) {
1742 PyObject *o = PyTuple_GetItem(args, 0);
1743 if (PyFloat_Check(o)) {
1744 Py_INCREF(o);
1745 return o;
1746 }
1747 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001748 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001749 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001750 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001751 return Tkinter_Error(self);
1752 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001753}
1754
1755static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001756Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001757{
Barry Warsawfa701a81997-01-16 00:15:11 +00001758 char *s;
1759 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001760
Martin v. Löwisffad6332002-11-26 09:28:05 +00001761 if (PyTuple_Size(args) == 1) {
1762 PyObject *o = PyTuple_GetItem(args, 0);
1763 if (PyInt_Check(o)) {
1764 Py_INCREF(o);
1765 return o;
1766 }
1767 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001768 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001769 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001770 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1771 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001772 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001773}
1774
1775static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001776Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001777{
Barry Warsawfa701a81997-01-16 00:15:11 +00001778 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001779 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001780 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001781
Guido van Rossum43713e52000-02-29 13:59:29 +00001782 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001783 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001784
1785 CHECK_TCL_APPARTMENT;
1786
Guido van Rossum00d93061998-05-28 23:06:38 +00001787 ENTER_TCL
1788 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001789 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001790 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001791 res = Tkinter_Error(self);
1792 else
1793 res = Py_BuildValue("s", Tkapp_Result(self));
1794 LEAVE_OVERLAP_TCL
1795 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001796}
1797
1798static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001799Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001800{
Barry Warsawfa701a81997-01-16 00:15:11 +00001801 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001802 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001803 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001804 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001805
Guido van Rossum43713e52000-02-29 13:59:29 +00001806 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001807 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001808
1809 CHECK_TCL_APPARTMENT;
1810
Guido van Rossum00d93061998-05-28 23:06:38 +00001811 ENTER_TCL
1812 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001813 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001814 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001815 res = Tkinter_Error(self);
1816 else
1817 res = Py_BuildValue("l", v);
1818 LEAVE_OVERLAP_TCL
1819 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001820}
1821
1822static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001823Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Barry Warsawfa701a81997-01-16 00:15:11 +00001825 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001826 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001827 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001828 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001829
Guido van Rossum43713e52000-02-29 13:59:29 +00001830 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001831 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001832 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001833 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001834 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001835 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001836 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001837 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001838 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001839 res = Tkinter_Error(self);
1840 else
1841 res = Py_BuildValue("d", v);
1842 LEAVE_OVERLAP_TCL
1843 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001844}
1845
1846static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001847Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001848{
Barry Warsawfa701a81997-01-16 00:15:11 +00001849 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001850 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001851 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001852 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001853
Guido van Rossum43713e52000-02-29 13:59:29 +00001854 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001855 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001856 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001857 ENTER_TCL
1858 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001859 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001860 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001861 res = Tkinter_Error(self);
1862 else
1863 res = Py_BuildValue("i", v);
1864 LEAVE_OVERLAP_TCL
1865 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001866}
1867
Barry Warsawfa701a81997-01-16 00:15:11 +00001868
1869
Guido van Rossum18468821994-06-20 07:49:28 +00001870static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001871Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001872{
Barry Warsawfa701a81997-01-16 00:15:11 +00001873 char *list;
1874 int argc;
1875 char **argv;
1876 PyObject *v;
1877 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001878
Martin v. Löwisffad6332002-11-26 09:28:05 +00001879 if (PyTuple_Size(args) == 1) {
1880 v = PyTuple_GetItem(args, 0);
1881 if (PyTuple_Check(v)) {
1882 Py_INCREF(v);
1883 return v;
1884 }
1885 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001886 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001887 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001888
Neal Norwitzd1c55102003-05-29 00:17:03 +00001889 if (Tcl_SplitList(Tkapp_Interp(self), list,
1890 &argc, &argv) == TCL_ERROR) {
1891 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001892 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001893 }
Guido van Rossum18468821994-06-20 07:49:28 +00001894
Barry Warsawfa701a81997-01-16 00:15:11 +00001895 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001896 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001897
Barry Warsawfa701a81997-01-16 00:15:11 +00001898 for (i = 0; i < argc; i++) {
1899 PyObject *s = PyString_FromString(argv[i]);
1900 if (!s || PyTuple_SetItem(v, i, s)) {
1901 Py_DECREF(v);
1902 v = NULL;
1903 goto finally;
1904 }
1905 }
Guido van Rossum18468821994-06-20 07:49:28 +00001906
Barry Warsawfa701a81997-01-16 00:15:11 +00001907 finally:
1908 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001909 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001910 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001911}
1912
1913static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001914Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001915{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001916 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001917 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001918
Martin v. Löwisffad6332002-11-26 09:28:05 +00001919 if (PyTuple_Size(args) == 1) {
1920 PyObject* o = PyTuple_GetItem(args, 0);
1921 if (PyTuple_Check(o)) {
1922 o = SplitObj(o);
1923 return o;
1924 }
1925 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001926 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001927 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001928 v = Split(list);
1929 PyMem_Free(list);
1930 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001931}
1932
1933static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001934Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001935{
Barry Warsawfa701a81997-01-16 00:15:11 +00001936 char *s = Merge(args);
1937 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001938
Barry Warsawfa701a81997-01-16 00:15:11 +00001939 if (s) {
1940 res = PyString_FromString(s);
1941 ckfree(s);
1942 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001943
1944 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001945}
1946
Barry Warsawfa701a81997-01-16 00:15:11 +00001947
1948
Guido van Rossum18468821994-06-20 07:49:28 +00001949/** Tcl Command **/
1950
Guido van Rossum00d93061998-05-28 23:06:38 +00001951/* Client data struct */
1952typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001953 PyObject *self;
1954 PyObject *func;
1955} PythonCmd_ClientData;
1956
1957static int
Fred Drake509d79a2000-07-08 04:04:38 +00001958PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001959{
1960 errorInCmd = 1;
1961 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1962 LEAVE_PYTHON
1963 return TCL_ERROR;
1964}
1965
Guido van Rossum18468821994-06-20 07:49:28 +00001966/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001967 * function or method.
1968 */
Guido van Rossum18468821994-06-20 07:49:28 +00001969static int
Fred Drake509d79a2000-07-08 04:04:38 +00001970PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001971{
Guido van Rossum00d93061998-05-28 23:06:38 +00001972 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001973 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001974 int i, rv;
1975 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001976
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001977 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001978
Barry Warsawfa701a81997-01-16 00:15:11 +00001979 /* TBD: no error checking here since we know, via the
1980 * Tkapp_CreateCommand() that the client data is a two-tuple
1981 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001982 self = data->self;
1983 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Barry Warsawfa701a81997-01-16 00:15:11 +00001985 /* Create argument list (argv1, ..., argvN) */
1986 if (!(arg = PyTuple_New(argc - 1)))
1987 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001988
Barry Warsawfa701a81997-01-16 00:15:11 +00001989 for (i = 0; i < (argc - 1); i++) {
1990 PyObject *s = PyString_FromString(argv[i + 1]);
1991 if (!s || PyTuple_SetItem(arg, i, s)) {
1992 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001993 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001994 }
1995 }
1996 res = PyEval_CallObject(func, arg);
1997 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001998
Barry Warsawfa701a81997-01-16 00:15:11 +00001999 if (res == NULL)
2000 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002001
Barry Warsawfa701a81997-01-16 00:15:11 +00002002 if (!(tmp = PyList_New(0))) {
2003 Py_DECREF(res);
2004 return PythonCmd_Error(interp);
2005 }
2006
Guido van Rossum2834b972000-10-06 16:58:26 +00002007 s = AsString(res, tmp);
2008 if (s == NULL) {
2009 rv = PythonCmd_Error(interp);
2010 }
2011 else {
2012 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2013 rv = TCL_OK;
2014 }
2015
Barry Warsawfa701a81997-01-16 00:15:11 +00002016 Py_DECREF(res);
2017 Py_DECREF(tmp);
2018
Guido van Rossum00d93061998-05-28 23:06:38 +00002019 LEAVE_PYTHON
2020
Guido van Rossum2834b972000-10-06 16:58:26 +00002021 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002022}
2023
2024static void
Fred Drake509d79a2000-07-08 04:04:38 +00002025PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002026{
Guido van Rossum00d93061998-05-28 23:06:38 +00002027 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2028
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002029 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002030 Py_XDECREF(data->self);
2031 Py_XDECREF(data->func);
2032 PyMem_DEL(data);
2033 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002034}
2035
Barry Warsawfa701a81997-01-16 00:15:11 +00002036
2037
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002038
2039TCL_DECLARE_MUTEX(command_mutex)
2040
2041typedef struct CommandEvent{
2042 Tcl_Event ev;
2043 Tcl_Interp* interp;
2044 char *name;
2045 int create;
2046 int *status;
2047 ClientData *data;
2048 Tcl_Condition done;
2049} CommandEvent;
2050
2051static int
2052Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002053{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054 if (ev->create)
2055 *ev->status = Tcl_CreateCommand(
2056 ev->interp, ev->name, PythonCmd,
2057 ev->data, PythonCmdDelete) == NULL;
2058 else
2059 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2060 Tcl_MutexLock(&command_mutex);
2061 Tcl_ConditionNotify(&ev->done);
2062 Tcl_MutexUnlock(&command_mutex);
2063 return 1;
2064}
2065
2066static PyObject *
2067Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2068{
2069 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002070 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002071 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002072 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002073 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002074
Guido van Rossum43713e52000-02-29 13:59:29 +00002075 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002076 return NULL;
2077 if (!PyCallable_Check(func)) {
2078 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002079 return NULL;
2080 }
Guido van Rossum18468821994-06-20 07:49:28 +00002081
Martin v. Löwisa9656492003-03-30 08:44:58 +00002082#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002083 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002084 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002085 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002086#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002087
Guido van Rossum00d93061998-05-28 23:06:38 +00002088 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002089 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002090 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002091 Py_XINCREF(self);
2092 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002093 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002094 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002095
2096 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2097 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2098 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2099 ev->interp = self->interp;
2100 ev->create = 1;
2101 ev->name = cmdName;
2102 ev->data = (ClientData)data;
2103 ev->status = &err;
2104 ev->done = NULL;
2105 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2106 }
2107 else {
2108 ENTER_TCL
2109 err = Tcl_CreateCommand(
2110 Tkapp_Interp(self), cmdName, PythonCmd,
2111 (ClientData)data, PythonCmdDelete) == NULL;
2112 LEAVE_TCL
2113 }
2114 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002115 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002116 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002117 return NULL;
2118 }
Guido van Rossum18468821994-06-20 07:49:28 +00002119
Barry Warsawfa701a81997-01-16 00:15:11 +00002120 Py_INCREF(Py_None);
2121 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002122}
2123
Barry Warsawfa701a81997-01-16 00:15:11 +00002124
2125
Guido van Rossum18468821994-06-20 07:49:28 +00002126static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002127Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002128{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002129 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002130 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002131 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002132
Guido van Rossum43713e52000-02-29 13:59:29 +00002133 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002134 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002135 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2136 CommandEvent *ev;
2137 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2138 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2139 ev->interp = self->interp;
2140 ev->create = 0;
2141 ev->name = cmdName;
2142 ev->status = &err;
2143 ev->done = NULL;
2144 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2145 &command_mutex);
2146 }
2147 else {
2148 ENTER_TCL
2149 err = Tcl_DeleteCommand(self->interp, cmdName);
2150 LEAVE_TCL
2151 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002152 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002153 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2154 return NULL;
2155 }
2156 Py_INCREF(Py_None);
2157 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002158}
2159
Barry Warsawfa701a81997-01-16 00:15:11 +00002160
2161
Guido van Rossum00d93061998-05-28 23:06:38 +00002162#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002163/** File Handler **/
2164
Guido van Rossum00d93061998-05-28 23:06:38 +00002165typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002166 PyObject *func;
2167 PyObject *file;
2168 int id;
2169 struct _fhcdata *next;
2170} FileHandler_ClientData;
2171
2172static FileHandler_ClientData *HeadFHCD;
2173
2174static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002175NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002176{
2177 FileHandler_ClientData *p;
2178 p = PyMem_NEW(FileHandler_ClientData, 1);
2179 if (p != NULL) {
2180 Py_XINCREF(func);
2181 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002182 p->func = func;
2183 p->file = file;
2184 p->id = id;
2185 p->next = HeadFHCD;
2186 HeadFHCD = p;
2187 }
2188 return p;
2189}
2190
2191static void
Fred Drake509d79a2000-07-08 04:04:38 +00002192DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002193{
2194 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002195
2196 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002197 while ((p = *pp) != NULL) {
2198 if (p->id == id) {
2199 *pp = p->next;
2200 Py_XDECREF(p->func);
2201 Py_XDECREF(p->file);
2202 PyMem_DEL(p);
2203 }
2204 else
2205 pp = &p->next;
2206 }
2207}
2208
Guido van Rossuma597dde1995-01-10 20:56:29 +00002209static void
Fred Drake509d79a2000-07-08 04:04:38 +00002210FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002211{
Guido van Rossum00d93061998-05-28 23:06:38 +00002212 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002213 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002214
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002215 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002216 func = data->func;
2217 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002218
Barry Warsawfa701a81997-01-16 00:15:11 +00002219 arg = Py_BuildValue("(Oi)", file, (long) mask);
2220 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002221 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002222
2223 if (res == NULL) {
2224 errorInCmd = 1;
2225 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2226 }
2227 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002228 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002229}
2230
Guido van Rossum18468821994-06-20 07:49:28 +00002231static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002232Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2233 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002234{
Guido van Rossum00d93061998-05-28 23:06:38 +00002235 FileHandler_ClientData *data;
2236 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002237 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002238
Guido van Rossum2834b972000-10-06 16:58:26 +00002239 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2240 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002242
Martin v. Löwisa9656492003-03-30 08:44:58 +00002243#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002244 if (!self && !tcl_lock) {
2245 /* We don't have the Tcl lock since Tcl is threaded. */
2246 PyErr_SetString(PyExc_RuntimeError,
2247 "_tkinter.createfilehandler not supported "
2248 "for threaded Tcl");
2249 return NULL;
2250 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002251#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002252
2253 if (self) {
2254 CHECK_TCL_APPARTMENT;
2255 }
2256
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002257 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002258 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002259 return NULL;
2260 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002261 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002262 return NULL;
2263 }
2264
Guido van Rossuma80649b2000-03-28 20:07:05 +00002265 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002266 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002267 return NULL;
2268
Barry Warsawfa701a81997-01-16 00:15:11 +00002269 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002270 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002271 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002272 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002273 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002275}
2276
2277static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002278Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002279{
Barry Warsawfa701a81997-01-16 00:15:11 +00002280 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002281 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002282
Guido van Rossum43713e52000-02-29 13:59:29 +00002283 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002285
Martin v. Löwisa9656492003-03-30 08:44:58 +00002286#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002287 if (!self && !tcl_lock) {
2288 /* We don't have the Tcl lock since Tcl is threaded. */
2289 PyErr_SetString(PyExc_RuntimeError,
2290 "_tkinter.deletefilehandler not supported "
2291 "for threaded Tcl");
2292 return NULL;
2293 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002294#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002295
2296 if (self) {
2297 CHECK_TCL_APPARTMENT;
2298 }
2299
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002300 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002301 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002302 return NULL;
2303
Guido van Rossuma80649b2000-03-28 20:07:05 +00002304 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002305
Barry Warsawfa701a81997-01-16 00:15:11 +00002306 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002307 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002308 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002310 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002311 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002312}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002313#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002314
Barry Warsawfa701a81997-01-16 00:15:11 +00002315
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316/**** Tktt Object (timer token) ****/
2317
Jeremy Hylton938ace62002-07-17 16:30:39 +00002318static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002319
Guido van Rossum00d93061998-05-28 23:06:38 +00002320typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002321 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002322 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002324} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002325
2326static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002327Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328{
Barry Warsawfa701a81997-01-16 00:15:11 +00002329 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002330 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331
Guido van Rossum43713e52000-02-29 13:59:29 +00002332 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002333 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002334 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002335 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002336 v->token = NULL;
2337 }
2338 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002339 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002340 Py_DECREF(func);
2341 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002342 }
2343 Py_INCREF(Py_None);
2344 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345}
2346
2347static PyMethodDef Tktt_methods[] =
2348{
Neal Norwitzb0493252002-03-31 14:44:22 +00002349 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002350 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351};
2352
2353static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002354Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355{
Barry Warsawfa701a81997-01-16 00:15:11 +00002356 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357
Guido van Rossumb18618d2000-05-03 23:44:39 +00002358 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002359 if (v == NULL)
2360 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002361
Guido van Rossum00d93061998-05-28 23:06:38 +00002362 Py_INCREF(func);
2363 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002364 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002365
2366 /* Extra reference, deleted when called or when handler is deleted */
2367 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002368 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002369}
2370
2371static void
Fred Drake509d79a2000-07-08 04:04:38 +00002372Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373{
Guido van Rossum00d93061998-05-28 23:06:38 +00002374 TkttObject *v = (TkttObject *)self;
2375 PyObject *func = v->func;
2376
2377 Py_XDECREF(func);
2378
Guido van Rossumb18618d2000-05-03 23:44:39 +00002379 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002380}
2381
Guido van Rossum597ac201998-05-12 14:36:19 +00002382static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002383Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384{
Barry Warsawfa701a81997-01-16 00:15:11 +00002385 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002386 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002387
Tim Peters885d4572001-11-28 20:27:42 +00002388 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002389 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002390 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002391}
2392
2393static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002394Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395{
Barry Warsawfa701a81997-01-16 00:15:11 +00002396 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397}
2398
2399static PyTypeObject Tktt_Type =
2400{
Guido van Rossum35d43371997-08-02 00:09:09 +00002401 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002402 0, /*ob_size */
2403 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002404 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002405 0, /*tp_itemsize */
2406 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002407 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002408 Tktt_GetAttr, /*tp_getattr */
2409 0, /*tp_setattr */
2410 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002411 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002412 0, /*tp_as_number */
2413 0, /*tp_as_sequence */
2414 0, /*tp_as_mapping */
2415 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002416};
2417
Barry Warsawfa701a81997-01-16 00:15:11 +00002418
2419
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002420/** Timer Handler **/
2421
2422static void
Fred Drake509d79a2000-07-08 04:04:38 +00002423TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002424{
Guido van Rossum00d93061998-05-28 23:06:38 +00002425 TkttObject *v = (TkttObject *)clientData;
2426 PyObject *func = v->func;
2427 PyObject *res;
2428
2429 if (func == NULL)
2430 return;
2431
2432 v->func = NULL;
2433
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002434 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002435
2436 res = PyEval_CallObject(func, NULL);
2437 Py_DECREF(func);
2438 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002439
Barry Warsawfa701a81997-01-16 00:15:11 +00002440 if (res == NULL) {
2441 errorInCmd = 1;
2442 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2443 }
2444 else
2445 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002446
2447 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002448}
2449
2450static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002451Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002452{
Barry Warsawfa701a81997-01-16 00:15:11 +00002453 int milliseconds;
2454 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002455 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002456
Guido van Rossum2834b972000-10-06 16:58:26 +00002457 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2458 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002459 return NULL;
2460 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002461 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002462 return NULL;
2463 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002464
Martin v. Löwisa9656492003-03-30 08:44:58 +00002465#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002466 if (!self && !tcl_lock) {
2467 /* We don't have the Tcl lock since Tcl is threaded. */
2468 PyErr_SetString(PyExc_RuntimeError,
2469 "_tkinter.createtimerhandler not supported "
2470 "for threaded Tcl");
2471 return NULL;
2472 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002473#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002474
2475 if (self) {
2476 CHECK_TCL_APPARTMENT;
2477 }
2478
Guido van Rossum00d93061998-05-28 23:06:38 +00002479 v = Tktt_New(func);
2480 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2481 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002482
Guido van Rossum00d93061998-05-28 23:06:38 +00002483 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002484}
2485
Barry Warsawfa701a81997-01-16 00:15:11 +00002486
Guido van Rossum18468821994-06-20 07:49:28 +00002487/** Event Loop **/
2488
Guido van Rossum18468821994-06-20 07:49:28 +00002489static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002490Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002491{
Barry Warsawfa701a81997-01-16 00:15:11 +00002492 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002493 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002494#ifdef WITH_THREAD
2495 PyThreadState *tstate = PyThreadState_Get();
2496#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002497
Guido van Rossum43713e52000-02-29 13:59:29 +00002498 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002499 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002500
Martin v. Löwisa9656492003-03-30 08:44:58 +00002501#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002502 if (!self && !tcl_lock) {
2503 /* We don't have the Tcl lock since Tcl is threaded. */
2504 PyErr_SetString(PyExc_RuntimeError,
2505 "_tkinter.mainloop not supported "
2506 "for threaded Tcl");
2507 return NULL;
2508 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002509#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002510
2511 if (self) {
2512 CHECK_TCL_APPARTMENT;
2513 self->dispatching = 1;
2514 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002515
Barry Warsawfa701a81997-01-16 00:15:11 +00002516 quitMainLoop = 0;
2517 while (Tk_GetNumMainWindows() > threshold &&
2518 !quitMainLoop &&
2519 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002520 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002521 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002522
2523#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002524 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002525 /* Allow other Python threads to run. */
2526 ENTER_TCL
2527 result = Tcl_DoOneEvent(0);
2528 LEAVE_TCL
2529 }
2530 else {
2531 Py_BEGIN_ALLOW_THREADS
2532 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2533 tcl_tstate = tstate;
2534 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2535 tcl_tstate = NULL;
2536 if(tcl_lock)PyThread_release_lock(tcl_lock);
2537 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002538 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002539 Py_END_ALLOW_THREADS
2540 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002541#else
2542 result = Tcl_DoOneEvent(0);
2543#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002544
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002545 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002546 if (self)
2547 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002548 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002549 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002550 if (result < 0)
2551 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002552 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002553 if (self)
2554 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002555 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002556
Barry Warsawfa701a81997-01-16 00:15:11 +00002557 if (errorInCmd) {
2558 errorInCmd = 0;
2559 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2560 excInCmd = valInCmd = trbInCmd = NULL;
2561 return NULL;
2562 }
2563 Py_INCREF(Py_None);
2564 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002565}
2566
2567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002568Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002569{
Guido van Rossum35d43371997-08-02 00:09:09 +00002570 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002571 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002572
Guido van Rossum43713e52000-02-29 13:59:29 +00002573 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002574 return NULL;
2575
Guido van Rossum00d93061998-05-28 23:06:38 +00002576 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002577 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002578 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002579 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002580}
2581
2582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002583Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002584{
2585
Guido van Rossum43713e52000-02-29 13:59:29 +00002586 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002587 return NULL;
2588
2589 quitMainLoop = 1;
2590 Py_INCREF(Py_None);
2591 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002592}
2593
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002594static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002595Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002596{
2597
Guido van Rossum43713e52000-02-29 13:59:29 +00002598 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002599 return NULL;
2600
2601 return PyInt_FromLong((long)Tkapp_Interp(self));
2602}
2603
David Aschere2b4b322004-02-18 05:59:53 +00002604static PyObject *
2605Tkapp_TkInit(PyObject *self, PyObject *args)
2606{
2607 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002608 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002609 const char * _tk_exists = NULL;
2610 PyObject *res = NULL;
2611 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002612 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002613
2614 /* We want to guard against calling Tk_Init() multiple times */
2615 CHECK_TCL_APPARTMENT;
2616 ENTER_TCL
2617 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2618 ENTER_OVERLAP
2619 if (err == TCL_ERROR) {
2620 res = Tkinter_Error(self);
2621 } else {
2622 _tk_exists = Tkapp_Result(self);
2623 }
2624 LEAVE_OVERLAP_TCL
2625 if (err == TCL_ERROR) {
2626 return NULL;
2627 }
2628 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2629 if (Tk_Init(interp) == TCL_ERROR) {
2630 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2631 return NULL;
2632 }
2633 }
2634 Py_INCREF(Py_None);
2635 return Py_None;
2636}
Barry Warsawfa701a81997-01-16 00:15:11 +00002637
Martin v. Löwisffad6332002-11-26 09:28:05 +00002638static PyObject *
2639Tkapp_WantObjects(PyObject *self, PyObject *args)
2640{
2641
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002642 int wantobjects = -1;
2643 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002644 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002645 if (wantobjects == -1)
2646 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002647 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002648
2649 Py_INCREF(Py_None);
2650 return Py_None;
2651}
2652
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002653static PyObject *
2654Tkapp_WillDispatch(PyObject *self, PyObject *args)
2655{
2656
2657 ((TkappObject*)self)->dispatching = 1;
2658
2659 Py_INCREF(Py_None);
2660 return Py_None;
2661}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002662
Barry Warsawfa701a81997-01-16 00:15:11 +00002663
Guido van Rossum18468821994-06-20 07:49:28 +00002664/**** Tkapp Method List ****/
2665
2666static PyMethodDef Tkapp_methods[] =
2667{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002668 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002669 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002670 {"call", Tkapp_Call, METH_OLDARGS},
2671 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2672 {"eval", Tkapp_Eval, METH_VARARGS},
2673 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2674 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2675 {"record", Tkapp_Record, METH_VARARGS},
2676 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2677 {"setvar", Tkapp_SetVar, METH_VARARGS},
2678 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2679 {"getvar", Tkapp_GetVar, METH_VARARGS},
2680 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2681 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2682 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2683 {"getint", Tkapp_GetInt, METH_VARARGS},
2684 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2685 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2686 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2687 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2688 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2689 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2690 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2691 {"split", Tkapp_Split, METH_VARARGS},
2692 {"merge", Tkapp_Merge, METH_OLDARGS},
2693 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2694 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002695#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002696 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2697 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002698#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002699 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2700 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2701 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2702 {"quit", Tkapp_Quit, METH_VARARGS},
2703 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002704 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002705 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002706};
2707
Barry Warsawfa701a81997-01-16 00:15:11 +00002708
2709
Guido van Rossum18468821994-06-20 07:49:28 +00002710/**** Tkapp Type Methods ****/
2711
2712static void
Fred Drake509d79a2000-07-08 04:04:38 +00002713Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002714{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002715 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002716 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002717 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002718 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002719 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002720 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002721}
2722
2723static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002724Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002725{
Guido van Rossum35d43371997-08-02 00:09:09 +00002726 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002727}
2728
2729static PyTypeObject Tkapp_Type =
2730{
Guido van Rossum35d43371997-08-02 00:09:09 +00002731 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002732 0, /*ob_size */
2733 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002734 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002735 0, /*tp_itemsize */
2736 Tkapp_Dealloc, /*tp_dealloc */
2737 0, /*tp_print */
2738 Tkapp_GetAttr, /*tp_getattr */
2739 0, /*tp_setattr */
2740 0, /*tp_compare */
2741 0, /*tp_repr */
2742 0, /*tp_as_number */
2743 0, /*tp_as_sequence */
2744 0, /*tp_as_mapping */
2745 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002746};
2747
Barry Warsawfa701a81997-01-16 00:15:11 +00002748
2749
Guido van Rossum18468821994-06-20 07:49:28 +00002750/**** Tkinter Module ****/
2751
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002752typedef struct {
2753 PyObject* tuple;
2754 int size; /* current size */
2755 int maxsize; /* allocated size */
2756} FlattenContext;
2757
2758static int
2759_bump(FlattenContext* context, int size)
2760{
Guido van Rossum2834b972000-10-06 16:58:26 +00002761 /* expand tuple to hold (at least) size new items.
2762 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002763
2764 int maxsize = context->maxsize * 2;
2765
2766 if (maxsize < context->size + size)
2767 maxsize = context->size + size;
2768
2769 context->maxsize = maxsize;
2770
Tim Peters4324aa32001-05-28 22:30:08 +00002771 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772}
2773
2774static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002775_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002776{
2777 /* add tuple or list to argument tuple (recursively) */
2778
2779 int i, size;
2780
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002781 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002782 PyErr_SetString(PyExc_ValueError,
2783 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002784 return 0;
2785 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002786 size = PyList_GET_SIZE(item);
2787 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002788 if (context->size + size > context->maxsize &&
2789 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002790 return 0;
2791 /* copy items to output tuple */
2792 for (i = 0; i < size; i++) {
2793 PyObject *o = PyList_GET_ITEM(item, i);
2794 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002795 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002796 return 0;
2797 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002798 if (context->size + 1 > context->maxsize &&
2799 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002800 return 0;
2801 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002802 PyTuple_SET_ITEM(context->tuple,
2803 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804 }
2805 }
2806 } else if (PyTuple_Check(item)) {
2807 /* same, for tuples */
2808 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002809 if (context->size + size > context->maxsize &&
2810 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811 return 0;
2812 for (i = 0; i < size; i++) {
2813 PyObject *o = PyTuple_GET_ITEM(item, i);
2814 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002815 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002816 return 0;
2817 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002818 if (context->size + 1 > context->maxsize &&
2819 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002820 return 0;
2821 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002822 PyTuple_SET_ITEM(context->tuple,
2823 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002824 }
2825 }
2826 } else {
2827 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2828 return 0;
2829 }
2830 return 1;
2831}
2832
2833static PyObject *
2834Tkinter_Flatten(PyObject* self, PyObject* args)
2835{
2836 FlattenContext context;
2837 PyObject* item;
2838
2839 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2840 return NULL;
2841
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002842 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002843 if (context.maxsize <= 0)
2844 return PyTuple_New(0);
2845
2846 context.tuple = PyTuple_New(context.maxsize);
2847 if (!context.tuple)
2848 return NULL;
2849
2850 context.size = 0;
2851
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002852 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002853 return NULL;
2854
Tim Peters4324aa32001-05-28 22:30:08 +00002855 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002856 return NULL;
2857
2858 return context.tuple;
2859}
2860
Guido van Rossum18468821994-06-20 07:49:28 +00002861static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002862Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002863{
Barry Warsawfa701a81997-01-16 00:15:11 +00002864 char *screenName = NULL;
2865 char *baseName = NULL;
2866 char *className = NULL;
2867 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002868 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002869 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002870 int sync = 0; /* pass -sync to wish */
2871 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002872
Guido van Rossum35d43371997-08-02 00:09:09 +00002873 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002874 if (baseName != NULL)
2875 baseName++;
2876 else
2877 baseName = Py_GetProgramName();
2878 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002879
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002880 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002881 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002882 &interactive, &wantobjects, &wantTk,
2883 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002884 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002885
Barry Warsawfa701a81997-01-16 00:15:11 +00002886 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002887 interactive, wantobjects, wantTk,
2888 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002889}
2890
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002891static PyObject *
2892Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2893{
2894 int new_val;
2895 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2896 return NULL;
2897 if (new_val < 0) {
2898 PyErr_SetString(PyExc_ValueError,
2899 "busywaitinterval must be >= 0");
2900 return NULL;
2901 }
2902 Tkinter_busywaitinterval = new_val;
2903 Py_INCREF(Py_None);
2904 return Py_None;
2905}
2906
2907static char setbusywaitinterval_doc[] =
2908"setbusywaitinterval(n) -> None\n\
2909\n\
2910Set the busy-wait interval in milliseconds between successive\n\
2911calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2912It should be set to a divisor of the maximum time between\n\
2913frames in an animation.";
2914
2915static PyObject *
2916Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2917{
2918 return PyInt_FromLong(Tkinter_busywaitinterval);
2919}
2920
2921static char getbusywaitinterval_doc[] =
2922"getbusywaitinterval() -> int\n\
2923\n\
2924Return the current busy-wait interval between successive\n\
2925calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2926
Guido van Rossum18468821994-06-20 07:49:28 +00002927static PyMethodDef moduleMethods[] =
2928{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002929 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2930 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002931#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002932 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2933 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002934#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002935 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2936 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2937 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2938 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002939 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2940 setbusywaitinterval_doc},
2941 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2942 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002943 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002944};
2945
Guido van Rossum7bf15641998-05-22 18:28:17 +00002946#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002947
2948static int stdin_ready = 0;
2949
Guido van Rossumad4db171998-06-13 13:56:28 +00002950#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002951static void
Fred Drake509d79a2000-07-08 04:04:38 +00002952MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002953{
2954 stdin_ready = 1;
2955}
Guido van Rossumad4db171998-06-13 13:56:28 +00002956#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002957
Martin v. Löwisa9656492003-03-30 08:44:58 +00002958#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002959static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002960#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002961
Guido van Rossum18468821994-06-20 07:49:28 +00002962static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002963EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002964{
Guido van Rossumad4db171998-06-13 13:56:28 +00002965#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002966 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002967#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002968#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002969 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002970#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002971 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002972 errorInCmd = 0;
2973#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002974 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002975 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002976#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002977 while (!errorInCmd && !stdin_ready) {
2978 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002979#ifdef MS_WINDOWS
2980 if (_kbhit()) {
2981 stdin_ready = 1;
2982 break;
2983 }
2984#endif
2985#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002986 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002987 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002988 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002989
Guido van Rossum00d93061998-05-28 23:06:38 +00002990 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002991
2992 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002993 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002994 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002995 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002996 Py_END_ALLOW_THREADS
2997#else
2998 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002999#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003000
3001 if (result < 0)
3002 break;
3003 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003004#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00003005 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003006#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003007 if (errorInCmd) {
3008 errorInCmd = 0;
3009 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3010 excInCmd = valInCmd = trbInCmd = NULL;
3011 PyErr_Print();
3012 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003013#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003014 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003015#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003016 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003017}
Guido van Rossum18468821994-06-20 07:49:28 +00003018
Guido van Rossum00d93061998-05-28 23:06:38 +00003019#endif
3020
Guido van Rossum7bf15641998-05-22 18:28:17 +00003021static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003022EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003023{
Guido van Rossum00d93061998-05-28 23:06:38 +00003024#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003025 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003026#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003027 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003028#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003029 PyOS_InputHook = EventHook;
3030 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003031#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003032}
3033
3034static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003035DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003036{
Guido van Rossum00d93061998-05-28 23:06:38 +00003037#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003038 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3039 PyOS_InputHook = NULL;
3040 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003041#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003042}
3043
Barry Warsawfa701a81997-01-16 00:15:11 +00003044
3045/* all errors will be checked in one fell swoop in init_tkinter() */
3046static void
Fred Drake509d79a2000-07-08 04:04:38 +00003047ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003048{
3049 PyObject *v = PyInt_FromLong(val);
3050 if (v) {
3051 PyDict_SetItemString(d, name, v);
3052 Py_DECREF(v);
3053 }
3054}
3055static void
Fred Drake509d79a2000-07-08 04:04:38 +00003056ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003057{
3058 PyObject *v = PyString_FromString(val);
3059 if (v) {
3060 PyDict_SetItemString(d, name, v);
3061 Py_DECREF(v);
3062 }
3063}
3064
3065
Mark Hammond62b1ab12002-07-23 06:31:15 +00003066PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003067init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003068{
Barry Warsawfa701a81997-01-16 00:15:11 +00003069 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003070
Barry Warsawfa701a81997-01-16 00:15:11 +00003071 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003072
3073#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003074 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003075#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003076
Barry Warsawfa701a81997-01-16 00:15:11 +00003077 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003078
Barry Warsawfa701a81997-01-16 00:15:11 +00003079 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003080 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003081 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003082
Guido van Rossum35d43371997-08-02 00:09:09 +00003083 ins_long(d, "READABLE", TCL_READABLE);
3084 ins_long(d, "WRITABLE", TCL_WRITABLE);
3085 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3086 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3087 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3088 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3089 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3090 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3091 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003092 ins_string(d, "TK_VERSION", TK_VERSION);
3093 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003094
Guido van Rossum83551bf1997-09-13 00:44:23 +00003095 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003096
3097 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003098 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3099
Martin v. Löwisffad6332002-11-26 09:28:05 +00003100 PyTclObject_Type.ob_type = &PyType_Type;
3101 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003102
3103#ifdef TK_AQUA
3104 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3105 * start waking up. Note that Tcl_FindExecutable will do this, this
3106 * code must be above it! The original warning from
3107 * tkMacOSXAppInit.c is copied below.
3108 *
3109 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3110 * Tcl interpreter for now. It probably should work to do this
3111 * in the other order, but for now it doesn't seem to.
3112 *
3113 */
3114 Tk_MacOSXSetupTkNotifier();
3115#endif
3116
3117
Guido van Rossume187b0e2000-03-27 21:46:29 +00003118 /* This helps the dynamic loader; in Unicode aware Tcl versions
3119 it also helps Tcl find its encodings. */
3120 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003121
Barry Warsawfa701a81997-01-16 00:15:11 +00003122 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003123 return;
3124
Guido van Rossum43ff8681998-07-14 18:02:13 +00003125#if 0
3126 /* This was not a good idea; through <Destroy> bindings,
3127 Tcl_Finalize() may invoke Python code but at that point the
3128 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003129 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003130#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003131
Guido van Rossum18468821994-06-20 07:49:28 +00003132}