blob: cdb28e52c311345f1816e914a1f4a75d20f2af02 [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 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300522 else if (PyUnicode_Check(arg)) {
523 int argc;
524 char **argv;
525 char *list = PyUnicode_AsUTF8(arg);
526
527 if (list == NULL ||
528 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
529 Py_INCREF(arg);
530 return arg;
531 }
532 Tcl_Free(FREECAST argv);
533 if (argc > 1)
534 return Split(list);
535 /* Fall through, returning arg. */
536 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 else if (PyBytes_Check(arg)) {
538 int argc;
539 char **argv;
540 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
543 Py_INCREF(arg);
544 return arg;
545 }
546 Tcl_Free(FREECAST argv);
547 if (argc > 1)
548 return Split(PyBytes_AsString(arg));
549 /* Fall through, returning arg. */
550 }
551 Py_INCREF(arg);
552 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000553}
Barry Warsawfa701a81997-01-16 00:15:11 +0000554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555
Guido van Rossum18468821994-06-20 07:49:28 +0000556/**** Tkapp Object ****/
557
558#ifndef WITH_APPINIT
559int
Fred Drake509d79a2000-07-08 04:04:38 +0000560Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 if (Tcl_Init(interp) == TCL_ERROR) {
565 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
566 return TCL_ERROR;
567 }
Guilherme Polob681df42009-02-09 22:33:59 +0000568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 _tkinter_skip_tk_init = Tcl_GetVar(interp,
570 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
571 if (_tkinter_skip_tk_init != NULL &&
572 strcmp(_tkinter_skip_tk_init, "1") == 0) {
573 return TCL_OK;
574 }
Guilherme Polob681df42009-02-09 22:33:59 +0000575
576#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 if (tk_load_failed) {
578 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
579 return TCL_ERROR;
580 }
Guilherme Polob681df42009-02-09 22:33:59 +0000581#endif
582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000584#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000585 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000586#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
588 return TCL_ERROR;
589 }
Guilherme Polob681df42009-02-09 22:33:59 +0000590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000592}
593#endif /* !WITH_APPINIT */
594
Guido van Rossum18468821994-06-20 07:49:28 +0000595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596
Barry Warsawfa701a81997-01-16 00:15:11 +0000597
598/* Initialize the Tk application; see the `main' function in
599 * `tkMain.c'.
600 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000601
Thomas Wouters58d05102000-07-24 14:43:35 +0000602static void EnableEventHook(void); /* Forward */
603static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000604
Barry Warsawfa701a81997-01-16 00:15:11 +0000605static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000606Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000608{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 TkappObject *v;
610 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 v = PyObject_New(TkappObject, &Tkapp_Type);
613 if (v == NULL)
614 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 v->interp = Tcl_CreateInterp();
617 v->wantobjects = wantobjects;
618 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
619 TCL_GLOBAL_ONLY) != NULL;
620 v->thread_id = Tcl_GetCurrentThread();
621 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000622
623#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 if (v->threaded) {
625 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
626 Py_DECREF(v);
627 return 0;
628 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000629#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000630#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 if (v->threaded && tcl_lock) {
632 /* If Tcl is threaded, we don't need the lock. */
633 PyThread_free_lock(tcl_lock);
634 tcl_lock = NULL;
635 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000636#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 v->BooleanType = Tcl_GetObjType("boolean");
639 v->ByteArrayType = Tcl_GetObjType("bytearray");
640 v->DoubleType = Tcl_GetObjType("double");
641 v->IntType = Tcl_GetObjType("int");
642 v->ListType = Tcl_GetObjType("list");
643 v->ProcBodyType = Tcl_GetObjType("procbody");
644 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 /* Delete the 'exit' command, which can screw things up */
647 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 if (screenName != NULL)
650 Tcl_SetVar2(v->interp, "env", "DISPLAY",
651 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 if (interactive)
654 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
655 else
656 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 /* This is used to get the application class for Tk 4.1 and up */
659 argv0 = (char*)ckalloc(strlen(className) + 1);
660 if (!argv0) {
661 PyErr_NoMemory();
662 Py_DECREF(v);
663 return NULL;
664 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200667 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
668 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
670 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 if (! wantTk) {
673 Tcl_SetVar(v->interp,
674 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
675 }
Guilherme Polob681df42009-02-09 22:33:59 +0000676#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 else if (tk_load_failed) {
678 Tcl_SetVar(v->interp,
679 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
680 }
Guilherme Polob681df42009-02-09 22:33:59 +0000681#endif
David Aschere2b4b322004-02-18 05:59:53 +0000682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 /* some initial arguments need to be in argv */
684 if (sync || use) {
685 char *args;
686 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 if (sync)
689 len += sizeof "-sync";
690 if (use)
691 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 args = (char*)ckalloc(len);
694 if (!args) {
695 PyErr_NoMemory();
696 Py_DECREF(v);
697 return NULL;
698 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 args[0] = '\0';
701 if (sync)
702 strcat(args, "-sync");
703 if (use) {
704 if (sync)
705 strcat(args, " ");
706 strcat(args, "-use ");
707 strcat(args, use);
708 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
711 ckfree(args);
712 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 if (Tcl_AppInit(v->interp) != TCL_OK) {
715 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000716#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 if (wantTk) {
718 const char *_tkinter_tk_failed;
719 _tkinter_tk_failed = Tcl_GetVar(v->interp,
720 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000721
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 if ( _tkinter_tk_failed != NULL &&
723 strcmp(_tkinter_tk_failed, "1") == 0) {
724 tk_load_failed = 1;
725 }
726 }
Guilherme Polob681df42009-02-09 22:33:59 +0000727#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 Py_DECREF((PyObject *)v);
729 return (TkappObject *)result;
730 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000733
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000734 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000735}
736
Barry Warsawfa701a81997-01-16 00:15:11 +0000737
Benjamin Peterson5879d412009-03-30 14:51:56 +0000738#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000739static void
740Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000742{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 Py_BEGIN_ALLOW_THREADS;
744 Tcl_MutexLock(mutex);
745 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
746 Tcl_ThreadAlert(self->thread_id);
747 Tcl_ConditionWait(cond, mutex, NULL);
748 Tcl_MutexUnlock(mutex);
749 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000750}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000751#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753
Guido van Rossum18468821994-06-20 07:49:28 +0000754/** Tcl Eval **/
755
Martin v. Löwisffad6332002-11-26 09:28:05 +0000756typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 PyObject_HEAD
758 Tcl_Obj *value;
759 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000760} PyTclObject;
761
Neal Norwitz227b5332006-03-22 09:28:35 +0000762static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000764
765static PyObject *
766newPyTclObject(Tcl_Obj *arg)
767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 PyTclObject *self;
769 self = PyObject_New(PyTclObject, &PyTclObject_Type);
770 if (self == NULL)
771 return NULL;
772 Tcl_IncrRefCount(arg);
773 self->value = arg;
774 self->string = NULL;
775 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000776}
777
778static void
779PyTclObject_dealloc(PyTclObject *self)
780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 Tcl_DecrRefCount(self->value);
782 Py_XDECREF(self->string);
783 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000784}
785
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000786static char*
787PyTclObject_TclString(PyObject *self)
788{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000790}
791
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000792/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000793PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000794"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000795
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000796static PyObject *
797PyTclObject_string(PyTclObject *self, void *ignored)
798{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000799 char *s;
800 int len;
801 if (!self->string) {
802 s = Tcl_GetStringFromObj(self->value, &len);
803 self->string = PyUnicode_FromStringAndSize(s, len);
804 if (!self->string)
805 return NULL;
806 }
807 Py_INCREF(self->string);
808 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000809}
810
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000811static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000812PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000813{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 char *s;
815 int len;
816 if (self->string && PyUnicode_Check(self->string)) {
817 Py_INCREF(self->string);
818 return self->string;
819 }
820 /* XXX Could chache result if it is non-ASCII. */
821 s = Tcl_GetStringFromObj(self->value, &len);
822 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000823}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000824
Martin v. Löwisffad6332002-11-26 09:28:05 +0000825static PyObject *
826PyTclObject_repr(PyTclObject *self)
827{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 return PyUnicode_FromFormat("<%s object at %p>",
829 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000830}
831
Mark Dickinson211c6252009-02-01 10:28:51 +0000832#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
833
834static PyObject *
835PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000836{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 int result;
838 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000840 /* neither argument should be NULL, unless something's gone wrong */
841 if (self == NULL || other == NULL) {
842 PyErr_BadInternalCall();
843 return NULL;
844 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 /* both arguments should be instances of PyTclObject */
847 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
848 v = Py_NotImplemented;
849 goto finished;
850 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000852 if (self == other)
853 /* fast path when self and other are identical */
854 result = 0;
855 else
856 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
857 Tcl_GetString(((PyTclObject *)other)->value));
858 /* Convert return value to a Boolean */
859 switch (op) {
860 case Py_EQ:
861 v = TEST_COND(result == 0);
862 break;
863 case Py_NE:
864 v = TEST_COND(result != 0);
865 break;
866 case Py_LE:
867 v = TEST_COND(result <= 0);
868 break;
869 case Py_GE:
870 v = TEST_COND(result >= 0);
871 break;
872 case Py_LT:
873 v = TEST_COND(result < 0);
874 break;
875 case Py_GT:
876 v = TEST_COND(result > 0);
877 break;
878 default:
879 PyErr_BadArgument();
880 return NULL;
881 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000882 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 Py_INCREF(v);
884 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000885}
886
Martin v. Löwis39195712003-01-04 00:33:13 +0000887PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
888
Martin v. Löwisffad6332002-11-26 09:28:05 +0000889static PyObject*
890get_typename(PyTclObject* obj, void* ignored)
891{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000892 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000893}
894
Martin v. Löwis39195712003-01-04 00:33:13 +0000895
Martin v. Löwisffad6332002-11-26 09:28:05 +0000896static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 {"typename", (getter)get_typename, NULL, get_typename__doc__},
898 {"string", (getter)PyTclObject_string, NULL,
899 PyTclObject_string__doc__},
900 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000901};
902
Neal Norwitz227b5332006-03-22 09:28:35 +0000903static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000904 PyVarObject_HEAD_INIT(NULL, 0)
905 "_tkinter.Tcl_Obj", /*tp_name*/
906 sizeof(PyTclObject), /*tp_basicsize*/
907 0, /*tp_itemsize*/
908 /* methods */
909 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
910 0, /*tp_print*/
911 0, /*tp_getattr*/
912 0, /*tp_setattr*/
913 0, /*tp_reserved*/
914 (reprfunc)PyTclObject_repr, /*tp_repr*/
915 0, /*tp_as_number*/
916 0, /*tp_as_sequence*/
917 0, /*tp_as_mapping*/
918 0, /*tp_hash*/
919 0, /*tp_call*/
920 (reprfunc)PyTclObject_str, /*tp_str*/
921 PyObject_GenericGetAttr, /*tp_getattro*/
922 0, /*tp_setattro*/
923 0, /*tp_as_buffer*/
924 Py_TPFLAGS_DEFAULT, /*tp_flags*/
925 0, /*tp_doc*/
926 0, /*tp_traverse*/
927 0, /*tp_clear*/
928 PyTclObject_richcompare, /*tp_richcompare*/
929 0, /*tp_weaklistoffset*/
930 0, /*tp_iter*/
931 0, /*tp_iternext*/
932 0, /*tp_methods*/
933 0, /*tp_members*/
934 PyTclObject_getsetlist, /*tp_getset*/
935 0, /*tp_base*/
936 0, /*tp_dict*/
937 0, /*tp_descr_get*/
938 0, /*tp_descr_set*/
939 0, /*tp_dictoffset*/
940 0, /*tp_init*/
941 0, /*tp_alloc*/
942 0, /*tp_new*/
943 0, /*tp_free*/
944 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000945};
946
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000947static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000948AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000949{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000950 Tcl_Obj *result;
951 long longVal;
952 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 if (PyBytes_Check(value))
955 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
956 PyBytes_GET_SIZE(value));
957 else if (PyBool_Check(value))
958 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
959 else if (PyLong_CheckExact(value) &&
960 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
961 !overflow)) {
962 /* If there is an overflow in the long conversion,
963 fall through to default object handling. */
964 return Tcl_NewLongObj(longVal);
965 }
966 else if (PyFloat_Check(value))
967 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
968 else if (PyTuple_Check(value)) {
969 Tcl_Obj **argv = (Tcl_Obj**)
970 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
971 int i;
972 if(!argv)
973 return 0;
974 for(i=0;i<PyTuple_Size(value);i++)
975 argv[i] = AsObj(PyTuple_GetItem(value,i));
976 result = Tcl_NewListObj(PyTuple_Size(value), argv);
977 ckfree(FREECAST argv);
978 return result;
979 }
980 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200981 void *inbuf;
982 Py_ssize_t size;
983 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 Tcl_UniChar *outbuf = NULL;
985 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200986 size_t allocsize;
987
988 if (PyUnicode_READY(value) == -1)
989 return NULL;
990
991 inbuf = PyUnicode_DATA(value);
992 size = PyUnicode_GET_LENGTH(value);
993 kind = PyUnicode_KIND(value);
994 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
995 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000996 /* Else overflow occurred, and we take the next exit */
997 if (!outbuf) {
998 PyErr_NoMemory();
999 return NULL;
1000 }
1001 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001002 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1003 /* We cannot test for sizeof(Tcl_UniChar) directly,
1004 so we test for UTF-8 size instead. */
1005#if TCL_UTF_MAX == 3
1006 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001007 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001008 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001009 "character U+%x is above the range "
1010 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001011 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 ckfree(FREECAST outbuf);
1013 return NULL;
1014 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001015#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001016 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001017 }
1018 result = Tcl_NewUnicodeObj(outbuf, size);
1019 ckfree(FREECAST outbuf);
1020 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001021 }
1022 else if(PyTclObject_Check(value)) {
1023 Tcl_Obj *v = ((PyTclObject*)value)->value;
1024 Tcl_IncrRefCount(v);
1025 return v;
1026 }
1027 else {
1028 PyObject *v = PyObject_Str(value);
1029 if (!v)
1030 return 0;
1031 result = AsObj(v);
1032 Py_DECREF(v);
1033 return result;
1034 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001035}
1036
Martin v. Löwisffad6332002-11-26 09:28:05 +00001037static PyObject*
1038FromObj(PyObject* tkapp, Tcl_Obj *value)
1039{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001040 PyObject *result = NULL;
1041 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 if (value->typePtr == NULL) {
1044 return PyUnicode_FromStringAndSize(value->bytes,
1045 value->length);
1046 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001048 if (value->typePtr == app->BooleanType) {
1049 result = value->internalRep.longValue ? Py_True : Py_False;
1050 Py_INCREF(result);
1051 return result;
1052 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001053
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 if (value->typePtr == app->ByteArrayType) {
1055 int size;
1056 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1057 return PyBytes_FromStringAndSize(data, size);
1058 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001059
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 if (value->typePtr == app->DoubleType) {
1061 return PyFloat_FromDouble(value->internalRep.doubleValue);
1062 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 if (value->typePtr == app->IntType) {
1065 return PyLong_FromLong(value->internalRep.longValue);
1066 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 if (value->typePtr == app->ListType) {
1069 int size;
1070 int i, status;
1071 PyObject *elem;
1072 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1075 if (status == TCL_ERROR)
1076 return Tkinter_Error(tkapp);
1077 result = PyTuple_New(size);
1078 if (!result)
1079 return NULL;
1080 for (i = 0; i < size; i++) {
1081 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1082 value, i, &tcl_elem);
1083 if (status == TCL_ERROR) {
1084 Py_DECREF(result);
1085 return Tkinter_Error(tkapp);
1086 }
1087 elem = FromObj(tkapp, tcl_elem);
1088 if (!elem) {
1089 Py_DECREF(result);
1090 return NULL;
1091 }
1092 PyTuple_SetItem(result, i, elem);
1093 }
1094 return result;
1095 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001097 if (value->typePtr == app->ProcBodyType) {
1098 /* fall through: return tcl object. */
1099 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001100
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001101 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001102#if TCL_UTF_MAX==3
1103 return PyUnicode_FromKindAndData(
1104 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1105 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001106#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001107 return PyUnicode_FromKindAndData(
1108 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1109 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001110#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001111 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001113 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001114}
1115
Benjamin Peterson5879d412009-03-30 14:51:56 +00001116#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001117/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001118TCL_DECLARE_MUTEX(call_mutex)
1119
1120typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001121 Tcl_Event ev; /* Must be first */
1122 TkappObject *self;
1123 PyObject *args;
1124 int flags;
1125 PyObject **res;
1126 PyObject **exc_type, **exc_value, **exc_tb;
1127 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001128} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001129#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001130
1131void
1132Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001133{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 int i;
1135 for (i = 0; i < objc; i++)
1136 Tcl_DecrRefCount(objv[i]);
1137 if (objv != objStore)
1138 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001139}
Guido van Rossum18468821994-06-20 07:49:28 +00001140
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001141/* Convert Python objects to Tcl objects. This must happen in the
1142 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001143
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144static Tcl_Obj**
1145Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1146{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001147 Tcl_Obj **objv = objStore;
1148 int objc = 0, i;
1149 if (args == NULL)
1150 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 else if (!PyTuple_Check(args)) {
1153 objv[0] = AsObj(args);
1154 if (objv[0] == 0)
1155 goto finally;
1156 objc = 1;
1157 Tcl_IncrRefCount(objv[0]);
1158 }
1159 else {
1160 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 if (objc > ARGSZ) {
1163 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1164 if (objv == NULL) {
1165 PyErr_NoMemory();
1166 objc = 0;
1167 goto finally;
1168 }
1169 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001171 for (i = 0; i < objc; i++) {
1172 PyObject *v = PyTuple_GetItem(args, i);
1173 if (v == Py_None) {
1174 objc = i;
1175 break;
1176 }
1177 objv[i] = AsObj(v);
1178 if (!objv[i]) {
1179 /* Reset objc, so it attempts to clear
1180 objects only up to i. */
1181 objc = i;
1182 goto finally;
1183 }
1184 Tcl_IncrRefCount(objv[i]);
1185 }
1186 }
1187 *pobjc = objc;
1188 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001189finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001190 Tkapp_CallDeallocArgs(objv, objStore, objc);
1191 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001192}
Guido van Rossum212643f1998-04-29 16:22:14 +00001193
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001194/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001195
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001196static PyObject*
1197Tkapp_CallResult(TkappObject *self)
1198{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001199 PyObject *res = NULL;
1200 if(self->wantobjects) {
1201 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1202 /* Not sure whether the IncrRef is necessary, but something
1203 may overwrite the interpreter result while we are
1204 converting it. */
1205 Tcl_IncrRefCount(value);
1206 res = FromObj((PyObject*)self, value);
1207 Tcl_DecrRefCount(value);
1208 } else {
1209 const char *s = Tcl_GetStringResult(self->interp);
1210 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1213 }
1214 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001215}
Guido van Rossum632de272000-03-29 00:19:50 +00001216
Benjamin Peterson5879d412009-03-30 14:51:56 +00001217#ifdef WITH_THREAD
1218
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219/* Tkapp_CallProc is the event procedure that is executed in the context of
1220 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1221 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001222
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223static int
1224Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 Tcl_Obj *objStore[ARGSZ];
1227 Tcl_Obj **objv;
1228 int objc;
1229 int i;
1230 ENTER_PYTHON
1231 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1232 if (!objv) {
1233 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1234 *(e->res) = NULL;
1235 }
1236 LEAVE_PYTHON
1237 if (!objv)
1238 goto done;
1239 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1240 ENTER_PYTHON
1241 if (i == TCL_ERROR) {
1242 *(e->res) = NULL;
1243 *(e->exc_type) = NULL;
1244 *(e->exc_tb) = NULL;
1245 *(e->exc_value) = PyObject_CallFunction(
1246 Tkinter_TclError, "s",
1247 Tcl_GetStringResult(e->self->interp));
1248 }
1249 else {
1250 *(e->res) = Tkapp_CallResult(e->self);
1251 }
1252 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001253
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001254 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001255done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 /* Wake up calling thread. */
1257 Tcl_MutexLock(&call_mutex);
1258 Tcl_ConditionNotify(e->done);
1259 Tcl_MutexUnlock(&call_mutex);
1260 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001261}
1262
Benjamin Peterson5879d412009-03-30 14:51:56 +00001263#endif
1264
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001265/* This is the main entry point for calling a Tcl command.
1266 It supports three cases, with regard to threading:
1267 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1268 the context of the calling thread.
1269 2. Tcl is threaded, caller of the command is in the interpreter thread:
1270 Execute the command in the calling thread. Since the Tcl lock will
1271 not be used, we can merge that with case 1.
1272 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1273 the interpreter thread. Allocation of Tcl objects needs to occur in the
1274 interpreter thread, so we ship the PyObject* args to the target thread,
1275 and perform processing there. */
1276
1277static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001278Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 Tcl_Obj *objStore[ARGSZ];
1281 Tcl_Obj **objv = NULL;
1282 int objc, i;
1283 PyObject *res = NULL;
1284 TkappObject *self = (TkappObject*)selfptr;
1285 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 /* If args is a single tuple, replace with contents of tuple */
1288 if (1 == PyTuple_Size(args)){
1289 PyObject* item = PyTuple_GetItem(args, 0);
1290 if (PyTuple_Check(item))
1291 args = item;
1292 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001293#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1295 /* We cannot call the command directly. Instead, we must
1296 marshal the parameters to the interpreter thread. */
1297 Tkapp_CallEvent *ev;
1298 Tcl_Condition cond = NULL;
1299 PyObject *exc_type, *exc_value, *exc_tb;
1300 if (!WaitForMainloop(self))
1301 return NULL;
1302 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1303 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1304 ev->self = self;
1305 ev->args = args;
1306 ev->res = &res;
1307 ev->exc_type = &exc_type;
1308 ev->exc_value = &exc_value;
1309 ev->exc_tb = &exc_tb;
1310 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 if (res == NULL) {
1315 if (exc_type)
1316 PyErr_Restore(exc_type, exc_value, exc_tb);
1317 else
1318 PyErr_SetObject(Tkinter_TclError, exc_value);
1319 }
1320 Tcl_ConditionFinalize(&cond);
1321 }
1322 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001323#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 objv = Tkapp_CallArgs(args, objStore, &objc);
1327 if (!objv)
1328 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001330 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001332 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001334 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001336 if (i == TCL_ERROR)
1337 Tkinter_Error(selfptr);
1338 else
1339 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 Tkapp_CallDeallocArgs(objv, objStore, objc);
1344 }
1345 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001346}
1347
1348
1349static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001350Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001351{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 /* Could do the same here as for Tkapp_Call(), but this is not used
1353 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1354 way for the user to do what all its Global* variants do (save and
1355 reset the scope pointer, call the local version, restore the saved
1356 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001358 char *cmd;
1359 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001360
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001361 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1362 "globalcall is deprecated and will be removed in 3.4",
1363 1) < 0)
1364 return 0;
1365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 cmd = Merge(args);
1369 if (cmd) {
1370 int err;
1371 ENTER_TCL
1372 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1373 ENTER_OVERLAP
1374 if (err == TCL_ERROR)
1375 res = Tkinter_Error(self);
1376 else
1377 res = PyUnicode_FromString(Tkapp_Result(self));
1378 LEAVE_OVERLAP_TCL
1379 ckfree(cmd);
1380 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001383}
1384
1385static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001386Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001387{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 char *script;
1389 PyObject *res = NULL;
1390 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 if (!PyArg_ParseTuple(args, "s:eval", &script))
1393 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 ENTER_TCL
1398 err = Tcl_Eval(Tkapp_Interp(self), script);
1399 ENTER_OVERLAP
1400 if (err == TCL_ERROR)
1401 res = Tkinter_Error(self);
1402 else
1403 res = PyUnicode_FromString(Tkapp_Result(self));
1404 LEAVE_OVERLAP_TCL
1405 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001406}
1407
1408static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001409Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001410{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 char *script;
1412 PyObject *res = NULL;
1413 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001414
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001415 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1416 "globaleval is deprecated and will be removed in 3.4",
1417 1) < 0)
1418 return 0;
1419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1421 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001423 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001425 ENTER_TCL
1426 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1427 ENTER_OVERLAP
1428 if (err == TCL_ERROR)
1429 res = Tkinter_Error(self);
1430 else
1431 res = PyUnicode_FromString(Tkapp_Result(self));
1432 LEAVE_OVERLAP_TCL
1433 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001434}
1435
1436static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001437Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001438{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 char *fileName;
1440 PyObject *res = NULL;
1441 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1444 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001446 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 ENTER_TCL
1449 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1450 ENTER_OVERLAP
1451 if (err == TCL_ERROR)
1452 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 else
1455 res = PyUnicode_FromString(Tkapp_Result(self));
1456 LEAVE_OVERLAP_TCL
1457 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001458}
1459
1460static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001461Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001462{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 char *script;
1464 PyObject *res = NULL;
1465 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 if (!PyArg_ParseTuple(args, "s", &script))
1468 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001470 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 ENTER_TCL
1473 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1474 ENTER_OVERLAP
1475 if (err == TCL_ERROR)
1476 res = Tkinter_Error(self);
1477 else
1478 res = PyUnicode_FromString(Tkapp_Result(self));
1479 LEAVE_OVERLAP_TCL
1480 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001481}
1482
1483static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001484Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001485{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1489 return NULL;
1490 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001492 ENTER_TCL
1493 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1494 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 Py_INCREF(Py_None);
1497 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001498}
1499
Barry Warsawfa701a81997-01-16 00:15:11 +00001500
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001501
Guido van Rossum18468821994-06-20 07:49:28 +00001502/** Tcl Variable **/
1503
Benjamin Peterson5879d412009-03-30 14:51:56 +00001504typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1505
1506#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507TCL_DECLARE_MUTEX(var_mutex)
1508
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001509typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 Tcl_Event ev; /* must be first */
1511 PyObject *self;
1512 PyObject *args;
1513 int flags;
1514 EventFunc func;
1515 PyObject **res;
1516 PyObject **exc_type;
1517 PyObject **exc_val;
1518 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001519} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001520#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001521
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001522static int
1523varname_converter(PyObject *in, void *_out)
1524{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 char **out = (char**)_out;
1526 if (PyBytes_Check(in)) {
1527 *out = PyBytes_AsString(in);
1528 return 1;
1529 }
1530 if (PyUnicode_Check(in)) {
1531 *out = _PyUnicode_AsString(in);
1532 return 1;
1533 }
1534 if (PyTclObject_Check(in)) {
1535 *out = PyTclObject_TclString(in);
1536 return 1;
1537 }
1538 /* XXX: Should give diagnostics. */
1539 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001540}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001541
Benjamin Peterson5879d412009-03-30 14:51:56 +00001542#ifdef WITH_THREAD
1543
Martin v. Löwis59683e82008-06-13 07:50:45 +00001544static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001545var_perform(VarEvent *ev)
1546{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1548 if (!*(ev->res)) {
1549 PyObject *exc, *val, *tb;
1550 PyErr_Fetch(&exc, &val, &tb);
1551 PyErr_NormalizeException(&exc, &val, &tb);
1552 *(ev->exc_type) = exc;
1553 *(ev->exc_val) = val;
1554 Py_DECREF(tb);
1555 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001556
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001557}
1558
1559static int
1560var_proc(VarEvent* ev, int flags)
1561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001562 ENTER_PYTHON
1563 var_perform(ev);
1564 Tcl_MutexLock(&var_mutex);
1565 Tcl_ConditionNotify(ev->cond);
1566 Tcl_MutexUnlock(&var_mutex);
1567 LEAVE_PYTHON
1568 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001569}
1570
Benjamin Peterson5879d412009-03-30 14:51:56 +00001571#endif
1572
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001573static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001574var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001575{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001576#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 TkappObject *self = (TkappObject*)selfptr;
1578 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1579 TkappObject *self = (TkappObject*)selfptr;
1580 VarEvent *ev;
1581 PyObject *res, *exc_type, *exc_val;
1582 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001584 /* The current thread is not the interpreter thread. Marshal
1585 the call to the interpreter thread, then wait for
1586 completion. */
1587 if (!WaitForMainloop(self))
1588 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001590 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001592 ev->self = selfptr;
1593 ev->args = args;
1594 ev->flags = flags;
1595 ev->func = func;
1596 ev->res = &res;
1597 ev->exc_type = &exc_type;
1598 ev->exc_val = &exc_val;
1599 ev->cond = &cond;
1600 ev->ev.proc = (Tcl_EventProc*)var_proc;
1601 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1602 Tcl_ConditionFinalize(&cond);
1603 if (!res) {
1604 PyErr_SetObject(exc_type, exc_val);
1605 Py_DECREF(exc_type);
1606 Py_DECREF(exc_val);
1607 return NULL;
1608 }
1609 return res;
1610 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001611#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 /* Tcl is not threaded, or this is the interpreter thread. */
1613 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001614}
1615
Guido van Rossum18468821994-06-20 07:49:28 +00001616static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001617SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001618{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 char *name1, *name2;
1620 PyObject *newValue;
1621 PyObject *res = NULL;
1622 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 if (PyArg_ParseTuple(args, "O&O:setvar",
1625 varname_converter, &name1, &newValue)) {
1626 /* XXX Acquire tcl lock??? */
1627 newval = AsObj(newValue);
1628 if (newval == NULL)
1629 return NULL;
1630 ENTER_TCL
1631 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1632 newval, flags);
1633 ENTER_OVERLAP
1634 if (!ok)
1635 Tkinter_Error(self);
1636 else {
1637 res = Py_None;
1638 Py_INCREF(res);
1639 }
1640 LEAVE_OVERLAP_TCL
1641 }
1642 else {
1643 PyErr_Clear();
1644 if (PyArg_ParseTuple(args, "ssO:setvar",
1645 &name1, &name2, &newValue)) {
1646 /* XXX must hold tcl lock already??? */
1647 newval = AsObj(newValue);
1648 ENTER_TCL
1649 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1650 ENTER_OVERLAP
1651 if (!ok)
1652 Tkinter_Error(self);
1653 else {
1654 res = Py_None;
1655 Py_INCREF(res);
1656 }
1657 LEAVE_OVERLAP_TCL
1658 }
1659 else {
1660 return NULL;
1661 }
1662 }
1663 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001664}
1665
1666static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001667Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001668{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
1672static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001673Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001674{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001675 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001676}
1677
Barry Warsawfa701a81997-01-16 00:15:11 +00001678
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001679
Guido van Rossum18468821994-06-20 07:49:28 +00001680static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001681GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001682{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 char *name1, *name2=NULL;
1684 PyObject *res = NULL;
1685 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001687 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1688 varname_converter, &name1, &name2))
1689 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001691 ENTER_TCL
1692 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1693 ENTER_OVERLAP
1694 if (tres == NULL) {
1695 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1696 } else {
1697 if (((TkappObject*)self)->wantobjects) {
1698 res = FromObj(self, tres);
1699 }
1700 else {
1701 res = PyUnicode_FromString(Tcl_GetString(tres));
1702 }
1703 }
1704 LEAVE_OVERLAP_TCL
1705 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001706}
1707
1708static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001709Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001710{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001711 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001712}
1713
1714static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001715Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001716{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001718}
1719
Barry Warsawfa701a81997-01-16 00:15:11 +00001720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721
Guido van Rossum18468821994-06-20 07:49:28 +00001722static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001723UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001724{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001725 char *name1, *name2=NULL;
1726 int code;
1727 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001729 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1730 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001732 ENTER_TCL
1733 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1734 ENTER_OVERLAP
1735 if (code == TCL_ERROR)
1736 res = Tkinter_Error(self);
1737 else {
1738 Py_INCREF(Py_None);
1739 res = Py_None;
1740 }
1741 LEAVE_OVERLAP_TCL
1742 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001743}
1744
1745static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001746Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001747{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001748 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001749}
1750
1751static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001752Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001754 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001755}
1756
Barry Warsawfa701a81997-01-16 00:15:11 +00001757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758
Guido van Rossum18468821994-06-20 07:49:28 +00001759/** Tcl to Python **/
1760
1761static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001762Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001763{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001764 char *s;
1765 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 if (PyTuple_Size(args) == 1) {
1768 PyObject* o = PyTuple_GetItem(args, 0);
1769 if (PyLong_Check(o)) {
1770 Py_INCREF(o);
1771 return o;
1772 }
1773 }
1774 if (!PyArg_ParseTuple(args, "s:getint", &s))
1775 return NULL;
1776 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1777 return Tkinter_Error(self);
1778 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001779}
1780
1781static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001782Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001783{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001784 char *s;
1785 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 if (PyTuple_Size(args) == 1) {
1788 PyObject *o = PyTuple_GetItem(args, 0);
1789 if (PyFloat_Check(o)) {
1790 Py_INCREF(o);
1791 return o;
1792 }
1793 }
1794 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1795 return NULL;
1796 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1797 return Tkinter_Error(self);
1798 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001799}
1800
1801static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001802Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001803{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001804 char *s;
1805 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001807 if (PyTuple_Size(args) == 1) {
1808 PyObject *o = PyTuple_GetItem(args, 0);
1809 if (PyLong_Check(o)) {
1810 Py_INCREF(o);
1811 return o;
1812 }
1813 }
1814 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1815 return NULL;
1816 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1817 return Tkinter_Error(self);
1818 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001819}
1820
1821static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001822Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001823{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001824 char *s;
1825 PyObject *res = NULL;
1826 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1829 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001830
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001831 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001833 ENTER_TCL
1834 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1835 ENTER_OVERLAP
1836 if (retval == TCL_ERROR)
1837 res = Tkinter_Error(self);
1838 else
1839 res = Py_BuildValue("s", Tkapp_Result(self));
1840 LEAVE_OVERLAP_TCL
1841 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001842}
1843
1844static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001845Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001846{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 char *s;
1848 PyObject *res = NULL;
1849 int retval;
1850 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1853 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001854
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001855 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001856
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001857 ENTER_TCL
1858 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1859 ENTER_OVERLAP
1860 if (retval == TCL_ERROR)
1861 res = Tkinter_Error(self);
1862 else
1863 res = Py_BuildValue("l", v);
1864 LEAVE_OVERLAP_TCL
1865 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001866}
1867
1868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 char *s;
1872 PyObject *res = NULL;
1873 double v;
1874 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1877 return NULL;
1878 CHECK_TCL_APPARTMENT;
1879 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1880 ENTER_TCL
1881 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1882 ENTER_OVERLAP
1883 PyFPE_END_PROTECT(retval)
1884 if (retval == TCL_ERROR)
1885 res = Tkinter_Error(self);
1886 else
1887 res = Py_BuildValue("d", v);
1888 LEAVE_OVERLAP_TCL
1889 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001890}
1891
1892static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001893Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001894{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 char *s;
1896 PyObject *res = NULL;
1897 int retval;
1898 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1901 return NULL;
1902 CHECK_TCL_APPARTMENT;
1903 ENTER_TCL
1904 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1905 ENTER_OVERLAP
1906 if (retval == TCL_ERROR)
1907 res = Tkinter_Error(self);
1908 else
1909 res = Py_BuildValue("i", v);
1910 LEAVE_OVERLAP_TCL
1911 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001912}
1913
Barry Warsawfa701a81997-01-16 00:15:11 +00001914
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001915
Guido van Rossum18468821994-06-20 07:49:28 +00001916static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001917Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001918{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001919 char *list;
1920 int argc;
1921 char **argv;
1922 PyObject *v;
1923 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001924
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 if (PyTuple_Size(args) == 1) {
1926 v = PyTuple_GetItem(args, 0);
1927 if (PyTuple_Check(v)) {
1928 Py_INCREF(v);
1929 return v;
1930 }
1931 }
1932 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1933 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 if (Tcl_SplitList(Tkapp_Interp(self), list,
1936 &argc, &argv) == TCL_ERROR) {
1937 PyMem_Free(list);
1938 return Tkinter_Error(self);
1939 }
Guido van Rossum18468821994-06-20 07:49:28 +00001940
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001941 if (!(v = PyTuple_New(argc)))
1942 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 for (i = 0; i < argc; i++) {
1945 PyObject *s = PyUnicode_FromString(argv[i]);
1946 if (!s || PyTuple_SetItem(v, i, s)) {
1947 Py_DECREF(v);
1948 v = NULL;
1949 goto finally;
1950 }
1951 }
Guido van Rossum18468821994-06-20 07:49:28 +00001952
Barry Warsawfa701a81997-01-16 00:15:11 +00001953 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954 ckfree(FREECAST argv);
1955 PyMem_Free(list);
1956 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001957}
1958
1959static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001960Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001961{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962 PyObject *v;
1963 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965 if (PyTuple_Size(args) == 1) {
1966 PyObject* o = PyTuple_GetItem(args, 0);
1967 if (PyTuple_Check(o)) {
1968 o = SplitObj(o);
1969 return o;
1970 }
1971 }
1972 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1973 return NULL;
1974 v = Split(list);
1975 PyMem_Free(list);
1976 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001977}
1978
1979static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001980Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001981{
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001982 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001983 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001985 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1986 "merge is deprecated and will be removed in 3.4",
1987 1) < 0)
1988 return 0;
1989
1990 s = Merge(args);
1991
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001992 if (s) {
1993 res = PyUnicode_FromString(s);
1994 ckfree(s);
1995 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001998}
1999
Barry Warsawfa701a81997-01-16 00:15:11 +00002000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001
Guido van Rossum18468821994-06-20 07:49:28 +00002002/** Tcl Command **/
2003
Guido van Rossum00d93061998-05-28 23:06:38 +00002004/* Client data struct */
2005typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002006 PyObject *self;
2007 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002008} PythonCmd_ClientData;
2009
2010static int
Fred Drake509d79a2000-07-08 04:04:38 +00002011PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002012{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002013 errorInCmd = 1;
2014 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2015 LEAVE_PYTHON
2016 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002017}
2018
Guido van Rossum18468821994-06-20 07:49:28 +00002019/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002020 * function or method.
2021 */
Guido van Rossum18468821994-06-20 07:49:28 +00002022static int
Fred Drake509d79a2000-07-08 04:04:38 +00002023PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002024{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002025 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002026 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 int i, rv;
2028 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002030 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002032 /* TBD: no error checking here since we know, via the
2033 * Tkapp_CreateCommand() that the client data is a two-tuple
2034 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002037 /* Create argument list (argv1, ..., argvN) */
2038 if (!(arg = PyTuple_New(argc - 1)))
2039 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 for (i = 0; i < (argc - 1); i++) {
2042 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002043 if (!s) {
2044 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2045 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2046 !strcmp(argv[i + 1], "\xC0\x80")) {
2047 PyErr_Clear();
2048 /* Convert to "strict" utf-8 null */
2049 s = PyUnicode_FromString("\0");
2050 } else {
2051 Py_DECREF(arg);
2052 return PythonCmd_Error(interp);
2053 }
2054 }
2055 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002056 Py_DECREF(arg);
2057 return PythonCmd_Error(interp);
2058 }
2059 }
2060 res = PyEval_CallObject(func, arg);
2061 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 if (res == NULL)
2064 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002066 obj_res = AsObj(res);
2067 if (obj_res == NULL) {
2068 Py_DECREF(res);
2069 return PythonCmd_Error(interp);
2070 }
2071 else {
2072 Tcl_SetObjResult(interp, obj_res);
2073 rv = TCL_OK;
2074 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002075
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002076 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002078 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002081}
2082
2083static void
Fred Drake509d79a2000-07-08 04:04:38 +00002084PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002085{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002086 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088 ENTER_PYTHON
2089 Py_XDECREF(data->self);
2090 Py_XDECREF(data->func);
2091 PyMem_DEL(data);
2092 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002093}
2094
Barry Warsawfa701a81997-01-16 00:15:11 +00002095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002096
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002097
Benjamin Peterson5879d412009-03-30 14:51:56 +00002098#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002099TCL_DECLARE_MUTEX(command_mutex)
2100
2101typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 Tcl_Event ev;
2103 Tcl_Interp* interp;
2104 char *name;
2105 int create;
2106 int *status;
2107 ClientData *data;
2108 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002109} CommandEvent;
2110
2111static int
2112Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002113{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002114 if (ev->create)
2115 *ev->status = Tcl_CreateCommand(
2116 ev->interp, ev->name, PythonCmd,
2117 ev->data, PythonCmdDelete) == NULL;
2118 else
2119 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2120 Tcl_MutexLock(&command_mutex);
2121 Tcl_ConditionNotify(ev->done);
2122 Tcl_MutexUnlock(&command_mutex);
2123 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002124}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002125#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002126
2127static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002128Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002129{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002130 TkappObject *self = (TkappObject*)selfptr;
2131 PythonCmd_ClientData *data;
2132 char *cmdName;
2133 PyObject *func;
2134 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2137 return NULL;
2138 if (!PyCallable_Check(func)) {
2139 PyErr_SetString(PyExc_TypeError, "command not callable");
2140 return NULL;
2141 }
Guido van Rossum18468821994-06-20 07:49:28 +00002142
Martin v. Löwisa9656492003-03-30 08:44:58 +00002143#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2145 !WaitForMainloop(self))
2146 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002147#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002148
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002149 data = PyMem_NEW(PythonCmd_ClientData, 1);
2150 if (!data)
2151 return PyErr_NoMemory();
2152 Py_INCREF(self);
2153 Py_INCREF(func);
2154 data->self = selfptr;
2155 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002156#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002157 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2158 Tcl_Condition cond = NULL;
2159 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2160 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2161 ev->interp = self->interp;
2162 ev->create = 1;
2163 ev->name = cmdName;
2164 ev->data = (ClientData)data;
2165 ev->status = &err;
2166 ev->done = &cond;
2167 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2168 Tcl_ConditionFinalize(&cond);
2169 }
2170 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002171#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 {
2173 ENTER_TCL
2174 err = Tcl_CreateCommand(
2175 Tkapp_Interp(self), cmdName, PythonCmd,
2176 (ClientData)data, PythonCmdDelete) == NULL;
2177 LEAVE_TCL
2178 }
2179 if (err) {
2180 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2181 PyMem_DEL(data);
2182 return NULL;
2183 }
Guido van Rossum18468821994-06-20 07:49:28 +00002184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002185 Py_INCREF(Py_None);
2186 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002187}
2188
Barry Warsawfa701a81997-01-16 00:15:11 +00002189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190
Guido van Rossum18468821994-06-20 07:49:28 +00002191static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002192Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002193{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 TkappObject *self = (TkappObject*)selfptr;
2195 char *cmdName;
2196 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2199 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002200
2201#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2203 Tcl_Condition cond = NULL;
2204 CommandEvent *ev;
2205 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2206 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2207 ev->interp = self->interp;
2208 ev->create = 0;
2209 ev->name = cmdName;
2210 ev->status = &err;
2211 ev->done = &cond;
2212 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2213 &command_mutex);
2214 Tcl_ConditionFinalize(&cond);
2215 }
2216 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002217#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218 {
2219 ENTER_TCL
2220 err = Tcl_DeleteCommand(self->interp, cmdName);
2221 LEAVE_TCL
2222 }
2223 if (err == -1) {
2224 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2225 return NULL;
2226 }
2227 Py_INCREF(Py_None);
2228 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002229}
2230
Barry Warsawfa701a81997-01-16 00:15:11 +00002231
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002232
Guido van Rossum00d93061998-05-28 23:06:38 +00002233#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002234/** File Handler **/
2235
Guido van Rossum00d93061998-05-28 23:06:38 +00002236typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 PyObject *func;
2238 PyObject *file;
2239 int id;
2240 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002241} FileHandler_ClientData;
2242
2243static FileHandler_ClientData *HeadFHCD;
2244
2245static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002246NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002247{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 FileHandler_ClientData *p;
2249 p = PyMem_NEW(FileHandler_ClientData, 1);
2250 if (p != NULL) {
2251 Py_XINCREF(func);
2252 Py_XINCREF(file);
2253 p->func = func;
2254 p->file = file;
2255 p->id = id;
2256 p->next = HeadFHCD;
2257 HeadFHCD = p;
2258 }
2259 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002260}
2261
2262static void
Fred Drake509d79a2000-07-08 04:04:38 +00002263DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002264{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 pp = &HeadFHCD;
2268 while ((p = *pp) != NULL) {
2269 if (p->id == id) {
2270 *pp = p->next;
2271 Py_XDECREF(p->func);
2272 Py_XDECREF(p->file);
2273 PyMem_DEL(p);
2274 }
2275 else
2276 pp = &p->next;
2277 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002278}
2279
Guido van Rossuma597dde1995-01-10 20:56:29 +00002280static void
Fred Drake509d79a2000-07-08 04:04:38 +00002281FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002282{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2284 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 ENTER_PYTHON
2287 func = data->func;
2288 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002290 arg = Py_BuildValue("(Oi)", file, (long) mask);
2291 res = PyEval_CallObject(func, arg);
2292 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 if (res == NULL) {
2295 errorInCmd = 1;
2296 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2297 }
2298 Py_XDECREF(res);
2299 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002300}
2301
Guido van Rossum18468821994-06-20 07:49:28 +00002302static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002303Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2304 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002305{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002306 FileHandler_ClientData *data;
2307 PyObject *file, *func;
2308 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002309
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2311 &file, &mask, &func))
2312 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 tfile = PyObject_AsFileDescriptor(file);
2317 if (tfile < 0)
2318 return NULL;
2319 if (!PyCallable_Check(func)) {
2320 PyErr_SetString(PyExc_TypeError, "bad argument list");
2321 return NULL;
2322 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 data = NewFHCD(func, file, tfile);
2325 if (data == NULL)
2326 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 /* Ought to check for null Tcl_File object... */
2329 ENTER_TCL
2330 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2331 LEAVE_TCL
2332 Py_INCREF(Py_None);
2333 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002334}
2335
2336static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002337Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002338{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002339 PyObject *file;
2340 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2343 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002347 tfile = PyObject_AsFileDescriptor(file);
2348 if (tfile < 0)
2349 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002351 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353 /* Ought to check for null Tcl_File object... */
2354 ENTER_TCL
2355 Tcl_DeleteFileHandler(tfile);
2356 LEAVE_TCL
2357 Py_INCREF(Py_None);
2358 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002359}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002360#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363/**** Tktt Object (timer token) ****/
2364
Jeremy Hylton938ace62002-07-17 16:30:39 +00002365static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366
Guido van Rossum00d93061998-05-28 23:06:38 +00002367typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002368 PyObject_HEAD
2369 Tcl_TimerToken token;
2370 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002371} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002372
2373static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002374Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002376 TkttObject *v = (TkttObject *)self;
2377 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2380 return NULL;
2381 if (v->token != NULL) {
2382 Tcl_DeleteTimerHandler(v->token);
2383 v->token = NULL;
2384 }
2385 if (func != NULL) {
2386 v->func = NULL;
2387 Py_DECREF(func);
2388 Py_DECREF(v); /* See Tktt_New() */
2389 }
2390 Py_INCREF(Py_None);
2391 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002392}
2393
2394static PyMethodDef Tktt_methods[] =
2395{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2397 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002398};
2399
2400static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002401Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 v = PyObject_New(TkttObject, &Tktt_Type);
2406 if (v == NULL)
2407 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 Py_INCREF(func);
2410 v->token = NULL;
2411 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 /* Extra reference, deleted when called or when handler is deleted */
2414 Py_INCREF(v);
2415 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002416}
2417
2418static void
Fred Drake509d79a2000-07-08 04:04:38 +00002419Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002420{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002421 TkttObject *v = (TkttObject *)self;
2422 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002427}
2428
Guido van Rossum597ac201998-05-12 14:36:19 +00002429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002430Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002433 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2434 v,
2435 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002436}
2437
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002438static PyTypeObject Tktt_Type =
2439{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 PyVarObject_HEAD_INIT(NULL, 0)
2441 "tktimertoken", /*tp_name */
2442 sizeof(TkttObject), /*tp_basicsize */
2443 0, /*tp_itemsize */
2444 Tktt_Dealloc, /*tp_dealloc */
2445 0, /*tp_print */
2446 0, /*tp_getattr */
2447 0, /*tp_setattr */
2448 0, /*tp_reserved */
2449 Tktt_Repr, /*tp_repr */
2450 0, /*tp_as_number */
2451 0, /*tp_as_sequence */
2452 0, /*tp_as_mapping */
2453 0, /*tp_hash */
2454 0, /*tp_call*/
2455 0, /*tp_str*/
2456 0, /*tp_getattro*/
2457 0, /*tp_setattro*/
2458 0, /*tp_as_buffer*/
2459 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2460 0, /*tp_doc*/
2461 0, /*tp_traverse*/
2462 0, /*tp_clear*/
2463 0, /*tp_richcompare*/
2464 0, /*tp_weaklistoffset*/
2465 0, /*tp_iter*/
2466 0, /*tp_iternext*/
2467 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002468};
2469
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472/** Timer Handler **/
2473
2474static void
Fred Drake509d79a2000-07-08 04:04:38 +00002475TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002476{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 TkttObject *v = (TkttObject *)clientData;
2478 PyObject *func = v->func;
2479 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002481 if (func == NULL)
2482 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 res = PyEval_CallObject(func, NULL);
2489 Py_DECREF(func);
2490 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 if (res == NULL) {
2493 errorInCmd = 1;
2494 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2495 }
2496 else
2497 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002498
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002500}
2501
2502static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002503Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002504{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 int milliseconds;
2506 PyObject *func;
2507 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2510 &milliseconds, &func))
2511 return NULL;
2512 if (!PyCallable_Check(func)) {
2513 PyErr_SetString(PyExc_TypeError, "bad argument list");
2514 return NULL;
2515 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002517 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002519 v = Tktt_New(func);
2520 if (v) {
2521 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2522 (ClientData)v);
2523 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002524
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002525 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002526}
2527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528
Guido van Rossum18468821994-06-20 07:49:28 +00002529/** Event Loop **/
2530
Guido van Rossum18468821994-06-20 07:49:28 +00002531static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002532Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002533{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 int threshold = 0;
2535 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002536#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002538#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002539
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002540 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2541 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 CHECK_TCL_APPARTMENT;
2544 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 quitMainLoop = 0;
2547 while (Tk_GetNumMainWindows() > threshold &&
2548 !quitMainLoop &&
2549 !errorInCmd)
2550 {
2551 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002552
2553#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 if (self->threaded) {
2555 /* Allow other Python threads to run. */
2556 ENTER_TCL
2557 result = Tcl_DoOneEvent(0);
2558 LEAVE_TCL
2559 }
2560 else {
2561 Py_BEGIN_ALLOW_THREADS
2562 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2563 tcl_tstate = tstate;
2564 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2565 tcl_tstate = NULL;
2566 if(tcl_lock)PyThread_release_lock(tcl_lock);
2567 if (result == 0)
2568 Sleep(Tkinter_busywaitinterval);
2569 Py_END_ALLOW_THREADS
2570 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002571#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002573#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002575 if (PyErr_CheckSignals() != 0) {
2576 self->dispatching = 0;
2577 return NULL;
2578 }
2579 if (result < 0)
2580 break;
2581 }
2582 self->dispatching = 0;
2583 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002584
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 if (errorInCmd) {
2586 errorInCmd = 0;
2587 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2588 excInCmd = valInCmd = trbInCmd = NULL;
2589 return NULL;
2590 }
2591 Py_INCREF(Py_None);
2592 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002593}
2594
2595static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002596Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002597{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002598 int flags = 0;
2599 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2602 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 ENTER_TCL
2605 rv = Tcl_DoOneEvent(flags);
2606 LEAVE_TCL
2607 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002608}
2609
2610static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002611Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002612{
2613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614 if (!PyArg_ParseTuple(args, ":quit"))
2615 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 quitMainLoop = 1;
2618 Py_INCREF(Py_None);
2619 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002620}
2621
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002622static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002623Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002624{
2625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 if (!PyArg_ParseTuple(args, ":interpaddr"))
2627 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002628
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002630}
2631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002633Tkapp_TkInit(PyObject *self, PyObject *args)
2634{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635 Tcl_Interp *interp = Tkapp_Interp(self);
2636 const char * _tk_exists = NULL;
2637 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002638
Guilherme Polob681df42009-02-09 22:33:59 +00002639#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002640 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2641 * first call failed.
2642 * To avoid the deadlock, we just refuse the second call through
2643 * a static variable.
2644 */
2645 if (tk_load_failed) {
2646 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2647 return NULL;
2648 }
Guilherme Polob681df42009-02-09 22:33:59 +00002649#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002651 /* We want to guard against calling Tk_Init() multiple times */
2652 CHECK_TCL_APPARTMENT;
2653 ENTER_TCL
2654 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2655 ENTER_OVERLAP
2656 if (err == TCL_ERROR) {
2657 /* This sets an exception, but we cannot return right
2658 away because we need to exit the overlap first. */
2659 Tkinter_Error(self);
2660 } else {
2661 _tk_exists = Tkapp_Result(self);
2662 }
2663 LEAVE_OVERLAP_TCL
2664 if (err == TCL_ERROR) {
2665 return NULL;
2666 }
2667 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2668 if (Tk_Init(interp) == TCL_ERROR) {
2669 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002670#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002672#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673 return NULL;
2674 }
2675 }
2676 Py_INCREF(Py_None);
2677 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002678}
Barry Warsawfa701a81997-01-16 00:15:11 +00002679
Martin v. Löwisffad6332002-11-26 09:28:05 +00002680static PyObject *
2681Tkapp_WantObjects(PyObject *self, PyObject *args)
2682{
2683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 int wantobjects = -1;
2685 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2686 return NULL;
2687 if (wantobjects == -1)
2688 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2689 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002691 Py_INCREF(Py_None);
2692 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002693}
2694
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002695static PyObject *
2696Tkapp_WillDispatch(PyObject *self, PyObject *args)
2697{
2698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002701 Py_INCREF(Py_None);
2702 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002703}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002705
Guido van Rossum18468821994-06-20 07:49:28 +00002706/**** Tkapp Method List ****/
2707
2708static PyMethodDef Tkapp_methods[] =
2709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002710 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2711 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2712 {"call", Tkapp_Call, METH_VARARGS},
2713 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2714 {"eval", Tkapp_Eval, METH_VARARGS},
2715 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2716 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2717 {"record", Tkapp_Record, METH_VARARGS},
2718 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2719 {"setvar", Tkapp_SetVar, METH_VARARGS},
2720 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2721 {"getvar", Tkapp_GetVar, METH_VARARGS},
2722 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2723 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2724 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2725 {"getint", Tkapp_GetInt, METH_VARARGS},
2726 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2727 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2728 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2729 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2730 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2731 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2732 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2733 {"split", Tkapp_Split, METH_VARARGS},
2734 {"merge", Tkapp_Merge, METH_VARARGS},
2735 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2736 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002737#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2739 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002740#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2742 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2743 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2744 {"quit", Tkapp_Quit, METH_VARARGS},
2745 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2746 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2747 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002748};
2749
Barry Warsawfa701a81997-01-16 00:15:11 +00002750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751
Guido van Rossum18468821994-06-20 07:49:28 +00002752/**** Tkapp Type Methods ****/
2753
2754static void
Fred Drake509d79a2000-07-08 04:04:38 +00002755Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 /*CHECK_TCL_APPARTMENT;*/
2758 ENTER_TCL
2759 Tcl_DeleteInterp(Tkapp_Interp(self));
2760 LEAVE_TCL
2761 PyObject_Del(self);
2762 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002763}
2764
Guido van Rossum18468821994-06-20 07:49:28 +00002765static PyTypeObject Tkapp_Type =
2766{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 PyVarObject_HEAD_INIT(NULL, 0)
2768 "tkapp", /*tp_name */
2769 sizeof(TkappObject), /*tp_basicsize */
2770 0, /*tp_itemsize */
2771 Tkapp_Dealloc, /*tp_dealloc */
2772 0, /*tp_print */
2773 0, /*tp_getattr */
2774 0, /*tp_setattr */
2775 0, /*tp_reserved */
2776 0, /*tp_repr */
2777 0, /*tp_as_number */
2778 0, /*tp_as_sequence */
2779 0, /*tp_as_mapping */
2780 0, /*tp_hash */
2781 0, /*tp_call*/
2782 0, /*tp_str*/
2783 0, /*tp_getattro*/
2784 0, /*tp_setattro*/
2785 0, /*tp_as_buffer*/
2786 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2787 0, /*tp_doc*/
2788 0, /*tp_traverse*/
2789 0, /*tp_clear*/
2790 0, /*tp_richcompare*/
2791 0, /*tp_weaklistoffset*/
2792 0, /*tp_iter*/
2793 0, /*tp_iternext*/
2794 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002795};
2796
Barry Warsawfa701a81997-01-16 00:15:11 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798
Guido van Rossum18468821994-06-20 07:49:28 +00002799/**** Tkinter Module ****/
2800
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 PyObject* tuple;
2803 int size; /* current size */
2804 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002805} FlattenContext;
2806
2807static int
2808_bump(FlattenContext* context, int size)
2809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 /* expand tuple to hold (at least) size new items.
2811 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 if (maxsize < context->size + size)
2816 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002817
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002818 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002819
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002820 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002821}
2822
2823static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002824_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002825{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002826 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002830 if (depth > 1000) {
2831 PyErr_SetString(PyExc_ValueError,
2832 "nesting too deep in _flatten");
2833 return 0;
2834 } else if (PyList_Check(item)) {
2835 size = PyList_GET_SIZE(item);
2836 /* preallocate (assume no nesting) */
2837 if (context->size + size > context->maxsize &&
2838 !_bump(context, size))
2839 return 0;
2840 /* copy items to output tuple */
2841 for (i = 0; i < size; i++) {
2842 PyObject *o = PyList_GET_ITEM(item, i);
2843 if (PyList_Check(o) || PyTuple_Check(o)) {
2844 if (!_flatten1(context, o, depth + 1))
2845 return 0;
2846 } else if (o != Py_None) {
2847 if (context->size + 1 > context->maxsize &&
2848 !_bump(context, 1))
2849 return 0;
2850 Py_INCREF(o);
2851 PyTuple_SET_ITEM(context->tuple,
2852 context->size++, o);
2853 }
2854 }
2855 } else if (PyTuple_Check(item)) {
2856 /* same, for tuples */
2857 size = PyTuple_GET_SIZE(item);
2858 if (context->size + size > context->maxsize &&
2859 !_bump(context, size))
2860 return 0;
2861 for (i = 0; i < size; i++) {
2862 PyObject *o = PyTuple_GET_ITEM(item, i);
2863 if (PyList_Check(o) || PyTuple_Check(o)) {
2864 if (!_flatten1(context, o, depth + 1))
2865 return 0;
2866 } else if (o != Py_None) {
2867 if (context->size + 1 > context->maxsize &&
2868 !_bump(context, 1))
2869 return 0;
2870 Py_INCREF(o);
2871 PyTuple_SET_ITEM(context->tuple,
2872 context->size++, o);
2873 }
2874 }
2875 } else {
2876 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2877 return 0;
2878 }
2879 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002880}
2881
2882static PyObject *
2883Tkinter_Flatten(PyObject* self, PyObject* args)
2884{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002885 FlattenContext context;
2886 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2889 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002891 context.maxsize = PySequence_Size(item);
2892 if (context.maxsize < 0)
2893 return NULL;
2894 if (context.maxsize == 0)
2895 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002897 context.tuple = PyTuple_New(context.maxsize);
2898 if (!context.tuple)
2899 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002900
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 if (!_flatten1(&context, item,0))
2904 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906 if (_PyTuple_Resize(&context.tuple, context.size))
2907 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002909 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002910}
2911
Guido van Rossum18468821994-06-20 07:49:28 +00002912static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002913Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002914{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002915 char *screenName = NULL;
2916 char *baseName = NULL; /* XXX this is not used anymore;
2917 try getting rid of it. */
2918 char *className = NULL;
2919 int interactive = 0;
2920 int wantobjects = 0;
2921 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2922 int sync = 0; /* pass -sync to wish */
2923 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002924
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002925 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002927 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2928 &screenName, &baseName, &className,
2929 &interactive, &wantobjects, &wantTk,
2930 &sync, &use))
2931 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933 return (PyObject *) Tkapp_New(screenName, className,
2934 interactive, wantobjects, wantTk,
2935 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002936}
2937
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002938static PyObject *
2939Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2940{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002941 int new_val;
2942 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2943 return NULL;
2944 if (new_val < 0) {
2945 PyErr_SetString(PyExc_ValueError,
2946 "busywaitinterval must be >= 0");
2947 return NULL;
2948 }
2949 Tkinter_busywaitinterval = new_val;
2950 Py_INCREF(Py_None);
2951 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002952}
2953
2954static char setbusywaitinterval_doc[] =
2955"setbusywaitinterval(n) -> None\n\
2956\n\
2957Set the busy-wait interval in milliseconds between successive\n\
2958calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2959It should be set to a divisor of the maximum time between\n\
2960frames in an animation.";
2961
2962static PyObject *
2963Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2964{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002965 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002966}
2967
2968static char getbusywaitinterval_doc[] =
2969"getbusywaitinterval() -> int\n\
2970\n\
2971Return the current busy-wait interval between successive\n\
2972calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2973
Guido van Rossum18468821994-06-20 07:49:28 +00002974static PyMethodDef moduleMethods[] =
2975{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002976 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2977 {"create", Tkinter_Create, METH_VARARGS},
2978 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2979 setbusywaitinterval_doc},
2980 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2981 METH_NOARGS, getbusywaitinterval_doc},
2982 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002983};
2984
Guido van Rossum7bf15641998-05-22 18:28:17 +00002985#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002986
2987static int stdin_ready = 0;
2988
Guido van Rossumad4db171998-06-13 13:56:28 +00002989#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002990static void
Fred Drake509d79a2000-07-08 04:04:38 +00002991MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002994}
Guido van Rossumad4db171998-06-13 13:56:28 +00002995#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002996
Martin v. Löwisa9656492003-03-30 08:44:58 +00002997#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002998static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002999#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003000
Guido van Rossum18468821994-06-20 07:49:28 +00003001static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003002EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003003{
Guido van Rossumad4db171998-06-13 13:56:28 +00003004#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003005 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003006#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003007#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003009#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 stdin_ready = 0;
3011 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003012#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003013 tfile = fileno(stdin);
3014 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003015#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 while (!errorInCmd && !stdin_ready) {
3017 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003018#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003019 if (_kbhit()) {
3020 stdin_ready = 1;
3021 break;
3022 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003023#endif
3024#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003025 Py_BEGIN_ALLOW_THREADS
3026 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3027 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003031 tcl_tstate = NULL;
3032 if(tcl_lock)PyThread_release_lock(tcl_lock);
3033 if (result == 0)
3034 Sleep(Tkinter_busywaitinterval);
3035 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003036#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003037 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003038#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040 if (result < 0)
3041 break;
3042 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003043#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003044 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003045#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003046 if (errorInCmd) {
3047 errorInCmd = 0;
3048 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3049 excInCmd = valInCmd = trbInCmd = NULL;
3050 PyErr_Print();
3051 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003052#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003054#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003056}
Guido van Rossum18468821994-06-20 07:49:28 +00003057
Guido van Rossum00d93061998-05-28 23:06:38 +00003058#endif
3059
Guido van Rossum7bf15641998-05-22 18:28:17 +00003060static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003061EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003062{
Guido van Rossum00d93061998-05-28 23:06:38 +00003063#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003064 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003065#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003066 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003067#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003068 PyOS_InputHook = EventHook;
3069 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003070#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003071}
3072
3073static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003074DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003075{
Guido van Rossum00d93061998-05-28 23:06:38 +00003076#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003077 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3078 PyOS_InputHook = NULL;
3079 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003080#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003081}
3082
Barry Warsawfa701a81997-01-16 00:15:11 +00003083
3084/* all errors will be checked in one fell swoop in init_tkinter() */
3085static void
Fred Drake509d79a2000-07-08 04:04:38 +00003086ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003087{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088 PyObject *v = PyLong_FromLong(val);
3089 if (v) {
3090 PyDict_SetItemString(d, name, v);
3091 Py_DECREF(v);
3092 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003093}
3094static void
Fred Drake509d79a2000-07-08 04:04:38 +00003095ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003096{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003097 PyObject *v = PyUnicode_FromString(val);
3098 if (v) {
3099 PyDict_SetItemString(d, name, v);
3100 Py_DECREF(v);
3101 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003102}
3103
3104
Martin v. Löwis1a214512008-06-11 05:26:20 +00003105static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003106 PyModuleDef_HEAD_INIT,
3107 "_tkinter",
3108 NULL,
3109 -1,
3110 moduleMethods,
3111 NULL,
3112 NULL,
3113 NULL,
3114 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003115};
3116
Mark Hammond62b1ab12002-07-23 06:31:15 +00003117PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003118PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003119{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003120 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 if (PyType_Ready(&Tkapp_Type) < 0)
3123 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003124
3125#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003126 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003127#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 m = PyModule_Create(&_tkintermodule);
3130 if (m == NULL)
3131 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 d = PyModule_GetDict(m);
3134 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3135 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003137 ins_long(d, "READABLE", TCL_READABLE);
3138 ins_long(d, "WRITABLE", TCL_WRITABLE);
3139 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3140 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3141 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3142 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3143 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3144 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3145 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3146 ins_string(d, "TK_VERSION", TK_VERSION);
3147 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003148
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003149 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003150
Jesus Ceaef86d122012-07-19 21:18:07 +02003151 if (PyType_Ready(&Tktt_Type) < 0) {
3152 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003154 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003155 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003157 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3158 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003159
3160#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003161 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3162 * start waking up. Note that Tcl_FindExecutable will do this, this
3163 * code must be above it! The original warning from
3164 * tkMacOSXAppInit.c is copied below.
3165 *
3166 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3167 * Tcl interpreter for now. It probably should work to do this
3168 * in the other order, but for now it doesn't seem to.
3169 *
3170 */
3171 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003172#endif
3173
3174
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003175 /* This helps the dynamic loader; in Unicode aware Tcl versions
3176 it also helps Tcl find its encodings. */
3177 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3178 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003179 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003180 if (cexe)
3181 Tcl_FindExecutable(PyBytes_AsString(cexe));
3182 Py_XDECREF(cexe);
3183 Py_DECREF(uexe);
3184 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003185
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003186 if (PyErr_Occurred()) {
3187 Py_DECREF(m);
3188 return NULL;
3189 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003190
Guido van Rossum43ff8681998-07-14 18:02:13 +00003191#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003192 /* This was not a good idea; through <Destroy> bindings,
3193 Tcl_Finalize() may invoke Python code but at that point the
3194 interpreter and thread state have already been destroyed! */
3195 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003196#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003197 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003198}