blob: 48e7cebfe034cd3fe6ed710d3c8ee61120f39952 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Jason Tishlerbbe89612002-12-31 20:30:46 +000070/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000071#ifndef CONST84_RETURN
72#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000073#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000074#define CONST
75#endif
76
Guido van Rossum3e819a71997-08-01 19:29:02 +000077#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000079#if TKMAJORMINOR < 8002
80#error "Tk older than 8.2 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
101/* Tcl_CreateFileHandler() changed several times; these macros deal with the
102 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
103 Unix, only because Jack added it back); when available on Windows, it only
104 applies to sockets. */
105
Guido van Rossum7bf15641998-05-22 18:28:17 +0000106#ifdef MS_WINDOWS
107#define FHANDLETYPE TCL_WIN_SOCKET
108#else
109#define FHANDLETYPE TCL_UNIX_FD
110#endif
111
Guido van Rossum00d93061998-05-28 23:06:38 +0000112/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
113 which uses this to handle Tcl events while the user is typing commands. */
114
115#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#define WAIT_FOR_STDIN
117#endif
118
Guido van Rossum00d93061998-05-28 23:06:38 +0000119#endif /* HAVE_CREATEFILEHANDLER */
120
Guido van Rossumad4db171998-06-13 13:56:28 +0000121#ifdef MS_WINDOWS
122#include <conio.h>
123#define WAIT_FOR_STDIN
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126#ifdef WITH_THREAD
127
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000128/* The threading situation is complicated. Tcl is not thread-safe, except
129 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000130 So we need to use a lock around all uses of Tcl. Previously, the Python
131 interpreter lock was used for this. However, this causes problems when
132 other Python threads need to run while Tcl is blocked waiting for events.
133
134 To solve this problem, a separate lock for Tcl is introduced. Holding it
135 is incompatible with holding Python's interpreter lock. The following four
136 macros manipulate both locks together.
137
138 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
139 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
140 that could call an event handler, or otherwise affect the state of a Tcl
141 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000142 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000143 released and the lock for Tcl has been acquired.
144
Guido van Rossum5e977831998-06-15 14:03:52 +0000145 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
146 (For example, when transferring data from the Tcl interpreter result to a
147 Python string object.) This can be done by using different macros to close
148 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
149 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
150 releases the Tcl lock.
151
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000152 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 handlers when the handler needs to use Python. Such event handlers are
154 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000155 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000156 the Python interpreter lock, restoring the appropriate thread state, and
157 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
158 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000159 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000160
161 These locks expand to several statements and brackets; they should not be
162 used in branches of if statements and the like.
163
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000164 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
165 only valid in the thread that created it, and all Tk activity must happen in this
166 thread, also. That means that the mainloop must be invoked in the thread that
167 created the interpreter. Invoking commands from other threads is possible;
168 _tkinter will queue an event for the interpreter thread, which will then
169 execute the command and pass back the result. If the main thread is not in the
170 mainloop, and invoking commands causes an exception; if the main loop is running
171 but not processing events, the command invocation will block.
172
173 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
174 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
175 threads. So we use the Tcl TLS API.
176
Guido van Rossum00d93061998-05-28 23:06:38 +0000177*/
178
Guido van Rossum65d5b571998-12-21 19:32:43 +0000179static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180
181#ifdef TCL_THREADS
182static Tcl_ThreadDataKey state_key;
183typedef PyThreadState *ThreadSpecificData;
184#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
185#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000186static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000187#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
189#define ENTER_TCL \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000190 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000191 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
193#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000195
Guido van Rossum62320c91998-06-15 04:36:09 +0000196#define ENTER_OVERLAP \
197 Py_END_ALLOW_THREADS
198
199#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000200 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000201
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000202#define ENTER_PYTHON \
203 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
206#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000207 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
209
210#define CHECK_TCL_APPARTMENT \
211 if (((TkappObject *)self)->threaded && \
212 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
213 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
214 return 0; \
215 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000216
217#else
218
219#define ENTER_TCL
220#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000221#define ENTER_OVERLAP
222#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000223#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000224#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000225#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#endif
228
Guido van Rossum97867b21996-08-08 19:09:53 +0000229#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000230#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000231#endif
232
Guido van Rossum18468821994-06-20 07:49:28 +0000233/**** Tkapp Object Declaration ****/
234
Jeremy Hylton938ace62002-07-17 16:30:39 +0000235static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000236
Guido van Rossum00d93061998-05-28 23:06:38 +0000237typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +0000238 PyObject_HEAD
239 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000240 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000241 int threaded; /* True if tcl_platform[threaded] */
242 Tcl_ThreadId thread_id;
243 int dispatching;
244 /* We cannot include tclInt.h, as this is internal.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000245 So we cache interesting types here. */
246 Tcl_ObjType *BooleanType;
247 Tcl_ObjType *ByteArrayType;
248 Tcl_ObjType *DoubleType;
249 Tcl_ObjType *IntType;
250 Tcl_ObjType *ListType;
251 Tcl_ObjType *ProcBodyType;
252 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000253} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000254
255#define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000256#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000257#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000258
Guido van Rossum35d43371997-08-02 00:09:09 +0000259#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000260(void *) v, ((PyObject *) v)->ob_refcnt))
Guido van Rossum18468821994-06-20 07:49:28 +0000261
Barry Warsawfa701a81997-01-16 00:15:11 +0000262
263
Guido van Rossum18468821994-06-20 07:49:28 +0000264/**** Error Handling ****/
265
266static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000267static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000268static int errorInCmd = 0;
269static PyObject *excInCmd;
270static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000271static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000272
Barry Warsawfa701a81997-01-16 00:15:11 +0000273
274
Guido van Rossum18468821994-06-20 07:49:28 +0000275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000276Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000277{
Barry Warsawfa701a81997-01-16 00:15:11 +0000278 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
279 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000280}
281
Barry Warsawfa701a81997-01-16 00:15:11 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Guido van Rossum18468821994-06-20 07:49:28 +0000284/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000285
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000286static int Tkinter_busywaitinterval = 20;
287
Guido van Rossum00d93061998-05-28 23:06:38 +0000288#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000289#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000290
Guido van Rossum00d93061998-05-28 23:06:38 +0000291/* Millisecond sleep() for Unix platforms. */
292
293static void
Fred Drake509d79a2000-07-08 04:04:38 +0000294Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000295{
296 /* XXX Too bad if you don't have select(). */
297 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000298 t.tv_sec = milli/1000;
299 t.tv_usec = (milli%1000) * 1000;
300 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
301}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000302#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000303
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000304/* Wait up to 1s for the mainloop to come up. */
305
306static int
307WaitForMainloop(TkappObject* self)
308{
309 int i;
310 for (i = 0; i < 10; i++) {
311 if (self->dispatching)
312 return 1;
313 Py_BEGIN_ALLOW_THREADS
314 Sleep(100);
315 Py_END_ALLOW_THREADS
316 }
317 if (self->dispatching)
318 return 1;
319 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
320 return 0;
321}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000322#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000323
Guido van Rossum00d93061998-05-28 23:06:38 +0000324
Guido van Rossum18468821994-06-20 07:49:28 +0000325static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000326AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000327{
Guido van Rossum35d43371997-08-02 00:09:09 +0000328 if (PyString_Check(value))
329 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000330#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000331 else if (PyUnicode_Check(value)) {
332 PyObject *v = PyUnicode_AsUTF8String(value);
333 if (v == NULL)
334 return NULL;
335 if (PyList_Append(tmp, v) != 0) {
336 Py_DECREF(v);
337 return NULL;
338 }
339 Py_DECREF(v);
340 return PyString_AsString(v);
341 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000342#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000343 else {
344 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000345 if (v == NULL)
346 return NULL;
347 if (PyList_Append(tmp, v) != 0) {
348 Py_DECREF(v);
349 return NULL;
350 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 Py_DECREF(v);
352 return PyString_AsString(v);
353 }
Guido van Rossum18468821994-06-20 07:49:28 +0000354}
355
Barry Warsawfa701a81997-01-16 00:15:11 +0000356
357
Guido van Rossum18468821994-06-20 07:49:28 +0000358#define ARGSZ 64
359
360static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000361Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000362{
Barry Warsawfa701a81997-01-16 00:15:11 +0000363 PyObject *tmp = NULL;
364 char *argvStore[ARGSZ];
365 char **argv = NULL;
366 int fvStore[ARGSZ];
367 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000368 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000369 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000370
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 if (!(tmp = PyList_New(0)))
372 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000373
Barry Warsawfa701a81997-01-16 00:15:11 +0000374 argv = argvStore;
375 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000376
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 if (args == NULL)
378 argc = 0;
379
380 else if (!PyTuple_Check(args)) {
381 argc = 1;
382 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000383 if (!(argv[0] = AsString(args, tmp)))
384 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000385 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000386 else {
387 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Barry Warsawfa701a81997-01-16 00:15:11 +0000389 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000390 argv = (char **)ckalloc(argc * sizeof(char *));
391 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000392 if (argv == NULL || fv == NULL) {
393 PyErr_NoMemory();
394 goto finally;
395 }
396 }
397
398 for (i = 0; i < argc; i++) {
399 PyObject *v = PyTuple_GetItem(args, i);
400 if (PyTuple_Check(v)) {
401 fv[i] = 1;
402 if (!(argv[i] = Merge(v)))
403 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000404 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000405 }
406 else if (v == Py_None) {
407 argc = i;
408 break;
409 }
410 else {
411 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 if (!(argv[i] = AsString(v, tmp)))
413 goto finally;
414 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000415 }
416 }
Guido van Rossum18468821994-06-20 07:49:28 +0000417 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000418 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000419 if (res == NULL)
420 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000421
Barry Warsawfa701a81997-01-16 00:15:11 +0000422 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000423 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000424 if (fv[i]) {
425 ckfree(argv[i]);
426 }
427 if (argv != argvStore)
428 ckfree(FREECAST argv);
429 if (fv != fvStore)
430 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000431
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 Py_DECREF(tmp);
433 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000434}
435
Barry Warsawfa701a81997-01-16 00:15:11 +0000436
437
Guido van Rossum18468821994-06-20 07:49:28 +0000438static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000439Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000440{
Barry Warsawfa701a81997-01-16 00:15:11 +0000441 int argc;
442 char **argv;
443 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000444
Barry Warsawfa701a81997-01-16 00:15:11 +0000445 if (list == NULL) {
446 Py_INCREF(Py_None);
447 return Py_None;
448 }
Guido van Rossum18468821994-06-20 07:49:28 +0000449
Guido van Rossum00d93061998-05-28 23:06:38 +0000450 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 /* Not a list.
452 * Could be a quoted string containing funnies, e.g. {"}.
453 * Return the string itself.
454 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 return PyString_FromString(list);
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Barry Warsawfa701a81997-01-16 00:15:11 +0000458 if (argc == 0)
459 v = PyString_FromString("");
460 else if (argc == 1)
461 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000462 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000463 int i;
464 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000467 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000468 Py_DECREF(v);
469 v = NULL;
470 break;
471 }
472 PyTuple_SetItem(v, i, w);
473 }
474 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000477}
478
Martin v. Löwisffad6332002-11-26 09:28:05 +0000479/* In some cases, Tcl will still return strings that are supposed to be
480 lists. SplitObj walks through a nested tuple, finding string objects that
481 need to be split. */
482
483PyObject *
484SplitObj(PyObject *arg)
485{
486 if (PyTuple_Check(arg)) {
487 int i, size;
488 PyObject *elem, *newelem, *result;
489
490 size = PyTuple_Size(arg);
491 result = NULL;
492 /* Recursively invoke SplitObj for all tuple items.
493 If this does not return a new object, no action is
494 needed. */
495 for(i = 0; i < size; i++) {
496 elem = PyTuple_GetItem(arg, i);
497 newelem = SplitObj(elem);
498 if (!newelem) {
499 Py_XDECREF(result);
500 return NULL;
501 }
502 if (!result) {
503 int k;
504 if (newelem == elem) {
505 Py_DECREF(newelem);
506 continue;
507 }
508 result = PyTuple_New(size);
509 if (!result)
510 return NULL;
511 for(k = 0; k < i; k++) {
512 elem = PyTuple_GetItem(arg, k);
513 Py_INCREF(elem);
514 PyTuple_SetItem(result, k, elem);
515 }
516 }
517 PyTuple_SetItem(result, i, newelem);
518 }
519 if (result)
520 return result;
521 /* Fall through, returning arg. */
522 }
523 else if (PyString_Check(arg)) {
524 int argc;
525 char **argv;
526 char *list = PyString_AsString(arg);
527
528 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
529 Py_INCREF(arg);
530 return arg;
531 }
532 Tcl_Free(FREECAST argv);
533 if (argc > 1)
534 return Split(PyString_AsString(arg));
535 /* Fall through, returning arg. */
536 }
537 Py_INCREF(arg);
538 return arg;
539}
Barry Warsawfa701a81997-01-16 00:15:11 +0000540
541
Guido van Rossum18468821994-06-20 07:49:28 +0000542/**** Tkapp Object ****/
543
544#ifndef WITH_APPINIT
545int
Fred Drake509d79a2000-07-08 04:04:38 +0000546Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000547{
Barry Warsawfa701a81997-01-16 00:15:11 +0000548 Tk_Window main;
David Aschere2b4b322004-02-18 05:59:53 +0000549 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000550
Barry Warsawfa701a81997-01-16 00:15:11 +0000551 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000552 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000553 return TCL_ERROR;
554 }
David Aschere2b4b322004-02-18 05:59:53 +0000555 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
556 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
557 main = Tk_MainWindow(interp);
558 if (Tk_Init(interp) == TCL_ERROR) {
559 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
560 return TCL_ERROR;
561 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000562 }
563 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000564}
565#endif /* !WITH_APPINIT */
566
Guido van Rossum18468821994-06-20 07:49:28 +0000567
Barry Warsawfa701a81997-01-16 00:15:11 +0000568
569
570/* Initialize the Tk application; see the `main' function in
571 * `tkMain.c'.
572 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000573
Thomas Wouters58d05102000-07-24 14:43:35 +0000574static void EnableEventHook(void); /* Forward */
575static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000576
Barry Warsawfa701a81997-01-16 00:15:11 +0000577static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000578Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000579 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000580{
581 TkappObject *v;
582 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000583
Guido van Rossumb18618d2000-05-03 23:44:39 +0000584 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000585 if (v == NULL)
586 return NULL;
587
588 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000589 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000590 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
591 TCL_GLOBAL_ONLY) != NULL;
592 v->thread_id = Tcl_GetCurrentThread();
593 v->dispatching = 0;
594
595#ifndef TCL_THREADS
596 if (v->threaded) {
597 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
598 Py_DECREF(v);
599 return 0;
600 }
601#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000602#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000603 if (v->threaded && tcl_lock) {
604 /* If Tcl is threaded, we don't need the lock. */
605 PyThread_free_lock(tcl_lock);
606 tcl_lock = NULL;
607 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000608#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000609
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000610 v->BooleanType = Tcl_GetObjType("boolean");
611 v->ByteArrayType = Tcl_GetObjType("bytearray");
612 v->DoubleType = Tcl_GetObjType("double");
613 v->IntType = Tcl_GetObjType("int");
614 v->ListType = Tcl_GetObjType("list");
615 v->ProcBodyType = Tcl_GetObjType("procbody");
616 v->StringType = Tcl_GetObjType("string");
617
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000618 /* Delete the 'exit' command, which can screw things up */
619 Tcl_DeleteCommand(v->interp, "exit");
620
Barry Warsawfa701a81997-01-16 00:15:11 +0000621 if (screenName != NULL)
622 Tcl_SetVar2(v->interp, "env", "DISPLAY",
623 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000624
Barry Warsawfa701a81997-01-16 00:15:11 +0000625 if (interactive)
626 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
627 else
628 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000629
Barry Warsawfa701a81997-01-16 00:15:11 +0000630 /* This is used to get the application class for Tk 4.1 and up */
631 argv0 = (char*)ckalloc(strlen(className) + 1);
632 if (!argv0) {
633 PyErr_NoMemory();
634 Py_DECREF(v);
635 return NULL;
636 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000637
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 strcpy(argv0, className);
Neal Norwitz9dbc7dd2005-12-19 06:08:59 +0000639 if (isupper(Py_CHARMASK(argv0[0])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000640 argv0[0] = tolower(argv0[0]);
641 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
642 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000643
David Aschere2b4b322004-02-18 05:59:53 +0000644 if (! wantTk) {
645 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
646 }
647
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000648 /* some initial arguments need to be in argv */
649 if (sync || use) {
Tim Peters51fa3b72004-08-04 02:16:48 +0000650 char *args;
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000651 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000652
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000653 if (sync)
654 len += sizeof "-sync";
655 if (use)
656 len += strlen(use) + sizeof "-use ";
657
Tim Peters51fa3b72004-08-04 02:16:48 +0000658 args = (char*)ckalloc(len);
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659 if (!args) {
660 PyErr_NoMemory();
661 Py_DECREF(v);
662 return NULL;
663 }
664
665 args[0] = '\0';
666 if (sync)
667 strcat(args, "-sync");
668 if (use) {
669 if (sync)
670 strcat(args, " ");
671 strcat(args, "-use ");
672 strcat(args, use);
673 }
674
675 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
676 ckfree(args);
677 }
678
Barry Warsawfa701a81997-01-16 00:15:11 +0000679 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000680 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000681
Guido van Rossum7bf15641998-05-22 18:28:17 +0000682 EnableEventHook();
683
Barry Warsawfa701a81997-01-16 00:15:11 +0000684 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000685}
686
Barry Warsawfa701a81997-01-16 00:15:11 +0000687
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000688static void
689Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
690 Tcl_Condition *cond, Tcl_Mutex *mutex)
691{
692 Py_BEGIN_ALLOW_THREADS;
693 Tcl_MutexLock(mutex);
694 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
695 Tcl_ThreadAlert(self->thread_id);
696 Tcl_ConditionWait(cond, mutex, NULL);
697 Tcl_MutexUnlock(mutex);
698 Py_END_ALLOW_THREADS
699}
700
Barry Warsawfa701a81997-01-16 00:15:11 +0000701
Guido van Rossum18468821994-06-20 07:49:28 +0000702/** Tcl Eval **/
703
Martin v. Löwisffad6332002-11-26 09:28:05 +0000704typedef struct {
705 PyObject_HEAD
706 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000707 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000708} PyTclObject;
709
710staticforward PyTypeObject PyTclObject_Type;
711#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
712
713static PyObject *
714newPyTclObject(Tcl_Obj *arg)
715{
716 PyTclObject *self;
717 self = PyObject_New(PyTclObject, &PyTclObject_Type);
718 if (self == NULL)
719 return NULL;
720 Tcl_IncrRefCount(arg);
721 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000722 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000723 return (PyObject*)self;
724}
725
726static void
727PyTclObject_dealloc(PyTclObject *self)
728{
729 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000730 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000731 PyObject_Del(self);
732}
733
734static PyObject *
735PyTclObject_str(PyTclObject *self)
736{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000737 if (self->string && PyString_Check(self->string)) {
738 Py_INCREF(self->string);
739 return self->string;
740 }
741 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742 return PyString_FromString(Tcl_GetString(self->value));
743}
744
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000745static char*
746PyTclObject_TclString(PyObject *self)
747{
748 return Tcl_GetString(((PyTclObject*)self)->value);
749}
750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000752PyDoc_STRVAR(PyTclObject_string__doc__,
753"the string representation of this object, either as string or Unicode");
754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755static PyObject *
756PyTclObject_string(PyTclObject *self, void *ignored)
757{
758 char *s;
759 int i, len;
760 if (!self->string) {
761 s = Tcl_GetStringFromObj(self->value, &len);
762 for (i = 0; i < len; i++)
763 if (s[i] & 0x80)
764 break;
765#ifdef Py_USING_UNICODE
766 if (i == len)
767 /* It is an ASCII string. */
768 self->string = PyString_FromStringAndSize(s, len);
769 else {
770 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
771 if (!self->string) {
772 PyErr_Clear();
773 self->string = PyString_FromStringAndSize(s, len);
774 }
775 }
776#else
777 self->string = PyString_FromStringAndSize(s, len);
778#endif
779 if (!self->string)
780 return NULL;
781 }
782 Py_INCREF(self->string);
783 return self->string;
784}
785
786#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000787PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
788
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000789static PyObject *
790PyTclObject_unicode(PyTclObject *self, void *ignored)
791{
792 char *s;
793 int len;
794 if (self->string && PyUnicode_Check(self->string)) {
795 Py_INCREF(self->string);
796 return self->string;
797 }
798 /* XXX Could chache result if it is non-ASCII. */
799 s = Tcl_GetStringFromObj(self->value, &len);
800 return PyUnicode_DecodeUTF8(s, len, "strict");
801}
802#endif
803
Martin v. Löwisffad6332002-11-26 09:28:05 +0000804static PyObject *
805PyTclObject_repr(PyTclObject *self)
806{
807 char buf[50];
Martin v. Löwisfba73692004-11-13 11:13:35 +0000808 PyOS_snprintf(buf, 50, "<%s object at %p>",
809 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810 return PyString_FromString(buf);
811}
812
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000813static int
814PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
815{
816 int res;
817 res = strcmp(Tcl_GetString(self->value),
818 Tcl_GetString(other->value));
819 if (res < 0) return -1;
820 if (res > 0) return 1;
821 return 0;
822}
823
Martin v. Löwis39195712003-01-04 00:33:13 +0000824PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
825
Martin v. Löwisffad6332002-11-26 09:28:05 +0000826static PyObject*
827get_typename(PyTclObject* obj, void* ignored)
828{
829 return PyString_FromString(obj->value->typePtr->name);
830}
831
Martin v. Löwis39195712003-01-04 00:33:13 +0000832
Martin v. Löwisffad6332002-11-26 09:28:05 +0000833static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000834 {"typename", (getter)get_typename, NULL, get_typename__doc__},
835 {"string", (getter)PyTclObject_string, NULL,
836 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837 {0},
838};
839
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000840static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000841#ifdef Py_USING_UNICODE
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000842 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000843 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000844#endif
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000845 {0}
846};
847
Martin v. Löwisffad6332002-11-26 09:28:05 +0000848statichere PyTypeObject PyTclObject_Type = {
849 PyObject_HEAD_INIT(NULL)
850 0, /*ob_size*/
851 "_tkinter.Tcl_Obj", /*tp_name*/
852 sizeof(PyTclObject), /*tp_basicsize*/
853 0, /*tp_itemsize*/
854 /* methods */
855 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
856 0, /*tp_print*/
857 0, /*tp_getattr*/
858 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000859 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860 (reprfunc)PyTclObject_repr, /*tp_repr*/
861 0, /*tp_as_number*/
862 0, /*tp_as_sequence*/
863 0, /*tp_as_mapping*/
864 0, /*tp_hash*/
865 0, /*tp_call*/
866 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000867 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000868 0, /*tp_setattro*/
869 0, /*tp_as_buffer*/
870 Py_TPFLAGS_DEFAULT, /*tp_flags*/
871 0, /*tp_doc*/
872 0, /*tp_traverse*/
873 0, /*tp_clear*/
874 0, /*tp_richcompare*/
875 0, /*tp_weaklistoffset*/
876 0, /*tp_iter*/
877 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000878 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000879 0, /*tp_members*/
880 PyTclObject_getsetlist, /*tp_getset*/
881 0, /*tp_base*/
882 0, /*tp_dict*/
883 0, /*tp_descr_get*/
884 0, /*tp_descr_set*/
885 0, /*tp_dictoffset*/
886 0, /*tp_init*/
887 0, /*tp_alloc*/
888 0, /*tp_new*/
889 0, /*tp_free*/
890 0, /*tp_is_gc*/
891};
892
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000893static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000894AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000895{
896 Tcl_Obj *result;
897
898 if (PyString_Check(value))
899 return Tcl_NewStringObj(PyString_AS_STRING(value),
900 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000901 else if (PyBool_Check(value))
902 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000903 else if (PyInt_Check(value))
904 return Tcl_NewLongObj(PyInt_AS_LONG(value));
905 else if (PyFloat_Check(value))
906 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
907 else if (PyTuple_Check(value)) {
908 Tcl_Obj **argv = (Tcl_Obj**)
909 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
910 int i;
911 if(!argv)
912 return 0;
913 for(i=0;i<PyTuple_Size(value);i++)
914 argv[i] = AsObj(PyTuple_GetItem(value,i));
915 result = Tcl_NewListObj(PyTuple_Size(value), argv);
916 ckfree(FREECAST argv);
917 return result;
918 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000919#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000920 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000921 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
922 int size = PyUnicode_GET_SIZE(value);
923 /* This #ifdef assumes that Tcl uses UCS-2.
924 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000925#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000926 Tcl_UniChar *outbuf;
927 int i;
928 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
929 if (!outbuf) {
930 PyErr_NoMemory();
931 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000932 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000933 for (i = 0; i < size; i++) {
934 if (inbuf[i] >= 0x10000) {
935 /* Tcl doesn't do UTF-16, yet. */
936 PyErr_SetString(PyExc_ValueError,
937 "unsupported character");
938 ckfree(FREECAST outbuf);
939 return NULL;
940 }
941 outbuf[i] = inbuf[i];
942 }
943 result = Tcl_NewUnicodeObj(outbuf, size);
944 ckfree(FREECAST outbuf);
945 return result;
946#else
947 return Tcl_NewUnicodeObj(inbuf, size);
948#endif
949
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000950 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000951#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952 else if(PyTclObject_Check(value)) {
953 Tcl_Obj *v = ((PyTclObject*)value)->value;
954 Tcl_IncrRefCount(v);
955 return v;
956 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000957 else {
958 PyObject *v = PyObject_Str(value);
959 if (!v)
960 return 0;
961 result = AsObj(v);
962 Py_DECREF(v);
963 return result;
964 }
965}
966
Martin v. Löwisffad6332002-11-26 09:28:05 +0000967static PyObject*
968FromObj(PyObject* tkapp, Tcl_Obj *value)
969{
970 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000971 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000972
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000973 if (value->typePtr == NULL) {
974 /* If the result contains any bytes with the top bit set,
975 it's UTF-8 and we should decode it to Unicode */
976#ifdef Py_USING_UNICODE
977 int i;
978 char *s = value->bytes;
979 int len = value->length;
980 for (i = 0; i < len; i++) {
981 if (value->bytes[i] & 0x80)
982 break;
983 }
984
985 if (i == value->length)
986 result = PyString_FromStringAndSize(s, len);
987 else {
988 /* Convert UTF-8 to Unicode string */
989 result = PyUnicode_DecodeUTF8(s, len, "strict");
990 if (result == NULL) {
991 PyErr_Clear();
992 result = PyString_FromStringAndSize(s, len);
993 }
994 }
995#else
Martin v. Löwise2713be2005-03-08 15:03:08 +0000996 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000997#endif
998 return result;
999 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001000
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001001 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002 result = value->internalRep.longValue ? Py_True : Py_False;
1003 Py_INCREF(result);
1004 return result;
1005 }
1006
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001007 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001009 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001010 return PyString_FromStringAndSize(data, size);
1011 }
1012
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001013 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014 return PyFloat_FromDouble(value->internalRep.doubleValue);
1015 }
1016
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001017 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001018 return PyInt_FromLong(value->internalRep.longValue);
1019 }
1020
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001021 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022 int size;
1023 int i, status;
1024 PyObject *elem;
1025 Tcl_Obj *tcl_elem;
1026
1027 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1028 if (status == TCL_ERROR)
1029 return Tkinter_Error(tkapp);
1030 result = PyTuple_New(size);
1031 if (!result)
1032 return NULL;
1033 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001034 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001035 value, i, &tcl_elem);
1036 if (status == TCL_ERROR) {
1037 Py_DECREF(result);
1038 return Tkinter_Error(tkapp);
1039 }
1040 elem = FromObj(tkapp, tcl_elem);
1041 if (!elem) {
1042 Py_DECREF(result);
1043 return NULL;
1044 }
1045 PyTuple_SetItem(result, i, elem);
1046 }
1047 return result;
1048 }
1049
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001050 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001051 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001052 }
1053
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001054 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001056#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001057 PyObject *result;
1058 int size;
1059 Tcl_UniChar *input;
1060 Py_UNICODE *output;
1061
1062 size = Tcl_GetCharLength(value);
1063 result = PyUnicode_FromUnicode(NULL, size);
1064 if (!result)
1065 return NULL;
1066 input = Tcl_GetUnicode(value);
1067 output = PyUnicode_AS_UNICODE(result);
1068 while (size--)
1069 *output++ = *input++;
1070 return result;
1071#else
1072 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1073 Tcl_GetCharLength(value));
1074#endif
1075#else
1076 int size;
1077 char *c;
1078 c = Tcl_GetStringFromObj(value, &size);
1079 return PyString_FromStringAndSize(c, size);
1080#endif
1081 }
1082
1083 return newPyTclObject(value);
1084}
1085
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001086/* This mutex synchronizes inter-thread command calls. */
1087
1088TCL_DECLARE_MUTEX(call_mutex)
1089
1090typedef struct Tkapp_CallEvent {
1091 Tcl_Event ev; /* Must be first */
1092 TkappObject *self;
1093 PyObject *args;
1094 int flags;
1095 PyObject **res;
1096 PyObject **exc_type, **exc_value, **exc_tb;
1097 Tcl_Condition done;
1098} Tkapp_CallEvent;
1099
1100void
1101Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001102{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001103 int i;
1104 for (i = 0; i < objc; i++)
1105 Tcl_DecrRefCount(objv[i]);
1106 if (objv != objStore)
1107 ckfree(FREECAST objv);
1108}
Guido van Rossum18468821994-06-20 07:49:28 +00001109
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001110/* Convert Python objects to Tcl objects. This must happen in the
1111 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001112
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001113static Tcl_Obj**
1114Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1115{
1116 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001117 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001118 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001119 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001120
Guido van Rossum212643f1998-04-29 16:22:14 +00001121 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001122 objv[0] = AsObj(args);
1123 if (objv[0] == 0)
1124 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001125 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001126 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001127 }
1128 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001129 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001130
Guido van Rossum632de272000-03-29 00:19:50 +00001131 if (objc > ARGSZ) {
1132 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1133 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001134 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001135 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001136 goto finally;
1137 }
1138 }
1139
Guido van Rossum632de272000-03-29 00:19:50 +00001140 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001141 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001142 if (v == Py_None) {
1143 objc = i;
1144 break;
1145 }
Guido van Rossum632de272000-03-29 00:19:50 +00001146 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001147 if (!objv[i]) {
1148 /* Reset objc, so it attempts to clear
1149 objects only up to i. */
1150 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001151 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001152 }
Guido van Rossum632de272000-03-29 00:19:50 +00001153 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001154 }
1155 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156 *pobjc = objc;
1157 return objv;
1158finally:
1159 Tkapp_CallDeallocArgs(objv, objStore, objc);
1160 return NULL;
1161}
Guido van Rossum212643f1998-04-29 16:22:14 +00001162
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001164
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165static PyObject*
1166Tkapp_CallResult(TkappObject *self)
1167{
1168 PyObject *res = NULL;
1169 if(self->wantobjects) {
1170 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001171 /* Not sure whether the IncrRef is necessary, but something
1172 may overwrite the interpreter result while we are
1173 converting it. */
1174 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001176 Tcl_DecrRefCount(value);
1177 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001179 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001180
Guido van Rossum990f5c62000-05-04 15:07:16 +00001181 /* If the result contains any bytes with the top bit set,
1182 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001183#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001184 while (*p != '\0') {
1185 if (*p & 0x80)
1186 break;
1187 p++;
1188 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001189
Guido van Rossum990f5c62000-05-04 15:07:16 +00001190 if (*p == '\0')
1191 res = PyString_FromStringAndSize(s, (int)(p-s));
1192 else {
1193 /* Convert UTF-8 to Unicode string */
1194 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001195 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1196 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001197 PyErr_Clear();
1198 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001199 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001200 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001201#else
1202 p = strchr(p, '\0');
1203 res = PyString_FromStringAndSize(s, (int)(p-s));
1204#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001205 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001206 return res;
1207}
Guido van Rossum632de272000-03-29 00:19:50 +00001208
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209/* Tkapp_CallProc is the event procedure that is executed in the context of
1210 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1211 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001212
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213static int
1214Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1215{
1216 Tcl_Obj *objStore[ARGSZ];
1217 Tcl_Obj **objv;
1218 int objc;
1219 int i;
1220 ENTER_PYTHON
1221 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1222 if (!objv) {
1223 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1224 *(e->res) = NULL;
1225 }
1226 LEAVE_PYTHON
1227 if (!objv)
1228 goto done;
1229 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1230 ENTER_PYTHON
1231 if (i == TCL_ERROR) {
1232 *(e->res) = NULL;
1233 *(e->exc_type) = NULL;
1234 *(e->exc_tb) = NULL;
1235 *(e->exc_value) = PyObject_CallFunction(
1236 Tkinter_TclError, "s",
1237 Tcl_GetStringResult(e->self->interp));
1238 }
1239 else {
1240 *(e->res) = Tkapp_CallResult(e->self);
1241 }
1242 LEAVE_PYTHON
1243 done:
1244 /* Wake up calling thread. */
1245 Tcl_MutexLock(&call_mutex);
1246 Tcl_ConditionNotify(&e->done);
1247 Tcl_MutexUnlock(&call_mutex);
1248 return 1;
1249}
1250
1251/* This is the main entry point for calling a Tcl command.
1252 It supports three cases, with regard to threading:
1253 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1254 the context of the calling thread.
1255 2. Tcl is threaded, caller of the command is in the interpreter thread:
1256 Execute the command in the calling thread. Since the Tcl lock will
1257 not be used, we can merge that with case 1.
1258 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1259 the interpreter thread. Allocation of Tcl objects needs to occur in the
1260 interpreter thread, so we ship the PyObject* args to the target thread,
1261 and perform processing there. */
1262
1263static PyObject *
1264Tkapp_Call(PyObject *_self, PyObject *args)
1265{
1266 Tcl_Obj *objStore[ARGSZ];
1267 Tcl_Obj **objv = NULL;
1268 int objc, i;
1269 PyObject *res = NULL;
1270 TkappObject *self = (TkappObject*)_self;
1271 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1272 int flags = TCL_EVAL_DIRECT;
1273
Martin v. Löwisa9656492003-03-30 08:44:58 +00001274#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1276 /* We cannot call the command directly. Instead, we must
1277 marshal the parameters to the interpreter thread. */
1278 Tkapp_CallEvent *ev;
1279 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001280 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001282 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1283 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1284 ev->self = self;
1285 ev->args = args;
1286 ev->res = &res;
1287 ev->exc_type = &exc_type;
1288 ev->exc_value = &exc_value;
1289 ev->exc_tb = &exc_tb;
1290 ev->done = (Tcl_Condition)0;
1291
1292 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1293
1294 if (res == NULL) {
1295 if (exc_type)
1296 PyErr_Restore(exc_type, exc_value, exc_tb);
1297 else
1298 PyErr_SetObject(Tkinter_TclError, exc_value);
1299 }
1300 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001301 else
1302#endif
1303 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304
1305 objv = Tkapp_CallArgs(args, objStore, &objc);
1306 if (!objv)
1307 return NULL;
1308
1309 ENTER_TCL
1310
1311 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1312
1313 ENTER_OVERLAP
1314
1315 if (i == TCL_ERROR)
1316 Tkinter_Error(_self);
1317 else
1318 res = Tkapp_CallResult(self);
1319
1320 LEAVE_OVERLAP_TCL
1321
1322 Tkapp_CallDeallocArgs(objv, objStore, objc);
1323 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001324 return res;
1325}
1326
1327
1328static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001329Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001330{
Guido van Rossum212643f1998-04-29 16:22:14 +00001331 /* Could do the same here as for Tkapp_Call(), but this is not used
1332 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1333 way for the user to do what all its Global* variants do (save and
1334 reset the scope pointer, call the local version, restore the saved
1335 scope pointer). */
1336
Guido van Rossum62320c91998-06-15 04:36:09 +00001337 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001338 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001339
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340 CHECK_TCL_APPARTMENT;
1341
Guido van Rossum62320c91998-06-15 04:36:09 +00001342 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001343 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001344 int err;
1345 ENTER_TCL
1346 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001347 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001348 if (err == TCL_ERROR)
1349 res = Tkinter_Error(self);
1350 else
1351 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001352 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001353 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001354 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001355
1356 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001357}
1358
1359static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001360Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001361{
Barry Warsawfa701a81997-01-16 00:15:11 +00001362 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001363 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001365
Guido van Rossum43713e52000-02-29 13:59:29 +00001366 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001367 return NULL;
1368
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369 CHECK_TCL_APPARTMENT;
1370
Guido van Rossum00d93061998-05-28 23:06:38 +00001371 ENTER_TCL
1372 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001374 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001375 res = Tkinter_Error(self);
1376 else
1377 res = PyString_FromString(Tkapp_Result(self));
1378 LEAVE_OVERLAP_TCL
1379 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001380}
1381
1382static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001383Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001384{
Barry Warsawfa701a81997-01-16 00:15:11 +00001385 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001386 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001388
Guido van Rossum43713e52000-02-29 13:59:29 +00001389 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001390 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001391
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392 CHECK_TCL_APPARTMENT;
1393
Guido van Rossum00d93061998-05-28 23:06:38 +00001394 ENTER_TCL
1395 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001397 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001398 res = Tkinter_Error(self);
1399 else
1400 res = PyString_FromString(Tkapp_Result(self));
1401 LEAVE_OVERLAP_TCL
1402 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001403}
1404
1405static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001406Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001407{
Barry Warsawfa701a81997-01-16 00:15:11 +00001408 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001409 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001410 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001411
Guido van Rossum43713e52000-02-29 13:59:29 +00001412 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001413 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001414
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001415 CHECK_TCL_APPARTMENT;
1416
Guido van Rossum00d93061998-05-28 23:06:38 +00001417 ENTER_TCL
1418 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001419 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001420 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001421 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001422
Guido van Rossum62320c91998-06-15 04:36:09 +00001423 else
1424 res = PyString_FromString(Tkapp_Result(self));
1425 LEAVE_OVERLAP_TCL
1426 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001427}
1428
1429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001430Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001431{
Barry Warsawfa701a81997-01-16 00:15:11 +00001432 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001433 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001434 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001435
Guido van Rossum35d43371997-08-02 00:09:09 +00001436 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001437 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001438
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439 CHECK_TCL_APPARTMENT;
1440
Guido van Rossum00d93061998-05-28 23:06:38 +00001441 ENTER_TCL
1442 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001443 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001444 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001445 res = Tkinter_Error(self);
1446 else
1447 res = PyString_FromString(Tkapp_Result(self));
1448 LEAVE_OVERLAP_TCL
1449 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001450}
1451
1452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001453Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001454{
Barry Warsawfa701a81997-01-16 00:15:11 +00001455 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001456
Guido van Rossum43713e52000-02-29 13:59:29 +00001457 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001458 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001459 CHECK_TCL_APPARTMENT;
1460
Guido van Rossum00d93061998-05-28 23:06:38 +00001461 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001462 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001463 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001464
Barry Warsawfa701a81997-01-16 00:15:11 +00001465 Py_INCREF(Py_None);
1466 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001467}
1468
Barry Warsawfa701a81997-01-16 00:15:11 +00001469
1470
Guido van Rossum18468821994-06-20 07:49:28 +00001471/** Tcl Variable **/
1472
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473TCL_DECLARE_MUTEX(var_mutex)
1474
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001475typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476typedef struct VarEvent {
1477 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001478 PyObject *self;
1479 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001481 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001483 PyObject **exc_type;
1484 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486} VarEvent;
1487
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001488static int
1489varname_converter(PyObject *in, void *_out)
1490{
1491 char **out = (char**)_out;
1492 if (PyString_Check(in)) {
1493 *out = PyString_AsString(in);
1494 return 1;
1495 }
1496 if (PyTclObject_Check(in)) {
1497 *out = PyTclObject_TclString(in);
1498 return 1;
1499 }
1500 /* XXX: Should give diagnostics. */
1501 return 0;
1502}
1503
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001504void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505var_perform(VarEvent *ev)
1506{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001507 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1508 if (!*(ev->res)) {
1509 PyObject *exc, *val, *tb;
1510 PyErr_Fetch(&exc, &val, &tb);
1511 PyErr_NormalizeException(&exc, &val, &tb);
1512 *(ev->exc_type) = exc;
1513 *(ev->exc_val) = val;
1514 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001516
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001517}
1518
1519static int
1520var_proc(VarEvent* ev, int flags)
1521{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001522 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001523 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001524 Tcl_MutexLock(&var_mutex);
1525 Tcl_ConditionNotify(&ev->cond);
1526 Tcl_MutexUnlock(&var_mutex);
1527 LEAVE_PYTHON
1528 return 1;
1529}
1530
1531static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001532var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001533{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001535#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001537 TkappObject *self = (TkappObject*)_self;
1538 VarEvent *ev;
1539 PyObject *res, *exc_type, *exc_val;
1540
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001541 /* The current thread is not the interpreter thread. Marshal
1542 the call to the interpreter thread, then wait for
1543 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001544 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001545 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001546
1547 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1548
1549 ev->self = _self;
1550 ev->args = args;
1551 ev->flags = flags;
1552 ev->func = func;
1553 ev->res = &res;
1554 ev->exc_type = &exc_type;
1555 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001556 ev->cond = NULL;
1557 ev->ev.proc = (Tcl_EventProc*)var_proc;
1558 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001559 if (!res) {
1560 PyErr_SetObject(exc_type, exc_val);
1561 Py_DECREF(exc_type);
1562 Py_DECREF(exc_val);
1563 return NULL;
1564 }
1565 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001566 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001567#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001568 /* Tcl is not threaded, or this is the interpreter thread. */
1569 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001570}
1571
Guido van Rossum18468821994-06-20 07:49:28 +00001572static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001573SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001574{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001575 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001576 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001577 PyObject *res = NULL;
1578 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001579
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001580 if (PyArg_ParseTuple(args, "O&O:setvar",
1581 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001582 /* XXX Acquire tcl lock??? */
1583 newval = AsObj(newValue);
1584 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001585 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001586 ENTER_TCL
1587 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1588 newval, flags);
1589 ENTER_OVERLAP
1590 if (!ok)
1591 Tkinter_Error(self);
1592 else {
1593 res = Py_None;
1594 Py_INCREF(res);
1595 }
1596 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001597 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001598 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001599 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001600 if (PyArg_ParseTuple(args, "ssO:setvar",
1601 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001602 /* XXX must hold tcl lock already??? */
1603 newval = AsObj(newValue);
1604 ENTER_TCL
1605 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1606 ENTER_OVERLAP
1607 if (!ok)
1608 Tkinter_Error(self);
1609 else {
1610 res = Py_None;
1611 Py_INCREF(res);
1612 }
1613 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001614 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001615 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001616 return NULL;
1617 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001619 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001620}
1621
1622static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001623Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001624{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001625 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001626}
1627
1628static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001629Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001630{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001631 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001632}
1633
Barry Warsawfa701a81997-01-16 00:15:11 +00001634
1635
Guido van Rossum18468821994-06-20 07:49:28 +00001636static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001637GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001638{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001639 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001640 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001641 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001642
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001643 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1644 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001645 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001646
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001647 ENTER_TCL
1648 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1649 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001650 if (tres == NULL) {
1651 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1652 } else {
1653 if (((TkappObject*)self)->wantobjects) {
1654 res = FromObj(self, tres);
1655 }
1656 else {
1657 res = PyString_FromString(Tcl_GetString(tres));
1658 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001659 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001660 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001661 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001662}
1663
1664static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001665Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001666{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001667 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001668}
1669
1670static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001671Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001672{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001673 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001674}
1675
Barry Warsawfa701a81997-01-16 00:15:11 +00001676
1677
Guido van Rossum18468821994-06-20 07:49:28 +00001678static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001679UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001680{
Guido van Rossum35d43371997-08-02 00:09:09 +00001681 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001682 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001683 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001684
Guido van Rossum43713e52000-02-29 13:59:29 +00001685 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001686 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001687
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001688 ENTER_TCL
1689 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1690 ENTER_OVERLAP
1691 if (code == TCL_ERROR)
1692 res = Tkinter_Error(self);
1693 else {
1694 Py_INCREF(Py_None);
1695 res = Py_None;
1696 }
1697 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001698 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001699}
1700
1701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001704 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001705}
1706
1707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001710 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001711}
1712
Barry Warsawfa701a81997-01-16 00:15:11 +00001713
1714
Guido van Rossum18468821994-06-20 07:49:28 +00001715/** Tcl to Python **/
1716
1717static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001718Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001719{
Barry Warsawfa701a81997-01-16 00:15:11 +00001720 char *s;
1721 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001722
Martin v. Löwisffad6332002-11-26 09:28:05 +00001723 if (PyTuple_Size(args) == 1) {
1724 PyObject* o = PyTuple_GetItem(args, 0);
1725 if (PyInt_Check(o)) {
1726 Py_INCREF(o);
1727 return o;
1728 }
1729 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001730 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001731 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001732 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001733 return Tkinter_Error(self);
1734 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001735}
1736
1737static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001738Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001739{
Barry Warsawfa701a81997-01-16 00:15:11 +00001740 char *s;
1741 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001742
Martin v. Löwisffad6332002-11-26 09:28:05 +00001743 if (PyTuple_Size(args) == 1) {
1744 PyObject *o = PyTuple_GetItem(args, 0);
1745 if (PyFloat_Check(o)) {
1746 Py_INCREF(o);
1747 return o;
1748 }
1749 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001750 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001751 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001752 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001753 return Tkinter_Error(self);
1754 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001755}
1756
1757static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001758Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001759{
Barry Warsawfa701a81997-01-16 00:15:11 +00001760 char *s;
1761 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Martin v. Löwisffad6332002-11-26 09:28:05 +00001763 if (PyTuple_Size(args) == 1) {
1764 PyObject *o = PyTuple_GetItem(args, 0);
1765 if (PyInt_Check(o)) {
1766 Py_INCREF(o);
1767 return o;
1768 }
1769 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001770 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001771 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001772 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1773 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001774 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001775}
1776
1777static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001778Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001779{
Barry Warsawfa701a81997-01-16 00:15:11 +00001780 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001781 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001782 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001783
Guido van Rossum43713e52000-02-29 13:59:29 +00001784 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001785 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001786
1787 CHECK_TCL_APPARTMENT;
1788
Guido van Rossum00d93061998-05-28 23:06:38 +00001789 ENTER_TCL
1790 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001791 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001792 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001793 res = Tkinter_Error(self);
1794 else
1795 res = Py_BuildValue("s", Tkapp_Result(self));
1796 LEAVE_OVERLAP_TCL
1797 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001798}
1799
1800static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001801Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001802{
Barry Warsawfa701a81997-01-16 00:15:11 +00001803 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001804 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001805 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001806 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001807
Guido van Rossum43713e52000-02-29 13:59:29 +00001808 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001809 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001810
1811 CHECK_TCL_APPARTMENT;
1812
Guido van Rossum00d93061998-05-28 23:06:38 +00001813 ENTER_TCL
1814 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001815 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001816 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001817 res = Tkinter_Error(self);
1818 else
1819 res = Py_BuildValue("l", v);
1820 LEAVE_OVERLAP_TCL
1821 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001822}
1823
1824static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001825Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001826{
Barry Warsawfa701a81997-01-16 00:15:11 +00001827 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001828 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001830 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001831
Guido van Rossum43713e52000-02-29 13:59:29 +00001832 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001833 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001834 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001835 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001836 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001837 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001838 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001839 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001840 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001841 res = Tkinter_Error(self);
1842 else
1843 res = Py_BuildValue("d", v);
1844 LEAVE_OVERLAP_TCL
1845 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001846}
1847
1848static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001849Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001850{
Barry Warsawfa701a81997-01-16 00:15:11 +00001851 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001852 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001853 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001854 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001855
Guido van Rossum43713e52000-02-29 13:59:29 +00001856 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001857 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001858 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001859 ENTER_TCL
1860 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001861 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001862 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001863 res = Tkinter_Error(self);
1864 else
1865 res = Py_BuildValue("i", v);
1866 LEAVE_OVERLAP_TCL
1867 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001868}
1869
Barry Warsawfa701a81997-01-16 00:15:11 +00001870
1871
Guido van Rossum18468821994-06-20 07:49:28 +00001872static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001873Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001874{
Barry Warsawfa701a81997-01-16 00:15:11 +00001875 char *list;
1876 int argc;
1877 char **argv;
1878 PyObject *v;
1879 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001880
Martin v. Löwisffad6332002-11-26 09:28:05 +00001881 if (PyTuple_Size(args) == 1) {
1882 v = PyTuple_GetItem(args, 0);
1883 if (PyTuple_Check(v)) {
1884 Py_INCREF(v);
1885 return v;
1886 }
1887 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001888 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001889 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001890
Neal Norwitzd1c55102003-05-29 00:17:03 +00001891 if (Tcl_SplitList(Tkapp_Interp(self), list,
1892 &argc, &argv) == TCL_ERROR) {
1893 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001894 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001895 }
Guido van Rossum18468821994-06-20 07:49:28 +00001896
Barry Warsawfa701a81997-01-16 00:15:11 +00001897 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001898 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001899
Barry Warsawfa701a81997-01-16 00:15:11 +00001900 for (i = 0; i < argc; i++) {
1901 PyObject *s = PyString_FromString(argv[i]);
1902 if (!s || PyTuple_SetItem(v, i, s)) {
1903 Py_DECREF(v);
1904 v = NULL;
1905 goto finally;
1906 }
1907 }
Guido van Rossum18468821994-06-20 07:49:28 +00001908
Barry Warsawfa701a81997-01-16 00:15:11 +00001909 finally:
1910 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001911 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001912 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001913}
1914
1915static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001916Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001917{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001918 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001919 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001920
Martin v. Löwisffad6332002-11-26 09:28:05 +00001921 if (PyTuple_Size(args) == 1) {
1922 PyObject* o = PyTuple_GetItem(args, 0);
1923 if (PyTuple_Check(o)) {
1924 o = SplitObj(o);
1925 return o;
1926 }
1927 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001928 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001929 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001930 v = Split(list);
1931 PyMem_Free(list);
1932 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001933}
1934
1935static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001936Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001937{
Barry Warsawfa701a81997-01-16 00:15:11 +00001938 char *s = Merge(args);
1939 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001940
Barry Warsawfa701a81997-01-16 00:15:11 +00001941 if (s) {
1942 res = PyString_FromString(s);
1943 ckfree(s);
1944 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001945
1946 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001947}
1948
Barry Warsawfa701a81997-01-16 00:15:11 +00001949
1950
Guido van Rossum18468821994-06-20 07:49:28 +00001951/** Tcl Command **/
1952
Guido van Rossum00d93061998-05-28 23:06:38 +00001953/* Client data struct */
1954typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001955 PyObject *self;
1956 PyObject *func;
1957} PythonCmd_ClientData;
1958
1959static int
Fred Drake509d79a2000-07-08 04:04:38 +00001960PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001961{
1962 errorInCmd = 1;
1963 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1964 LEAVE_PYTHON
1965 return TCL_ERROR;
1966}
1967
Guido van Rossum18468821994-06-20 07:49:28 +00001968/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001969 * function or method.
1970 */
Guido van Rossum18468821994-06-20 07:49:28 +00001971static int
Fred Drake509d79a2000-07-08 04:04:38 +00001972PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001973{
Guido van Rossum00d93061998-05-28 23:06:38 +00001974 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001975 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001976 int i, rv;
1977 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001978
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001979 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001980
Barry Warsawfa701a81997-01-16 00:15:11 +00001981 /* TBD: no error checking here since we know, via the
1982 * Tkapp_CreateCommand() that the client data is a two-tuple
1983 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001984 self = data->self;
1985 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001986
Barry Warsawfa701a81997-01-16 00:15:11 +00001987 /* Create argument list (argv1, ..., argvN) */
1988 if (!(arg = PyTuple_New(argc - 1)))
1989 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001990
Barry Warsawfa701a81997-01-16 00:15:11 +00001991 for (i = 0; i < (argc - 1); i++) {
1992 PyObject *s = PyString_FromString(argv[i + 1]);
1993 if (!s || PyTuple_SetItem(arg, i, s)) {
1994 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001995 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001996 }
1997 }
1998 res = PyEval_CallObject(func, arg);
1999 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002000
Barry Warsawfa701a81997-01-16 00:15:11 +00002001 if (res == NULL)
2002 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002003
Barry Warsawfa701a81997-01-16 00:15:11 +00002004 if (!(tmp = PyList_New(0))) {
2005 Py_DECREF(res);
2006 return PythonCmd_Error(interp);
2007 }
2008
Guido van Rossum2834b972000-10-06 16:58:26 +00002009 s = AsString(res, tmp);
2010 if (s == NULL) {
2011 rv = PythonCmd_Error(interp);
2012 }
2013 else {
2014 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2015 rv = TCL_OK;
2016 }
2017
Barry Warsawfa701a81997-01-16 00:15:11 +00002018 Py_DECREF(res);
2019 Py_DECREF(tmp);
2020
Guido van Rossum00d93061998-05-28 23:06:38 +00002021 LEAVE_PYTHON
2022
Guido van Rossum2834b972000-10-06 16:58:26 +00002023 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002024}
2025
2026static void
Fred Drake509d79a2000-07-08 04:04:38 +00002027PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002028{
Guido van Rossum00d93061998-05-28 23:06:38 +00002029 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2030
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002031 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002032 Py_XDECREF(data->self);
2033 Py_XDECREF(data->func);
2034 PyMem_DEL(data);
2035 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002036}
2037
Barry Warsawfa701a81997-01-16 00:15:11 +00002038
2039
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002040
2041TCL_DECLARE_MUTEX(command_mutex)
2042
2043typedef struct CommandEvent{
2044 Tcl_Event ev;
2045 Tcl_Interp* interp;
2046 char *name;
2047 int create;
2048 int *status;
2049 ClientData *data;
2050 Tcl_Condition done;
2051} CommandEvent;
2052
2053static int
2054Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002055{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056 if (ev->create)
2057 *ev->status = Tcl_CreateCommand(
2058 ev->interp, ev->name, PythonCmd,
2059 ev->data, PythonCmdDelete) == NULL;
2060 else
2061 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2062 Tcl_MutexLock(&command_mutex);
2063 Tcl_ConditionNotify(&ev->done);
2064 Tcl_MutexUnlock(&command_mutex);
2065 return 1;
2066}
2067
2068static PyObject *
2069Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2070{
2071 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002072 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002073 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002074 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002075 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002076
Guido van Rossum43713e52000-02-29 13:59:29 +00002077 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002078 return NULL;
2079 if (!PyCallable_Check(func)) {
2080 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002081 return NULL;
2082 }
Guido van Rossum18468821994-06-20 07:49:28 +00002083
Martin v. Löwisa9656492003-03-30 08:44:58 +00002084#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002085 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002086 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002087 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002088#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002089
Guido van Rossum00d93061998-05-28 23:06:38 +00002090 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002091 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002092 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002093 Py_XINCREF(self);
2094 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002095 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002096 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002097
2098 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2099 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2100 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2101 ev->interp = self->interp;
2102 ev->create = 1;
2103 ev->name = cmdName;
2104 ev->data = (ClientData)data;
2105 ev->status = &err;
2106 ev->done = NULL;
2107 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2108 }
2109 else {
2110 ENTER_TCL
2111 err = Tcl_CreateCommand(
2112 Tkapp_Interp(self), cmdName, PythonCmd,
2113 (ClientData)data, PythonCmdDelete) == NULL;
2114 LEAVE_TCL
2115 }
2116 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002117 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002118 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002119 return NULL;
2120 }
Guido van Rossum18468821994-06-20 07:49:28 +00002121
Barry Warsawfa701a81997-01-16 00:15:11 +00002122 Py_INCREF(Py_None);
2123 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002124}
2125
Barry Warsawfa701a81997-01-16 00:15:11 +00002126
2127
Guido van Rossum18468821994-06-20 07:49:28 +00002128static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002129Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002131 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002132 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002133 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Guido van Rossum43713e52000-02-29 13:59:29 +00002135 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002136 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002137 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2138 CommandEvent *ev;
2139 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2140 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2141 ev->interp = self->interp;
2142 ev->create = 0;
2143 ev->name = cmdName;
2144 ev->status = &err;
2145 ev->done = NULL;
2146 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2147 &command_mutex);
2148 }
2149 else {
2150 ENTER_TCL
2151 err = Tcl_DeleteCommand(self->interp, cmdName);
2152 LEAVE_TCL
2153 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002154 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002155 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2156 return NULL;
2157 }
2158 Py_INCREF(Py_None);
2159 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002160}
2161
Barry Warsawfa701a81997-01-16 00:15:11 +00002162
2163
Guido van Rossum00d93061998-05-28 23:06:38 +00002164#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002165/** File Handler **/
2166
Guido van Rossum00d93061998-05-28 23:06:38 +00002167typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002168 PyObject *func;
2169 PyObject *file;
2170 int id;
2171 struct _fhcdata *next;
2172} FileHandler_ClientData;
2173
2174static FileHandler_ClientData *HeadFHCD;
2175
2176static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002177NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002178{
2179 FileHandler_ClientData *p;
2180 p = PyMem_NEW(FileHandler_ClientData, 1);
2181 if (p != NULL) {
2182 Py_XINCREF(func);
2183 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002184 p->func = func;
2185 p->file = file;
2186 p->id = id;
2187 p->next = HeadFHCD;
2188 HeadFHCD = p;
2189 }
2190 return p;
2191}
2192
2193static void
Fred Drake509d79a2000-07-08 04:04:38 +00002194DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002195{
2196 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002197
2198 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002199 while ((p = *pp) != NULL) {
2200 if (p->id == id) {
2201 *pp = p->next;
2202 Py_XDECREF(p->func);
2203 Py_XDECREF(p->file);
2204 PyMem_DEL(p);
2205 }
2206 else
2207 pp = &p->next;
2208 }
2209}
2210
Guido van Rossuma597dde1995-01-10 20:56:29 +00002211static void
Fred Drake509d79a2000-07-08 04:04:38 +00002212FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002213{
Guido van Rossum00d93061998-05-28 23:06:38 +00002214 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002215 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002216
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002217 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002218 func = data->func;
2219 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002220
Barry Warsawfa701a81997-01-16 00:15:11 +00002221 arg = Py_BuildValue("(Oi)", file, (long) mask);
2222 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002223 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002224
2225 if (res == NULL) {
2226 errorInCmd = 1;
2227 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2228 }
2229 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002230 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002231}
2232
Guido van Rossum18468821994-06-20 07:49:28 +00002233static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002234Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2235 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002236{
Guido van Rossum00d93061998-05-28 23:06:38 +00002237 FileHandler_ClientData *data;
2238 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002239 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002240
Guido van Rossum2834b972000-10-06 16:58:26 +00002241 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2242 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002243 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002244
Martin v. Löwisa9656492003-03-30 08:44:58 +00002245#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002246 if (!self && !tcl_lock) {
2247 /* We don't have the Tcl lock since Tcl is threaded. */
2248 PyErr_SetString(PyExc_RuntimeError,
2249 "_tkinter.createfilehandler not supported "
2250 "for threaded Tcl");
2251 return NULL;
2252 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002253#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002254
2255 if (self) {
2256 CHECK_TCL_APPARTMENT;
2257 }
2258
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002259 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002260 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002261 return NULL;
2262 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002263 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002264 return NULL;
2265 }
2266
Guido van Rossuma80649b2000-03-28 20:07:05 +00002267 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002268 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002269 return NULL;
2270
Barry Warsawfa701a81997-01-16 00:15:11 +00002271 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002272 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002273 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002274 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002275 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002276 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002277}
2278
2279static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002280Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002281{
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002283 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002284
Guido van Rossum43713e52000-02-29 13:59:29 +00002285 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002287
Martin v. Löwisa9656492003-03-30 08:44:58 +00002288#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002289 if (!self && !tcl_lock) {
2290 /* We don't have the Tcl lock since Tcl is threaded. */
2291 PyErr_SetString(PyExc_RuntimeError,
2292 "_tkinter.deletefilehandler not supported "
2293 "for threaded Tcl");
2294 return NULL;
2295 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002296#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002297
2298 if (self) {
2299 CHECK_TCL_APPARTMENT;
2300 }
2301
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002302 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002303 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002304 return NULL;
2305
Guido van Rossuma80649b2000-03-28 20:07:05 +00002306 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002307
Barry Warsawfa701a81997-01-16 00:15:11 +00002308 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002310 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002311 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002312 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002313 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002314}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002315#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002316
Barry Warsawfa701a81997-01-16 00:15:11 +00002317
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318/**** Tktt Object (timer token) ****/
2319
Jeremy Hylton938ace62002-07-17 16:30:39 +00002320static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002321
Guido van Rossum00d93061998-05-28 23:06:38 +00002322typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002324 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002325 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002326} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002327
2328static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002329Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330{
Barry Warsawfa701a81997-01-16 00:15:11 +00002331 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002332 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333
Guido van Rossum43713e52000-02-29 13:59:29 +00002334 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002336 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002337 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002338 v->token = NULL;
2339 }
2340 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002342 Py_DECREF(func);
2343 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002344 }
2345 Py_INCREF(Py_None);
2346 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347}
2348
2349static PyMethodDef Tktt_methods[] =
2350{
Neal Norwitzb0493252002-03-31 14:44:22 +00002351 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002352 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353};
2354
2355static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002356Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357{
Barry Warsawfa701a81997-01-16 00:15:11 +00002358 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359
Guido van Rossumb18618d2000-05-03 23:44:39 +00002360 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002361 if (v == NULL)
2362 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363
Guido van Rossum00d93061998-05-28 23:06:38 +00002364 Py_INCREF(func);
2365 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002366 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002367
2368 /* Extra reference, deleted when called or when handler is deleted */
2369 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002370 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371}
2372
2373static void
Fred Drake509d79a2000-07-08 04:04:38 +00002374Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375{
Guido van Rossum00d93061998-05-28 23:06:38 +00002376 TkttObject *v = (TkttObject *)self;
2377 PyObject *func = v->func;
2378
2379 Py_XDECREF(func);
2380
Guido van Rossumb18618d2000-05-03 23:44:39 +00002381 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382}
2383
Guido van Rossum597ac201998-05-12 14:36:19 +00002384static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002385Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386{
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002388 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002389
Tim Peters885d4572001-11-28 20:27:42 +00002390 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002391 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002392 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393}
2394
2395static PyObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002396Tktt_GetAttr(PyObject *self, const char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397{
Barry Warsawfa701a81997-01-16 00:15:11 +00002398 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399}
2400
2401static PyTypeObject Tktt_Type =
2402{
Guido van Rossum35d43371997-08-02 00:09:09 +00002403 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002404 0, /*ob_size */
2405 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002406 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002407 0, /*tp_itemsize */
2408 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002409 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002410 Tktt_GetAttr, /*tp_getattr */
2411 0, /*tp_setattr */
2412 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002413 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002414 0, /*tp_as_number */
2415 0, /*tp_as_sequence */
2416 0, /*tp_as_mapping */
2417 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002418};
2419
Barry Warsawfa701a81997-01-16 00:15:11 +00002420
2421
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002422/** Timer Handler **/
2423
2424static void
Fred Drake509d79a2000-07-08 04:04:38 +00002425TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002426{
Guido van Rossum00d93061998-05-28 23:06:38 +00002427 TkttObject *v = (TkttObject *)clientData;
2428 PyObject *func = v->func;
2429 PyObject *res;
2430
2431 if (func == NULL)
2432 return;
2433
2434 v->func = NULL;
2435
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002436 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002437
2438 res = PyEval_CallObject(func, NULL);
2439 Py_DECREF(func);
2440 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002441
Barry Warsawfa701a81997-01-16 00:15:11 +00002442 if (res == NULL) {
2443 errorInCmd = 1;
2444 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2445 }
2446 else
2447 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002448
2449 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002450}
2451
2452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002453Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002454{
Barry Warsawfa701a81997-01-16 00:15:11 +00002455 int milliseconds;
2456 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002457 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002458
Guido van Rossum2834b972000-10-06 16:58:26 +00002459 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2460 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002461 return NULL;
2462 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002463 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002464 return NULL;
2465 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002466
Martin v. Löwisa9656492003-03-30 08:44:58 +00002467#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002468 if (!self && !tcl_lock) {
2469 /* We don't have the Tcl lock since Tcl is threaded. */
2470 PyErr_SetString(PyExc_RuntimeError,
2471 "_tkinter.createtimerhandler not supported "
2472 "for threaded Tcl");
2473 return NULL;
2474 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002475#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002476
2477 if (self) {
2478 CHECK_TCL_APPARTMENT;
2479 }
2480
Guido van Rossum00d93061998-05-28 23:06:38 +00002481 v = Tktt_New(func);
2482 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2483 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002484
Guido van Rossum00d93061998-05-28 23:06:38 +00002485 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002486}
2487
Barry Warsawfa701a81997-01-16 00:15:11 +00002488
Guido van Rossum18468821994-06-20 07:49:28 +00002489/** Event Loop **/
2490
Guido van Rossum18468821994-06-20 07:49:28 +00002491static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002492Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002493{
Barry Warsawfa701a81997-01-16 00:15:11 +00002494 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002495 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002496#ifdef WITH_THREAD
2497 PyThreadState *tstate = PyThreadState_Get();
2498#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002499
Guido van Rossum43713e52000-02-29 13:59:29 +00002500 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002501 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002502
Martin v. Löwisa9656492003-03-30 08:44:58 +00002503#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002504 if (!self && !tcl_lock) {
2505 /* We don't have the Tcl lock since Tcl is threaded. */
2506 PyErr_SetString(PyExc_RuntimeError,
2507 "_tkinter.mainloop not supported "
2508 "for threaded Tcl");
2509 return NULL;
2510 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002511#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002512
2513 if (self) {
2514 CHECK_TCL_APPARTMENT;
2515 self->dispatching = 1;
2516 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002517
Barry Warsawfa701a81997-01-16 00:15:11 +00002518 quitMainLoop = 0;
2519 while (Tk_GetNumMainWindows() > threshold &&
2520 !quitMainLoop &&
2521 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002522 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002523 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002524
2525#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002526 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002527 /* Allow other Python threads to run. */
2528 ENTER_TCL
2529 result = Tcl_DoOneEvent(0);
2530 LEAVE_TCL
2531 }
2532 else {
2533 Py_BEGIN_ALLOW_THREADS
2534 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2535 tcl_tstate = tstate;
2536 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2537 tcl_tstate = NULL;
2538 if(tcl_lock)PyThread_release_lock(tcl_lock);
2539 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002540 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002541 Py_END_ALLOW_THREADS
2542 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002543#else
2544 result = Tcl_DoOneEvent(0);
2545#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002546
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002547 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002548 if (self)
2549 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002550 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002551 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002552 if (result < 0)
2553 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002554 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002555 if (self)
2556 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002557 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002558
Barry Warsawfa701a81997-01-16 00:15:11 +00002559 if (errorInCmd) {
2560 errorInCmd = 0;
2561 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2562 excInCmd = valInCmd = trbInCmd = NULL;
2563 return NULL;
2564 }
2565 Py_INCREF(Py_None);
2566 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002567}
2568
2569static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002570Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002571{
Guido van Rossum35d43371997-08-02 00:09:09 +00002572 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002573 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002574
Guido van Rossum43713e52000-02-29 13:59:29 +00002575 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002576 return NULL;
2577
Guido van Rossum00d93061998-05-28 23:06:38 +00002578 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002579 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002580 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002581 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002582}
2583
2584static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002585Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002586{
2587
Guido van Rossum43713e52000-02-29 13:59:29 +00002588 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002589 return NULL;
2590
2591 quitMainLoop = 1;
2592 Py_INCREF(Py_None);
2593 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002594}
2595
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002596static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002597Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002598{
2599
Guido van Rossum43713e52000-02-29 13:59:29 +00002600 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002601 return NULL;
2602
2603 return PyInt_FromLong((long)Tkapp_Interp(self));
2604}
2605
David Aschere2b4b322004-02-18 05:59:53 +00002606static PyObject *
2607Tkapp_TkInit(PyObject *self, PyObject *args)
2608{
2609 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002610 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002611 const char * _tk_exists = NULL;
2612 PyObject *res = NULL;
2613 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002614 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002615
2616 /* We want to guard against calling Tk_Init() multiple times */
2617 CHECK_TCL_APPARTMENT;
2618 ENTER_TCL
2619 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2620 ENTER_OVERLAP
2621 if (err == TCL_ERROR) {
2622 res = Tkinter_Error(self);
2623 } else {
2624 _tk_exists = Tkapp_Result(self);
2625 }
2626 LEAVE_OVERLAP_TCL
2627 if (err == TCL_ERROR) {
2628 return NULL;
2629 }
2630 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2631 if (Tk_Init(interp) == TCL_ERROR) {
2632 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2633 return NULL;
2634 }
2635 }
2636 Py_INCREF(Py_None);
2637 return Py_None;
2638}
Barry Warsawfa701a81997-01-16 00:15:11 +00002639
Martin v. Löwisffad6332002-11-26 09:28:05 +00002640static PyObject *
2641Tkapp_WantObjects(PyObject *self, PyObject *args)
2642{
2643
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002644 int wantobjects = -1;
2645 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002646 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002647 if (wantobjects == -1)
2648 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002649 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002650
2651 Py_INCREF(Py_None);
2652 return Py_None;
2653}
2654
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002655static PyObject *
2656Tkapp_WillDispatch(PyObject *self, PyObject *args)
2657{
2658
2659 ((TkappObject*)self)->dispatching = 1;
2660
2661 Py_INCREF(Py_None);
2662 return Py_None;
2663}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002664
Barry Warsawfa701a81997-01-16 00:15:11 +00002665
Guido van Rossum18468821994-06-20 07:49:28 +00002666/**** Tkapp Method List ****/
2667
2668static PyMethodDef Tkapp_methods[] =
2669{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002670 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002671 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002672 {"call", Tkapp_Call, METH_OLDARGS},
2673 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2674 {"eval", Tkapp_Eval, METH_VARARGS},
2675 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2676 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2677 {"record", Tkapp_Record, METH_VARARGS},
2678 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2679 {"setvar", Tkapp_SetVar, METH_VARARGS},
2680 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2681 {"getvar", Tkapp_GetVar, METH_VARARGS},
2682 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2683 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2684 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2685 {"getint", Tkapp_GetInt, METH_VARARGS},
2686 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2687 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2688 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2689 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2690 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2691 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2692 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2693 {"split", Tkapp_Split, METH_VARARGS},
2694 {"merge", Tkapp_Merge, METH_OLDARGS},
2695 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2696 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002697#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002698 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2699 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002700#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002701 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2702 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2703 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2704 {"quit", Tkapp_Quit, METH_VARARGS},
2705 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002706 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002707 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002708};
2709
Barry Warsawfa701a81997-01-16 00:15:11 +00002710
2711
Guido van Rossum18468821994-06-20 07:49:28 +00002712/**** Tkapp Type Methods ****/
2713
2714static void
Fred Drake509d79a2000-07-08 04:04:38 +00002715Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002716{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002717 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002718 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002719 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002720 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002721 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002722 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002723}
2724
2725static PyObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002726Tkapp_GetAttr(PyObject *self, const char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002727{
Guido van Rossum35d43371997-08-02 00:09:09 +00002728 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002729}
2730
2731static PyTypeObject Tkapp_Type =
2732{
Guido van Rossum35d43371997-08-02 00:09:09 +00002733 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002734 0, /*ob_size */
2735 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002736 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002737 0, /*tp_itemsize */
2738 Tkapp_Dealloc, /*tp_dealloc */
2739 0, /*tp_print */
2740 Tkapp_GetAttr, /*tp_getattr */
2741 0, /*tp_setattr */
2742 0, /*tp_compare */
2743 0, /*tp_repr */
2744 0, /*tp_as_number */
2745 0, /*tp_as_sequence */
2746 0, /*tp_as_mapping */
2747 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002748};
2749
Barry Warsawfa701a81997-01-16 00:15:11 +00002750
2751
Guido van Rossum18468821994-06-20 07:49:28 +00002752/**** Tkinter Module ****/
2753
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002754typedef struct {
2755 PyObject* tuple;
2756 int size; /* current size */
2757 int maxsize; /* allocated size */
2758} FlattenContext;
2759
2760static int
2761_bump(FlattenContext* context, int size)
2762{
Guido van Rossum2834b972000-10-06 16:58:26 +00002763 /* expand tuple to hold (at least) size new items.
2764 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002765
2766 int maxsize = context->maxsize * 2;
2767
2768 if (maxsize < context->size + size)
2769 maxsize = context->size + size;
2770
2771 context->maxsize = maxsize;
2772
Tim Peters4324aa32001-05-28 22:30:08 +00002773 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002774}
2775
2776static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002777_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002778{
2779 /* add tuple or list to argument tuple (recursively) */
2780
2781 int i, size;
2782
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002783 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002784 PyErr_SetString(PyExc_ValueError,
2785 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002786 return 0;
2787 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788 size = PyList_GET_SIZE(item);
2789 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002790 if (context->size + size > context->maxsize &&
2791 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792 return 0;
2793 /* copy items to output tuple */
2794 for (i = 0; i < size; i++) {
2795 PyObject *o = PyList_GET_ITEM(item, i);
2796 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002797 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002798 return 0;
2799 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002800 if (context->size + 1 > context->maxsize &&
2801 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002802 return 0;
2803 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002804 PyTuple_SET_ITEM(context->tuple,
2805 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806 }
2807 }
2808 } else if (PyTuple_Check(item)) {
2809 /* same, for tuples */
2810 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002811 if (context->size + size > context->maxsize &&
2812 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002813 return 0;
2814 for (i = 0; i < size; i++) {
2815 PyObject *o = PyTuple_GET_ITEM(item, i);
2816 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002817 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002818 return 0;
2819 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002820 if (context->size + 1 > context->maxsize &&
2821 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002822 return 0;
2823 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002824 PyTuple_SET_ITEM(context->tuple,
2825 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002826 }
2827 }
2828 } else {
2829 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2830 return 0;
2831 }
2832 return 1;
2833}
2834
2835static PyObject *
2836Tkinter_Flatten(PyObject* self, PyObject* args)
2837{
2838 FlattenContext context;
2839 PyObject* item;
2840
2841 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2842 return NULL;
2843
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002844 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002845 if (context.maxsize <= 0)
2846 return PyTuple_New(0);
2847
2848 context.tuple = PyTuple_New(context.maxsize);
2849 if (!context.tuple)
2850 return NULL;
2851
2852 context.size = 0;
2853
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002854 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002855 return NULL;
2856
Tim Peters4324aa32001-05-28 22:30:08 +00002857 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002858 return NULL;
2859
2860 return context.tuple;
2861}
2862
Guido van Rossum18468821994-06-20 07:49:28 +00002863static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002864Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002865{
Barry Warsawfa701a81997-01-16 00:15:11 +00002866 char *screenName = NULL;
2867 char *baseName = NULL;
2868 char *className = NULL;
2869 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002870 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002871 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002872 int sync = 0; /* pass -sync to wish */
2873 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002874
Guido van Rossum35d43371997-08-02 00:09:09 +00002875 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002876 if (baseName != NULL)
2877 baseName++;
2878 else
2879 baseName = Py_GetProgramName();
2880 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002881
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002882 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002883 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002884 &interactive, &wantobjects, &wantTk,
2885 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002886 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002887
Barry Warsawfa701a81997-01-16 00:15:11 +00002888 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002889 interactive, wantobjects, wantTk,
2890 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002891}
2892
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002893static PyObject *
2894Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2895{
2896 int new_val;
2897 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2898 return NULL;
2899 if (new_val < 0) {
2900 PyErr_SetString(PyExc_ValueError,
2901 "busywaitinterval must be >= 0");
2902 return NULL;
2903 }
2904 Tkinter_busywaitinterval = new_val;
2905 Py_INCREF(Py_None);
2906 return Py_None;
2907}
2908
2909static char setbusywaitinterval_doc[] =
2910"setbusywaitinterval(n) -> None\n\
2911\n\
2912Set the busy-wait interval in milliseconds between successive\n\
2913calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2914It should be set to a divisor of the maximum time between\n\
2915frames in an animation.";
2916
2917static PyObject *
2918Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2919{
2920 return PyInt_FromLong(Tkinter_busywaitinterval);
2921}
2922
2923static char getbusywaitinterval_doc[] =
2924"getbusywaitinterval() -> int\n\
2925\n\
2926Return the current busy-wait interval between successive\n\
2927calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2928
Guido van Rossum18468821994-06-20 07:49:28 +00002929static PyMethodDef moduleMethods[] =
2930{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002931 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2932 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002933#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002934 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2935 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002936#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002937 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2938 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2939 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2940 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002941 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2942 setbusywaitinterval_doc},
2943 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2944 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002945 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002946};
2947
Guido van Rossum7bf15641998-05-22 18:28:17 +00002948#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002949
2950static int stdin_ready = 0;
2951
Guido van Rossumad4db171998-06-13 13:56:28 +00002952#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002953static void
Fred Drake509d79a2000-07-08 04:04:38 +00002954MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002955{
2956 stdin_ready = 1;
2957}
Guido van Rossumad4db171998-06-13 13:56:28 +00002958#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002959
Martin v. Löwisa9656492003-03-30 08:44:58 +00002960#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002961static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002962#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002963
Guido van Rossum18468821994-06-20 07:49:28 +00002964static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002965EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002966{
Guido van Rossumad4db171998-06-13 13:56:28 +00002967#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002968 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002969#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002970#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002971 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002972#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002973 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002974 errorInCmd = 0;
2975#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002976 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002977 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002978#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002979 while (!errorInCmd && !stdin_ready) {
2980 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002981#ifdef MS_WINDOWS
2982 if (_kbhit()) {
2983 stdin_ready = 1;
2984 break;
2985 }
2986#endif
2987#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002988 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002989 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002990 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002991
Guido van Rossum00d93061998-05-28 23:06:38 +00002992 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002993
2994 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002995 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002996 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002997 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002998 Py_END_ALLOW_THREADS
2999#else
3000 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003001#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003002
3003 if (result < 0)
3004 break;
3005 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003006#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00003007 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003008#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003009 if (errorInCmd) {
3010 errorInCmd = 0;
3011 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3012 excInCmd = valInCmd = trbInCmd = NULL;
3013 PyErr_Print();
3014 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003015#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003016 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003017#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003018 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003019}
Guido van Rossum18468821994-06-20 07:49:28 +00003020
Guido van Rossum00d93061998-05-28 23:06:38 +00003021#endif
3022
Guido van Rossum7bf15641998-05-22 18:28:17 +00003023static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003024EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003025{
Guido van Rossum00d93061998-05-28 23:06:38 +00003026#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003027 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003028#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003029 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003030#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003031 PyOS_InputHook = EventHook;
3032 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003033#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003034}
3035
3036static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003037DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003038{
Guido van Rossum00d93061998-05-28 23:06:38 +00003039#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003040 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3041 PyOS_InputHook = NULL;
3042 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003043#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003044}
3045
Barry Warsawfa701a81997-01-16 00:15:11 +00003046
3047/* all errors will be checked in one fell swoop in init_tkinter() */
3048static void
Fred Drake509d79a2000-07-08 04:04:38 +00003049ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003050{
3051 PyObject *v = PyInt_FromLong(val);
3052 if (v) {
3053 PyDict_SetItemString(d, name, v);
3054 Py_DECREF(v);
3055 }
3056}
3057static void
Fred Drake509d79a2000-07-08 04:04:38 +00003058ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003059{
3060 PyObject *v = PyString_FromString(val);
3061 if (v) {
3062 PyDict_SetItemString(d, name, v);
3063 Py_DECREF(v);
3064 }
3065}
3066
3067
Mark Hammond62b1ab12002-07-23 06:31:15 +00003068PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003069init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003070{
Barry Warsawfa701a81997-01-16 00:15:11 +00003071 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003072
Barry Warsawfa701a81997-01-16 00:15:11 +00003073 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003074
3075#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003076 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003077#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003078
Barry Warsawfa701a81997-01-16 00:15:11 +00003079 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003080
Barry Warsawfa701a81997-01-16 00:15:11 +00003081 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003082 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003083 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003084
Guido van Rossum35d43371997-08-02 00:09:09 +00003085 ins_long(d, "READABLE", TCL_READABLE);
3086 ins_long(d, "WRITABLE", TCL_WRITABLE);
3087 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3088 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3089 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3090 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3091 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3092 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3093 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003094 ins_string(d, "TK_VERSION", TK_VERSION);
3095 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003096
Guido van Rossum83551bf1997-09-13 00:44:23 +00003097 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003098
3099 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003100 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3101
Martin v. Löwisffad6332002-11-26 09:28:05 +00003102 PyTclObject_Type.ob_type = &PyType_Type;
3103 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003104
3105#ifdef TK_AQUA
3106 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3107 * start waking up. Note that Tcl_FindExecutable will do this, this
3108 * code must be above it! The original warning from
3109 * tkMacOSXAppInit.c is copied below.
3110 *
3111 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3112 * Tcl interpreter for now. It probably should work to do this
3113 * in the other order, but for now it doesn't seem to.
3114 *
3115 */
3116 Tk_MacOSXSetupTkNotifier();
3117#endif
3118
3119
Guido van Rossume187b0e2000-03-27 21:46:29 +00003120 /* This helps the dynamic loader; in Unicode aware Tcl versions
3121 it also helps Tcl find its encodings. */
3122 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003123
Barry Warsawfa701a81997-01-16 00:15:11 +00003124 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003125 return;
3126
Guido van Rossum43ff8681998-07-14 18:02:13 +00003127#if 0
3128 /* This was not a good idea; through <Destroy> bindings,
3129 Tcl_Finalize() may invoke Python code but at that point the
3130 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003131 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003132#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003133
Guido van Rossum18468821994-06-20 07:49:28 +00003134}