blob: 36aa0109123de514701e74635f999ec5b50d67cb [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,
David Aschere2b4b322004-02-18 05:59:53 +0000579 int interactive, int wantobjects, int wantTk)
Barry Warsawfa701a81997-01-16 00:15:11 +0000580{
581 TkappObject *v;
582 char *argv0;
Guido van Rossumb18618d2000-05-03 23:44:39 +0000583 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000584 if (v == NULL)
585 return NULL;
586
587 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000588 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000589 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
590 TCL_GLOBAL_ONLY) != NULL;
591 v->thread_id = Tcl_GetCurrentThread();
592 v->dispatching = 0;
593
594#ifndef TCL_THREADS
595 if (v->threaded) {
596 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
597 Py_DECREF(v);
598 return 0;
599 }
600#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000601#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000602 if (v->threaded && tcl_lock) {
603 /* If Tcl is threaded, we don't need the lock. */
604 PyThread_free_lock(tcl_lock);
605 tcl_lock = NULL;
606 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000607#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000608
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000609 v->BooleanType = Tcl_GetObjType("boolean");
610 v->ByteArrayType = Tcl_GetObjType("bytearray");
611 v->DoubleType = Tcl_GetObjType("double");
612 v->IntType = Tcl_GetObjType("int");
613 v->ListType = Tcl_GetObjType("list");
614 v->ProcBodyType = Tcl_GetObjType("procbody");
615 v->StringType = Tcl_GetObjType("string");
616
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000617 /* Delete the 'exit' command, which can screw things up */
618 Tcl_DeleteCommand(v->interp, "exit");
619
Barry Warsawfa701a81997-01-16 00:15:11 +0000620 if (screenName != NULL)
621 Tcl_SetVar2(v->interp, "env", "DISPLAY",
622 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000623
Barry Warsawfa701a81997-01-16 00:15:11 +0000624 if (interactive)
625 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
626 else
627 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000628
Barry Warsawfa701a81997-01-16 00:15:11 +0000629 /* This is used to get the application class for Tk 4.1 and up */
630 argv0 = (char*)ckalloc(strlen(className) + 1);
631 if (!argv0) {
632 PyErr_NoMemory();
633 Py_DECREF(v);
634 return NULL;
635 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000636
Barry Warsawfa701a81997-01-16 00:15:11 +0000637 strcpy(argv0, className);
Guido van Rossum730806d1998-04-10 22:27:42 +0000638 if (isupper((int)(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000639 argv0[0] = tolower(argv0[0]);
640 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
641 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000642
David Aschere2b4b322004-02-18 05:59:53 +0000643 if (! wantTk) {
644 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
645 }
646
Barry Warsawfa701a81997-01-16 00:15:11 +0000647 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000648 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000649
Guido van Rossum7bf15641998-05-22 18:28:17 +0000650 EnableEventHook();
651
Barry Warsawfa701a81997-01-16 00:15:11 +0000652 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000653}
654
Barry Warsawfa701a81997-01-16 00:15:11 +0000655
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000656static void
657Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
658 Tcl_Condition *cond, Tcl_Mutex *mutex)
659{
660 Py_BEGIN_ALLOW_THREADS;
661 Tcl_MutexLock(mutex);
662 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
663 Tcl_ThreadAlert(self->thread_id);
664 Tcl_ConditionWait(cond, mutex, NULL);
665 Tcl_MutexUnlock(mutex);
666 Py_END_ALLOW_THREADS
667}
668
Barry Warsawfa701a81997-01-16 00:15:11 +0000669
Guido van Rossum18468821994-06-20 07:49:28 +0000670/** Tcl Eval **/
671
Martin v. Löwisffad6332002-11-26 09:28:05 +0000672typedef struct {
673 PyObject_HEAD
674 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000675 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000676} PyTclObject;
677
678staticforward PyTypeObject PyTclObject_Type;
679#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
680
681static PyObject *
682newPyTclObject(Tcl_Obj *arg)
683{
684 PyTclObject *self;
685 self = PyObject_New(PyTclObject, &PyTclObject_Type);
686 if (self == NULL)
687 return NULL;
688 Tcl_IncrRefCount(arg);
689 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000690 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000691 return (PyObject*)self;
692}
693
694static void
695PyTclObject_dealloc(PyTclObject *self)
696{
697 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000698 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000699 PyObject_Del(self);
700}
701
702static PyObject *
703PyTclObject_str(PyTclObject *self)
704{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000705 if (self->string && PyString_Check(self->string)) {
706 Py_INCREF(self->string);
707 return self->string;
708 }
709 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000710 return PyString_FromString(Tcl_GetString(self->value));
711}
712
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000713static char*
714PyTclObject_TclString(PyObject *self)
715{
716 return Tcl_GetString(((PyTclObject*)self)->value);
717}
718
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000719/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000720PyDoc_STRVAR(PyTclObject_string__doc__,
721"the string representation of this object, either as string or Unicode");
722
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000723static PyObject *
724PyTclObject_string(PyTclObject *self, void *ignored)
725{
726 char *s;
727 int i, len;
728 if (!self->string) {
729 s = Tcl_GetStringFromObj(self->value, &len);
730 for (i = 0; i < len; i++)
731 if (s[i] & 0x80)
732 break;
733#ifdef Py_USING_UNICODE
734 if (i == len)
735 /* It is an ASCII string. */
736 self->string = PyString_FromStringAndSize(s, len);
737 else {
738 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
739 if (!self->string) {
740 PyErr_Clear();
741 self->string = PyString_FromStringAndSize(s, len);
742 }
743 }
744#else
745 self->string = PyString_FromStringAndSize(s, len);
746#endif
747 if (!self->string)
748 return NULL;
749 }
750 Py_INCREF(self->string);
751 return self->string;
752}
753
754#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000755PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
756
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000757static PyObject *
758PyTclObject_unicode(PyTclObject *self, void *ignored)
759{
760 char *s;
761 int len;
762 if (self->string && PyUnicode_Check(self->string)) {
763 Py_INCREF(self->string);
764 return self->string;
765 }
766 /* XXX Could chache result if it is non-ASCII. */
767 s = Tcl_GetStringFromObj(self->value, &len);
768 return PyUnicode_DecodeUTF8(s, len, "strict");
769}
770#endif
771
Martin v. Löwisffad6332002-11-26 09:28:05 +0000772static PyObject *
773PyTclObject_repr(PyTclObject *self)
774{
775 char buf[50];
776 PyOS_snprintf(buf, 50, "<%s object at 0x%.8x>",
777 self->value->typePtr->name, (int)self->value);
778 return PyString_FromString(buf);
779}
780
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000781static int
782PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
783{
784 int res;
785 res = strcmp(Tcl_GetString(self->value),
786 Tcl_GetString(other->value));
787 if (res < 0) return -1;
788 if (res > 0) return 1;
789 return 0;
790}
791
Martin v. Löwis39195712003-01-04 00:33:13 +0000792PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
793
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794static PyObject*
795get_typename(PyTclObject* obj, void* ignored)
796{
797 return PyString_FromString(obj->value->typePtr->name);
798}
799
Martin v. Löwis39195712003-01-04 00:33:13 +0000800
Martin v. Löwisffad6332002-11-26 09:28:05 +0000801static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000802 {"typename", (getter)get_typename, NULL, get_typename__doc__},
803 {"string", (getter)PyTclObject_string, NULL,
804 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000805 {0},
806};
807
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000808static PyMethodDef PyTclObject_methods[] = {
809 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000810 PyTclObject_unicode__doc__},
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000811 {0}
812};
813
Martin v. Löwisffad6332002-11-26 09:28:05 +0000814statichere PyTypeObject PyTclObject_Type = {
815 PyObject_HEAD_INIT(NULL)
816 0, /*ob_size*/
817 "_tkinter.Tcl_Obj", /*tp_name*/
818 sizeof(PyTclObject), /*tp_basicsize*/
819 0, /*tp_itemsize*/
820 /* methods */
821 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
822 0, /*tp_print*/
823 0, /*tp_getattr*/
824 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000825 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000826 (reprfunc)PyTclObject_repr, /*tp_repr*/
827 0, /*tp_as_number*/
828 0, /*tp_as_sequence*/
829 0, /*tp_as_mapping*/
830 0, /*tp_hash*/
831 0, /*tp_call*/
832 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000833 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000834 0, /*tp_setattro*/
835 0, /*tp_as_buffer*/
836 Py_TPFLAGS_DEFAULT, /*tp_flags*/
837 0, /*tp_doc*/
838 0, /*tp_traverse*/
839 0, /*tp_clear*/
840 0, /*tp_richcompare*/
841 0, /*tp_weaklistoffset*/
842 0, /*tp_iter*/
843 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000844 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000845 0, /*tp_members*/
846 PyTclObject_getsetlist, /*tp_getset*/
847 0, /*tp_base*/
848 0, /*tp_dict*/
849 0, /*tp_descr_get*/
850 0, /*tp_descr_set*/
851 0, /*tp_dictoffset*/
852 0, /*tp_init*/
853 0, /*tp_alloc*/
854 0, /*tp_new*/
855 0, /*tp_free*/
856 0, /*tp_is_gc*/
857};
858
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000859static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000860AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000861{
862 Tcl_Obj *result;
863
864 if (PyString_Check(value))
865 return Tcl_NewStringObj(PyString_AS_STRING(value),
866 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000867 else if (PyBool_Check(value))
868 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000869 else if (PyInt_Check(value))
870 return Tcl_NewLongObj(PyInt_AS_LONG(value));
871 else if (PyFloat_Check(value))
872 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
873 else if (PyTuple_Check(value)) {
874 Tcl_Obj **argv = (Tcl_Obj**)
875 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
876 int i;
877 if(!argv)
878 return 0;
879 for(i=0;i<PyTuple_Size(value);i++)
880 argv[i] = AsObj(PyTuple_GetItem(value,i));
881 result = Tcl_NewListObj(PyTuple_Size(value), argv);
882 ckfree(FREECAST argv);
883 return result;
884 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000885#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000886 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000887 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
888 int size = PyUnicode_GET_SIZE(value);
889 /* This #ifdef assumes that Tcl uses UCS-2.
890 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000891#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000892 Tcl_UniChar *outbuf;
893 int i;
894 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
895 if (!outbuf) {
896 PyErr_NoMemory();
897 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000898 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000899 for (i = 0; i < size; i++) {
900 if (inbuf[i] >= 0x10000) {
901 /* Tcl doesn't do UTF-16, yet. */
902 PyErr_SetString(PyExc_ValueError,
903 "unsupported character");
904 ckfree(FREECAST outbuf);
905 return NULL;
906 }
907 outbuf[i] = inbuf[i];
908 }
909 result = Tcl_NewUnicodeObj(outbuf, size);
910 ckfree(FREECAST outbuf);
911 return result;
912#else
913 return Tcl_NewUnicodeObj(inbuf, size);
914#endif
915
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000916 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000917#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000918 else if(PyTclObject_Check(value)) {
919 Tcl_Obj *v = ((PyTclObject*)value)->value;
920 Tcl_IncrRefCount(v);
921 return v;
922 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000923 else {
924 PyObject *v = PyObject_Str(value);
925 if (!v)
926 return 0;
927 result = AsObj(v);
928 Py_DECREF(v);
929 return result;
930 }
931}
932
Martin v. Löwisffad6332002-11-26 09:28:05 +0000933static PyObject*
934FromObj(PyObject* tkapp, Tcl_Obj *value)
935{
936 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000937 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000938
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000939 if (value->typePtr == NULL) {
940 /* If the result contains any bytes with the top bit set,
941 it's UTF-8 and we should decode it to Unicode */
942#ifdef Py_USING_UNICODE
943 int i;
944 char *s = value->bytes;
945 int len = value->length;
946 for (i = 0; i < len; i++) {
947 if (value->bytes[i] & 0x80)
948 break;
949 }
950
951 if (i == value->length)
952 result = PyString_FromStringAndSize(s, len);
953 else {
954 /* Convert UTF-8 to Unicode string */
955 result = PyUnicode_DecodeUTF8(s, len, "strict");
956 if (result == NULL) {
957 PyErr_Clear();
958 result = PyString_FromStringAndSize(s, len);
959 }
960 }
961#else
962 res = PyString_FromStringAndSize(value->bytes, value->length);
963#endif
964 return result;
965 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000966
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000967 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000968 result = value->internalRep.longValue ? Py_True : Py_False;
969 Py_INCREF(result);
970 return result;
971 }
972
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000973 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000974 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000975 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000976 return PyString_FromStringAndSize(data, size);
977 }
978
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000979 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000980 return PyFloat_FromDouble(value->internalRep.doubleValue);
981 }
982
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000983 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984 return PyInt_FromLong(value->internalRep.longValue);
985 }
986
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000987 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000988 int size;
989 int i, status;
990 PyObject *elem;
991 Tcl_Obj *tcl_elem;
992
993 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
994 if (status == TCL_ERROR)
995 return Tkinter_Error(tkapp);
996 result = PyTuple_New(size);
997 if (!result)
998 return NULL;
999 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001000 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001001 value, i, &tcl_elem);
1002 if (status == TCL_ERROR) {
1003 Py_DECREF(result);
1004 return Tkinter_Error(tkapp);
1005 }
1006 elem = FromObj(tkapp, tcl_elem);
1007 if (!elem) {
1008 Py_DECREF(result);
1009 return NULL;
1010 }
1011 PyTuple_SetItem(result, i, elem);
1012 }
1013 return result;
1014 }
1015
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001016 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001017 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001018 }
1019
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001020 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001021#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001022#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001023 PyObject *result;
1024 int size;
1025 Tcl_UniChar *input;
1026 Py_UNICODE *output;
1027
1028 size = Tcl_GetCharLength(value);
1029 result = PyUnicode_FromUnicode(NULL, size);
1030 if (!result)
1031 return NULL;
1032 input = Tcl_GetUnicode(value);
1033 output = PyUnicode_AS_UNICODE(result);
1034 while (size--)
1035 *output++ = *input++;
1036 return result;
1037#else
1038 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1039 Tcl_GetCharLength(value));
1040#endif
1041#else
1042 int size;
1043 char *c;
1044 c = Tcl_GetStringFromObj(value, &size);
1045 return PyString_FromStringAndSize(c, size);
1046#endif
1047 }
1048
1049 return newPyTclObject(value);
1050}
1051
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001052/* This mutex synchronizes inter-thread command calls. */
1053
1054TCL_DECLARE_MUTEX(call_mutex)
1055
1056typedef struct Tkapp_CallEvent {
1057 Tcl_Event ev; /* Must be first */
1058 TkappObject *self;
1059 PyObject *args;
1060 int flags;
1061 PyObject **res;
1062 PyObject **exc_type, **exc_value, **exc_tb;
1063 Tcl_Condition done;
1064} Tkapp_CallEvent;
1065
1066void
1067Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001068{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001069 int i;
1070 for (i = 0; i < objc; i++)
1071 Tcl_DecrRefCount(objv[i]);
1072 if (objv != objStore)
1073 ckfree(FREECAST objv);
1074}
Guido van Rossum18468821994-06-20 07:49:28 +00001075
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001076/* Convert Python objects to Tcl objects. This must happen in the
1077 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001078
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001079static Tcl_Obj**
1080Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1081{
1082 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001083 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001084 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001085 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001086
Guido van Rossum212643f1998-04-29 16:22:14 +00001087 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001088 objv[0] = AsObj(args);
1089 if (objv[0] == 0)
1090 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001091 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001092 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001093 }
1094 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001095 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001096
Guido van Rossum632de272000-03-29 00:19:50 +00001097 if (objc > ARGSZ) {
1098 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1099 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001100 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001101 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001102 goto finally;
1103 }
1104 }
1105
Guido van Rossum632de272000-03-29 00:19:50 +00001106 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001107 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001108 if (v == Py_None) {
1109 objc = i;
1110 break;
1111 }
Guido van Rossum632de272000-03-29 00:19:50 +00001112 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001113 if (!objv[i]) {
1114 /* Reset objc, so it attempts to clear
1115 objects only up to i. */
1116 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001117 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001118 }
Guido van Rossum632de272000-03-29 00:19:50 +00001119 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001120 }
1121 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001122 *pobjc = objc;
1123 return objv;
1124finally:
1125 Tkapp_CallDeallocArgs(objv, objStore, objc);
1126 return NULL;
1127}
Guido van Rossum212643f1998-04-29 16:22:14 +00001128
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001129/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001130
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001131static PyObject*
1132Tkapp_CallResult(TkappObject *self)
1133{
1134 PyObject *res = NULL;
1135 if(self->wantobjects) {
1136 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001137 /* Not sure whether the IncrRef is necessary, but something
1138 may overwrite the interpreter result while we are
1139 converting it. */
1140 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001141 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001142 Tcl_DecrRefCount(value);
1143 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001145 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001146
Guido van Rossum990f5c62000-05-04 15:07:16 +00001147 /* If the result contains any bytes with the top bit set,
1148 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001149#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001150 while (*p != '\0') {
1151 if (*p & 0x80)
1152 break;
1153 p++;
1154 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001155
Guido van Rossum990f5c62000-05-04 15:07:16 +00001156 if (*p == '\0')
1157 res = PyString_FromStringAndSize(s, (int)(p-s));
1158 else {
1159 /* Convert UTF-8 to Unicode string */
1160 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001161 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1162 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163 PyErr_Clear();
1164 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001165 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001166 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001167#else
1168 p = strchr(p, '\0');
1169 res = PyString_FromStringAndSize(s, (int)(p-s));
1170#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001171 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001172 return res;
1173}
Guido van Rossum632de272000-03-29 00:19:50 +00001174
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175/* Tkapp_CallProc is the event procedure that is executed in the context of
1176 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1177 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001178
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001179static int
1180Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1181{
1182 Tcl_Obj *objStore[ARGSZ];
1183 Tcl_Obj **objv;
1184 int objc;
1185 int i;
1186 ENTER_PYTHON
1187 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1188 if (!objv) {
1189 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1190 *(e->res) = NULL;
1191 }
1192 LEAVE_PYTHON
1193 if (!objv)
1194 goto done;
1195 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1196 ENTER_PYTHON
1197 if (i == TCL_ERROR) {
1198 *(e->res) = NULL;
1199 *(e->exc_type) = NULL;
1200 *(e->exc_tb) = NULL;
1201 *(e->exc_value) = PyObject_CallFunction(
1202 Tkinter_TclError, "s",
1203 Tcl_GetStringResult(e->self->interp));
1204 }
1205 else {
1206 *(e->res) = Tkapp_CallResult(e->self);
1207 }
1208 LEAVE_PYTHON
1209 done:
1210 /* Wake up calling thread. */
1211 Tcl_MutexLock(&call_mutex);
1212 Tcl_ConditionNotify(&e->done);
1213 Tcl_MutexUnlock(&call_mutex);
1214 return 1;
1215}
1216
1217/* This is the main entry point for calling a Tcl command.
1218 It supports three cases, with regard to threading:
1219 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1220 the context of the calling thread.
1221 2. Tcl is threaded, caller of the command is in the interpreter thread:
1222 Execute the command in the calling thread. Since the Tcl lock will
1223 not be used, we can merge that with case 1.
1224 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1225 the interpreter thread. Allocation of Tcl objects needs to occur in the
1226 interpreter thread, so we ship the PyObject* args to the target thread,
1227 and perform processing there. */
1228
1229static PyObject *
1230Tkapp_Call(PyObject *_self, PyObject *args)
1231{
1232 Tcl_Obj *objStore[ARGSZ];
1233 Tcl_Obj **objv = NULL;
1234 int objc, i;
1235 PyObject *res = NULL;
1236 TkappObject *self = (TkappObject*)_self;
1237 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1238 int flags = TCL_EVAL_DIRECT;
1239
Martin v. Löwisa9656492003-03-30 08:44:58 +00001240#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001241 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1242 /* We cannot call the command directly. Instead, we must
1243 marshal the parameters to the interpreter thread. */
1244 Tkapp_CallEvent *ev;
1245 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001246 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001247 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1249 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1250 ev->self = self;
1251 ev->args = args;
1252 ev->res = &res;
1253 ev->exc_type = &exc_type;
1254 ev->exc_value = &exc_value;
1255 ev->exc_tb = &exc_tb;
1256 ev->done = (Tcl_Condition)0;
1257
1258 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1259
1260 if (res == NULL) {
1261 if (exc_type)
1262 PyErr_Restore(exc_type, exc_value, exc_tb);
1263 else
1264 PyErr_SetObject(Tkinter_TclError, exc_value);
1265 }
1266 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001267 else
1268#endif
1269 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270
1271 objv = Tkapp_CallArgs(args, objStore, &objc);
1272 if (!objv)
1273 return NULL;
1274
1275 ENTER_TCL
1276
1277 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1278
1279 ENTER_OVERLAP
1280
1281 if (i == TCL_ERROR)
1282 Tkinter_Error(_self);
1283 else
1284 res = Tkapp_CallResult(self);
1285
1286 LEAVE_OVERLAP_TCL
1287
1288 Tkapp_CallDeallocArgs(objv, objStore, objc);
1289 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001290 return res;
1291}
1292
1293
1294static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001295Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001296{
Guido van Rossum212643f1998-04-29 16:22:14 +00001297 /* Could do the same here as for Tkapp_Call(), but this is not used
1298 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1299 way for the user to do what all its Global* variants do (save and
1300 reset the scope pointer, call the local version, restore the saved
1301 scope pointer). */
1302
Guido van Rossum62320c91998-06-15 04:36:09 +00001303 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001304 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001305
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306 CHECK_TCL_APPARTMENT;
1307
Guido van Rossum62320c91998-06-15 04:36:09 +00001308 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001309 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001310 int err;
1311 ENTER_TCL
1312 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001313 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001314 if (err == TCL_ERROR)
1315 res = Tkinter_Error(self);
1316 else
1317 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001318 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001319 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001320 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001321
1322 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001323}
1324
1325static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001326Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001327{
Barry Warsawfa701a81997-01-16 00:15:11 +00001328 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001329 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001330 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001331
Guido van Rossum43713e52000-02-29 13:59:29 +00001332 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001333 return NULL;
1334
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335 CHECK_TCL_APPARTMENT;
1336
Guido van Rossum00d93061998-05-28 23:06:38 +00001337 ENTER_TCL
1338 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001339 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001340 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001341 res = Tkinter_Error(self);
1342 else
1343 res = PyString_FromString(Tkapp_Result(self));
1344 LEAVE_OVERLAP_TCL
1345 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001346}
1347
1348static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001349Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001350{
Barry Warsawfa701a81997-01-16 00:15:11 +00001351 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001352 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001353 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001354
Guido van Rossum43713e52000-02-29 13:59:29 +00001355 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001356 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001357
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001358 CHECK_TCL_APPARTMENT;
1359
Guido van Rossum00d93061998-05-28 23:06:38 +00001360 ENTER_TCL
1361 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001362 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001363 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001364 res = Tkinter_Error(self);
1365 else
1366 res = PyString_FromString(Tkapp_Result(self));
1367 LEAVE_OVERLAP_TCL
1368 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001369}
1370
1371static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001372Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001373{
Barry Warsawfa701a81997-01-16 00:15:11 +00001374 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001375 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001376 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001377
Guido van Rossum43713e52000-02-29 13:59:29 +00001378 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001379 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001380
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001381 CHECK_TCL_APPARTMENT;
1382
Guido van Rossum00d93061998-05-28 23:06:38 +00001383 ENTER_TCL
1384 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001385 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001386 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001387 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001388
Guido van Rossum62320c91998-06-15 04:36:09 +00001389 else
1390 res = PyString_FromString(Tkapp_Result(self));
1391 LEAVE_OVERLAP_TCL
1392 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001393}
1394
1395static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001396Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001397{
Barry Warsawfa701a81997-01-16 00:15:11 +00001398 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001399 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001400 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001401
Guido van Rossum35d43371997-08-02 00:09:09 +00001402 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001403 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001404
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405 CHECK_TCL_APPARTMENT;
1406
Guido van Rossum00d93061998-05-28 23:06:38 +00001407 ENTER_TCL
1408 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001409 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001410 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001411 res = Tkinter_Error(self);
1412 else
1413 res = PyString_FromString(Tkapp_Result(self));
1414 LEAVE_OVERLAP_TCL
1415 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001416}
1417
1418static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001419Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001420{
Barry Warsawfa701a81997-01-16 00:15:11 +00001421 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001422
Guido van Rossum43713e52000-02-29 13:59:29 +00001423 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001424 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001425 CHECK_TCL_APPARTMENT;
1426
Guido van Rossum00d93061998-05-28 23:06:38 +00001427 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001428 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001429 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001430
Barry Warsawfa701a81997-01-16 00:15:11 +00001431 Py_INCREF(Py_None);
1432 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001433}
1434
Barry Warsawfa701a81997-01-16 00:15:11 +00001435
1436
Guido van Rossum18468821994-06-20 07:49:28 +00001437/** Tcl Variable **/
1438
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439TCL_DECLARE_MUTEX(var_mutex)
1440
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001441typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001442typedef struct VarEvent {
1443 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001444 PyObject *self;
1445 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001447 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001448 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001449 PyObject **exc_type;
1450 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452} VarEvent;
1453
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001454static int
1455varname_converter(PyObject *in, void *_out)
1456{
1457 char **out = (char**)_out;
1458 if (PyString_Check(in)) {
1459 *out = PyString_AsString(in);
1460 return 1;
1461 }
1462 if (PyTclObject_Check(in)) {
1463 *out = PyTclObject_TclString(in);
1464 return 1;
1465 }
1466 /* XXX: Should give diagnostics. */
1467 return 0;
1468}
1469
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001470void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471var_perform(VarEvent *ev)
1472{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001473 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1474 if (!*(ev->res)) {
1475 PyObject *exc, *val, *tb;
1476 PyErr_Fetch(&exc, &val, &tb);
1477 PyErr_NormalizeException(&exc, &val, &tb);
1478 *(ev->exc_type) = exc;
1479 *(ev->exc_val) = val;
1480 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001481 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001482
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483}
1484
1485static int
1486var_proc(VarEvent* ev, int flags)
1487{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001489 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490 Tcl_MutexLock(&var_mutex);
1491 Tcl_ConditionNotify(&ev->cond);
1492 Tcl_MutexUnlock(&var_mutex);
1493 LEAVE_PYTHON
1494 return 1;
1495}
1496
1497static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001498var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001499{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001501#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001502 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001503 TkappObject *self = (TkappObject*)_self;
1504 VarEvent *ev;
1505 PyObject *res, *exc_type, *exc_val;
1506
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507 /* The current thread is not the interpreter thread. Marshal
1508 the call to the interpreter thread, then wait for
1509 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001510 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001511 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001512
1513 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1514
1515 ev->self = _self;
1516 ev->args = args;
1517 ev->flags = flags;
1518 ev->func = func;
1519 ev->res = &res;
1520 ev->exc_type = &exc_type;
1521 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001522 ev->cond = NULL;
1523 ev->ev.proc = (Tcl_EventProc*)var_proc;
1524 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001525 if (!res) {
1526 PyErr_SetObject(exc_type, exc_val);
1527 Py_DECREF(exc_type);
1528 Py_DECREF(exc_val);
1529 return NULL;
1530 }
1531 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001533#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001534 /* Tcl is not threaded, or this is the interpreter thread. */
1535 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536}
1537
Guido van Rossum18468821994-06-20 07:49:28 +00001538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001539SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001540{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001541 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001542 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001543 PyObject *res = NULL;
1544 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001545
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001546 if (PyArg_ParseTuple(args, "O&O:setvar",
1547 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001548 /* XXX Acquire tcl lock??? */
1549 newval = AsObj(newValue);
1550 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001551 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001552 ENTER_TCL
1553 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1554 newval, flags);
1555 ENTER_OVERLAP
1556 if (!ok)
1557 Tkinter_Error(self);
1558 else {
1559 res = Py_None;
1560 Py_INCREF(res);
1561 }
1562 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001563 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001564 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001565 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001566 if (PyArg_ParseTuple(args, "ssO:setvar",
1567 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001568 /* XXX must hold tcl lock already??? */
1569 newval = AsObj(newValue);
1570 ENTER_TCL
1571 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1572 ENTER_OVERLAP
1573 if (!ok)
1574 Tkinter_Error(self);
1575 else {
1576 res = Py_None;
1577 Py_INCREF(res);
1578 }
1579 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001580 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001581 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001582 return NULL;
1583 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001584 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001585 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001586}
1587
1588static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001589Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001590{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001591 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001592}
1593
1594static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001595Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001596{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001597 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001598}
1599
Barry Warsawfa701a81997-01-16 00:15:11 +00001600
1601
Guido van Rossum18468821994-06-20 07:49:28 +00001602static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001603GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001604{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001605 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001606 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001607 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001608
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001609 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1610 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001611 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001612
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001613 ENTER_TCL
1614 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1615 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001616 if (tres == NULL) {
1617 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1618 } else {
1619 if (((TkappObject*)self)->wantobjects) {
1620 res = FromObj(self, tres);
1621 }
1622 else {
1623 res = PyString_FromString(Tcl_GetString(tres));
1624 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001625 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001626 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001627 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001628}
1629
1630static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001631Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001632{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001633 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001634}
1635
1636static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001637Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001638{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001639 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
Barry Warsawfa701a81997-01-16 00:15:11 +00001642
1643
Guido van Rossum18468821994-06-20 07:49:28 +00001644static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001645UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001646{
Guido van Rossum35d43371997-08-02 00:09:09 +00001647 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001648 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001649 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001650
Guido van Rossum43713e52000-02-29 13:59:29 +00001651 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001652 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001653
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001654 ENTER_TCL
1655 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1656 ENTER_OVERLAP
1657 if (code == TCL_ERROR)
1658 res = Tkinter_Error(self);
1659 else {
1660 Py_INCREF(Py_None);
1661 res = Py_None;
1662 }
1663 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001664 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001665}
1666
1667static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001668Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001669{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001670 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001671}
1672
1673static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001674Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001675{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001676 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001677}
1678
Barry Warsawfa701a81997-01-16 00:15:11 +00001679
1680
Guido van Rossum18468821994-06-20 07:49:28 +00001681/** Tcl to Python **/
1682
1683static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001684Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001685{
Barry Warsawfa701a81997-01-16 00:15:11 +00001686 char *s;
1687 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001688
Martin v. Löwisffad6332002-11-26 09:28:05 +00001689 if (PyTuple_Size(args) == 1) {
1690 PyObject* o = PyTuple_GetItem(args, 0);
1691 if (PyInt_Check(o)) {
1692 Py_INCREF(o);
1693 return o;
1694 }
1695 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001696 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001697 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001698 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001699 return Tkinter_Error(self);
1700 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001701}
1702
1703static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001704Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001705{
Barry Warsawfa701a81997-01-16 00:15:11 +00001706 char *s;
1707 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001708
Martin v. Löwisffad6332002-11-26 09:28:05 +00001709 if (PyTuple_Size(args) == 1) {
1710 PyObject *o = PyTuple_GetItem(args, 0);
1711 if (PyFloat_Check(o)) {
1712 Py_INCREF(o);
1713 return o;
1714 }
1715 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001716 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001717 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001718 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001719 return Tkinter_Error(self);
1720 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001721}
1722
1723static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001724Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001725{
Barry Warsawfa701a81997-01-16 00:15:11 +00001726 char *s;
1727 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001728
Martin v. Löwisffad6332002-11-26 09:28:05 +00001729 if (PyTuple_Size(args) == 1) {
1730 PyObject *o = PyTuple_GetItem(args, 0);
1731 if (PyInt_Check(o)) {
1732 Py_INCREF(o);
1733 return o;
1734 }
1735 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001736 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001737 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001738 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1739 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001740 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001741}
1742
1743static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001744Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001745{
Barry Warsawfa701a81997-01-16 00:15:11 +00001746 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001747 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001748 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001749
Guido van Rossum43713e52000-02-29 13:59:29 +00001750 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001751 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001752
1753 CHECK_TCL_APPARTMENT;
1754
Guido van Rossum00d93061998-05-28 23:06:38 +00001755 ENTER_TCL
1756 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001757 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001758 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001759 res = Tkinter_Error(self);
1760 else
1761 res = Py_BuildValue("s", Tkapp_Result(self));
1762 LEAVE_OVERLAP_TCL
1763 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
1766static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001767Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001768{
Barry Warsawfa701a81997-01-16 00:15:11 +00001769 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001770 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001771 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001772 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001773
Guido van Rossum43713e52000-02-29 13:59:29 +00001774 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001775 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001776
1777 CHECK_TCL_APPARTMENT;
1778
Guido van Rossum00d93061998-05-28 23:06:38 +00001779 ENTER_TCL
1780 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001781 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001782 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001783 res = Tkinter_Error(self);
1784 else
1785 res = Py_BuildValue("l", v);
1786 LEAVE_OVERLAP_TCL
1787 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001788}
1789
1790static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001791Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001792{
Barry Warsawfa701a81997-01-16 00:15:11 +00001793 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001794 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001795 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001796 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001797
Guido van Rossum43713e52000-02-29 13:59:29 +00001798 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001799 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001800 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001801 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001802 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001803 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001804 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001805 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001806 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001807 res = Tkinter_Error(self);
1808 else
1809 res = Py_BuildValue("d", v);
1810 LEAVE_OVERLAP_TCL
1811 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001812}
1813
1814static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001815Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001816{
Barry Warsawfa701a81997-01-16 00:15:11 +00001817 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001818 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001819 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001820 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001821
Guido van Rossum43713e52000-02-29 13:59:29 +00001822 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001823 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001824 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001825 ENTER_TCL
1826 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001827 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001828 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001829 res = Tkinter_Error(self);
1830 else
1831 res = Py_BuildValue("i", v);
1832 LEAVE_OVERLAP_TCL
1833 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
Barry Warsawfa701a81997-01-16 00:15:11 +00001836
1837
Guido van Rossum18468821994-06-20 07:49:28 +00001838static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001839Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001840{
Barry Warsawfa701a81997-01-16 00:15:11 +00001841 char *list;
1842 int argc;
1843 char **argv;
1844 PyObject *v;
1845 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001846
Martin v. Löwisffad6332002-11-26 09:28:05 +00001847 if (PyTuple_Size(args) == 1) {
1848 v = PyTuple_GetItem(args, 0);
1849 if (PyTuple_Check(v)) {
1850 Py_INCREF(v);
1851 return v;
1852 }
1853 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001854 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001855 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001856
Neal Norwitzd1c55102003-05-29 00:17:03 +00001857 if (Tcl_SplitList(Tkapp_Interp(self), list,
1858 &argc, &argv) == TCL_ERROR) {
1859 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001860 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001861 }
Guido van Rossum18468821994-06-20 07:49:28 +00001862
Barry Warsawfa701a81997-01-16 00:15:11 +00001863 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001864 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001865
Barry Warsawfa701a81997-01-16 00:15:11 +00001866 for (i = 0; i < argc; i++) {
1867 PyObject *s = PyString_FromString(argv[i]);
1868 if (!s || PyTuple_SetItem(v, i, s)) {
1869 Py_DECREF(v);
1870 v = NULL;
1871 goto finally;
1872 }
1873 }
Guido van Rossum18468821994-06-20 07:49:28 +00001874
Barry Warsawfa701a81997-01-16 00:15:11 +00001875 finally:
1876 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001877 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001878 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001879}
1880
1881static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001882Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001883{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001884 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001885 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001886
Martin v. Löwisffad6332002-11-26 09:28:05 +00001887 if (PyTuple_Size(args) == 1) {
1888 PyObject* o = PyTuple_GetItem(args, 0);
1889 if (PyTuple_Check(o)) {
1890 o = SplitObj(o);
1891 return o;
1892 }
1893 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001894 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001895 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001896 v = Split(list);
1897 PyMem_Free(list);
1898 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001899}
1900
1901static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001902Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001903{
Barry Warsawfa701a81997-01-16 00:15:11 +00001904 char *s = Merge(args);
1905 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001906
Barry Warsawfa701a81997-01-16 00:15:11 +00001907 if (s) {
1908 res = PyString_FromString(s);
1909 ckfree(s);
1910 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001911
1912 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001913}
1914
Barry Warsawfa701a81997-01-16 00:15:11 +00001915
1916
Guido van Rossum18468821994-06-20 07:49:28 +00001917/** Tcl Command **/
1918
Guido van Rossum00d93061998-05-28 23:06:38 +00001919/* Client data struct */
1920typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001921 PyObject *self;
1922 PyObject *func;
1923} PythonCmd_ClientData;
1924
1925static int
Fred Drake509d79a2000-07-08 04:04:38 +00001926PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001927{
1928 errorInCmd = 1;
1929 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1930 LEAVE_PYTHON
1931 return TCL_ERROR;
1932}
1933
Guido van Rossum18468821994-06-20 07:49:28 +00001934/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001935 * function or method.
1936 */
Guido van Rossum18468821994-06-20 07:49:28 +00001937static int
Fred Drake509d79a2000-07-08 04:04:38 +00001938PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001939{
Guido van Rossum00d93061998-05-28 23:06:38 +00001940 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001941 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001942 int i, rv;
1943 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001944
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001945 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001946
Barry Warsawfa701a81997-01-16 00:15:11 +00001947 /* TBD: no error checking here since we know, via the
1948 * Tkapp_CreateCommand() that the client data is a two-tuple
1949 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001950 self = data->self;
1951 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001952
Barry Warsawfa701a81997-01-16 00:15:11 +00001953 /* Create argument list (argv1, ..., argvN) */
1954 if (!(arg = PyTuple_New(argc - 1)))
1955 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001956
Barry Warsawfa701a81997-01-16 00:15:11 +00001957 for (i = 0; i < (argc - 1); i++) {
1958 PyObject *s = PyString_FromString(argv[i + 1]);
1959 if (!s || PyTuple_SetItem(arg, i, s)) {
1960 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001961 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001962 }
1963 }
1964 res = PyEval_CallObject(func, arg);
1965 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001966
Barry Warsawfa701a81997-01-16 00:15:11 +00001967 if (res == NULL)
1968 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001969
Barry Warsawfa701a81997-01-16 00:15:11 +00001970 if (!(tmp = PyList_New(0))) {
1971 Py_DECREF(res);
1972 return PythonCmd_Error(interp);
1973 }
1974
Guido van Rossum2834b972000-10-06 16:58:26 +00001975 s = AsString(res, tmp);
1976 if (s == NULL) {
1977 rv = PythonCmd_Error(interp);
1978 }
1979 else {
1980 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1981 rv = TCL_OK;
1982 }
1983
Barry Warsawfa701a81997-01-16 00:15:11 +00001984 Py_DECREF(res);
1985 Py_DECREF(tmp);
1986
Guido van Rossum00d93061998-05-28 23:06:38 +00001987 LEAVE_PYTHON
1988
Guido van Rossum2834b972000-10-06 16:58:26 +00001989 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001990}
1991
1992static void
Fred Drake509d79a2000-07-08 04:04:38 +00001993PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001994{
Guido van Rossum00d93061998-05-28 23:06:38 +00001995 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1996
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001997 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001998 Py_XDECREF(data->self);
1999 Py_XDECREF(data->func);
2000 PyMem_DEL(data);
2001 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002002}
2003
Barry Warsawfa701a81997-01-16 00:15:11 +00002004
2005
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002006
2007TCL_DECLARE_MUTEX(command_mutex)
2008
2009typedef struct CommandEvent{
2010 Tcl_Event ev;
2011 Tcl_Interp* interp;
2012 char *name;
2013 int create;
2014 int *status;
2015 ClientData *data;
2016 Tcl_Condition done;
2017} CommandEvent;
2018
2019static int
2020Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002021{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002022 if (ev->create)
2023 *ev->status = Tcl_CreateCommand(
2024 ev->interp, ev->name, PythonCmd,
2025 ev->data, PythonCmdDelete) == NULL;
2026 else
2027 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2028 Tcl_MutexLock(&command_mutex);
2029 Tcl_ConditionNotify(&ev->done);
2030 Tcl_MutexUnlock(&command_mutex);
2031 return 1;
2032}
2033
2034static PyObject *
2035Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2036{
2037 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002038 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002039 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002040 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002041 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002042
Guido van Rossum43713e52000-02-29 13:59:29 +00002043 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002044 return NULL;
2045 if (!PyCallable_Check(func)) {
2046 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002047 return NULL;
2048 }
Guido van Rossum18468821994-06-20 07:49:28 +00002049
Martin v. Löwisa9656492003-03-30 08:44:58 +00002050#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002051 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002052 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002053 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002054#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002055
Guido van Rossum00d93061998-05-28 23:06:38 +00002056 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002057 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002058 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002059 Py_XINCREF(self);
2060 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002061 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002062 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002063
2064 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2065 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2066 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2067 ev->interp = self->interp;
2068 ev->create = 1;
2069 ev->name = cmdName;
2070 ev->data = (ClientData)data;
2071 ev->status = &err;
2072 ev->done = NULL;
2073 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2074 }
2075 else {
2076 ENTER_TCL
2077 err = Tcl_CreateCommand(
2078 Tkapp_Interp(self), cmdName, PythonCmd,
2079 (ClientData)data, PythonCmdDelete) == NULL;
2080 LEAVE_TCL
2081 }
2082 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002083 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002084 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002085 return NULL;
2086 }
Guido van Rossum18468821994-06-20 07:49:28 +00002087
Barry Warsawfa701a81997-01-16 00:15:11 +00002088 Py_INCREF(Py_None);
2089 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002090}
2091
Barry Warsawfa701a81997-01-16 00:15:11 +00002092
2093
Guido van Rossum18468821994-06-20 07:49:28 +00002094static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002095Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002096{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002097 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002098 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002099 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002100
Guido van Rossum43713e52000-02-29 13:59:29 +00002101 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002102 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002103 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2104 CommandEvent *ev;
2105 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2106 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2107 ev->interp = self->interp;
2108 ev->create = 0;
2109 ev->name = cmdName;
2110 ev->status = &err;
2111 ev->done = NULL;
2112 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2113 &command_mutex);
2114 }
2115 else {
2116 ENTER_TCL
2117 err = Tcl_DeleteCommand(self->interp, cmdName);
2118 LEAVE_TCL
2119 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002120 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002121 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2122 return NULL;
2123 }
2124 Py_INCREF(Py_None);
2125 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002126}
2127
Barry Warsawfa701a81997-01-16 00:15:11 +00002128
2129
Guido van Rossum00d93061998-05-28 23:06:38 +00002130#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002131/** File Handler **/
2132
Guido van Rossum00d93061998-05-28 23:06:38 +00002133typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002134 PyObject *func;
2135 PyObject *file;
2136 int id;
2137 struct _fhcdata *next;
2138} FileHandler_ClientData;
2139
2140static FileHandler_ClientData *HeadFHCD;
2141
2142static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002143NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002144{
2145 FileHandler_ClientData *p;
2146 p = PyMem_NEW(FileHandler_ClientData, 1);
2147 if (p != NULL) {
2148 Py_XINCREF(func);
2149 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002150 p->func = func;
2151 p->file = file;
2152 p->id = id;
2153 p->next = HeadFHCD;
2154 HeadFHCD = p;
2155 }
2156 return p;
2157}
2158
2159static void
Fred Drake509d79a2000-07-08 04:04:38 +00002160DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002161{
2162 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002163
2164 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002165 while ((p = *pp) != NULL) {
2166 if (p->id == id) {
2167 *pp = p->next;
2168 Py_XDECREF(p->func);
2169 Py_XDECREF(p->file);
2170 PyMem_DEL(p);
2171 }
2172 else
2173 pp = &p->next;
2174 }
2175}
2176
Guido van Rossuma597dde1995-01-10 20:56:29 +00002177static void
Fred Drake509d79a2000-07-08 04:04:38 +00002178FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002179{
Guido van Rossum00d93061998-05-28 23:06:38 +00002180 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002181 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002182
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002183 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002184 func = data->func;
2185 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002186
Barry Warsawfa701a81997-01-16 00:15:11 +00002187 arg = Py_BuildValue("(Oi)", file, (long) mask);
2188 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002189 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002190
2191 if (res == NULL) {
2192 errorInCmd = 1;
2193 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2194 }
2195 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002196 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002197}
2198
Guido van Rossum18468821994-06-20 07:49:28 +00002199static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002200Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2201 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002202{
Guido van Rossum00d93061998-05-28 23:06:38 +00002203 FileHandler_ClientData *data;
2204 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002205 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002206
Guido van Rossum2834b972000-10-06 16:58:26 +00002207 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2208 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002209 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002210
Martin v. Löwisa9656492003-03-30 08:44:58 +00002211#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002212 if (!self && !tcl_lock) {
2213 /* We don't have the Tcl lock since Tcl is threaded. */
2214 PyErr_SetString(PyExc_RuntimeError,
2215 "_tkinter.createfilehandler not supported "
2216 "for threaded Tcl");
2217 return NULL;
2218 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002219#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002220
2221 if (self) {
2222 CHECK_TCL_APPARTMENT;
2223 }
2224
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002225 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002226 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002227 return NULL;
2228 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002229 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002230 return NULL;
2231 }
2232
Guido van Rossuma80649b2000-03-28 20:07:05 +00002233 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002234 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002235 return NULL;
2236
Barry Warsawfa701a81997-01-16 00:15:11 +00002237 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002238 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002239 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002240 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002241 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002242 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002243}
2244
2245static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002246Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002247{
Barry Warsawfa701a81997-01-16 00:15:11 +00002248 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002249 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002250
Guido van Rossum43713e52000-02-29 13:59:29 +00002251 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002252 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002253
Martin v. Löwisa9656492003-03-30 08:44:58 +00002254#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002255 if (!self && !tcl_lock) {
2256 /* We don't have the Tcl lock since Tcl is threaded. */
2257 PyErr_SetString(PyExc_RuntimeError,
2258 "_tkinter.deletefilehandler not supported "
2259 "for threaded Tcl");
2260 return NULL;
2261 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002262#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002263
2264 if (self) {
2265 CHECK_TCL_APPARTMENT;
2266 }
2267
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002268 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002269 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002270 return NULL;
2271
Guido van Rossuma80649b2000-03-28 20:07:05 +00002272 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002273
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002275 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002276 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002277 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002278 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002279 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002280}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002281#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002282
Barry Warsawfa701a81997-01-16 00:15:11 +00002283
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284/**** Tktt Object (timer token) ****/
2285
Jeremy Hylton938ace62002-07-17 16:30:39 +00002286static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002287
Guido van Rossum00d93061998-05-28 23:06:38 +00002288typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002289 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002290 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002291 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002292} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002293
2294static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002295Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002296{
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002298 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299
Guido van Rossum43713e52000-02-29 13:59:29 +00002300 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002301 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002302 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002303 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002304 v->token = NULL;
2305 }
2306 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002307 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002308 Py_DECREF(func);
2309 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002310 }
2311 Py_INCREF(Py_None);
2312 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002313}
2314
2315static PyMethodDef Tktt_methods[] =
2316{
Neal Norwitzb0493252002-03-31 14:44:22 +00002317 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002318 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002319};
2320
2321static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002322Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002323{
Barry Warsawfa701a81997-01-16 00:15:11 +00002324 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002325
Guido van Rossumb18618d2000-05-03 23:44:39 +00002326 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002327 if (v == NULL)
2328 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329
Guido van Rossum00d93061998-05-28 23:06:38 +00002330 Py_INCREF(func);
2331 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002332 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002333
2334 /* Extra reference, deleted when called or when handler is deleted */
2335 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002336 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337}
2338
2339static void
Fred Drake509d79a2000-07-08 04:04:38 +00002340Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341{
Guido van Rossum00d93061998-05-28 23:06:38 +00002342 TkttObject *v = (TkttObject *)self;
2343 PyObject *func = v->func;
2344
2345 Py_XDECREF(func);
2346
Guido van Rossumb18618d2000-05-03 23:44:39 +00002347 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348}
2349
Guido van Rossum597ac201998-05-12 14:36:19 +00002350static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002351Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002352{
Barry Warsawfa701a81997-01-16 00:15:11 +00002353 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002354 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355
Tim Peters885d4572001-11-28 20:27:42 +00002356 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002357 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002358 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359}
2360
2361static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002362Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363{
Barry Warsawfa701a81997-01-16 00:15:11 +00002364 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002365}
2366
2367static PyTypeObject Tktt_Type =
2368{
Guido van Rossum35d43371997-08-02 00:09:09 +00002369 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002370 0, /*ob_size */
2371 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002372 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002373 0, /*tp_itemsize */
2374 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002375 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002376 Tktt_GetAttr, /*tp_getattr */
2377 0, /*tp_setattr */
2378 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002379 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002380 0, /*tp_as_number */
2381 0, /*tp_as_sequence */
2382 0, /*tp_as_mapping */
2383 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384};
2385
Barry Warsawfa701a81997-01-16 00:15:11 +00002386
2387
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388/** Timer Handler **/
2389
2390static void
Fred Drake509d79a2000-07-08 04:04:38 +00002391TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002392{
Guido van Rossum00d93061998-05-28 23:06:38 +00002393 TkttObject *v = (TkttObject *)clientData;
2394 PyObject *func = v->func;
2395 PyObject *res;
2396
2397 if (func == NULL)
2398 return;
2399
2400 v->func = NULL;
2401
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002402 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002403
2404 res = PyEval_CallObject(func, NULL);
2405 Py_DECREF(func);
2406 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002407
Barry Warsawfa701a81997-01-16 00:15:11 +00002408 if (res == NULL) {
2409 errorInCmd = 1;
2410 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2411 }
2412 else
2413 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002414
2415 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002416}
2417
2418static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002419Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002420{
Barry Warsawfa701a81997-01-16 00:15:11 +00002421 int milliseconds;
2422 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002423 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002424
Guido van Rossum2834b972000-10-06 16:58:26 +00002425 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2426 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002427 return NULL;
2428 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002429 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002430 return NULL;
2431 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002432
Martin v. Löwisa9656492003-03-30 08:44:58 +00002433#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002434 if (!self && !tcl_lock) {
2435 /* We don't have the Tcl lock since Tcl is threaded. */
2436 PyErr_SetString(PyExc_RuntimeError,
2437 "_tkinter.createtimerhandler not supported "
2438 "for threaded Tcl");
2439 return NULL;
2440 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002441#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002442
2443 if (self) {
2444 CHECK_TCL_APPARTMENT;
2445 }
2446
Guido van Rossum00d93061998-05-28 23:06:38 +00002447 v = Tktt_New(func);
2448 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2449 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002450
Guido van Rossum00d93061998-05-28 23:06:38 +00002451 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002452}
2453
Barry Warsawfa701a81997-01-16 00:15:11 +00002454
Guido van Rossum18468821994-06-20 07:49:28 +00002455/** Event Loop **/
2456
Guido van Rossum18468821994-06-20 07:49:28 +00002457static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002458Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002459{
Barry Warsawfa701a81997-01-16 00:15:11 +00002460 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002461 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002462#ifdef WITH_THREAD
2463 PyThreadState *tstate = PyThreadState_Get();
2464#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002465
Guido van Rossum43713e52000-02-29 13:59:29 +00002466 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002467 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002468
Martin v. Löwisa9656492003-03-30 08:44:58 +00002469#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002470 if (!self && !tcl_lock) {
2471 /* We don't have the Tcl lock since Tcl is threaded. */
2472 PyErr_SetString(PyExc_RuntimeError,
2473 "_tkinter.mainloop not supported "
2474 "for threaded Tcl");
2475 return NULL;
2476 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002477#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002478
2479 if (self) {
2480 CHECK_TCL_APPARTMENT;
2481 self->dispatching = 1;
2482 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002483
Barry Warsawfa701a81997-01-16 00:15:11 +00002484 quitMainLoop = 0;
2485 while (Tk_GetNumMainWindows() > threshold &&
2486 !quitMainLoop &&
2487 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002488 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002489 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002490
2491#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002492 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002493 /* Allow other Python threads to run. */
2494 ENTER_TCL
2495 result = Tcl_DoOneEvent(0);
2496 LEAVE_TCL
2497 }
2498 else {
2499 Py_BEGIN_ALLOW_THREADS
2500 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2501 tcl_tstate = tstate;
2502 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2503 tcl_tstate = NULL;
2504 if(tcl_lock)PyThread_release_lock(tcl_lock);
2505 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002506 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002507 Py_END_ALLOW_THREADS
2508 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002509#else
2510 result = Tcl_DoOneEvent(0);
2511#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002512
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002513 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002514 if (self)
2515 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002516 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002517 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002518 if (result < 0)
2519 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002520 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002521 if (self)
2522 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002523 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002524
Barry Warsawfa701a81997-01-16 00:15:11 +00002525 if (errorInCmd) {
2526 errorInCmd = 0;
2527 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2528 excInCmd = valInCmd = trbInCmd = NULL;
2529 return NULL;
2530 }
2531 Py_INCREF(Py_None);
2532 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002533}
2534
2535static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002536Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002537{
Guido van Rossum35d43371997-08-02 00:09:09 +00002538 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002539 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002540
Guido van Rossum43713e52000-02-29 13:59:29 +00002541 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002542 return NULL;
2543
Guido van Rossum00d93061998-05-28 23:06:38 +00002544 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002545 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002546 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002547 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002548}
2549
2550static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002551Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002552{
2553
Guido van Rossum43713e52000-02-29 13:59:29 +00002554 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002555 return NULL;
2556
2557 quitMainLoop = 1;
2558 Py_INCREF(Py_None);
2559 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002560}
2561
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002562static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002563Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002564{
2565
Guido van Rossum43713e52000-02-29 13:59:29 +00002566 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002567 return NULL;
2568
2569 return PyInt_FromLong((long)Tkapp_Interp(self));
2570}
2571
David Aschere2b4b322004-02-18 05:59:53 +00002572static PyObject *
2573Tkapp_TkInit(PyObject *self, PyObject *args)
2574{
2575 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002576 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002577 const char * _tk_exists = NULL;
2578 PyObject *res = NULL;
2579 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002580 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002581
2582 /* We want to guard against calling Tk_Init() multiple times */
2583 CHECK_TCL_APPARTMENT;
2584 ENTER_TCL
2585 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2586 ENTER_OVERLAP
2587 if (err == TCL_ERROR) {
2588 res = Tkinter_Error(self);
2589 } else {
2590 _tk_exists = Tkapp_Result(self);
2591 }
2592 LEAVE_OVERLAP_TCL
2593 if (err == TCL_ERROR) {
2594 return NULL;
2595 }
2596 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2597 if (Tk_Init(interp) == TCL_ERROR) {
2598 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2599 return NULL;
2600 }
2601 }
2602 Py_INCREF(Py_None);
2603 return Py_None;
2604}
Barry Warsawfa701a81997-01-16 00:15:11 +00002605
Martin v. Löwisffad6332002-11-26 09:28:05 +00002606static PyObject *
2607Tkapp_WantObjects(PyObject *self, PyObject *args)
2608{
2609
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002610 int wantobjects = -1;
2611 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002612 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002613 if (wantobjects == -1)
2614 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002615 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002616
2617 Py_INCREF(Py_None);
2618 return Py_None;
2619}
2620
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002621static PyObject *
2622Tkapp_WillDispatch(PyObject *self, PyObject *args)
2623{
2624
2625 ((TkappObject*)self)->dispatching = 1;
2626
2627 Py_INCREF(Py_None);
2628 return Py_None;
2629}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002630
Barry Warsawfa701a81997-01-16 00:15:11 +00002631
Guido van Rossum18468821994-06-20 07:49:28 +00002632/**** Tkapp Method List ****/
2633
2634static PyMethodDef Tkapp_methods[] =
2635{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002636 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002637 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002638 {"call", Tkapp_Call, METH_OLDARGS},
2639 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2640 {"eval", Tkapp_Eval, METH_VARARGS},
2641 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2642 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2643 {"record", Tkapp_Record, METH_VARARGS},
2644 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2645 {"setvar", Tkapp_SetVar, METH_VARARGS},
2646 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2647 {"getvar", Tkapp_GetVar, METH_VARARGS},
2648 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2649 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2650 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2651 {"getint", Tkapp_GetInt, METH_VARARGS},
2652 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2653 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2654 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2655 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2656 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2657 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2658 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2659 {"split", Tkapp_Split, METH_VARARGS},
2660 {"merge", Tkapp_Merge, METH_OLDARGS},
2661 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2662 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002663#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002664 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2665 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002666#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002667 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2668 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2669 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2670 {"quit", Tkapp_Quit, METH_VARARGS},
2671 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002672 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002673 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002674};
2675
Barry Warsawfa701a81997-01-16 00:15:11 +00002676
2677
Guido van Rossum18468821994-06-20 07:49:28 +00002678/**** Tkapp Type Methods ****/
2679
2680static void
Fred Drake509d79a2000-07-08 04:04:38 +00002681Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002682{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002683 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002684 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002685 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002686 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002687 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002688 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002689}
2690
2691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002692Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002693{
Guido van Rossum35d43371997-08-02 00:09:09 +00002694 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002695}
2696
2697static PyTypeObject Tkapp_Type =
2698{
Guido van Rossum35d43371997-08-02 00:09:09 +00002699 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002700 0, /*ob_size */
2701 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002702 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002703 0, /*tp_itemsize */
2704 Tkapp_Dealloc, /*tp_dealloc */
2705 0, /*tp_print */
2706 Tkapp_GetAttr, /*tp_getattr */
2707 0, /*tp_setattr */
2708 0, /*tp_compare */
2709 0, /*tp_repr */
2710 0, /*tp_as_number */
2711 0, /*tp_as_sequence */
2712 0, /*tp_as_mapping */
2713 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002714};
2715
Barry Warsawfa701a81997-01-16 00:15:11 +00002716
2717
Guido van Rossum18468821994-06-20 07:49:28 +00002718/**** Tkinter Module ****/
2719
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002720typedef struct {
2721 PyObject* tuple;
2722 int size; /* current size */
2723 int maxsize; /* allocated size */
2724} FlattenContext;
2725
2726static int
2727_bump(FlattenContext* context, int size)
2728{
Guido van Rossum2834b972000-10-06 16:58:26 +00002729 /* expand tuple to hold (at least) size new items.
2730 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731
2732 int maxsize = context->maxsize * 2;
2733
2734 if (maxsize < context->size + size)
2735 maxsize = context->size + size;
2736
2737 context->maxsize = maxsize;
2738
Tim Peters4324aa32001-05-28 22:30:08 +00002739 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740}
2741
2742static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002743_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002744{
2745 /* add tuple or list to argument tuple (recursively) */
2746
2747 int i, size;
2748
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002749 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002750 PyErr_SetString(PyExc_ValueError,
2751 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002752 return 0;
2753 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002754 size = PyList_GET_SIZE(item);
2755 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002756 if (context->size + size > context->maxsize &&
2757 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002758 return 0;
2759 /* copy items to output tuple */
2760 for (i = 0; i < size; i++) {
2761 PyObject *o = PyList_GET_ITEM(item, i);
2762 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002763 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002764 return 0;
2765 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002766 if (context->size + 1 > context->maxsize &&
2767 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002768 return 0;
2769 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002770 PyTuple_SET_ITEM(context->tuple,
2771 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772 }
2773 }
2774 } else if (PyTuple_Check(item)) {
2775 /* same, for tuples */
2776 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002777 if (context->size + size > context->maxsize &&
2778 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002779 return 0;
2780 for (i = 0; i < size; i++) {
2781 PyObject *o = PyTuple_GET_ITEM(item, i);
2782 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002783 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002784 return 0;
2785 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002786 if (context->size + 1 > context->maxsize &&
2787 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788 return 0;
2789 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002790 PyTuple_SET_ITEM(context->tuple,
2791 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792 }
2793 }
2794 } else {
2795 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2796 return 0;
2797 }
2798 return 1;
2799}
2800
2801static PyObject *
2802Tkinter_Flatten(PyObject* self, PyObject* args)
2803{
2804 FlattenContext context;
2805 PyObject* item;
2806
2807 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2808 return NULL;
2809
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002810 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811 if (context.maxsize <= 0)
2812 return PyTuple_New(0);
2813
2814 context.tuple = PyTuple_New(context.maxsize);
2815 if (!context.tuple)
2816 return NULL;
2817
2818 context.size = 0;
2819
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002820 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002821 return NULL;
2822
Tim Peters4324aa32001-05-28 22:30:08 +00002823 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002824 return NULL;
2825
2826 return context.tuple;
2827}
2828
Guido van Rossum18468821994-06-20 07:49:28 +00002829static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002830Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002831{
Barry Warsawfa701a81997-01-16 00:15:11 +00002832 char *screenName = NULL;
2833 char *baseName = NULL;
2834 char *className = NULL;
2835 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002836 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002837 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Guido van Rossum18468821994-06-20 07:49:28 +00002838
Guido van Rossum35d43371997-08-02 00:09:09 +00002839 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002840 if (baseName != NULL)
2841 baseName++;
2842 else
2843 baseName = Py_GetProgramName();
2844 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002845
David Aschere2b4b322004-02-18 05:59:53 +00002846 if (!PyArg_ParseTuple(args, "|zssiii:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002847 &screenName, &baseName, &className,
David Aschere2b4b322004-02-18 05:59:53 +00002848 &interactive, &wantobjects, &wantTk))
Barry Warsawfa701a81997-01-16 00:15:11 +00002849 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002850
Barry Warsawfa701a81997-01-16 00:15:11 +00002851 return (PyObject *) Tkapp_New(screenName, baseName, className,
David Aschere2b4b322004-02-18 05:59:53 +00002852 interactive, wantobjects, wantTk);
Guido van Rossum18468821994-06-20 07:49:28 +00002853}
2854
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002855static PyObject *
2856Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2857{
2858 int new_val;
2859 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2860 return NULL;
2861 if (new_val < 0) {
2862 PyErr_SetString(PyExc_ValueError,
2863 "busywaitinterval must be >= 0");
2864 return NULL;
2865 }
2866 Tkinter_busywaitinterval = new_val;
2867 Py_INCREF(Py_None);
2868 return Py_None;
2869}
2870
2871static char setbusywaitinterval_doc[] =
2872"setbusywaitinterval(n) -> None\n\
2873\n\
2874Set the busy-wait interval in milliseconds between successive\n\
2875calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2876It should be set to a divisor of the maximum time between\n\
2877frames in an animation.";
2878
2879static PyObject *
2880Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2881{
2882 return PyInt_FromLong(Tkinter_busywaitinterval);
2883}
2884
2885static char getbusywaitinterval_doc[] =
2886"getbusywaitinterval() -> int\n\
2887\n\
2888Return the current busy-wait interval between successive\n\
2889calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2890
Guido van Rossum18468821994-06-20 07:49:28 +00002891static PyMethodDef moduleMethods[] =
2892{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002893 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2894 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002895#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002896 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2897 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002898#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002899 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2900 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2901 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2902 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002903 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2904 setbusywaitinterval_doc},
2905 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2906 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002907 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002908};
2909
Guido van Rossum7bf15641998-05-22 18:28:17 +00002910#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002911
2912static int stdin_ready = 0;
2913
Guido van Rossumad4db171998-06-13 13:56:28 +00002914#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002915static void
Fred Drake509d79a2000-07-08 04:04:38 +00002916MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002917{
2918 stdin_ready = 1;
2919}
Guido van Rossumad4db171998-06-13 13:56:28 +00002920#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002921
Martin v. Löwisa9656492003-03-30 08:44:58 +00002922#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002923static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002924#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002925
Guido van Rossum18468821994-06-20 07:49:28 +00002926static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002927EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002928{
Guido van Rossumad4db171998-06-13 13:56:28 +00002929#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002930 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002931#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002932#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002933 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002934#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002935 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002936 errorInCmd = 0;
2937#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002938 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002939 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002940#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002941 while (!errorInCmd && !stdin_ready) {
2942 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002943#ifdef MS_WINDOWS
2944 if (_kbhit()) {
2945 stdin_ready = 1;
2946 break;
2947 }
2948#endif
2949#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002950 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002951 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002952 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002953
Guido van Rossum00d93061998-05-28 23:06:38 +00002954 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002955
2956 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002957 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002958 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002959 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002960 Py_END_ALLOW_THREADS
2961#else
2962 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002963#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002964
2965 if (result < 0)
2966 break;
2967 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002968#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002969 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002970#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002971 if (errorInCmd) {
2972 errorInCmd = 0;
2973 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2974 excInCmd = valInCmd = trbInCmd = NULL;
2975 PyErr_Print();
2976 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002977#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002978 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002979#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002980 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002981}
Guido van Rossum18468821994-06-20 07:49:28 +00002982
Guido van Rossum00d93061998-05-28 23:06:38 +00002983#endif
2984
Guido van Rossum7bf15641998-05-22 18:28:17 +00002985static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002986EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002987{
Guido van Rossum00d93061998-05-28 23:06:38 +00002988#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002989 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002990#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002991 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002992#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002993 PyOS_InputHook = EventHook;
2994 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002995#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002996}
2997
2998static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002999DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003000{
Guido van Rossum00d93061998-05-28 23:06:38 +00003001#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003002 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3003 PyOS_InputHook = NULL;
3004 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003005#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003006}
3007
Barry Warsawfa701a81997-01-16 00:15:11 +00003008
3009/* all errors will be checked in one fell swoop in init_tkinter() */
3010static void
Fred Drake509d79a2000-07-08 04:04:38 +00003011ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003012{
3013 PyObject *v = PyInt_FromLong(val);
3014 if (v) {
3015 PyDict_SetItemString(d, name, v);
3016 Py_DECREF(v);
3017 }
3018}
3019static void
Fred Drake509d79a2000-07-08 04:04:38 +00003020ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003021{
3022 PyObject *v = PyString_FromString(val);
3023 if (v) {
3024 PyDict_SetItemString(d, name, v);
3025 Py_DECREF(v);
3026 }
3027}
3028
3029
Mark Hammond62b1ab12002-07-23 06:31:15 +00003030PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003031init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003032{
Barry Warsawfa701a81997-01-16 00:15:11 +00003033 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003034
Barry Warsawfa701a81997-01-16 00:15:11 +00003035 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003036
3037#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003038 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003039#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003040
Barry Warsawfa701a81997-01-16 00:15:11 +00003041 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003042
Barry Warsawfa701a81997-01-16 00:15:11 +00003043 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003044 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003045 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003046
Guido van Rossum35d43371997-08-02 00:09:09 +00003047 ins_long(d, "READABLE", TCL_READABLE);
3048 ins_long(d, "WRITABLE", TCL_WRITABLE);
3049 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3050 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3051 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3052 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3053 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3054 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3055 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003056 ins_string(d, "TK_VERSION", TK_VERSION);
3057 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003058
Guido van Rossum83551bf1997-09-13 00:44:23 +00003059 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003060
3061 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003062 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3063
Martin v. Löwisffad6332002-11-26 09:28:05 +00003064 PyTclObject_Type.ob_type = &PyType_Type;
3065 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003066
3067#ifdef TK_AQUA
3068 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3069 * start waking up. Note that Tcl_FindExecutable will do this, this
3070 * code must be above it! The original warning from
3071 * tkMacOSXAppInit.c is copied below.
3072 *
3073 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3074 * Tcl interpreter for now. It probably should work to do this
3075 * in the other order, but for now it doesn't seem to.
3076 *
3077 */
3078 Tk_MacOSXSetupTkNotifier();
3079#endif
3080
3081
Guido van Rossume187b0e2000-03-27 21:46:29 +00003082 /* This helps the dynamic loader; in Unicode aware Tcl versions
3083 it also helps Tcl find its encodings. */
3084 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003085
Barry Warsawfa701a81997-01-16 00:15:11 +00003086 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003087 return;
3088
Guido van Rossum43ff8681998-07-14 18:02:13 +00003089#if 0
3090 /* This was not a good idea; through <Destroy> bindings,
3091 Tcl_Finalize() may invoke Python code but at that point the
3092 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003093 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003094#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003095
Guido van Rossum18468821994-06-20 07:49:28 +00003096}