blob: 94ae48d388a18c9b1017e4b86bb6feb2fa88e4cd [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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
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
Christian Heimes217cfd12007-12-02 14:31:20 +000047#define PyBool_FromLong PyLong_FromLong
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000048#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
Guilherme Polo2d87e422009-04-10 22:19:09 +000070#include "tkinter.h"
71
Jason Tishlerbbe89612002-12-31 20:30:46 +000072/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#ifndef CONST84_RETURN
74#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000075#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#define CONST
77#endif
78
Guilherme Polo66917722009-02-09 22:35:27 +000079#if TK_VERSION_HEX < 0x08030102
80#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Jack Janseneddc1442003-11-20 01:44:59 +000083#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000084#define HAVE_CREATEFILEHANDLER
85#endif
86
Guido van Rossum00d93061998-05-28 23:06:38 +000087#ifdef HAVE_CREATEFILEHANDLER
88
Neal Norwitzd948a432006-01-08 01:08:55 +000089/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
90 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
91#ifndef TCL_UNIX_FD
92# ifdef TCL_WIN_SOCKET
93# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
94# else
95# define TCL_UNIX_FD 1
96# endif
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* Tcl_CreateFileHandler() changed several times; these macros deal with the
100 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
101 Unix, only because Jack added it back); when available on Windows, it only
102 applies to sockets. */
103
Guido van Rossum7bf15641998-05-22 18:28:17 +0000104#ifdef MS_WINDOWS
105#define FHANDLETYPE TCL_WIN_SOCKET
106#else
107#define FHANDLETYPE TCL_UNIX_FD
108#endif
109
Guido van Rossum00d93061998-05-28 23:06:38 +0000110/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
111 which uses this to handle Tcl events while the user is typing commands. */
112
113#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000114#define WAIT_FOR_STDIN
115#endif
116
Guido van Rossum00d93061998-05-28 23:06:38 +0000117#endif /* HAVE_CREATEFILEHANDLER */
118
Guido van Rossumad4db171998-06-13 13:56:28 +0000119#ifdef MS_WINDOWS
120#include <conio.h>
121#define WAIT_FOR_STDIN
122#endif
123
Guido van Rossum00d93061998-05-28 23:06:38 +0000124#ifdef WITH_THREAD
125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000126/* The threading situation is complicated. Tcl is not thread-safe, except
127 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000128 So we need to use a lock around all uses of Tcl. Previously, the Python
129 interpreter lock was used for this. However, this causes problems when
130 other Python threads need to run while Tcl is blocked waiting for events.
131
132 To solve this problem, a separate lock for Tcl is introduced. Holding it
133 is incompatible with holding Python's interpreter lock. The following four
134 macros manipulate both locks together.
135
136 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
137 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
138 that could call an event handler, or otherwise affect the state of a Tcl
139 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000140 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000141 released and the lock for Tcl has been acquired.
142
Guido van Rossum5e977831998-06-15 14:03:52 +0000143 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
144 (For example, when transferring data from the Tcl interpreter result to a
145 Python string object.) This can be done by using different macros to close
146 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
147 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
148 releases the Tcl lock.
149
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000150 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000151 handlers when the handler needs to use Python. Such event handlers are
152 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000153 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000154 the Python interpreter lock, restoring the appropriate thread state, and
155 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
156 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000157 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000158
159 These locks expand to several statements and brackets; they should not be
160 used in branches of if statements and the like.
161
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000162 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
163 only valid in the thread that created it, and all Tk activity must happen in this
164 thread, also. That means that the mainloop must be invoked in the thread that
165 created the interpreter. Invoking commands from other threads is possible;
166 _tkinter will queue an event for the interpreter thread, which will then
167 execute the command and pass back the result. If the main thread is not in the
168 mainloop, and invoking commands causes an exception; if the main loop is running
169 but not processing events, the command invocation will block.
170
171 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
172 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
173 threads. So we use the Tcl TLS API.
174
Guido van Rossum00d93061998-05-28 23:06:38 +0000175*/
176
Guido van Rossum65d5b571998-12-21 19:32:43 +0000177static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178
179#ifdef TCL_THREADS
180static Tcl_ThreadDataKey state_key;
181typedef PyThreadState *ThreadSpecificData;
182#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
183#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000184static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000185#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000186
187#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
189 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000190
191#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000192 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000193
Guido van Rossum62320c91998-06-15 04:36:09 +0000194#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000196
197#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000199
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
202 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
204#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 { PyThreadState *tstate = PyEval_SaveThread(); \
206 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000207
208#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 if (((TkappObject *)self)->threaded && \
210 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
211 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
212 return 0; \
213 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000214
215#else
216
217#define ENTER_TCL
218#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000219#define ENTER_OVERLAP
220#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000221#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000222#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000223#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000224
225#endif
226
Guido van Rossum97867b21996-08-08 19:09:53 +0000227#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000228#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000229#endif
230
Guido van Rossum18468821994-06-20 07:49:28 +0000231/**** Tkapp Object Declaration ****/
232
Jeremy Hylton938ace62002-07-17 16:30:39 +0000233static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000234
Guido van Rossum00d93061998-05-28 23:06:38 +0000235typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 PyObject_HEAD
237 Tcl_Interp *interp;
238 int wantobjects;
239 int threaded; /* True if tcl_platform[threaded] */
240 Tcl_ThreadId thread_id;
241 int dispatching;
242 /* We cannot include tclInt.h, as this is internal.
243 So we cache interesting types here. */
244 Tcl_ObjType *BooleanType;
245 Tcl_ObjType *ByteArrayType;
246 Tcl_ObjType *DoubleType;
247 Tcl_ObjType *IntType;
248 Tcl_ObjType *ListType;
249 Tcl_ObjType *ProcBodyType;
250 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000251} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000252
Christian Heimes90aa7642007-12-19 02:45:37 +0000253#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000254#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000255#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guido van Rossum35d43371997-08-02 00:09:09 +0000257#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000258(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000259
Barry Warsawfa701a81997-01-16 00:15:11 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262/**** Error Handling ****/
263
264static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000265static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000266static int errorInCmd = 0;
267static PyObject *excInCmd;
268static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000269static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guilherme Polob681df42009-02-09 22:33:59 +0000271#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000272static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000273#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275
Guido van Rossum18468821994-06-20 07:49:28 +0000276static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000277Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
280 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000281}
282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284
Guido van Rossum18468821994-06-20 07:49:28 +0000285/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000286
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000287static int Tkinter_busywaitinterval = 20;
288
Guido van Rossum00d93061998-05-28 23:06:38 +0000289#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000290#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000291
Guido van Rossum00d93061998-05-28 23:06:38 +0000292/* Millisecond sleep() for Unix platforms. */
293
294static void
Fred Drake509d79a2000-07-08 04:04:38 +0000295Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000296{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 /* XXX Too bad if you don't have select(). */
298 struct timeval t;
299 t.tv_sec = milli/1000;
300 t.tv_usec = (milli%1000) * 1000;
301 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000302}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000303#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000304
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000305/* Wait up to 1s for the mainloop to come up. */
306
307static int
308WaitForMainloop(TkappObject* self)
309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 int i;
311 for (i = 0; i < 10; i++) {
312 if (self->dispatching)
313 return 1;
314 Py_BEGIN_ALLOW_THREADS
315 Sleep(100);
316 Py_END_ALLOW_THREADS
317 }
318 if (self->dispatching)
319 return 1;
320 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
321 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000322}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000323#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325
Guido van Rossum18468821994-06-20 07:49:28 +0000326static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000327AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000328{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 if (PyBytes_Check(value))
330 return PyBytes_AsString(value);
331 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 PyBytes_AsString(v);
341 }
342 else {
343 PyObject *v = PyObject_Str(value);
344 if (v == NULL)
345 return NULL;
346 if (PyList_Append(tmp, v) != 0) {
347 Py_DECREF(v);
348 return NULL;
349 }
350 Py_DECREF(v);
351 return PyBytes_AsString(v);
352 }
Guido van Rossum18468821994-06-20 07:49:28 +0000353}
354
Barry Warsawfa701a81997-01-16 00:15:11 +0000355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356
Guido van Rossum18468821994-06-20 07:49:28 +0000357#define ARGSZ 64
358
359static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000360Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 PyObject *tmp = NULL;
363 char *argvStore[ARGSZ];
364 char **argv = NULL;
365 int fvStore[ARGSZ];
366 int *fv = NULL;
367 int argc = 0, fvc = 0, i;
368 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 if (!(tmp = PyList_New(0)))
371 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 argv = argvStore;
374 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 if (args == NULL)
377 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 else if (!PyTuple_Check(args)) {
380 argc = 1;
381 fv[0] = 0;
382 if (!(argv[0] = AsString(args, tmp)))
383 goto finally;
384 }
385 else {
386 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 if (argc > ARGSZ) {
389 argv = (char **)ckalloc(argc * sizeof(char *));
390 fv = (int *)ckalloc(argc * sizeof(int));
391 if (argv == NULL || fv == NULL) {
392 PyErr_NoMemory();
393 goto finally;
394 }
395 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 for (i = 0; i < argc; i++) {
398 PyObject *v = PyTuple_GetItem(args, i);
399 if (PyTuple_Check(v)) {
400 fv[i] = 1;
401 if (!(argv[i] = Merge(v)))
402 goto finally;
403 fvc++;
404 }
405 else if (v == Py_None) {
406 argc = i;
407 break;
408 }
409 else {
410 fv[i] = 0;
411 if (!(argv[i] = AsString(v, tmp)))
412 goto finally;
413 fvc++;
414 }
415 }
416 }
417 res = Tcl_Merge(argc, argv);
418 if (res == NULL)
419 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000420
Barry Warsawfa701a81997-01-16 00:15:11 +0000421 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 for (i = 0; i < fvc; i++)
423 if (fv[i]) {
424 ckfree(argv[i]);
425 }
426 if (argv != argvStore)
427 ckfree(FREECAST argv);
428 if (fv != fvStore)
429 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 Py_DECREF(tmp);
432 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000433}
434
Barry Warsawfa701a81997-01-16 00:15:11 +0000435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000436
Guido van Rossum18468821994-06-20 07:49:28 +0000437static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000438Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000439{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 int argc;
441 char **argv;
442 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000443
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 if (list == NULL) {
445 Py_INCREF(Py_None);
446 return Py_None;
447 }
Guido van Rossum18468821994-06-20 07:49:28 +0000448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
450 /* Not a list.
451 * Could be a quoted string containing funnies, e.g. {"}.
452 * Return the string itself.
453 */
454 return PyUnicode_FromString(list);
455 }
Guido van Rossum18468821994-06-20 07:49:28 +0000456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 if (argc == 0)
458 v = PyUnicode_FromString("");
459 else if (argc == 1)
460 v = PyUnicode_FromString(argv[0]);
461 else if ((v = PyTuple_New(argc)) != NULL) {
462 int i;
463 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000465 for (i = 0; i < argc; i++) {
466 if ((w = Split(argv[i])) == NULL) {
467 Py_DECREF(v);
468 v = NULL;
469 break;
470 }
471 PyTuple_SetItem(v, i, w);
472 }
473 }
474 Tcl_Free(FREECAST argv);
475 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000476}
477
Martin v. Löwisffad6332002-11-26 09:28:05 +0000478/* In some cases, Tcl will still return strings that are supposed to be
479 lists. SplitObj walks through a nested tuple, finding string objects that
480 need to be split. */
481
Martin v. Löwis59683e82008-06-13 07:50:45 +0000482static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000483SplitObj(PyObject *arg)
484{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 if (PyTuple_Check(arg)) {
486 int i, size;
487 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 size = PyTuple_Size(arg);
490 result = NULL;
491 /* Recursively invoke SplitObj for all tuple items.
492 If this does not return a new object, no action is
493 needed. */
494 for(i = 0; i < size; i++) {
495 elem = PyTuple_GetItem(arg, i);
496 newelem = SplitObj(elem);
497 if (!newelem) {
498 Py_XDECREF(result);
499 return NULL;
500 }
501 if (!result) {
502 int k;
503 if (newelem == elem) {
504 Py_DECREF(newelem);
505 continue;
506 }
507 result = PyTuple_New(size);
508 if (!result)
509 return NULL;
510 for(k = 0; k < i; k++) {
511 elem = PyTuple_GetItem(arg, k);
512 Py_INCREF(elem);
513 PyTuple_SetItem(result, k, elem);
514 }
515 }
516 PyTuple_SetItem(result, i, newelem);
517 }
518 if (result)
519 return result;
520 /* Fall through, returning arg. */
521 }
522 else if (PyBytes_Check(arg)) {
523 int argc;
524 char **argv;
525 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
528 Py_INCREF(arg);
529 return arg;
530 }
531 Tcl_Free(FREECAST argv);
532 if (argc > 1)
533 return Split(PyBytes_AsString(arg));
534 /* Fall through, returning arg. */
535 }
536 Py_INCREF(arg);
537 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000538}
Barry Warsawfa701a81997-01-16 00:15:11 +0000539
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540
Guido van Rossum18468821994-06-20 07:49:28 +0000541/**** Tkapp Object ****/
542
543#ifndef WITH_APPINIT
544int
Fred Drake509d79a2000-07-08 04:04:38 +0000545Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000546{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 if (Tcl_Init(interp) == TCL_ERROR) {
550 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
551 return TCL_ERROR;
552 }
Guilherme Polob681df42009-02-09 22:33:59 +0000553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 _tkinter_skip_tk_init = Tcl_GetVar(interp,
555 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
556 if (_tkinter_skip_tk_init != NULL &&
557 strcmp(_tkinter_skip_tk_init, "1") == 0) {
558 return TCL_OK;
559 }
Guilherme Polob681df42009-02-09 22:33:59 +0000560
561#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 if (tk_load_failed) {
563 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
564 return TCL_ERROR;
565 }
Guilherme Polob681df42009-02-09 22:33:59 +0000566#endif
567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000569#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000571#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
573 return TCL_ERROR;
574 }
Guilherme Polob681df42009-02-09 22:33:59 +0000575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000577}
578#endif /* !WITH_APPINIT */
579
Guido van Rossum18468821994-06-20 07:49:28 +0000580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581
Barry Warsawfa701a81997-01-16 00:15:11 +0000582
583/* Initialize the Tk application; see the `main' function in
584 * `tkMain.c'.
585 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000586
Thomas Wouters58d05102000-07-24 14:43:35 +0000587static void EnableEventHook(void); /* Forward */
588static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000589
Barry Warsawfa701a81997-01-16 00:15:11 +0000590static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000591Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 TkappObject *v;
595 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 v = PyObject_New(TkappObject, &Tkapp_Type);
598 if (v == NULL)
599 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 v->interp = Tcl_CreateInterp();
602 v->wantobjects = wantobjects;
603 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
604 TCL_GLOBAL_ONLY) != NULL;
605 v->thread_id = Tcl_GetCurrentThread();
606 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000607
608#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (v->threaded) {
610 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
611 Py_DECREF(v);
612 return 0;
613 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000614#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000615#ifdef WITH_THREAD
Martin v. Löwisdf50ceb2012-03-13 13:59:15 -0700616 if (!(v->threaded)) {
617 PyErr_SetString(PyExc_RuntimeError,
618 "Tcl/Tk was not compiled with --enable-threads but "
619 "Python has threads enabled");
620 Py_DECREF(v);
621 return 0;
622 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 if (v->threaded && tcl_lock) {
624 /* If Tcl is threaded, we don't need the lock. */
625 PyThread_free_lock(tcl_lock);
626 tcl_lock = NULL;
627 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000628#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 v->BooleanType = Tcl_GetObjType("boolean");
631 v->ByteArrayType = Tcl_GetObjType("bytearray");
632 v->DoubleType = Tcl_GetObjType("double");
633 v->IntType = Tcl_GetObjType("int");
634 v->ListType = Tcl_GetObjType("list");
635 v->ProcBodyType = Tcl_GetObjType("procbody");
636 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 /* Delete the 'exit' command, which can screw things up */
639 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 if (screenName != NULL)
642 Tcl_SetVar2(v->interp, "env", "DISPLAY",
643 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 if (interactive)
646 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
647 else
648 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 /* This is used to get the application class for Tk 4.1 and up */
651 argv0 = (char*)ckalloc(strlen(className) + 1);
652 if (!argv0) {
653 PyErr_NoMemory();
654 Py_DECREF(v);
655 return NULL;
656 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200659 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
660 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
662 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 if (! wantTk) {
665 Tcl_SetVar(v->interp,
666 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
667 }
Guilherme Polob681df42009-02-09 22:33:59 +0000668#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 else if (tk_load_failed) {
670 Tcl_SetVar(v->interp,
671 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
672 }
Guilherme Polob681df42009-02-09 22:33:59 +0000673#endif
David Aschere2b4b322004-02-18 05:59:53 +0000674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 /* some initial arguments need to be in argv */
676 if (sync || use) {
677 char *args;
678 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 if (sync)
681 len += sizeof "-sync";
682 if (use)
683 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 args = (char*)ckalloc(len);
686 if (!args) {
687 PyErr_NoMemory();
688 Py_DECREF(v);
689 return NULL;
690 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 args[0] = '\0';
693 if (sync)
694 strcat(args, "-sync");
695 if (use) {
696 if (sync)
697 strcat(args, " ");
698 strcat(args, "-use ");
699 strcat(args, use);
700 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
703 ckfree(args);
704 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 if (Tcl_AppInit(v->interp) != TCL_OK) {
707 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000708#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 if (wantTk) {
710 const char *_tkinter_tk_failed;
711 _tkinter_tk_failed = Tcl_GetVar(v->interp,
712 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 if ( _tkinter_tk_failed != NULL &&
715 strcmp(_tkinter_tk_failed, "1") == 0) {
716 tk_load_failed = 1;
717 }
718 }
Guilherme Polob681df42009-02-09 22:33:59 +0000719#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 Py_DECREF((PyObject *)v);
721 return (TkappObject *)result;
722 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000727}
728
Barry Warsawfa701a81997-01-16 00:15:11 +0000729
Benjamin Peterson5879d412009-03-30 14:51:56 +0000730#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000731static void
732Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000734{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 Py_BEGIN_ALLOW_THREADS;
736 Tcl_MutexLock(mutex);
737 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
738 Tcl_ThreadAlert(self->thread_id);
739 Tcl_ConditionWait(cond, mutex, NULL);
740 Tcl_MutexUnlock(mutex);
741 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000742}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000743#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745
Guido van Rossum18468821994-06-20 07:49:28 +0000746/** Tcl Eval **/
747
Martin v. Löwisffad6332002-11-26 09:28:05 +0000748typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 PyObject_HEAD
750 Tcl_Obj *value;
751 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000752} PyTclObject;
753
Neal Norwitz227b5332006-03-22 09:28:35 +0000754static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000756
757static PyObject *
758newPyTclObject(Tcl_Obj *arg)
759{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760 PyTclObject *self;
761 self = PyObject_New(PyTclObject, &PyTclObject_Type);
762 if (self == NULL)
763 return NULL;
764 Tcl_IncrRefCount(arg);
765 self->value = arg;
766 self->string = NULL;
767 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000768}
769
770static void
771PyTclObject_dealloc(PyTclObject *self)
772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000773 Tcl_DecrRefCount(self->value);
774 Py_XDECREF(self->string);
775 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000776}
777
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000778static char*
779PyTclObject_TclString(PyObject *self)
780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000782}
783
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000784/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000785PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000786"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000787
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000788static PyObject *
789PyTclObject_string(PyTclObject *self, void *ignored)
790{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 char *s;
792 int len;
793 if (!self->string) {
794 s = Tcl_GetStringFromObj(self->value, &len);
795 self->string = PyUnicode_FromStringAndSize(s, len);
796 if (!self->string)
797 return NULL;
798 }
799 Py_INCREF(self->string);
800 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000801}
802
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000803static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000804PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 char *s;
807 int len;
808 if (self->string && PyUnicode_Check(self->string)) {
809 Py_INCREF(self->string);
810 return self->string;
811 }
812 /* XXX Could chache result if it is non-ASCII. */
813 s = Tcl_GetStringFromObj(self->value, &len);
814 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000815}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000816
Martin v. Löwisffad6332002-11-26 09:28:05 +0000817static PyObject *
818PyTclObject_repr(PyTclObject *self)
819{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000820 return PyUnicode_FromFormat("<%s object at %p>",
821 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000822}
823
Mark Dickinson211c6252009-02-01 10:28:51 +0000824#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
825
826static PyObject *
827PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000828{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000829 int result;
830 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000832 /* neither argument should be NULL, unless something's gone wrong */
833 if (self == NULL || other == NULL) {
834 PyErr_BadInternalCall();
835 return NULL;
836 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000838 /* both arguments should be instances of PyTclObject */
839 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
840 v = Py_NotImplemented;
841 goto finished;
842 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000844 if (self == other)
845 /* fast path when self and other are identical */
846 result = 0;
847 else
848 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
849 Tcl_GetString(((PyTclObject *)other)->value));
850 /* Convert return value to a Boolean */
851 switch (op) {
852 case Py_EQ:
853 v = TEST_COND(result == 0);
854 break;
855 case Py_NE:
856 v = TEST_COND(result != 0);
857 break;
858 case Py_LE:
859 v = TEST_COND(result <= 0);
860 break;
861 case Py_GE:
862 v = TEST_COND(result >= 0);
863 break;
864 case Py_LT:
865 v = TEST_COND(result < 0);
866 break;
867 case Py_GT:
868 v = TEST_COND(result > 0);
869 break;
870 default:
871 PyErr_BadArgument();
872 return NULL;
873 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000874 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000875 Py_INCREF(v);
876 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000877}
878
Martin v. Löwis39195712003-01-04 00:33:13 +0000879PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
880
Martin v. Löwisffad6332002-11-26 09:28:05 +0000881static PyObject*
882get_typename(PyTclObject* obj, void* ignored)
883{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000884 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000885}
886
Martin v. Löwis39195712003-01-04 00:33:13 +0000887
Martin v. Löwisffad6332002-11-26 09:28:05 +0000888static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000889 {"typename", (getter)get_typename, NULL, get_typename__doc__},
890 {"string", (getter)PyTclObject_string, NULL,
891 PyTclObject_string__doc__},
892 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000893};
894
Neal Norwitz227b5332006-03-22 09:28:35 +0000895static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 PyVarObject_HEAD_INIT(NULL, 0)
897 "_tkinter.Tcl_Obj", /*tp_name*/
898 sizeof(PyTclObject), /*tp_basicsize*/
899 0, /*tp_itemsize*/
900 /* methods */
901 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
902 0, /*tp_print*/
903 0, /*tp_getattr*/
904 0, /*tp_setattr*/
905 0, /*tp_reserved*/
906 (reprfunc)PyTclObject_repr, /*tp_repr*/
907 0, /*tp_as_number*/
908 0, /*tp_as_sequence*/
909 0, /*tp_as_mapping*/
910 0, /*tp_hash*/
911 0, /*tp_call*/
912 (reprfunc)PyTclObject_str, /*tp_str*/
913 PyObject_GenericGetAttr, /*tp_getattro*/
914 0, /*tp_setattro*/
915 0, /*tp_as_buffer*/
916 Py_TPFLAGS_DEFAULT, /*tp_flags*/
917 0, /*tp_doc*/
918 0, /*tp_traverse*/
919 0, /*tp_clear*/
920 PyTclObject_richcompare, /*tp_richcompare*/
921 0, /*tp_weaklistoffset*/
922 0, /*tp_iter*/
923 0, /*tp_iternext*/
924 0, /*tp_methods*/
925 0, /*tp_members*/
926 PyTclObject_getsetlist, /*tp_getset*/
927 0, /*tp_base*/
928 0, /*tp_dict*/
929 0, /*tp_descr_get*/
930 0, /*tp_descr_set*/
931 0, /*tp_dictoffset*/
932 0, /*tp_init*/
933 0, /*tp_alloc*/
934 0, /*tp_new*/
935 0, /*tp_free*/
936 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000937};
938
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000939static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000940AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000941{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 Tcl_Obj *result;
943 long longVal;
944 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000945
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 if (PyBytes_Check(value))
947 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
948 PyBytes_GET_SIZE(value));
949 else if (PyBool_Check(value))
950 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
951 else if (PyLong_CheckExact(value) &&
952 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
953 !overflow)) {
954 /* If there is an overflow in the long conversion,
955 fall through to default object handling. */
956 return Tcl_NewLongObj(longVal);
957 }
958 else if (PyFloat_Check(value))
959 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
960 else if (PyTuple_Check(value)) {
961 Tcl_Obj **argv = (Tcl_Obj**)
962 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
963 int i;
964 if(!argv)
965 return 0;
966 for(i=0;i<PyTuple_Size(value);i++)
967 argv[i] = AsObj(PyTuple_GetItem(value,i));
968 result = Tcl_NewListObj(PyTuple_Size(value), argv);
969 ckfree(FREECAST argv);
970 return result;
971 }
972 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200973 void *inbuf;
974 Py_ssize_t size;
975 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 Tcl_UniChar *outbuf = NULL;
977 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200978 size_t allocsize;
979
980 if (PyUnicode_READY(value) == -1)
981 return NULL;
982
983 inbuf = PyUnicode_DATA(value);
984 size = PyUnicode_GET_LENGTH(value);
985 kind = PyUnicode_KIND(value);
986 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
987 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 /* Else overflow occurred, and we take the next exit */
989 if (!outbuf) {
990 PyErr_NoMemory();
991 return NULL;
992 }
993 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200994 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
995 /* We cannot test for sizeof(Tcl_UniChar) directly,
996 so we test for UTF-8 size instead. */
997#if TCL_UTF_MAX == 3
998 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 /* Tcl doesn't do UTF-16, yet. */
Victor Stinner7ab41922011-11-04 00:36:46 +01001000 PyErr_Format(PyExc_ValueError,
1001 "character U+%x is above the range "
1002 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001003 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 ckfree(FREECAST outbuf);
1005 return NULL;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001006#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001007 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001008 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 }
1010 result = Tcl_NewUnicodeObj(outbuf, size);
1011 ckfree(FREECAST outbuf);
1012 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 }
1014 else if(PyTclObject_Check(value)) {
1015 Tcl_Obj *v = ((PyTclObject*)value)->value;
1016 Tcl_IncrRefCount(v);
1017 return v;
1018 }
1019 else {
1020 PyObject *v = PyObject_Str(value);
1021 if (!v)
1022 return 0;
1023 result = AsObj(v);
1024 Py_DECREF(v);
1025 return result;
1026 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001027}
1028
Martin v. Löwisffad6332002-11-26 09:28:05 +00001029static PyObject*
1030FromObj(PyObject* tkapp, Tcl_Obj *value)
1031{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001032 PyObject *result = NULL;
1033 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 if (value->typePtr == NULL) {
1036 return PyUnicode_FromStringAndSize(value->bytes,
1037 value->length);
1038 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001040 if (value->typePtr == app->BooleanType) {
1041 result = value->internalRep.longValue ? Py_True : Py_False;
1042 Py_INCREF(result);
1043 return result;
1044 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001046 if (value->typePtr == app->ByteArrayType) {
1047 int size;
1048 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1049 return PyBytes_FromStringAndSize(data, size);
1050 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001051
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 if (value->typePtr == app->DoubleType) {
1053 return PyFloat_FromDouble(value->internalRep.doubleValue);
1054 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 if (value->typePtr == app->IntType) {
1057 return PyLong_FromLong(value->internalRep.longValue);
1058 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001059
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 if (value->typePtr == app->ListType) {
1061 int size;
1062 int i, status;
1063 PyObject *elem;
1064 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001066 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1067 if (status == TCL_ERROR)
1068 return Tkinter_Error(tkapp);
1069 result = PyTuple_New(size);
1070 if (!result)
1071 return NULL;
1072 for (i = 0; i < size; i++) {
1073 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1074 value, i, &tcl_elem);
1075 if (status == TCL_ERROR) {
1076 Py_DECREF(result);
1077 return Tkinter_Error(tkapp);
1078 }
1079 elem = FromObj(tkapp, tcl_elem);
1080 if (!elem) {
1081 Py_DECREF(result);
1082 return NULL;
1083 }
1084 PyTuple_SetItem(result, i, elem);
1085 }
1086 return result;
1087 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001088
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001089 if (value->typePtr == app->ProcBodyType) {
1090 /* fall through: return tcl object. */
1091 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001093 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001094#if TCL_UTF_MAX==3
1095 return PyUnicode_FromKindAndData(
1096 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1097 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001098#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001099 return PyUnicode_FromKindAndData(
1100 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1101 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001102#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001103 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001106}
1107
Benjamin Peterson5879d412009-03-30 14:51:56 +00001108#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001109/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001110TCL_DECLARE_MUTEX(call_mutex)
1111
1112typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001113 Tcl_Event ev; /* Must be first */
1114 TkappObject *self;
1115 PyObject *args;
1116 int flags;
1117 PyObject **res;
1118 PyObject **exc_type, **exc_value, **exc_tb;
1119 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001120} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001121#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001122
1123void
1124Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001125{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001126 int i;
1127 for (i = 0; i < objc; i++)
1128 Tcl_DecrRefCount(objv[i]);
1129 if (objv != objStore)
1130 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001131}
Guido van Rossum18468821994-06-20 07:49:28 +00001132
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001133/* Convert Python objects to Tcl objects. This must happen in the
1134 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001135
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001136static Tcl_Obj**
1137Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1138{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 Tcl_Obj **objv = objStore;
1140 int objc = 0, i;
1141 if (args == NULL)
1142 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001143
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001144 else if (!PyTuple_Check(args)) {
1145 objv[0] = AsObj(args);
1146 if (objv[0] == 0)
1147 goto finally;
1148 objc = 1;
1149 Tcl_IncrRefCount(objv[0]);
1150 }
1151 else {
1152 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001153
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001154 if (objc > ARGSZ) {
1155 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1156 if (objv == NULL) {
1157 PyErr_NoMemory();
1158 objc = 0;
1159 goto finally;
1160 }
1161 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 for (i = 0; i < objc; i++) {
1164 PyObject *v = PyTuple_GetItem(args, i);
1165 if (v == Py_None) {
1166 objc = i;
1167 break;
1168 }
1169 objv[i] = AsObj(v);
1170 if (!objv[i]) {
1171 /* Reset objc, so it attempts to clear
1172 objects only up to i. */
1173 objc = i;
1174 goto finally;
1175 }
1176 Tcl_IncrRefCount(objv[i]);
1177 }
1178 }
1179 *pobjc = objc;
1180 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001182 Tkapp_CallDeallocArgs(objv, objStore, objc);
1183 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001184}
Guido van Rossum212643f1998-04-29 16:22:14 +00001185
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001186/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001187
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001188static PyObject*
1189Tkapp_CallResult(TkappObject *self)
1190{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001191 PyObject *res = NULL;
1192 if(self->wantobjects) {
1193 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1194 /* Not sure whether the IncrRef is necessary, but something
1195 may overwrite the interpreter result while we are
1196 converting it. */
1197 Tcl_IncrRefCount(value);
1198 res = FromObj((PyObject*)self, value);
1199 Tcl_DecrRefCount(value);
1200 } else {
1201 const char *s = Tcl_GetStringResult(self->interp);
1202 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001204 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1205 }
1206 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001207}
Guido van Rossum632de272000-03-29 00:19:50 +00001208
Benjamin Peterson5879d412009-03-30 14:51:56 +00001209#ifdef WITH_THREAD
1210
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211/* Tkapp_CallProc is the event procedure that is executed in the context of
1212 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1213 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001214
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001215static int
1216Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1217{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001218 Tcl_Obj *objStore[ARGSZ];
1219 Tcl_Obj **objv;
1220 int objc;
1221 int i;
1222 ENTER_PYTHON
1223 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1224 if (!objv) {
1225 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1226 *(e->res) = NULL;
1227 }
1228 LEAVE_PYTHON
1229 if (!objv)
1230 goto done;
1231 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1232 ENTER_PYTHON
1233 if (i == TCL_ERROR) {
1234 *(e->res) = NULL;
1235 *(e->exc_type) = NULL;
1236 *(e->exc_tb) = NULL;
1237 *(e->exc_value) = PyObject_CallFunction(
1238 Tkinter_TclError, "s",
1239 Tcl_GetStringResult(e->self->interp));
1240 }
1241 else {
1242 *(e->res) = Tkapp_CallResult(e->self);
1243 }
1244 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001247done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001248 /* Wake up calling thread. */
1249 Tcl_MutexLock(&call_mutex);
1250 Tcl_ConditionNotify(e->done);
1251 Tcl_MutexUnlock(&call_mutex);
1252 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001253}
1254
Benjamin Peterson5879d412009-03-30 14:51:56 +00001255#endif
1256
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001257/* This is the main entry point for calling a Tcl command.
1258 It supports three cases, with regard to threading:
1259 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1260 the context of the calling thread.
1261 2. Tcl is threaded, caller of the command is in the interpreter thread:
1262 Execute the command in the calling thread. Since the Tcl lock will
1263 not be used, we can merge that with case 1.
1264 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1265 the interpreter thread. Allocation of Tcl objects needs to occur in the
1266 interpreter thread, so we ship the PyObject* args to the target thread,
1267 and perform processing there. */
1268
1269static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001270Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001271{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 Tcl_Obj *objStore[ARGSZ];
1273 Tcl_Obj **objv = NULL;
1274 int objc, i;
1275 PyObject *res = NULL;
1276 TkappObject *self = (TkappObject*)selfptr;
1277 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 /* If args is a single tuple, replace with contents of tuple */
1280 if (1 == PyTuple_Size(args)){
1281 PyObject* item = PyTuple_GetItem(args, 0);
1282 if (PyTuple_Check(item))
1283 args = item;
1284 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001285#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1287 /* We cannot call the command directly. Instead, we must
1288 marshal the parameters to the interpreter thread. */
1289 Tkapp_CallEvent *ev;
1290 Tcl_Condition cond = NULL;
1291 PyObject *exc_type, *exc_value, *exc_tb;
1292 if (!WaitForMainloop(self))
1293 return NULL;
1294 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1295 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1296 ev->self = self;
1297 ev->args = args;
1298 ev->res = &res;
1299 ev->exc_type = &exc_type;
1300 ev->exc_value = &exc_value;
1301 ev->exc_tb = &exc_tb;
1302 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001304 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 if (res == NULL) {
1307 if (exc_type)
1308 PyErr_Restore(exc_type, exc_value, exc_tb);
1309 else
1310 PyErr_SetObject(Tkinter_TclError, exc_value);
1311 }
1312 Tcl_ConditionFinalize(&cond);
1313 }
1314 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001315#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 objv = Tkapp_CallArgs(args, objStore, &objc);
1319 if (!objv)
1320 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 if (i == TCL_ERROR)
1329 Tkinter_Error(selfptr);
1330 else
1331 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 Tkapp_CallDeallocArgs(objv, objStore, objc);
1336 }
1337 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001338}
1339
1340
1341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001342Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 /* Could do the same here as for Tkapp_Call(), but this is not used
1345 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1346 way for the user to do what all its Global* variants do (save and
1347 reset the scope pointer, call the local version, restore the saved
1348 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 char *cmd;
1351 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 cmd = Merge(args);
1356 if (cmd) {
1357 int err;
1358 ENTER_TCL
1359 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1360 ENTER_OVERLAP
1361 if (err == TCL_ERROR)
1362 res = Tkinter_Error(self);
1363 else
1364 res = PyUnicode_FromString(Tkapp_Result(self));
1365 LEAVE_OVERLAP_TCL
1366 ckfree(cmd);
1367 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001370}
1371
1372static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001373Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001374{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 char *script;
1376 PyObject *res = NULL;
1377 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 if (!PyArg_ParseTuple(args, "s:eval", &script))
1380 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001384 ENTER_TCL
1385 err = Tcl_Eval(Tkapp_Interp(self), script);
1386 ENTER_OVERLAP
1387 if (err == TCL_ERROR)
1388 res = Tkinter_Error(self);
1389 else
1390 res = PyUnicode_FromString(Tkapp_Result(self));
1391 LEAVE_OVERLAP_TCL
1392 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001393}
1394
1395static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001396Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001397{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 char *script;
1399 PyObject *res = NULL;
1400 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001402 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1403 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 ENTER_TCL
1408 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1409 ENTER_OVERLAP
1410 if (err == TCL_ERROR)
1411 res = Tkinter_Error(self);
1412 else
1413 res = PyUnicode_FromString(Tkapp_Result(self));
1414 LEAVE_OVERLAP_TCL
1415 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001416}
1417
1418static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001419Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001420{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 char *fileName;
1422 PyObject *res = NULL;
1423 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001425 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1426 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001428 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 ENTER_TCL
1431 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1432 ENTER_OVERLAP
1433 if (err == TCL_ERROR)
1434 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 else
1437 res = PyUnicode_FromString(Tkapp_Result(self));
1438 LEAVE_OVERLAP_TCL
1439 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001440}
1441
1442static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001443Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001444{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 char *script;
1446 PyObject *res = NULL;
1447 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001449 if (!PyArg_ParseTuple(args, "s", &script))
1450 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 ENTER_TCL
1455 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1456 ENTER_OVERLAP
1457 if (err == TCL_ERROR)
1458 res = Tkinter_Error(self);
1459 else
1460 res = PyUnicode_FromString(Tkapp_Result(self));
1461 LEAVE_OVERLAP_TCL
1462 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001463}
1464
1465static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001466Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001470 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1471 return NULL;
1472 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 ENTER_TCL
1475 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1476 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001478 Py_INCREF(Py_None);
1479 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001480}
1481
Barry Warsawfa701a81997-01-16 00:15:11 +00001482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483
Guido van Rossum18468821994-06-20 07:49:28 +00001484/** Tcl Variable **/
1485
Benjamin Peterson5879d412009-03-30 14:51:56 +00001486typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1487
1488#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001489TCL_DECLARE_MUTEX(var_mutex)
1490
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001492 Tcl_Event ev; /* must be first */
1493 PyObject *self;
1494 PyObject *args;
1495 int flags;
1496 EventFunc func;
1497 PyObject **res;
1498 PyObject **exc_type;
1499 PyObject **exc_val;
1500 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001501} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001502#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001504static int
1505varname_converter(PyObject *in, void *_out)
1506{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001507 char **out = (char**)_out;
1508 if (PyBytes_Check(in)) {
1509 *out = PyBytes_AsString(in);
1510 return 1;
1511 }
1512 if (PyUnicode_Check(in)) {
1513 *out = _PyUnicode_AsString(in);
1514 return 1;
1515 }
1516 if (PyTclObject_Check(in)) {
1517 *out = PyTclObject_TclString(in);
1518 return 1;
1519 }
1520 /* XXX: Should give diagnostics. */
1521 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001522}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001523
Benjamin Peterson5879d412009-03-30 14:51:56 +00001524#ifdef WITH_THREAD
1525
Martin v. Löwis59683e82008-06-13 07:50:45 +00001526static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001527var_perform(VarEvent *ev)
1528{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001529 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1530 if (!*(ev->res)) {
1531 PyObject *exc, *val, *tb;
1532 PyErr_Fetch(&exc, &val, &tb);
1533 PyErr_NormalizeException(&exc, &val, &tb);
1534 *(ev->exc_type) = exc;
1535 *(ev->exc_val) = val;
1536 Py_DECREF(tb);
1537 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001538
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001539}
1540
1541static int
1542var_proc(VarEvent* ev, int flags)
1543{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 ENTER_PYTHON
1545 var_perform(ev);
1546 Tcl_MutexLock(&var_mutex);
1547 Tcl_ConditionNotify(ev->cond);
1548 Tcl_MutexUnlock(&var_mutex);
1549 LEAVE_PYTHON
1550 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001551}
1552
Benjamin Peterson5879d412009-03-30 14:51:56 +00001553#endif
1554
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001555static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001556var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001557{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001558#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001559 TkappObject *self = (TkappObject*)selfptr;
1560 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1561 TkappObject *self = (TkappObject*)selfptr;
1562 VarEvent *ev;
1563 PyObject *res, *exc_type, *exc_val;
1564 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 /* The current thread is not the interpreter thread. Marshal
1567 the call to the interpreter thread, then wait for
1568 completion. */
1569 if (!WaitForMainloop(self))
1570 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574 ev->self = selfptr;
1575 ev->args = args;
1576 ev->flags = flags;
1577 ev->func = func;
1578 ev->res = &res;
1579 ev->exc_type = &exc_type;
1580 ev->exc_val = &exc_val;
1581 ev->cond = &cond;
1582 ev->ev.proc = (Tcl_EventProc*)var_proc;
1583 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1584 Tcl_ConditionFinalize(&cond);
1585 if (!res) {
1586 PyErr_SetObject(exc_type, exc_val);
1587 Py_DECREF(exc_type);
1588 Py_DECREF(exc_val);
1589 return NULL;
1590 }
1591 return res;
1592 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001593#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001594 /* Tcl is not threaded, or this is the interpreter thread. */
1595 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001596}
1597
Guido van Rossum18468821994-06-20 07:49:28 +00001598static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001599SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001600{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 char *name1, *name2;
1602 PyObject *newValue;
1603 PyObject *res = NULL;
1604 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 if (PyArg_ParseTuple(args, "O&O:setvar",
1607 varname_converter, &name1, &newValue)) {
1608 /* XXX Acquire tcl lock??? */
1609 newval = AsObj(newValue);
1610 if (newval == NULL)
1611 return NULL;
1612 ENTER_TCL
1613 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1614 newval, flags);
1615 ENTER_OVERLAP
1616 if (!ok)
1617 Tkinter_Error(self);
1618 else {
1619 res = Py_None;
1620 Py_INCREF(res);
1621 }
1622 LEAVE_OVERLAP_TCL
1623 }
1624 else {
1625 PyErr_Clear();
1626 if (PyArg_ParseTuple(args, "ssO:setvar",
1627 &name1, &name2, &newValue)) {
1628 /* XXX must hold tcl lock already??? */
1629 newval = AsObj(newValue);
1630 ENTER_TCL
1631 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1632 ENTER_OVERLAP
1633 if (!ok)
1634 Tkinter_Error(self);
1635 else {
1636 res = Py_None;
1637 Py_INCREF(res);
1638 }
1639 LEAVE_OVERLAP_TCL
1640 }
1641 else {
1642 return NULL;
1643 }
1644 }
1645 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001646}
1647
1648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001649Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001650{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001651 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001652}
1653
1654static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001655Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001656{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001658}
1659
Barry Warsawfa701a81997-01-16 00:15:11 +00001660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001661
Guido van Rossum18468821994-06-20 07:49:28 +00001662static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001663GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001664{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665 char *name1, *name2=NULL;
1666 PyObject *res = NULL;
1667 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1670 varname_converter, &name1, &name2))
1671 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 ENTER_TCL
1674 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1675 ENTER_OVERLAP
1676 if (tres == NULL) {
1677 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1678 } else {
1679 if (((TkappObject*)self)->wantobjects) {
1680 res = FromObj(self, tres);
1681 }
1682 else {
1683 res = PyUnicode_FromString(Tcl_GetString(tres));
1684 }
1685 }
1686 LEAVE_OVERLAP_TCL
1687 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001688}
1689
1690static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001691Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001692{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001693 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001694}
1695
1696static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001697Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001698{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001699 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001700}
1701
Barry Warsawfa701a81997-01-16 00:15:11 +00001702
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001703
Guido van Rossum18468821994-06-20 07:49:28 +00001704static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001705UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001706{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001707 char *name1, *name2=NULL;
1708 int code;
1709 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001711 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1712 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001714 ENTER_TCL
1715 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1716 ENTER_OVERLAP
1717 if (code == TCL_ERROR)
1718 res = Tkinter_Error(self);
1719 else {
1720 Py_INCREF(Py_None);
1721 res = Py_None;
1722 }
1723 LEAVE_OVERLAP_TCL
1724 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001725}
1726
1727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001728Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001730 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001731}
1732
1733static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001734Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001737}
1738
Barry Warsawfa701a81997-01-16 00:15:11 +00001739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001740
Guido van Rossum18468821994-06-20 07:49:28 +00001741/** Tcl to Python **/
1742
1743static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001744Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 char *s;
1747 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001749 if (PyTuple_Size(args) == 1) {
1750 PyObject* o = PyTuple_GetItem(args, 0);
1751 if (PyLong_Check(o)) {
1752 Py_INCREF(o);
1753 return o;
1754 }
1755 }
1756 if (!PyArg_ParseTuple(args, "s:getint", &s))
1757 return NULL;
1758 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1759 return Tkinter_Error(self);
1760 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001761}
1762
1763static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001764Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001765{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001766 char *s;
1767 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 if (PyTuple_Size(args) == 1) {
1770 PyObject *o = PyTuple_GetItem(args, 0);
1771 if (PyFloat_Check(o)) {
1772 Py_INCREF(o);
1773 return o;
1774 }
1775 }
1776 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1777 return NULL;
1778 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1779 return Tkinter_Error(self);
1780 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001781}
1782
1783static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001784Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001785{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001786 char *s;
1787 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 if (PyTuple_Size(args) == 1) {
1790 PyObject *o = PyTuple_GetItem(args, 0);
1791 if (PyLong_Check(o)) {
1792 Py_INCREF(o);
1793 return o;
1794 }
1795 }
1796 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1797 return NULL;
1798 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1799 return Tkinter_Error(self);
1800 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001801}
1802
1803static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001804Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 char *s;
1807 PyObject *res = NULL;
1808 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001810 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1811 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001815 ENTER_TCL
1816 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1817 ENTER_OVERLAP
1818 if (retval == TCL_ERROR)
1819 res = Tkinter_Error(self);
1820 else
1821 res = Py_BuildValue("s", Tkapp_Result(self));
1822 LEAVE_OVERLAP_TCL
1823 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001824}
1825
1826static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001827Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001828{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 char *s;
1830 PyObject *res = NULL;
1831 int retval;
1832 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001833
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1835 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001838
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001839 ENTER_TCL
1840 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1841 ENTER_OVERLAP
1842 if (retval == TCL_ERROR)
1843 res = Tkinter_Error(self);
1844 else
1845 res = Py_BuildValue("l", v);
1846 LEAVE_OVERLAP_TCL
1847 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001848}
1849
1850static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001851Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001852{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001853 char *s;
1854 PyObject *res = NULL;
1855 double v;
1856 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001857
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001858 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1859 return NULL;
1860 CHECK_TCL_APPARTMENT;
1861 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1862 ENTER_TCL
1863 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1864 ENTER_OVERLAP
1865 PyFPE_END_PROTECT(retval)
1866 if (retval == TCL_ERROR)
1867 res = Tkinter_Error(self);
1868 else
1869 res = Py_BuildValue("d", v);
1870 LEAVE_OVERLAP_TCL
1871 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001872}
1873
1874static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001875Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001876{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 char *s;
1878 PyObject *res = NULL;
1879 int retval;
1880 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001881
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1883 return NULL;
1884 CHECK_TCL_APPARTMENT;
1885 ENTER_TCL
1886 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1887 ENTER_OVERLAP
1888 if (retval == TCL_ERROR)
1889 res = Tkinter_Error(self);
1890 else
1891 res = Py_BuildValue("i", v);
1892 LEAVE_OVERLAP_TCL
1893 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001894}
1895
Barry Warsawfa701a81997-01-16 00:15:11 +00001896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897
Guido van Rossum18468821994-06-20 07:49:28 +00001898static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001899Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001900{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001901 char *list;
1902 int argc;
1903 char **argv;
1904 PyObject *v;
1905 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001906
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001907 if (PyTuple_Size(args) == 1) {
1908 v = PyTuple_GetItem(args, 0);
1909 if (PyTuple_Check(v)) {
1910 Py_INCREF(v);
1911 return v;
1912 }
1913 }
1914 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1915 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001916
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 if (Tcl_SplitList(Tkapp_Interp(self), list,
1918 &argc, &argv) == TCL_ERROR) {
1919 PyMem_Free(list);
1920 return Tkinter_Error(self);
1921 }
Guido van Rossum18468821994-06-20 07:49:28 +00001922
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001923 if (!(v = PyTuple_New(argc)))
1924 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 for (i = 0; i < argc; i++) {
1927 PyObject *s = PyUnicode_FromString(argv[i]);
1928 if (!s || PyTuple_SetItem(v, i, s)) {
1929 Py_DECREF(v);
1930 v = NULL;
1931 goto finally;
1932 }
1933 }
Guido van Rossum18468821994-06-20 07:49:28 +00001934
Barry Warsawfa701a81997-01-16 00:15:11 +00001935 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936 ckfree(FREECAST argv);
1937 PyMem_Free(list);
1938 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001939}
1940
1941static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001942Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001943{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 PyObject *v;
1945 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001947 if (PyTuple_Size(args) == 1) {
1948 PyObject* o = PyTuple_GetItem(args, 0);
1949 if (PyTuple_Check(o)) {
1950 o = SplitObj(o);
1951 return o;
1952 }
1953 }
1954 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1955 return NULL;
1956 v = Split(list);
1957 PyMem_Free(list);
1958 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001959}
1960
1961static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001962Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001963{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 char *s = Merge(args);
1965 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001966
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001967 if (s) {
1968 res = PyUnicode_FromString(s);
1969 ckfree(s);
1970 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001971
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001973}
1974
Barry Warsawfa701a81997-01-16 00:15:11 +00001975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001976
Guido van Rossum18468821994-06-20 07:49:28 +00001977/** Tcl Command **/
1978
Guido van Rossum00d93061998-05-28 23:06:38 +00001979/* Client data struct */
1980typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 PyObject *self;
1982 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001983} PythonCmd_ClientData;
1984
1985static int
Fred Drake509d79a2000-07-08 04:04:38 +00001986PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001987{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 errorInCmd = 1;
1989 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1990 LEAVE_PYTHON
1991 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001992}
1993
Guido van Rossum18468821994-06-20 07:49:28 +00001994/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001995 * function or method.
1996 */
Guido van Rossum18468821994-06-20 07:49:28 +00001997static int
Fred Drake509d79a2000-07-08 04:04:38 +00001998PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001999{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002000 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002001 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002002 int i, rv;
2003 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002006
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002007 /* TBD: no error checking here since we know, via the
2008 * Tkapp_CreateCommand() that the client data is a two-tuple
2009 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002012 /* Create argument list (argv1, ..., argvN) */
2013 if (!(arg = PyTuple_New(argc - 1)))
2014 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 for (i = 0; i < (argc - 1); i++) {
2017 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002018 if (!s) {
2019 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2020 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2021 !strcmp(argv[i + 1], "\xC0\x80")) {
2022 PyErr_Clear();
2023 /* Convert to "strict" utf-8 null */
2024 s = PyUnicode_FromString("\0");
2025 } else {
2026 Py_DECREF(arg);
2027 return PythonCmd_Error(interp);
2028 }
2029 }
2030 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002031 Py_DECREF(arg);
2032 return PythonCmd_Error(interp);
2033 }
2034 }
2035 res = PyEval_CallObject(func, arg);
2036 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002037
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002038 if (res == NULL)
2039 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 obj_res = AsObj(res);
2042 if (obj_res == NULL) {
2043 Py_DECREF(res);
2044 return PythonCmd_Error(interp);
2045 }
2046 else {
2047 Tcl_SetObjResult(interp, obj_res);
2048 rv = TCL_OK;
2049 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002056}
2057
2058static void
Fred Drake509d79a2000-07-08 04:04:38 +00002059PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002060{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 ENTER_PYTHON
2064 Py_XDECREF(data->self);
2065 Py_XDECREF(data->func);
2066 PyMem_DEL(data);
2067 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002068}
2069
Barry Warsawfa701a81997-01-16 00:15:11 +00002070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002072
Benjamin Peterson5879d412009-03-30 14:51:56 +00002073#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002074TCL_DECLARE_MUTEX(command_mutex)
2075
2076typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002077 Tcl_Event ev;
2078 Tcl_Interp* interp;
2079 char *name;
2080 int create;
2081 int *status;
2082 ClientData *data;
2083 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084} CommandEvent;
2085
2086static int
2087Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002088{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 if (ev->create)
2090 *ev->status = Tcl_CreateCommand(
2091 ev->interp, ev->name, PythonCmd,
2092 ev->data, PythonCmdDelete) == NULL;
2093 else
2094 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2095 Tcl_MutexLock(&command_mutex);
2096 Tcl_ConditionNotify(ev->done);
2097 Tcl_MutexUnlock(&command_mutex);
2098 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002099}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002100#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002101
2102static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002103Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002104{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002105 TkappObject *self = (TkappObject*)selfptr;
2106 PythonCmd_ClientData *data;
2107 char *cmdName;
2108 PyObject *func;
2109 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002110
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002111 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2112 return NULL;
2113 if (!PyCallable_Check(func)) {
2114 PyErr_SetString(PyExc_TypeError, "command not callable");
2115 return NULL;
2116 }
Guido van Rossum18468821994-06-20 07:49:28 +00002117
Martin v. Löwisa9656492003-03-30 08:44:58 +00002118#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2120 !WaitForMainloop(self))
2121 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002122#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002124 data = PyMem_NEW(PythonCmd_ClientData, 1);
2125 if (!data)
2126 return PyErr_NoMemory();
2127 Py_INCREF(self);
2128 Py_INCREF(func);
2129 data->self = selfptr;
2130 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002131#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002132 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2133 Tcl_Condition cond = NULL;
2134 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2135 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2136 ev->interp = self->interp;
2137 ev->create = 1;
2138 ev->name = cmdName;
2139 ev->data = (ClientData)data;
2140 ev->status = &err;
2141 ev->done = &cond;
2142 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2143 Tcl_ConditionFinalize(&cond);
2144 }
2145 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002146#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002147 {
2148 ENTER_TCL
2149 err = Tcl_CreateCommand(
2150 Tkapp_Interp(self), cmdName, PythonCmd,
2151 (ClientData)data, PythonCmdDelete) == NULL;
2152 LEAVE_TCL
2153 }
2154 if (err) {
2155 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2156 PyMem_DEL(data);
2157 return NULL;
2158 }
Guido van Rossum18468821994-06-20 07:49:28 +00002159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 Py_INCREF(Py_None);
2161 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002162}
2163
Barry Warsawfa701a81997-01-16 00:15:11 +00002164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165
Guido van Rossum18468821994-06-20 07:49:28 +00002166static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002167Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002168{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002169 TkappObject *self = (TkappObject*)selfptr;
2170 char *cmdName;
2171 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2174 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002175
2176#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002177 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2178 Tcl_Condition cond = NULL;
2179 CommandEvent *ev;
2180 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2181 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2182 ev->interp = self->interp;
2183 ev->create = 0;
2184 ev->name = cmdName;
2185 ev->status = &err;
2186 ev->done = &cond;
2187 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2188 &command_mutex);
2189 Tcl_ConditionFinalize(&cond);
2190 }
2191 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002192#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193 {
2194 ENTER_TCL
2195 err = Tcl_DeleteCommand(self->interp, cmdName);
2196 LEAVE_TCL
2197 }
2198 if (err == -1) {
2199 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2200 return NULL;
2201 }
2202 Py_INCREF(Py_None);
2203 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002204}
2205
Barry Warsawfa701a81997-01-16 00:15:11 +00002206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207
Guido van Rossum00d93061998-05-28 23:06:38 +00002208#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002209/** File Handler **/
2210
Guido van Rossum00d93061998-05-28 23:06:38 +00002211typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212 PyObject *func;
2213 PyObject *file;
2214 int id;
2215 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002216} FileHandler_ClientData;
2217
2218static FileHandler_ClientData *HeadFHCD;
2219
2220static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002221NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002222{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002223 FileHandler_ClientData *p;
2224 p = PyMem_NEW(FileHandler_ClientData, 1);
2225 if (p != NULL) {
2226 Py_XINCREF(func);
2227 Py_XINCREF(file);
2228 p->func = func;
2229 p->file = file;
2230 p->id = id;
2231 p->next = HeadFHCD;
2232 HeadFHCD = p;
2233 }
2234 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002235}
2236
2237static void
Fred Drake509d79a2000-07-08 04:04:38 +00002238DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002239{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002240 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002242 pp = &HeadFHCD;
2243 while ((p = *pp) != NULL) {
2244 if (p->id == id) {
2245 *pp = p->next;
2246 Py_XDECREF(p->func);
2247 Py_XDECREF(p->file);
2248 PyMem_DEL(p);
2249 }
2250 else
2251 pp = &p->next;
2252 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002253}
2254
Guido van Rossuma597dde1995-01-10 20:56:29 +00002255static void
Fred Drake509d79a2000-07-08 04:04:38 +00002256FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002257{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2259 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 ENTER_PYTHON
2262 func = data->func;
2263 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 arg = Py_BuildValue("(Oi)", file, (long) mask);
2266 res = PyEval_CallObject(func, arg);
2267 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 if (res == NULL) {
2270 errorInCmd = 1;
2271 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2272 }
2273 Py_XDECREF(res);
2274 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002275}
2276
Guido van Rossum18468821994-06-20 07:49:28 +00002277static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002278Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2279 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002280{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002281 FileHandler_ClientData *data;
2282 PyObject *file, *func;
2283 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2286 &file, &mask, &func))
2287 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 tfile = PyObject_AsFileDescriptor(file);
2292 if (tfile < 0)
2293 return NULL;
2294 if (!PyCallable_Check(func)) {
2295 PyErr_SetString(PyExc_TypeError, "bad argument list");
2296 return NULL;
2297 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 data = NewFHCD(func, file, tfile);
2300 if (data == NULL)
2301 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 /* Ought to check for null Tcl_File object... */
2304 ENTER_TCL
2305 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2306 LEAVE_TCL
2307 Py_INCREF(Py_None);
2308 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002309}
2310
2311static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002312Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002313{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314 PyObject *file;
2315 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2318 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002319
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002320 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002322 tfile = PyObject_AsFileDescriptor(file);
2323 if (tfile < 0)
2324 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 /* Ought to check for null Tcl_File object... */
2329 ENTER_TCL
2330 Tcl_DeleteFileHandler(tfile);
2331 LEAVE_TCL
2332 Py_INCREF(Py_None);
2333 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002334}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002335#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002337
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002338/**** Tktt Object (timer token) ****/
2339
Jeremy Hylton938ace62002-07-17 16:30:39 +00002340static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341
Guido van Rossum00d93061998-05-28 23:06:38 +00002342typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 PyObject_HEAD
2344 Tcl_TimerToken token;
2345 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002346} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347
2348static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002349Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002350{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002351 TkttObject *v = (TkttObject *)self;
2352 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002354 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2355 return NULL;
2356 if (v->token != NULL) {
2357 Tcl_DeleteTimerHandler(v->token);
2358 v->token = NULL;
2359 }
2360 if (func != NULL) {
2361 v->func = NULL;
2362 Py_DECREF(func);
2363 Py_DECREF(v); /* See Tktt_New() */
2364 }
2365 Py_INCREF(Py_None);
2366 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367}
2368
2369static PyMethodDef Tktt_methods[] =
2370{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2372 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373};
2374
2375static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002376Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 v = PyObject_New(TkttObject, &Tktt_Type);
2381 if (v == NULL)
2382 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 Py_INCREF(func);
2385 v->token = NULL;
2386 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 /* Extra reference, deleted when called or when handler is deleted */
2389 Py_INCREF(v);
2390 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002391}
2392
2393static void
Fred Drake509d79a2000-07-08 04:04:38 +00002394Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 TkttObject *v = (TkttObject *)self;
2397 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002399 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402}
2403
Guido van Rossum597ac201998-05-12 14:36:19 +00002404static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002405Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002408 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2409 v,
2410 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002411}
2412
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002413static PyTypeObject Tktt_Type =
2414{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 PyVarObject_HEAD_INIT(NULL, 0)
2416 "tktimertoken", /*tp_name */
2417 sizeof(TkttObject), /*tp_basicsize */
2418 0, /*tp_itemsize */
2419 Tktt_Dealloc, /*tp_dealloc */
2420 0, /*tp_print */
2421 0, /*tp_getattr */
2422 0, /*tp_setattr */
2423 0, /*tp_reserved */
2424 Tktt_Repr, /*tp_repr */
2425 0, /*tp_as_number */
2426 0, /*tp_as_sequence */
2427 0, /*tp_as_mapping */
2428 0, /*tp_hash */
2429 0, /*tp_call*/
2430 0, /*tp_str*/
2431 0, /*tp_getattro*/
2432 0, /*tp_setattro*/
2433 0, /*tp_as_buffer*/
2434 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2435 0, /*tp_doc*/
2436 0, /*tp_traverse*/
2437 0, /*tp_clear*/
2438 0, /*tp_richcompare*/
2439 0, /*tp_weaklistoffset*/
2440 0, /*tp_iter*/
2441 0, /*tp_iternext*/
2442 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002443};
2444
Barry Warsawfa701a81997-01-16 00:15:11 +00002445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002446
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002447/** Timer Handler **/
2448
2449static void
Fred Drake509d79a2000-07-08 04:04:38 +00002450TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002451{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 TkttObject *v = (TkttObject *)clientData;
2453 PyObject *func = v->func;
2454 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456 if (func == NULL)
2457 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002463 res = PyEval_CallObject(func, NULL);
2464 Py_DECREF(func);
2465 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 if (res == NULL) {
2468 errorInCmd = 1;
2469 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2470 }
2471 else
2472 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002475}
2476
2477static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002478Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002479{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480 int milliseconds;
2481 PyObject *func;
2482 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2485 &milliseconds, &func))
2486 return NULL;
2487 if (!PyCallable_Check(func)) {
2488 PyErr_SetString(PyExc_TypeError, "bad argument list");
2489 return NULL;
2490 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494 v = Tktt_New(func);
2495 if (v) {
2496 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2497 (ClientData)v);
2498 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002500 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002501}
2502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503
Guido van Rossum18468821994-06-20 07:49:28 +00002504/** Event Loop **/
2505
Guido van Rossum18468821994-06-20 07:49:28 +00002506static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002507Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002508{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 int threshold = 0;
2510 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002511#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002513#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002515 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2516 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 CHECK_TCL_APPARTMENT;
2519 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521 quitMainLoop = 0;
2522 while (Tk_GetNumMainWindows() > threshold &&
2523 !quitMainLoop &&
2524 !errorInCmd)
2525 {
2526 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002527
2528#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002529 if (self->threaded) {
2530 /* Allow other Python threads to run. */
2531 ENTER_TCL
2532 result = Tcl_DoOneEvent(0);
2533 LEAVE_TCL
2534 }
2535 else {
2536 Py_BEGIN_ALLOW_THREADS
2537 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2538 tcl_tstate = tstate;
2539 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2540 tcl_tstate = NULL;
2541 if(tcl_lock)PyThread_release_lock(tcl_lock);
2542 if (result == 0)
2543 Sleep(Tkinter_busywaitinterval);
2544 Py_END_ALLOW_THREADS
2545 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002546#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002548#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002550 if (PyErr_CheckSignals() != 0) {
2551 self->dispatching = 0;
2552 return NULL;
2553 }
2554 if (result < 0)
2555 break;
2556 }
2557 self->dispatching = 0;
2558 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 if (errorInCmd) {
2561 errorInCmd = 0;
2562 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2563 excInCmd = valInCmd = trbInCmd = NULL;
2564 return NULL;
2565 }
2566 Py_INCREF(Py_None);
2567 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002568}
2569
2570static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002571Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002572{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002573 int flags = 0;
2574 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2577 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 ENTER_TCL
2580 rv = Tcl_DoOneEvent(flags);
2581 LEAVE_TCL
2582 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002583}
2584
2585static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002586Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002587{
2588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 if (!PyArg_ParseTuple(args, ":quit"))
2590 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 quitMainLoop = 1;
2593 Py_INCREF(Py_None);
2594 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002595}
2596
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002597static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002598Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002599{
2600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 if (!PyArg_ParseTuple(args, ":interpaddr"))
2602 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002605}
2606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002607static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002608Tkapp_TkInit(PyObject *self, PyObject *args)
2609{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002610 Tcl_Interp *interp = Tkapp_Interp(self);
2611 const char * _tk_exists = NULL;
2612 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002613
Guilherme Polob681df42009-02-09 22:33:59 +00002614#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002615 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2616 * first call failed.
2617 * To avoid the deadlock, we just refuse the second call through
2618 * a static variable.
2619 */
2620 if (tk_load_failed) {
2621 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2622 return NULL;
2623 }
Guilherme Polob681df42009-02-09 22:33:59 +00002624#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 /* We want to guard against calling Tk_Init() multiple times */
2627 CHECK_TCL_APPARTMENT;
2628 ENTER_TCL
2629 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2630 ENTER_OVERLAP
2631 if (err == TCL_ERROR) {
2632 /* This sets an exception, but we cannot return right
2633 away because we need to exit the overlap first. */
2634 Tkinter_Error(self);
2635 } else {
2636 _tk_exists = Tkapp_Result(self);
2637 }
2638 LEAVE_OVERLAP_TCL
2639 if (err == TCL_ERROR) {
2640 return NULL;
2641 }
2642 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2643 if (Tk_Init(interp) == TCL_ERROR) {
2644 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002645#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002646 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002647#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002648 return NULL;
2649 }
2650 }
2651 Py_INCREF(Py_None);
2652 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002653}
Barry Warsawfa701a81997-01-16 00:15:11 +00002654
Martin v. Löwisffad6332002-11-26 09:28:05 +00002655static PyObject *
2656Tkapp_WantObjects(PyObject *self, PyObject *args)
2657{
2658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 int wantobjects = -1;
2660 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2661 return NULL;
2662 if (wantobjects == -1)
2663 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2664 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 Py_INCREF(Py_None);
2667 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002668}
2669
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002670static PyObject *
2671Tkapp_WillDispatch(PyObject *self, PyObject *args)
2672{
2673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 Py_INCREF(Py_None);
2677 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002678}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002680
Guido van Rossum18468821994-06-20 07:49:28 +00002681/**** Tkapp Method List ****/
2682
2683static PyMethodDef Tkapp_methods[] =
2684{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002685 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2686 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2687 {"call", Tkapp_Call, METH_VARARGS},
2688 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2689 {"eval", Tkapp_Eval, METH_VARARGS},
2690 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2691 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2692 {"record", Tkapp_Record, METH_VARARGS},
2693 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2694 {"setvar", Tkapp_SetVar, METH_VARARGS},
2695 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2696 {"getvar", Tkapp_GetVar, METH_VARARGS},
2697 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2698 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2699 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2700 {"getint", Tkapp_GetInt, METH_VARARGS},
2701 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2702 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2703 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2704 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2705 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2706 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2707 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2708 {"split", Tkapp_Split, METH_VARARGS},
2709 {"merge", Tkapp_Merge, METH_VARARGS},
2710 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2711 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002712#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2714 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002715#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2717 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2718 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2719 {"quit", Tkapp_Quit, METH_VARARGS},
2720 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2721 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2722 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002723};
2724
Barry Warsawfa701a81997-01-16 00:15:11 +00002725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002726
Guido van Rossum18468821994-06-20 07:49:28 +00002727/**** Tkapp Type Methods ****/
2728
2729static void
Fred Drake509d79a2000-07-08 04:04:38 +00002730Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002731{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002732 /*CHECK_TCL_APPARTMENT;*/
2733 ENTER_TCL
2734 Tcl_DeleteInterp(Tkapp_Interp(self));
2735 LEAVE_TCL
2736 PyObject_Del(self);
2737 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002738}
2739
Guido van Rossum18468821994-06-20 07:49:28 +00002740static PyTypeObject Tkapp_Type =
2741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 PyVarObject_HEAD_INIT(NULL, 0)
2743 "tkapp", /*tp_name */
2744 sizeof(TkappObject), /*tp_basicsize */
2745 0, /*tp_itemsize */
2746 Tkapp_Dealloc, /*tp_dealloc */
2747 0, /*tp_print */
2748 0, /*tp_getattr */
2749 0, /*tp_setattr */
2750 0, /*tp_reserved */
2751 0, /*tp_repr */
2752 0, /*tp_as_number */
2753 0, /*tp_as_sequence */
2754 0, /*tp_as_mapping */
2755 0, /*tp_hash */
2756 0, /*tp_call*/
2757 0, /*tp_str*/
2758 0, /*tp_getattro*/
2759 0, /*tp_setattro*/
2760 0, /*tp_as_buffer*/
2761 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2762 0, /*tp_doc*/
2763 0, /*tp_traverse*/
2764 0, /*tp_clear*/
2765 0, /*tp_richcompare*/
2766 0, /*tp_weaklistoffset*/
2767 0, /*tp_iter*/
2768 0, /*tp_iternext*/
2769 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002770};
2771
Barry Warsawfa701a81997-01-16 00:15:11 +00002772
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002773
Guido van Rossum18468821994-06-20 07:49:28 +00002774/**** Tkinter Module ****/
2775
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002776typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 PyObject* tuple;
2778 int size; /* current size */
2779 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780} FlattenContext;
2781
2782static int
2783_bump(FlattenContext* context, int size)
2784{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 /* expand tuple to hold (at least) size new items.
2786 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002789
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002790 if (maxsize < context->size + size)
2791 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002794
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002796}
2797
2798static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002799_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 if (depth > 1000) {
2806 PyErr_SetString(PyExc_ValueError,
2807 "nesting too deep in _flatten");
2808 return 0;
2809 } else if (PyList_Check(item)) {
2810 size = PyList_GET_SIZE(item);
2811 /* preallocate (assume no nesting) */
2812 if (context->size + size > context->maxsize &&
2813 !_bump(context, size))
2814 return 0;
2815 /* copy items to output tuple */
2816 for (i = 0; i < size; i++) {
2817 PyObject *o = PyList_GET_ITEM(item, i);
2818 if (PyList_Check(o) || PyTuple_Check(o)) {
2819 if (!_flatten1(context, o, depth + 1))
2820 return 0;
2821 } else if (o != Py_None) {
2822 if (context->size + 1 > context->maxsize &&
2823 !_bump(context, 1))
2824 return 0;
2825 Py_INCREF(o);
2826 PyTuple_SET_ITEM(context->tuple,
2827 context->size++, o);
2828 }
2829 }
2830 } else if (PyTuple_Check(item)) {
2831 /* same, for tuples */
2832 size = PyTuple_GET_SIZE(item);
2833 if (context->size + size > context->maxsize &&
2834 !_bump(context, size))
2835 return 0;
2836 for (i = 0; i < size; i++) {
2837 PyObject *o = PyTuple_GET_ITEM(item, i);
2838 if (PyList_Check(o) || PyTuple_Check(o)) {
2839 if (!_flatten1(context, o, depth + 1))
2840 return 0;
2841 } else if (o != Py_None) {
2842 if (context->size + 1 > context->maxsize &&
2843 !_bump(context, 1))
2844 return 0;
2845 Py_INCREF(o);
2846 PyTuple_SET_ITEM(context->tuple,
2847 context->size++, o);
2848 }
2849 }
2850 } else {
2851 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2852 return 0;
2853 }
2854 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002855}
2856
2857static PyObject *
2858Tkinter_Flatten(PyObject* self, PyObject* args)
2859{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002860 FlattenContext context;
2861 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002862
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002863 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2864 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002866 context.maxsize = PySequence_Size(item);
2867 if (context.maxsize < 0)
2868 return NULL;
2869 if (context.maxsize == 0)
2870 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 context.tuple = PyTuple_New(context.maxsize);
2873 if (!context.tuple)
2874 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002876 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 if (!_flatten1(&context, item,0))
2879 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002881 if (_PyTuple_Resize(&context.tuple, context.size))
2882 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002883
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002884 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002885}
2886
Guido van Rossum18468821994-06-20 07:49:28 +00002887static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002888Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002889{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 char *screenName = NULL;
2891 char *baseName = NULL; /* XXX this is not used anymore;
2892 try getting rid of it. */
2893 char *className = NULL;
2894 int interactive = 0;
2895 int wantobjects = 0;
2896 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2897 int sync = 0; /* pass -sync to wish */
2898 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002901
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002902 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2903 &screenName, &baseName, &className,
2904 &interactive, &wantobjects, &wantTk,
2905 &sync, &use))
2906 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002908 return (PyObject *) Tkapp_New(screenName, className,
2909 interactive, wantobjects, wantTk,
2910 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002911}
2912
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002913static PyObject *
2914Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2915{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002916 int new_val;
2917 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2918 return NULL;
2919 if (new_val < 0) {
2920 PyErr_SetString(PyExc_ValueError,
2921 "busywaitinterval must be >= 0");
2922 return NULL;
2923 }
2924 Tkinter_busywaitinterval = new_val;
2925 Py_INCREF(Py_None);
2926 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002927}
2928
2929static char setbusywaitinterval_doc[] =
2930"setbusywaitinterval(n) -> None\n\
2931\n\
2932Set the busy-wait interval in milliseconds between successive\n\
2933calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2934It should be set to a divisor of the maximum time between\n\
2935frames in an animation.";
2936
2937static PyObject *
2938Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2939{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002941}
2942
2943static char getbusywaitinterval_doc[] =
2944"getbusywaitinterval() -> int\n\
2945\n\
2946Return the current busy-wait interval between successive\n\
2947calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2948
Guido van Rossum18468821994-06-20 07:49:28 +00002949static PyMethodDef moduleMethods[] =
2950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002951 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2952 {"create", Tkinter_Create, METH_VARARGS},
2953 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2954 setbusywaitinterval_doc},
2955 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2956 METH_NOARGS, getbusywaitinterval_doc},
2957 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002958};
2959
Guido van Rossum7bf15641998-05-22 18:28:17 +00002960#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002961
2962static int stdin_ready = 0;
2963
Guido van Rossumad4db171998-06-13 13:56:28 +00002964#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002965static void
Fred Drake509d79a2000-07-08 04:04:38 +00002966MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002967{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002968 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002969}
Guido van Rossumad4db171998-06-13 13:56:28 +00002970#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002971
Martin v. Löwisa9656492003-03-30 08:44:58 +00002972#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002973static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002974#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002975
Guido van Rossum18468821994-06-20 07:49:28 +00002976static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002977EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002978{
Guido van Rossumad4db171998-06-13 13:56:28 +00002979#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002980 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002981#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002982#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002983 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002984#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002985 stdin_ready = 0;
2986 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002987#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002988 tfile = fileno(stdin);
2989 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002990#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002991 while (!errorInCmd && !stdin_ready) {
2992 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002993#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002994 if (_kbhit()) {
2995 stdin_ready = 1;
2996 break;
2997 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002998#endif
2999#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003000 Py_BEGIN_ALLOW_THREADS
3001 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3002 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003005
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003006 tcl_tstate = NULL;
3007 if(tcl_lock)PyThread_release_lock(tcl_lock);
3008 if (result == 0)
3009 Sleep(Tkinter_busywaitinterval);
3010 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003011#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003013#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003015 if (result < 0)
3016 break;
3017 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003018#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003019 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003020#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 if (errorInCmd) {
3022 errorInCmd = 0;
3023 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3024 excInCmd = valInCmd = trbInCmd = NULL;
3025 PyErr_Print();
3026 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003027#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003028 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003029#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003030 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003031}
Guido van Rossum18468821994-06-20 07:49:28 +00003032
Guido van Rossum00d93061998-05-28 23:06:38 +00003033#endif
3034
Guido van Rossum7bf15641998-05-22 18:28:17 +00003035static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003036EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003037{
Guido van Rossum00d93061998-05-28 23:06:38 +00003038#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003039 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003040#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003041 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003042#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003043 PyOS_InputHook = EventHook;
3044 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003045#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003046}
3047
3048static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003049DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003050{
Guido van Rossum00d93061998-05-28 23:06:38 +00003051#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003052 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3053 PyOS_InputHook = NULL;
3054 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003055#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003056}
3057
Barry Warsawfa701a81997-01-16 00:15:11 +00003058
3059/* all errors will be checked in one fell swoop in init_tkinter() */
3060static void
Fred Drake509d79a2000-07-08 04:04:38 +00003061ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003063 PyObject *v = PyLong_FromLong(val);
3064 if (v) {
3065 PyDict_SetItemString(d, name, v);
3066 Py_DECREF(v);
3067 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003068}
3069static void
Fred Drake509d79a2000-07-08 04:04:38 +00003070ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003071{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003072 PyObject *v = PyUnicode_FromString(val);
3073 if (v) {
3074 PyDict_SetItemString(d, name, v);
3075 Py_DECREF(v);
3076 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003077}
3078
3079
Martin v. Löwis1a214512008-06-11 05:26:20 +00003080static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003081 PyModuleDef_HEAD_INIT,
3082 "_tkinter",
3083 NULL,
3084 -1,
3085 moduleMethods,
3086 NULL,
3087 NULL,
3088 NULL,
3089 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003090};
3091
Mark Hammond62b1ab12002-07-23 06:31:15 +00003092PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003093PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003094{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003097 if (PyType_Ready(&Tkapp_Type) < 0)
3098 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003099
3100#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003102#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003104 m = PyModule_Create(&_tkintermodule);
3105 if (m == NULL)
3106 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003108 d = PyModule_GetDict(m);
3109 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3110 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003112 ins_long(d, "READABLE", TCL_READABLE);
3113 ins_long(d, "WRITABLE", TCL_WRITABLE);
3114 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3115 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3116 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3117 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3118 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3119 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3120 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3121 ins_string(d, "TK_VERSION", TK_VERSION);
3122 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003126 if (PyType_Ready(&Tktt_Type) < 0)
3127 return NULL;
3128 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003129
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3131 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003132
3133#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003134 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3135 * start waking up. Note that Tcl_FindExecutable will do this, this
3136 * code must be above it! The original warning from
3137 * tkMacOSXAppInit.c is copied below.
3138 *
3139 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3140 * Tcl interpreter for now. It probably should work to do this
3141 * in the other order, but for now it doesn't seem to.
3142 *
3143 */
3144 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003145#endif
3146
3147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003148 /* This helps the dynamic loader; in Unicode aware Tcl versions
3149 it also helps Tcl find its encodings. */
3150 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3151 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003152 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 if (cexe)
3154 Tcl_FindExecutable(PyBytes_AsString(cexe));
3155 Py_XDECREF(cexe);
3156 Py_DECREF(uexe);
3157 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003158
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003159 if (PyErr_Occurred()) {
3160 Py_DECREF(m);
3161 return NULL;
3162 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003163
Guido van Rossum43ff8681998-07-14 18:02:13 +00003164#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003165 /* This was not a good idea; through <Destroy> bindings,
3166 Tcl_Finalize() may invoke Python code but at that point the
3167 interpreter and thread state have already been destroyed! */
3168 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003169#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003170 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003171}