blob: e6b72d3917235c4edd2cce66b1cf7708415d62f2 [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
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030050#define CHECK_SIZE(size, elemsize) \
51 ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
52
Martin v. Löwis71e25a02002-10-01 18:08:06 +000053/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
54 making _tkinter correct for this API means to break earlier
55 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
56 earlier versions. Once Tcl releases before 8.4 don't need to be supported
57 anymore, this should go. */
58#define USE_COMPAT_CONST
59
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000060/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
61 it always; if Tcl is not threaded, the thread functions in
62 Tcl are empty. */
63#define TCL_THREADS
64
Jack Jansencb852442001-12-09 23:15:56 +000065#ifdef TK_FRAMEWORK
66#include <Tcl/tcl.h>
67#include <Tk/tk.h>
68#else
Guido van Rossum18468821994-06-20 07:49:28 +000069#include <tcl.h>
70#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000071#endif
Guido van Rossum18468821994-06-20 07:49:28 +000072
Guilherme Polo2d87e422009-04-10 22:19:09 +000073#include "tkinter.h"
74
Jason Tishlerbbe89612002-12-31 20:30:46 +000075/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#ifndef CONST84_RETURN
77#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000078#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000079#define CONST
80#endif
81
Guilherme Polo66917722009-02-09 22:35:27 +000082#if TK_VERSION_HEX < 0x08030102
83#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000084#endif
85
Jack Janseneddc1442003-11-20 01:44:59 +000086#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000087#define HAVE_CREATEFILEHANDLER
88#endif
89
Guido van Rossum00d93061998-05-28 23:06:38 +000090#ifdef HAVE_CREATEFILEHANDLER
91
Neal Norwitzd948a432006-01-08 01:08:55 +000092/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
93 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
94#ifndef TCL_UNIX_FD
95# ifdef TCL_WIN_SOCKET
96# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
97# else
98# define TCL_UNIX_FD 1
99# endif
100#endif
101
Guido van Rossum00d93061998-05-28 23:06:38 +0000102/* Tcl_CreateFileHandler() changed several times; these macros deal with the
103 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
104 Unix, only because Jack added it back); when available on Windows, it only
105 applies to sockets. */
106
Guido van Rossum7bf15641998-05-22 18:28:17 +0000107#ifdef MS_WINDOWS
108#define FHANDLETYPE TCL_WIN_SOCKET
109#else
110#define FHANDLETYPE TCL_UNIX_FD
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
114 which uses this to handle Tcl events while the user is typing commands. */
115
116#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000117#define WAIT_FOR_STDIN
118#endif
119
Guido van Rossum00d93061998-05-28 23:06:38 +0000120#endif /* HAVE_CREATEFILEHANDLER */
121
Guido van Rossumad4db171998-06-13 13:56:28 +0000122#ifdef MS_WINDOWS
123#include <conio.h>
124#define WAIT_FOR_STDIN
125#endif
126
Guido van Rossum00d93061998-05-28 23:06:38 +0000127#ifdef WITH_THREAD
128
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000129/* The threading situation is complicated. Tcl is not thread-safe, except
130 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000131 So we need to use a lock around all uses of Tcl. Previously, the Python
132 interpreter lock was used for this. However, this causes problems when
133 other Python threads need to run while Tcl is blocked waiting for events.
134
135 To solve this problem, a separate lock for Tcl is introduced. Holding it
136 is incompatible with holding Python's interpreter lock. The following four
137 macros manipulate both locks together.
138
139 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
140 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
141 that could call an event handler, or otherwise affect the state of a Tcl
142 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000143 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000144 released and the lock for Tcl has been acquired.
145
Guido van Rossum5e977831998-06-15 14:03:52 +0000146 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
147 (For example, when transferring data from the Tcl interpreter result to a
148 Python string object.) This can be done by using different macros to close
149 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
150 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
151 releases the Tcl lock.
152
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000153 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000154 handlers when the handler needs to use Python. Such event handlers are
155 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000156 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000157 the Python interpreter lock, restoring the appropriate thread state, and
158 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
159 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000160 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000161
162 These locks expand to several statements and brackets; they should not be
163 used in branches of if statements and the like.
164
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000165 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
166 only valid in the thread that created it, and all Tk activity must happen in this
167 thread, also. That means that the mainloop must be invoked in the thread that
168 created the interpreter. Invoking commands from other threads is possible;
169 _tkinter will queue an event for the interpreter thread, which will then
170 execute the command and pass back the result. If the main thread is not in the
171 mainloop, and invoking commands causes an exception; if the main loop is running
172 but not processing events, the command invocation will block.
173
174 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
175 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
176 threads. So we use the Tcl TLS API.
177
Guido van Rossum00d93061998-05-28 23:06:38 +0000178*/
179
Guido van Rossum65d5b571998-12-21 19:32:43 +0000180static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181
182#ifdef TCL_THREADS
183static Tcl_ThreadDataKey state_key;
184typedef PyThreadState *ThreadSpecificData;
185#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
186#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000187static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000188#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000189
190#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
192 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000193
194#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000195 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000196
Guido van Rossum62320c91998-06-15 04:36:09 +0000197#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000199
200#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000202
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000203#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
205 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000206
207#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 { PyThreadState *tstate = PyEval_SaveThread(); \
209 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000210
211#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 if (((TkappObject *)self)->threaded && \
213 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
214 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
215 return 0; \
216 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000217
218#else
219
220#define ENTER_TCL
221#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000222#define ENTER_OVERLAP
223#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000224#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000225#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000226#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000227
228#endif
229
Guido van Rossum97867b21996-08-08 19:09:53 +0000230#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000231#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000232#endif
233
Guido van Rossum18468821994-06-20 07:49:28 +0000234/**** Tkapp Object Declaration ****/
235
Jeremy Hylton938ace62002-07-17 16:30:39 +0000236static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000237
Guido van Rossum00d93061998-05-28 23:06:38 +0000238typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239 PyObject_HEAD
240 Tcl_Interp *interp;
241 int wantobjects;
242 int threaded; /* True if tcl_platform[threaded] */
243 Tcl_ThreadId thread_id;
244 int dispatching;
245 /* We cannot include tclInt.h, as this is internal.
246 So we cache interesting types here. */
247 Tcl_ObjType *BooleanType;
248 Tcl_ObjType *ByteArrayType;
249 Tcl_ObjType *DoubleType;
250 Tcl_ObjType *IntType;
251 Tcl_ObjType *ListType;
252 Tcl_ObjType *ProcBodyType;
253 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000254} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000255
Christian Heimes90aa7642007-12-19 02:45:37 +0000256#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000257#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000258#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000259
Guido van Rossum35d43371997-08-02 00:09:09 +0000260#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000261(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000262
Barry Warsawfa701a81997-01-16 00:15:11 +0000263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264
Guido van Rossum18468821994-06-20 07:49:28 +0000265/**** Error Handling ****/
266
267static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000268static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000269static int errorInCmd = 0;
270static PyObject *excInCmd;
271static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000272static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000273
Guilherme Polob681df42009-02-09 22:33:59 +0000274#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000275static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000276#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278
Guido van Rossum18468821994-06-20 07:49:28 +0000279static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000280Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000281{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000282 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
283 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000284}
285
Barry Warsawfa701a81997-01-16 00:15:11 +0000286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287
Guido van Rossum18468821994-06-20 07:49:28 +0000288/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000289
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000290static int Tkinter_busywaitinterval = 20;
291
Guido van Rossum00d93061998-05-28 23:06:38 +0000292#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000293#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000294
Guido van Rossum00d93061998-05-28 23:06:38 +0000295/* Millisecond sleep() for Unix platforms. */
296
297static void
Fred Drake509d79a2000-07-08 04:04:38 +0000298Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000299{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000300 /* XXX Too bad if you don't have select(). */
301 struct timeval t;
302 t.tv_sec = milli/1000;
303 t.tv_usec = (milli%1000) * 1000;
304 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000305}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000306#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000307
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000308/* Wait up to 1s for the mainloop to come up. */
309
310static int
311WaitForMainloop(TkappObject* self)
312{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313 int i;
314 for (i = 0; i < 10; i++) {
315 if (self->dispatching)
316 return 1;
317 Py_BEGIN_ALLOW_THREADS
318 Sleep(100);
319 Py_END_ALLOW_THREADS
320 }
321 if (self->dispatching)
322 return 1;
323 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
324 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000325}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000326#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000328
Guido van Rossum18468821994-06-20 07:49:28 +0000329static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000330AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000331{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 if (PyBytes_Check(value))
333 return PyBytes_AsString(value);
334 else if (PyUnicode_Check(value)) {
335 PyObject *v = PyUnicode_AsUTF8String(value);
336 if (v == NULL)
337 return NULL;
338 if (PyList_Append(tmp, v) != 0) {
339 Py_DECREF(v);
340 return NULL;
341 }
342 Py_DECREF(v);
343 return PyBytes_AsString(v);
344 }
345 else {
346 PyObject *v = PyObject_Str(value);
347 if (v == NULL)
348 return NULL;
349 if (PyList_Append(tmp, v) != 0) {
350 Py_DECREF(v);
351 return NULL;
352 }
353 Py_DECREF(v);
354 return PyBytes_AsString(v);
355 }
Guido van Rossum18468821994-06-20 07:49:28 +0000356}
357
Barry Warsawfa701a81997-01-16 00:15:11 +0000358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000359
Guido van Rossum18468821994-06-20 07:49:28 +0000360#define ARGSZ 64
361
362static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000363Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000364{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000365 PyObject *tmp = NULL;
366 char *argvStore[ARGSZ];
367 char **argv = NULL;
368 int fvStore[ARGSZ];
369 int *fv = NULL;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300370 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 if (!(tmp = PyList_New(0)))
374 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 argv = argvStore;
377 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 if (args == NULL)
380 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 else if (!PyTuple_Check(args)) {
383 argc = 1;
384 fv[0] = 0;
385 if (!(argv[0] = AsString(args, tmp)))
386 goto finally;
387 }
388 else {
389 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 if (argc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300392 if (!CHECK_SIZE(argc, sizeof(char *))) {
393 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
394 goto finally;
395 }
396 argv = (char **)ckalloc((size_t)argc * sizeof(char *));
397 fv = (int *)ckalloc((size_t)argc * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 if (argv == NULL || fv == NULL) {
399 PyErr_NoMemory();
400 goto finally;
401 }
402 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 for (i = 0; i < argc; i++) {
405 PyObject *v = PyTuple_GetItem(args, i);
406 if (PyTuple_Check(v)) {
407 fv[i] = 1;
408 if (!(argv[i] = Merge(v)))
409 goto finally;
410 fvc++;
411 }
412 else if (v == Py_None) {
413 argc = i;
414 break;
415 }
416 else {
417 fv[i] = 0;
418 if (!(argv[i] = AsString(v, tmp)))
419 goto finally;
420 fvc++;
421 }
422 }
423 }
424 res = Tcl_Merge(argc, argv);
425 if (res == NULL)
426 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000427
Barry Warsawfa701a81997-01-16 00:15:11 +0000428 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 for (i = 0; i < fvc; i++)
430 if (fv[i]) {
431 ckfree(argv[i]);
432 }
433 if (argv != argvStore)
434 ckfree(FREECAST argv);
435 if (fv != fvStore)
436 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 Py_DECREF(tmp);
439 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000440}
441
Barry Warsawfa701a81997-01-16 00:15:11 +0000442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443
Guido van Rossum18468821994-06-20 07:49:28 +0000444static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000445Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000446{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000447 int argc;
448 char **argv;
449 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000451 if (list == NULL) {
452 Py_INCREF(Py_None);
453 return Py_None;
454 }
Guido van Rossum18468821994-06-20 07:49:28 +0000455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
457 /* Not a list.
458 * Could be a quoted string containing funnies, e.g. {"}.
459 * Return the string itself.
460 */
461 return PyUnicode_FromString(list);
462 }
Guido van Rossum18468821994-06-20 07:49:28 +0000463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 if (argc == 0)
465 v = PyUnicode_FromString("");
466 else if (argc == 1)
467 v = PyUnicode_FromString(argv[0]);
468 else if ((v = PyTuple_New(argc)) != NULL) {
469 int i;
470 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 for (i = 0; i < argc; i++) {
473 if ((w = Split(argv[i])) == NULL) {
474 Py_DECREF(v);
475 v = NULL;
476 break;
477 }
478 PyTuple_SetItem(v, i, w);
479 }
480 }
481 Tcl_Free(FREECAST argv);
482 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000483}
484
Martin v. Löwisffad6332002-11-26 09:28:05 +0000485/* In some cases, Tcl will still return strings that are supposed to be
486 lists. SplitObj walks through a nested tuple, finding string objects that
487 need to be split. */
488
Martin v. Löwis59683e82008-06-13 07:50:45 +0000489static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000490SplitObj(PyObject *arg)
491{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 if (PyTuple_Check(arg)) {
493 int i, size;
494 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 size = PyTuple_Size(arg);
497 result = NULL;
498 /* Recursively invoke SplitObj for all tuple items.
499 If this does not return a new object, no action is
500 needed. */
501 for(i = 0; i < size; i++) {
502 elem = PyTuple_GetItem(arg, i);
503 newelem = SplitObj(elem);
504 if (!newelem) {
505 Py_XDECREF(result);
506 return NULL;
507 }
508 if (!result) {
509 int k;
510 if (newelem == elem) {
511 Py_DECREF(newelem);
512 continue;
513 }
514 result = PyTuple_New(size);
515 if (!result)
516 return NULL;
517 for(k = 0; k < i; k++) {
518 elem = PyTuple_GetItem(arg, k);
519 Py_INCREF(elem);
520 PyTuple_SetItem(result, k, elem);
521 }
522 }
523 PyTuple_SetItem(result, i, newelem);
524 }
525 if (result)
526 return result;
527 /* Fall through, returning arg. */
528 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300529 else if (PyUnicode_Check(arg)) {
530 int argc;
531 char **argv;
532 char *list = PyUnicode_AsUTF8(arg);
533
534 if (list == NULL ||
535 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
536 Py_INCREF(arg);
537 return arg;
538 }
539 Tcl_Free(FREECAST argv);
540 if (argc > 1)
541 return Split(list);
542 /* Fall through, returning arg. */
543 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 else if (PyBytes_Check(arg)) {
545 int argc;
546 char **argv;
547 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
550 Py_INCREF(arg);
551 return arg;
552 }
553 Tcl_Free(FREECAST argv);
554 if (argc > 1)
555 return Split(PyBytes_AsString(arg));
556 /* Fall through, returning arg. */
557 }
558 Py_INCREF(arg);
559 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000560}
Barry Warsawfa701a81997-01-16 00:15:11 +0000561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562
Guido van Rossum18468821994-06-20 07:49:28 +0000563/**** Tkapp Object ****/
564
565#ifndef WITH_APPINIT
566int
Fred Drake509d79a2000-07-08 04:04:38 +0000567Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000568{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 if (Tcl_Init(interp) == TCL_ERROR) {
572 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
573 return TCL_ERROR;
574 }
Guilherme Polob681df42009-02-09 22:33:59 +0000575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 _tkinter_skip_tk_init = Tcl_GetVar(interp,
577 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
578 if (_tkinter_skip_tk_init != NULL &&
579 strcmp(_tkinter_skip_tk_init, "1") == 0) {
580 return TCL_OK;
581 }
Guilherme Polob681df42009-02-09 22:33:59 +0000582
583#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 if (tk_load_failed) {
585 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
586 return TCL_ERROR;
587 }
Guilherme Polob681df42009-02-09 22:33:59 +0000588#endif
589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000591#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000593#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
595 return TCL_ERROR;
596 }
Guilherme Polob681df42009-02-09 22:33:59 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000599}
600#endif /* !WITH_APPINIT */
601
Guido van Rossum18468821994-06-20 07:49:28 +0000602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603
Barry Warsawfa701a81997-01-16 00:15:11 +0000604
605/* Initialize the Tk application; see the `main' function in
606 * `tkMain.c'.
607 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000608
Thomas Wouters58d05102000-07-24 14:43:35 +0000609static void EnableEventHook(void); /* Forward */
610static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000611
Barry Warsawfa701a81997-01-16 00:15:11 +0000612static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000613Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000615{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 TkappObject *v;
617 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 v = PyObject_New(TkappObject, &Tkapp_Type);
620 if (v == NULL)
621 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 v->interp = Tcl_CreateInterp();
624 v->wantobjects = wantobjects;
625 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
626 TCL_GLOBAL_ONLY) != NULL;
627 v->thread_id = Tcl_GetCurrentThread();
628 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000629
630#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 if (v->threaded) {
632 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
633 Py_DECREF(v);
634 return 0;
635 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000636#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000637#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 if (v->threaded && tcl_lock) {
639 /* If Tcl is threaded, we don't need the lock. */
640 PyThread_free_lock(tcl_lock);
641 tcl_lock = NULL;
642 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000643#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 v->BooleanType = Tcl_GetObjType("boolean");
646 v->ByteArrayType = Tcl_GetObjType("bytearray");
647 v->DoubleType = Tcl_GetObjType("double");
648 v->IntType = Tcl_GetObjType("int");
649 v->ListType = Tcl_GetObjType("list");
650 v->ProcBodyType = Tcl_GetObjType("procbody");
651 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 /* Delete the 'exit' command, which can screw things up */
654 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 if (screenName != NULL)
657 Tcl_SetVar2(v->interp, "env", "DISPLAY",
658 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 if (interactive)
661 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
662 else
663 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 /* This is used to get the application class for Tk 4.1 and up */
666 argv0 = (char*)ckalloc(strlen(className) + 1);
667 if (!argv0) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
671 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200674 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
675 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
677 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000678
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 if (! wantTk) {
680 Tcl_SetVar(v->interp,
681 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
682 }
Guilherme Polob681df42009-02-09 22:33:59 +0000683#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 else if (tk_load_failed) {
685 Tcl_SetVar(v->interp,
686 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
687 }
Guilherme Polob681df42009-02-09 22:33:59 +0000688#endif
David Aschere2b4b322004-02-18 05:59:53 +0000689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 /* some initial arguments need to be in argv */
691 if (sync || use) {
692 char *args;
693 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 if (sync)
696 len += sizeof "-sync";
697 if (use)
698 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 args = (char*)ckalloc(len);
701 if (!args) {
702 PyErr_NoMemory();
703 Py_DECREF(v);
704 return NULL;
705 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 args[0] = '\0';
708 if (sync)
709 strcat(args, "-sync");
710 if (use) {
711 if (sync)
712 strcat(args, " ");
713 strcat(args, "-use ");
714 strcat(args, use);
715 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
718 ckfree(args);
719 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000721 if (Tcl_AppInit(v->interp) != TCL_OK) {
722 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000723#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 if (wantTk) {
725 const char *_tkinter_tk_failed;
726 _tkinter_tk_failed = Tcl_GetVar(v->interp,
727 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 if ( _tkinter_tk_failed != NULL &&
730 strcmp(_tkinter_tk_failed, "1") == 0) {
731 tk_load_failed = 1;
732 }
733 }
Guilherme Polob681df42009-02-09 22:33:59 +0000734#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 Py_DECREF((PyObject *)v);
736 return (TkappObject *)result;
737 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000739 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000742}
743
Barry Warsawfa701a81997-01-16 00:15:11 +0000744
Benjamin Peterson5879d412009-03-30 14:51:56 +0000745#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000746static void
747Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000749{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750 Py_BEGIN_ALLOW_THREADS;
751 Tcl_MutexLock(mutex);
752 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
753 Tcl_ThreadAlert(self->thread_id);
754 Tcl_ConditionWait(cond, mutex, NULL);
755 Tcl_MutexUnlock(mutex);
756 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000757}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000758#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000759
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760
Guido van Rossum18468821994-06-20 07:49:28 +0000761/** Tcl Eval **/
762
Martin v. Löwisffad6332002-11-26 09:28:05 +0000763typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 PyObject_HEAD
765 Tcl_Obj *value;
766 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000767} PyTclObject;
768
Neal Norwitz227b5332006-03-22 09:28:35 +0000769static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000771
772static PyObject *
773newPyTclObject(Tcl_Obj *arg)
774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 PyTclObject *self;
776 self = PyObject_New(PyTclObject, &PyTclObject_Type);
777 if (self == NULL)
778 return NULL;
779 Tcl_IncrRefCount(arg);
780 self->value = arg;
781 self->string = NULL;
782 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000783}
784
785static void
786PyTclObject_dealloc(PyTclObject *self)
787{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000788 Tcl_DecrRefCount(self->value);
789 Py_XDECREF(self->string);
790 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000791}
792
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000793static char*
794PyTclObject_TclString(PyObject *self)
795{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000797}
798
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000799/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000800PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000801"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000802
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000803static PyObject *
804PyTclObject_string(PyTclObject *self, void *ignored)
805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 char *s;
807 int len;
808 if (!self->string) {
809 s = Tcl_GetStringFromObj(self->value, &len);
810 self->string = PyUnicode_FromStringAndSize(s, len);
811 if (!self->string)
812 return NULL;
813 }
814 Py_INCREF(self->string);
815 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000816}
817
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000818static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000819PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000820{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000821 char *s;
822 int len;
823 if (self->string && PyUnicode_Check(self->string)) {
824 Py_INCREF(self->string);
825 return self->string;
826 }
827 /* XXX Could chache result if it is non-ASCII. */
828 s = Tcl_GetStringFromObj(self->value, &len);
829 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000830}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000831
Martin v. Löwisffad6332002-11-26 09:28:05 +0000832static PyObject *
833PyTclObject_repr(PyTclObject *self)
834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 return PyUnicode_FromFormat("<%s object at %p>",
836 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837}
838
Mark Dickinson211c6252009-02-01 10:28:51 +0000839#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
840
841static PyObject *
842PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000843{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000844 int result;
845 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 /* neither argument should be NULL, unless something's gone wrong */
848 if (self == NULL || other == NULL) {
849 PyErr_BadInternalCall();
850 return NULL;
851 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000852
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000853 /* both arguments should be instances of PyTclObject */
854 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
855 v = Py_NotImplemented;
856 goto finished;
857 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000858
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 if (self == other)
860 /* fast path when self and other are identical */
861 result = 0;
862 else
863 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
864 Tcl_GetString(((PyTclObject *)other)->value));
865 /* Convert return value to a Boolean */
866 switch (op) {
867 case Py_EQ:
868 v = TEST_COND(result == 0);
869 break;
870 case Py_NE:
871 v = TEST_COND(result != 0);
872 break;
873 case Py_LE:
874 v = TEST_COND(result <= 0);
875 break;
876 case Py_GE:
877 v = TEST_COND(result >= 0);
878 break;
879 case Py_LT:
880 v = TEST_COND(result < 0);
881 break;
882 case Py_GT:
883 v = TEST_COND(result > 0);
884 break;
885 default:
886 PyErr_BadArgument();
887 return NULL;
888 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000889 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000890 Py_INCREF(v);
891 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000892}
893
Martin v. Löwis39195712003-01-04 00:33:13 +0000894PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
895
Martin v. Löwisffad6332002-11-26 09:28:05 +0000896static PyObject*
897get_typename(PyTclObject* obj, void* ignored)
898{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000900}
901
Martin v. Löwis39195712003-01-04 00:33:13 +0000902
Martin v. Löwisffad6332002-11-26 09:28:05 +0000903static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000904 {"typename", (getter)get_typename, NULL, get_typename__doc__},
905 {"string", (getter)PyTclObject_string, NULL,
906 PyTclObject_string__doc__},
907 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000908};
909
Neal Norwitz227b5332006-03-22 09:28:35 +0000910static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000911 PyVarObject_HEAD_INIT(NULL, 0)
912 "_tkinter.Tcl_Obj", /*tp_name*/
913 sizeof(PyTclObject), /*tp_basicsize*/
914 0, /*tp_itemsize*/
915 /* methods */
916 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
917 0, /*tp_print*/
918 0, /*tp_getattr*/
919 0, /*tp_setattr*/
920 0, /*tp_reserved*/
921 (reprfunc)PyTclObject_repr, /*tp_repr*/
922 0, /*tp_as_number*/
923 0, /*tp_as_sequence*/
924 0, /*tp_as_mapping*/
925 0, /*tp_hash*/
926 0, /*tp_call*/
927 (reprfunc)PyTclObject_str, /*tp_str*/
928 PyObject_GenericGetAttr, /*tp_getattro*/
929 0, /*tp_setattro*/
930 0, /*tp_as_buffer*/
931 Py_TPFLAGS_DEFAULT, /*tp_flags*/
932 0, /*tp_doc*/
933 0, /*tp_traverse*/
934 0, /*tp_clear*/
935 PyTclObject_richcompare, /*tp_richcompare*/
936 0, /*tp_weaklistoffset*/
937 0, /*tp_iter*/
938 0, /*tp_iternext*/
939 0, /*tp_methods*/
940 0, /*tp_members*/
941 PyTclObject_getsetlist, /*tp_getset*/
942 0, /*tp_base*/
943 0, /*tp_dict*/
944 0, /*tp_descr_get*/
945 0, /*tp_descr_set*/
946 0, /*tp_dictoffset*/
947 0, /*tp_init*/
948 0, /*tp_alloc*/
949 0, /*tp_new*/
950 0, /*tp_free*/
951 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952};
953
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000954static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000955AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000956{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 Tcl_Obj *result;
958 long longVal;
959 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000961 if (PyBytes_Check(value))
962 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
963 PyBytes_GET_SIZE(value));
964 else if (PyBool_Check(value))
965 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
966 else if (PyLong_CheckExact(value) &&
967 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
968 !overflow)) {
969 /* If there is an overflow in the long conversion,
970 fall through to default object handling. */
971 return Tcl_NewLongObj(longVal);
972 }
973 else if (PyFloat_Check(value))
974 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
975 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300976 Tcl_Obj **argv;
977 Py_ssize_t size, i;
978
979 size = PyTuple_Size(value);
980 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
981 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
982 return NULL;
983 }
984 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 if(!argv)
986 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300987 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 argv[i] = AsObj(PyTuple_GetItem(value,i));
989 result = Tcl_NewListObj(PyTuple_Size(value), argv);
990 ckfree(FREECAST argv);
991 return result;
992 }
993 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200994 void *inbuf;
995 Py_ssize_t size;
996 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 Tcl_UniChar *outbuf = NULL;
998 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200999 size_t allocsize;
1000
1001 if (PyUnicode_READY(value) == -1)
1002 return NULL;
1003
1004 inbuf = PyUnicode_DATA(value);
1005 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001006 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1007 PyErr_SetString(PyExc_OverflowError, "string is too long");
1008 return NULL;
1009 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001010 kind = PyUnicode_KIND(value);
1011 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
1012 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 /* Else overflow occurred, and we take the next exit */
1014 if (!outbuf) {
1015 PyErr_NoMemory();
1016 return NULL;
1017 }
1018 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001019 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1020 /* We cannot test for sizeof(Tcl_UniChar) directly,
1021 so we test for UTF-8 size instead. */
1022#if TCL_UTF_MAX == 3
1023 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001025 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001026 "character U+%x is above the range "
1027 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001028 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 ckfree(FREECAST outbuf);
1030 return NULL;
1031 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001032#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001033 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 }
1035 result = Tcl_NewUnicodeObj(outbuf, size);
1036 ckfree(FREECAST outbuf);
1037 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001038 }
1039 else if(PyTclObject_Check(value)) {
1040 Tcl_Obj *v = ((PyTclObject*)value)->value;
1041 Tcl_IncrRefCount(v);
1042 return v;
1043 }
1044 else {
1045 PyObject *v = PyObject_Str(value);
1046 if (!v)
1047 return 0;
1048 result = AsObj(v);
1049 Py_DECREF(v);
1050 return result;
1051 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001052}
1053
Martin v. Löwisffad6332002-11-26 09:28:05 +00001054static PyObject*
1055FromObj(PyObject* tkapp, Tcl_Obj *value)
1056{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 PyObject *result = NULL;
1058 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001059
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 if (value->typePtr == NULL) {
1061 return PyUnicode_FromStringAndSize(value->bytes,
1062 value->length);
1063 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001065 if (value->typePtr == app->BooleanType) {
1066 result = value->internalRep.longValue ? Py_True : Py_False;
1067 Py_INCREF(result);
1068 return result;
1069 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001071 if (value->typePtr == app->ByteArrayType) {
1072 int size;
1073 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1074 return PyBytes_FromStringAndSize(data, size);
1075 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 if (value->typePtr == app->DoubleType) {
1078 return PyFloat_FromDouble(value->internalRep.doubleValue);
1079 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001081 if (value->typePtr == app->IntType) {
1082 return PyLong_FromLong(value->internalRep.longValue);
1083 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001084
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001085 if (value->typePtr == app->ListType) {
1086 int size;
1087 int i, status;
1088 PyObject *elem;
1089 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1092 if (status == TCL_ERROR)
1093 return Tkinter_Error(tkapp);
1094 result = PyTuple_New(size);
1095 if (!result)
1096 return NULL;
1097 for (i = 0; i < size; i++) {
1098 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1099 value, i, &tcl_elem);
1100 if (status == TCL_ERROR) {
1101 Py_DECREF(result);
1102 return Tkinter_Error(tkapp);
1103 }
1104 elem = FromObj(tkapp, tcl_elem);
1105 if (!elem) {
1106 Py_DECREF(result);
1107 return NULL;
1108 }
1109 PyTuple_SetItem(result, i, elem);
1110 }
1111 return result;
1112 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001114 if (value->typePtr == app->ProcBodyType) {
1115 /* fall through: return tcl object. */
1116 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001118 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001119#if TCL_UTF_MAX==3
1120 return PyUnicode_FromKindAndData(
1121 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1122 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001123#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001124 return PyUnicode_FromKindAndData(
1125 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1126 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001127#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001129
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001130 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001131}
1132
Benjamin Peterson5879d412009-03-30 14:51:56 +00001133#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001134/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001135TCL_DECLARE_MUTEX(call_mutex)
1136
1137typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 Tcl_Event ev; /* Must be first */
1139 TkappObject *self;
1140 PyObject *args;
1141 int flags;
1142 PyObject **res;
1143 PyObject **exc_type, **exc_value, **exc_tb;
1144 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001146#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001147
1148void
1149Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001150{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 int i;
1152 for (i = 0; i < objc; i++)
1153 Tcl_DecrRefCount(objv[i]);
1154 if (objv != objStore)
1155 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156}
Guido van Rossum18468821994-06-20 07:49:28 +00001157
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001158/* Convert Python objects to Tcl objects. This must happen in the
1159 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001160
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001161static Tcl_Obj**
1162Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001164 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001165 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001166 if (args == NULL)
1167 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001169 else if (!PyTuple_Check(args)) {
1170 objv[0] = AsObj(args);
1171 if (objv[0] == 0)
1172 goto finally;
1173 objc = 1;
1174 Tcl_IncrRefCount(objv[0]);
1175 }
1176 else {
1177 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001180 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1181 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1182 return NULL;
1183 }
1184 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001185 if (objv == NULL) {
1186 PyErr_NoMemory();
1187 objc = 0;
1188 goto finally;
1189 }
1190 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001192 for (i = 0; i < objc; i++) {
1193 PyObject *v = PyTuple_GetItem(args, i);
1194 if (v == Py_None) {
1195 objc = i;
1196 break;
1197 }
1198 objv[i] = AsObj(v);
1199 if (!objv[i]) {
1200 /* Reset objc, so it attempts to clear
1201 objects only up to i. */
1202 objc = i;
1203 goto finally;
1204 }
1205 Tcl_IncrRefCount(objv[i]);
1206 }
1207 }
1208 *pobjc = objc;
1209 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001210finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 Tkapp_CallDeallocArgs(objv, objStore, objc);
1212 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213}
Guido van Rossum212643f1998-04-29 16:22:14 +00001214
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001215/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001216
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001217static PyObject*
1218Tkapp_CallResult(TkappObject *self)
1219{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001220 PyObject *res = NULL;
1221 if(self->wantobjects) {
1222 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1223 /* Not sure whether the IncrRef is necessary, but something
1224 may overwrite the interpreter result while we are
1225 converting it. */
1226 Tcl_IncrRefCount(value);
1227 res = FromObj((PyObject*)self, value);
1228 Tcl_DecrRefCount(value);
1229 } else {
1230 const char *s = Tcl_GetStringResult(self->interp);
1231 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1234 }
1235 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236}
Guido van Rossum632de272000-03-29 00:19:50 +00001237
Benjamin Peterson5879d412009-03-30 14:51:56 +00001238#ifdef WITH_THREAD
1239
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001240/* Tkapp_CallProc is the event procedure that is executed in the context of
1241 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1242 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001243
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244static int
1245Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1246{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 Tcl_Obj *objStore[ARGSZ];
1248 Tcl_Obj **objv;
1249 int objc;
1250 int i;
1251 ENTER_PYTHON
1252 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1253 if (!objv) {
1254 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1255 *(e->res) = NULL;
1256 }
1257 LEAVE_PYTHON
1258 if (!objv)
1259 goto done;
1260 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1261 ENTER_PYTHON
1262 if (i == TCL_ERROR) {
1263 *(e->res) = NULL;
1264 *(e->exc_type) = NULL;
1265 *(e->exc_tb) = NULL;
1266 *(e->exc_value) = PyObject_CallFunction(
1267 Tkinter_TclError, "s",
1268 Tcl_GetStringResult(e->self->interp));
1269 }
1270 else {
1271 *(e->res) = Tkapp_CallResult(e->self);
1272 }
1273 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001276done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 /* Wake up calling thread. */
1278 Tcl_MutexLock(&call_mutex);
1279 Tcl_ConditionNotify(e->done);
1280 Tcl_MutexUnlock(&call_mutex);
1281 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001282}
1283
Benjamin Peterson5879d412009-03-30 14:51:56 +00001284#endif
1285
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001286/* This is the main entry point for calling a Tcl command.
1287 It supports three cases, with regard to threading:
1288 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1289 the context of the calling thread.
1290 2. Tcl is threaded, caller of the command is in the interpreter thread:
1291 Execute the command in the calling thread. Since the Tcl lock will
1292 not be used, we can merge that with case 1.
1293 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1294 the interpreter thread. Allocation of Tcl objects needs to occur in the
1295 interpreter thread, so we ship the PyObject* args to the target thread,
1296 and perform processing there. */
1297
1298static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001299Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001300{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001301 Tcl_Obj *objStore[ARGSZ];
1302 Tcl_Obj **objv = NULL;
1303 int objc, i;
1304 PyObject *res = NULL;
1305 TkappObject *self = (TkappObject*)selfptr;
1306 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 /* If args is a single tuple, replace with contents of tuple */
1309 if (1 == PyTuple_Size(args)){
1310 PyObject* item = PyTuple_GetItem(args, 0);
1311 if (PyTuple_Check(item))
1312 args = item;
1313 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001314#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1316 /* We cannot call the command directly. Instead, we must
1317 marshal the parameters to the interpreter thread. */
1318 Tkapp_CallEvent *ev;
1319 Tcl_Condition cond = NULL;
1320 PyObject *exc_type, *exc_value, *exc_tb;
1321 if (!WaitForMainloop(self))
1322 return NULL;
1323 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1324 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1325 ev->self = self;
1326 ev->args = args;
1327 ev->res = &res;
1328 ev->exc_type = &exc_type;
1329 ev->exc_value = &exc_value;
1330 ev->exc_tb = &exc_tb;
1331 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 if (res == NULL) {
1336 if (exc_type)
1337 PyErr_Restore(exc_type, exc_value, exc_tb);
1338 else
1339 PyErr_SetObject(Tkinter_TclError, exc_value);
1340 }
1341 Tcl_ConditionFinalize(&cond);
1342 }
1343 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001344#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001345 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 objv = Tkapp_CallArgs(args, objStore, &objc);
1348 if (!objv)
1349 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 if (i == TCL_ERROR)
1358 Tkinter_Error(selfptr);
1359 else
1360 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 Tkapp_CallDeallocArgs(objv, objStore, objc);
1365 }
1366 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001367}
1368
1369
1370static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001371Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001373 /* Could do the same here as for Tkapp_Call(), but this is not used
1374 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1375 way for the user to do what all its Global* variants do (save and
1376 reset the scope pointer, call the local version, restore the saved
1377 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 char *cmd;
1380 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001381
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001382 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1383 "globalcall is deprecated and will be removed in 3.4",
1384 1) < 0)
1385 return 0;
1386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001387 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001389 cmd = Merge(args);
1390 if (cmd) {
1391 int err;
1392 ENTER_TCL
1393 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1394 ENTER_OVERLAP
1395 if (err == TCL_ERROR)
1396 res = Tkinter_Error(self);
1397 else
1398 res = PyUnicode_FromString(Tkapp_Result(self));
1399 LEAVE_OVERLAP_TCL
1400 ckfree(cmd);
1401 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001404}
1405
1406static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001407Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001408{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001409 char *script;
1410 PyObject *res = NULL;
1411 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001413 if (!PyArg_ParseTuple(args, "s:eval", &script))
1414 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001416 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001418 ENTER_TCL
1419 err = Tcl_Eval(Tkapp_Interp(self), script);
1420 ENTER_OVERLAP
1421 if (err == TCL_ERROR)
1422 res = Tkinter_Error(self);
1423 else
1424 res = PyUnicode_FromString(Tkapp_Result(self));
1425 LEAVE_OVERLAP_TCL
1426 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001427}
1428
1429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001430Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 char *script;
1433 PyObject *res = NULL;
1434 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001435
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001436 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1437 "globaleval is deprecated and will be removed in 3.4",
1438 1) < 0)
1439 return 0;
1440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1442 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001443
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001444 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001446 ENTER_TCL
1447 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1448 ENTER_OVERLAP
1449 if (err == TCL_ERROR)
1450 res = Tkinter_Error(self);
1451 else
1452 res = PyUnicode_FromString(Tkapp_Result(self));
1453 LEAVE_OVERLAP_TCL
1454 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001455}
1456
1457static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001458Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001459{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 char *fileName;
1461 PyObject *res = NULL;
1462 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1465 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001469 ENTER_TCL
1470 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1471 ENTER_OVERLAP
1472 if (err == TCL_ERROR)
1473 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 else
1476 res = PyUnicode_FromString(Tkapp_Result(self));
1477 LEAVE_OVERLAP_TCL
1478 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001479}
1480
1481static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001482Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 char *script;
1485 PyObject *res = NULL;
1486 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 if (!PyArg_ParseTuple(args, "s", &script))
1489 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001493 ENTER_TCL
1494 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1495 ENTER_OVERLAP
1496 if (err == TCL_ERROR)
1497 res = Tkinter_Error(self);
1498 else
1499 res = PyUnicode_FromString(Tkapp_Result(self));
1500 LEAVE_OVERLAP_TCL
1501 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001502}
1503
1504static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001505Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001506{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001507 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001509 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1510 return NULL;
1511 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 ENTER_TCL
1514 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1515 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 Py_INCREF(Py_None);
1518 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001519}
1520
Barry Warsawfa701a81997-01-16 00:15:11 +00001521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522
Guido van Rossum18468821994-06-20 07:49:28 +00001523/** Tcl Variable **/
1524
Benjamin Peterson5879d412009-03-30 14:51:56 +00001525typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1526
1527#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528TCL_DECLARE_MUTEX(var_mutex)
1529
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001531 Tcl_Event ev; /* must be first */
1532 PyObject *self;
1533 PyObject *args;
1534 int flags;
1535 EventFunc func;
1536 PyObject **res;
1537 PyObject **exc_type;
1538 PyObject **exc_val;
1539 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001541#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001543static int
1544varname_converter(PyObject *in, void *_out)
1545{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 char **out = (char**)_out;
1547 if (PyBytes_Check(in)) {
1548 *out = PyBytes_AsString(in);
1549 return 1;
1550 }
1551 if (PyUnicode_Check(in)) {
1552 *out = _PyUnicode_AsString(in);
1553 return 1;
1554 }
1555 if (PyTclObject_Check(in)) {
1556 *out = PyTclObject_TclString(in);
1557 return 1;
1558 }
1559 /* XXX: Should give diagnostics. */
1560 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001561}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001562
Benjamin Peterson5879d412009-03-30 14:51:56 +00001563#ifdef WITH_THREAD
1564
Martin v. Löwis59683e82008-06-13 07:50:45 +00001565static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001566var_perform(VarEvent *ev)
1567{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1569 if (!*(ev->res)) {
1570 PyObject *exc, *val, *tb;
1571 PyErr_Fetch(&exc, &val, &tb);
1572 PyErr_NormalizeException(&exc, &val, &tb);
1573 *(ev->exc_type) = exc;
1574 *(ev->exc_val) = val;
1575 Py_DECREF(tb);
1576 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001577
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001578}
1579
1580static int
1581var_proc(VarEvent* ev, int flags)
1582{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 ENTER_PYTHON
1584 var_perform(ev);
1585 Tcl_MutexLock(&var_mutex);
1586 Tcl_ConditionNotify(ev->cond);
1587 Tcl_MutexUnlock(&var_mutex);
1588 LEAVE_PYTHON
1589 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001590}
1591
Benjamin Peterson5879d412009-03-30 14:51:56 +00001592#endif
1593
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001594static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001595var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001596{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001597#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001598 TkappObject *self = (TkappObject*)selfptr;
1599 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1600 TkappObject *self = (TkappObject*)selfptr;
1601 VarEvent *ev;
1602 PyObject *res, *exc_type, *exc_val;
1603 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 /* The current thread is not the interpreter thread. Marshal
1606 the call to the interpreter thread, then wait for
1607 completion. */
1608 if (!WaitForMainloop(self))
1609 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001611 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001613 ev->self = selfptr;
1614 ev->args = args;
1615 ev->flags = flags;
1616 ev->func = func;
1617 ev->res = &res;
1618 ev->exc_type = &exc_type;
1619 ev->exc_val = &exc_val;
1620 ev->cond = &cond;
1621 ev->ev.proc = (Tcl_EventProc*)var_proc;
1622 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1623 Tcl_ConditionFinalize(&cond);
1624 if (!res) {
1625 PyErr_SetObject(exc_type, exc_val);
1626 Py_DECREF(exc_type);
1627 Py_DECREF(exc_val);
1628 return NULL;
1629 }
1630 return res;
1631 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001632#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 /* Tcl is not threaded, or this is the interpreter thread. */
1634 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001635}
1636
Guido van Rossum18468821994-06-20 07:49:28 +00001637static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001638SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001639{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001640 char *name1, *name2;
1641 PyObject *newValue;
1642 PyObject *res = NULL;
1643 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 if (PyArg_ParseTuple(args, "O&O:setvar",
1646 varname_converter, &name1, &newValue)) {
1647 /* XXX Acquire tcl lock??? */
1648 newval = AsObj(newValue);
1649 if (newval == NULL)
1650 return NULL;
1651 ENTER_TCL
1652 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1653 newval, flags);
1654 ENTER_OVERLAP
1655 if (!ok)
1656 Tkinter_Error(self);
1657 else {
1658 res = Py_None;
1659 Py_INCREF(res);
1660 }
1661 LEAVE_OVERLAP_TCL
1662 }
1663 else {
1664 PyErr_Clear();
1665 if (PyArg_ParseTuple(args, "ssO:setvar",
1666 &name1, &name2, &newValue)) {
1667 /* XXX must hold tcl lock already??? */
1668 newval = AsObj(newValue);
1669 ENTER_TCL
1670 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1671 ENTER_OVERLAP
1672 if (!ok)
1673 Tkinter_Error(self);
1674 else {
1675 res = Py_None;
1676 Py_INCREF(res);
1677 }
1678 LEAVE_OVERLAP_TCL
1679 }
1680 else {
1681 return NULL;
1682 }
1683 }
1684 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001690 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001691}
1692
1693static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001694Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001695{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001697}
1698
Barry Warsawfa701a81997-01-16 00:15:11 +00001699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001700
Guido van Rossum18468821994-06-20 07:49:28 +00001701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001704 char *name1, *name2=NULL;
1705 PyObject *res = NULL;
1706 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1709 varname_converter, &name1, &name2))
1710 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 ENTER_TCL
1713 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1714 ENTER_OVERLAP
1715 if (tres == NULL) {
1716 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1717 } else {
1718 if (((TkappObject*)self)->wantobjects) {
1719 res = FromObj(self, tres);
1720 }
1721 else {
1722 res = PyUnicode_FromString(Tcl_GetString(tres));
1723 }
1724 }
1725 LEAVE_OVERLAP_TCL
1726 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001727}
1728
1729static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001730Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001731{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001732 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
1735static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001736Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001739}
1740
Barry Warsawfa701a81997-01-16 00:15:11 +00001741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742
Guido van Rossum18468821994-06-20 07:49:28 +00001743static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001744UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 char *name1, *name2=NULL;
1747 int code;
1748 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1751 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 ENTER_TCL
1754 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1755 ENTER_OVERLAP
1756 if (code == TCL_ERROR)
1757 res = Tkinter_Error(self);
1758 else {
1759 Py_INCREF(Py_None);
1760 res = Py_None;
1761 }
1762 LEAVE_OVERLAP_TCL
1763 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
1766static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001767Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001768{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001770}
1771
1772static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001773Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001776}
1777
Barry Warsawfa701a81997-01-16 00:15:11 +00001778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779
Guido van Rossum18468821994-06-20 07:49:28 +00001780/** Tcl to Python **/
1781
1782static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001783Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001784{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001785 char *s;
1786 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 if (PyTuple_Size(args) == 1) {
1789 PyObject* o = PyTuple_GetItem(args, 0);
1790 if (PyLong_Check(o)) {
1791 Py_INCREF(o);
1792 return o;
1793 }
1794 }
1795 if (!PyArg_ParseTuple(args, "s:getint", &s))
1796 return NULL;
1797 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1798 return Tkinter_Error(self);
1799 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001800}
1801
1802static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001803Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001804{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001805 char *s;
1806 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 if (PyTuple_Size(args) == 1) {
1809 PyObject *o = PyTuple_GetItem(args, 0);
1810 if (PyFloat_Check(o)) {
1811 Py_INCREF(o);
1812 return o;
1813 }
1814 }
1815 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1816 return NULL;
1817 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1818 return Tkinter_Error(self);
1819 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001820}
1821
1822static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001823Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 char *s;
1826 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828 if (PyTuple_Size(args) == 1) {
1829 PyObject *o = PyTuple_GetItem(args, 0);
1830 if (PyLong_Check(o)) {
1831 Py_INCREF(o);
1832 return o;
1833 }
1834 }
1835 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1836 return NULL;
1837 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1838 return Tkinter_Error(self);
1839 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001840}
1841
1842static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001843Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001844{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001845 char *s;
1846 PyObject *res = NULL;
1847 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1850 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001853
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001854 ENTER_TCL
1855 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1856 ENTER_OVERLAP
1857 if (retval == TCL_ERROR)
1858 res = Tkinter_Error(self);
1859 else
1860 res = Py_BuildValue("s", Tkapp_Result(self));
1861 LEAVE_OVERLAP_TCL
1862 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 char *s;
1869 PyObject *res = NULL;
1870 int retval;
1871 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1874 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878 ENTER_TCL
1879 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1880 ENTER_OVERLAP
1881 if (retval == TCL_ERROR)
1882 res = Tkinter_Error(self);
1883 else
1884 res = Py_BuildValue("l", v);
1885 LEAVE_OVERLAP_TCL
1886 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001887}
1888
1889static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001890Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001891{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001892 char *s;
1893 PyObject *res = NULL;
1894 double v;
1895 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001896
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1898 return NULL;
1899 CHECK_TCL_APPARTMENT;
1900 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1901 ENTER_TCL
1902 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1903 ENTER_OVERLAP
1904 PyFPE_END_PROTECT(retval)
1905 if (retval == TCL_ERROR)
1906 res = Tkinter_Error(self);
1907 else
1908 res = Py_BuildValue("d", v);
1909 LEAVE_OVERLAP_TCL
1910 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001911}
1912
1913static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001914Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001915{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001916 char *s;
1917 PyObject *res = NULL;
1918 int retval;
1919 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001920
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001921 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1922 return NULL;
1923 CHECK_TCL_APPARTMENT;
1924 ENTER_TCL
1925 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1926 ENTER_OVERLAP
1927 if (retval == TCL_ERROR)
1928 res = Tkinter_Error(self);
1929 else
1930 res = Py_BuildValue("i", v);
1931 LEAVE_OVERLAP_TCL
1932 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001933}
1934
Barry Warsawfa701a81997-01-16 00:15:11 +00001935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936
Guido van Rossum18468821994-06-20 07:49:28 +00001937static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001938Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001939{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 char *list;
1941 int argc;
1942 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001943 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001945
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001946 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1947 return NULL;
1948 if (PyTclObject_Check(arg)) {
1949 int objc;
1950 Tcl_Obj **objv;
1951 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1952 ((PyTclObject*)arg)->value,
1953 &objc, &objv) == TCL_ERROR) {
1954 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001955 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001956 if (!(v = PyTuple_New(objc)))
1957 return NULL;
1958 for (i = 0; i < objc; i++) {
1959 PyObject *s = FromObj(self, objv[i]);
1960 if (!s || PyTuple_SetItem(v, i, s)) {
1961 Py_DECREF(v);
1962 return NULL;
1963 }
1964 }
1965 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001966 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001967 if (PyTuple_Check(arg)) {
1968 Py_INCREF(arg);
1969 return arg;
1970 }
1971
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1973 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 if (Tcl_SplitList(Tkapp_Interp(self), list,
1976 &argc, &argv) == TCL_ERROR) {
1977 PyMem_Free(list);
1978 return Tkinter_Error(self);
1979 }
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 if (!(v = PyTuple_New(argc)))
1982 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001983
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001984 for (i = 0; i < argc; i++) {
1985 PyObject *s = PyUnicode_FromString(argv[i]);
1986 if (!s || PyTuple_SetItem(v, i, s)) {
1987 Py_DECREF(v);
1988 v = NULL;
1989 goto finally;
1990 }
1991 }
Guido van Rossum18468821994-06-20 07:49:28 +00001992
Barry Warsawfa701a81997-01-16 00:15:11 +00001993 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 ckfree(FREECAST argv);
1995 PyMem_Free(list);
1996 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001997}
1998
1999static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002000Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002001{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002002 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002004
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002005 if (!PyArg_ParseTuple(args, "O:split", &arg))
2006 return NULL;
2007 if (PyTclObject_Check(arg)) {
2008 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2009 int objc;
2010 Tcl_Obj **objv;
2011 int i;
2012 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2013 &objc, &objv) == TCL_ERROR) {
2014 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002016 if (objc == 0)
2017 return PyUnicode_FromString("");
2018 if (objc == 1)
2019 return FromObj(self, objv[0]);
2020 if (!(v = PyTuple_New(objc)))
2021 return NULL;
2022 for (i = 0; i < objc; i++) {
2023 PyObject *s = FromObj(self, objv[i]);
2024 if (!s || PyTuple_SetItem(v, i, s)) {
2025 Py_DECREF(v);
2026 return NULL;
2027 }
2028 }
2029 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002030 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002031 if (PyTuple_Check(arg))
2032 return SplitObj(arg);
2033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002034 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2035 return NULL;
2036 v = Split(list);
2037 PyMem_Free(list);
2038 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002039}
2040
2041static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002042Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002043{
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002044 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002045 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002046
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002047 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2048 "merge is deprecated and will be removed in 3.4",
2049 1) < 0)
2050 return 0;
2051
2052 s = Merge(args);
2053
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002054 if (s) {
2055 res = PyUnicode_FromString(s);
2056 ckfree(s);
2057 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002060}
2061
Barry Warsawfa701a81997-01-16 00:15:11 +00002062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063
Guido van Rossum18468821994-06-20 07:49:28 +00002064/** Tcl Command **/
2065
Guido van Rossum00d93061998-05-28 23:06:38 +00002066/* Client data struct */
2067typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002068 PyObject *self;
2069 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002070} PythonCmd_ClientData;
2071
2072static int
Fred Drake509d79a2000-07-08 04:04:38 +00002073PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002075 errorInCmd = 1;
2076 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2077 LEAVE_PYTHON
2078 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002079}
2080
Guido van Rossum18468821994-06-20 07:49:28 +00002081/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002082 * function or method.
2083 */
Guido van Rossum18468821994-06-20 07:49:28 +00002084static int
Fred Drake509d79a2000-07-08 04:04:38 +00002085PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002086{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002088 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 int i, rv;
2090 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002092 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002094 /* TBD: no error checking here since we know, via the
2095 * Tkapp_CreateCommand() that the client data is a two-tuple
2096 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002097 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002099 /* Create argument list (argv1, ..., argvN) */
2100 if (!(arg = PyTuple_New(argc - 1)))
2101 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002103 for (i = 0; i < (argc - 1); i++) {
2104 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002105 if (!s) {
2106 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2107 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2108 !strcmp(argv[i + 1], "\xC0\x80")) {
2109 PyErr_Clear();
2110 /* Convert to "strict" utf-8 null */
2111 s = PyUnicode_FromString("\0");
2112 } else {
2113 Py_DECREF(arg);
2114 return PythonCmd_Error(interp);
2115 }
2116 }
2117 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002118 Py_DECREF(arg);
2119 return PythonCmd_Error(interp);
2120 }
2121 }
2122 res = PyEval_CallObject(func, arg);
2123 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002125 if (res == NULL)
2126 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002127
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002128 obj_res = AsObj(res);
2129 if (obj_res == NULL) {
2130 Py_DECREF(res);
2131 return PythonCmd_Error(interp);
2132 }
2133 else {
2134 Tcl_SetObjResult(interp, obj_res);
2135 rv = TCL_OK;
2136 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002143}
2144
2145static void
Fred Drake509d79a2000-07-08 04:04:38 +00002146PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002147{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002148 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150 ENTER_PYTHON
2151 Py_XDECREF(data->self);
2152 Py_XDECREF(data->func);
2153 PyMem_DEL(data);
2154 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002155}
2156
Barry Warsawfa701a81997-01-16 00:15:11 +00002157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002159
Benjamin Peterson5879d412009-03-30 14:51:56 +00002160#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002161TCL_DECLARE_MUTEX(command_mutex)
2162
2163typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164 Tcl_Event ev;
2165 Tcl_Interp* interp;
2166 char *name;
2167 int create;
2168 int *status;
2169 ClientData *data;
2170 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002171} CommandEvent;
2172
2173static int
2174Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002175{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 if (ev->create)
2177 *ev->status = Tcl_CreateCommand(
2178 ev->interp, ev->name, PythonCmd,
2179 ev->data, PythonCmdDelete) == NULL;
2180 else
2181 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2182 Tcl_MutexLock(&command_mutex);
2183 Tcl_ConditionNotify(ev->done);
2184 Tcl_MutexUnlock(&command_mutex);
2185 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002186}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002187#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002188
2189static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002190Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002191{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 TkappObject *self = (TkappObject*)selfptr;
2193 PythonCmd_ClientData *data;
2194 char *cmdName;
2195 PyObject *func;
2196 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2199 return NULL;
2200 if (!PyCallable_Check(func)) {
2201 PyErr_SetString(PyExc_TypeError, "command not callable");
2202 return NULL;
2203 }
Guido van Rossum18468821994-06-20 07:49:28 +00002204
Martin v. Löwisa9656492003-03-30 08:44:58 +00002205#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2207 !WaitForMainloop(self))
2208 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002209#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002211 data = PyMem_NEW(PythonCmd_ClientData, 1);
2212 if (!data)
2213 return PyErr_NoMemory();
2214 Py_INCREF(self);
2215 Py_INCREF(func);
2216 data->self = selfptr;
2217 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002218#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002219 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2220 Tcl_Condition cond = NULL;
2221 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2222 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2223 ev->interp = self->interp;
2224 ev->create = 1;
2225 ev->name = cmdName;
2226 ev->data = (ClientData)data;
2227 ev->status = &err;
2228 ev->done = &cond;
2229 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2230 Tcl_ConditionFinalize(&cond);
2231 }
2232 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002233#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 {
2235 ENTER_TCL
2236 err = Tcl_CreateCommand(
2237 Tkapp_Interp(self), cmdName, PythonCmd,
2238 (ClientData)data, PythonCmdDelete) == NULL;
2239 LEAVE_TCL
2240 }
2241 if (err) {
2242 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2243 PyMem_DEL(data);
2244 return NULL;
2245 }
Guido van Rossum18468821994-06-20 07:49:28 +00002246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 Py_INCREF(Py_None);
2248 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002249}
2250
Barry Warsawfa701a81997-01-16 00:15:11 +00002251
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252
Guido van Rossum18468821994-06-20 07:49:28 +00002253static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002254Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002256 TkappObject *self = (TkappObject*)selfptr;
2257 char *cmdName;
2258 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2261 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002262
2263#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2265 Tcl_Condition cond = NULL;
2266 CommandEvent *ev;
2267 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2268 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2269 ev->interp = self->interp;
2270 ev->create = 0;
2271 ev->name = cmdName;
2272 ev->status = &err;
2273 ev->done = &cond;
2274 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2275 &command_mutex);
2276 Tcl_ConditionFinalize(&cond);
2277 }
2278 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002279#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 {
2281 ENTER_TCL
2282 err = Tcl_DeleteCommand(self->interp, cmdName);
2283 LEAVE_TCL
2284 }
2285 if (err == -1) {
2286 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2287 return NULL;
2288 }
2289 Py_INCREF(Py_None);
2290 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002291}
2292
Barry Warsawfa701a81997-01-16 00:15:11 +00002293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294
Guido van Rossum00d93061998-05-28 23:06:38 +00002295#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002296/** File Handler **/
2297
Guido van Rossum00d93061998-05-28 23:06:38 +00002298typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 PyObject *func;
2300 PyObject *file;
2301 int id;
2302 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002303} FileHandler_ClientData;
2304
2305static FileHandler_ClientData *HeadFHCD;
2306
2307static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002308NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 FileHandler_ClientData *p;
2311 p = PyMem_NEW(FileHandler_ClientData, 1);
2312 if (p != NULL) {
2313 Py_XINCREF(func);
2314 Py_XINCREF(file);
2315 p->func = func;
2316 p->file = file;
2317 p->id = id;
2318 p->next = HeadFHCD;
2319 HeadFHCD = p;
2320 }
2321 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002322}
2323
2324static void
Fred Drake509d79a2000-07-08 04:04:38 +00002325DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002326{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002329 pp = &HeadFHCD;
2330 while ((p = *pp) != NULL) {
2331 if (p->id == id) {
2332 *pp = p->next;
2333 Py_XDECREF(p->func);
2334 Py_XDECREF(p->file);
2335 PyMem_DEL(p);
2336 }
2337 else
2338 pp = &p->next;
2339 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002340}
2341
Guido van Rossuma597dde1995-01-10 20:56:29 +00002342static void
Fred Drake509d79a2000-07-08 04:04:38 +00002343FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002344{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2346 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 ENTER_PYTHON
2349 func = data->func;
2350 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 arg = Py_BuildValue("(Oi)", file, (long) mask);
2353 res = PyEval_CallObject(func, arg);
2354 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002356 if (res == NULL) {
2357 errorInCmd = 1;
2358 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2359 }
2360 Py_XDECREF(res);
2361 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002362}
2363
Guido van Rossum18468821994-06-20 07:49:28 +00002364static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002365Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2366 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002367{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002368 FileHandler_ClientData *data;
2369 PyObject *file, *func;
2370 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2373 &file, &mask, &func))
2374 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002376 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 tfile = PyObject_AsFileDescriptor(file);
2379 if (tfile < 0)
2380 return NULL;
2381 if (!PyCallable_Check(func)) {
2382 PyErr_SetString(PyExc_TypeError, "bad argument list");
2383 return NULL;
2384 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 data = NewFHCD(func, file, tfile);
2387 if (data == NULL)
2388 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 /* Ought to check for null Tcl_File object... */
2391 ENTER_TCL
2392 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2393 LEAVE_TCL
2394 Py_INCREF(Py_None);
2395 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002396}
2397
2398static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002399Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002400{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 PyObject *file;
2402 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2405 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 tfile = PyObject_AsFileDescriptor(file);
2410 if (tfile < 0)
2411 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 /* Ought to check for null Tcl_File object... */
2416 ENTER_TCL
2417 Tcl_DeleteFileHandler(tfile);
2418 LEAVE_TCL
2419 Py_INCREF(Py_None);
2420 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002421}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002422#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425/**** Tktt Object (timer token) ****/
2426
Jeremy Hylton938ace62002-07-17 16:30:39 +00002427static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002428
Guido van Rossum00d93061998-05-28 23:06:38 +00002429typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 PyObject_HEAD
2431 Tcl_TimerToken token;
2432 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002433} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434
2435static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002436Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002437{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 TkttObject *v = (TkttObject *)self;
2439 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002441 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2442 return NULL;
2443 if (v->token != NULL) {
2444 Tcl_DeleteTimerHandler(v->token);
2445 v->token = NULL;
2446 }
2447 if (func != NULL) {
2448 v->func = NULL;
2449 Py_DECREF(func);
2450 Py_DECREF(v); /* See Tktt_New() */
2451 }
2452 Py_INCREF(Py_None);
2453 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002454}
2455
2456static PyMethodDef Tktt_methods[] =
2457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2459 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002460};
2461
2462static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002463Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002464{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 v = PyObject_New(TkttObject, &Tktt_Type);
2468 if (v == NULL)
2469 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 Py_INCREF(func);
2472 v->token = NULL;
2473 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 /* Extra reference, deleted when called or when handler is deleted */
2476 Py_INCREF(v);
2477 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002478}
2479
2480static void
Fred Drake509d79a2000-07-08 04:04:38 +00002481Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002482{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002483 TkttObject *v = (TkttObject *)self;
2484 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002489}
2490
Guido van Rossum597ac201998-05-12 14:36:19 +00002491static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002492Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002493{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002495 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2496 v,
2497 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002498}
2499
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002500static PyTypeObject Tktt_Type =
2501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 PyVarObject_HEAD_INIT(NULL, 0)
2503 "tktimertoken", /*tp_name */
2504 sizeof(TkttObject), /*tp_basicsize */
2505 0, /*tp_itemsize */
2506 Tktt_Dealloc, /*tp_dealloc */
2507 0, /*tp_print */
2508 0, /*tp_getattr */
2509 0, /*tp_setattr */
2510 0, /*tp_reserved */
2511 Tktt_Repr, /*tp_repr */
2512 0, /*tp_as_number */
2513 0, /*tp_as_sequence */
2514 0, /*tp_as_mapping */
2515 0, /*tp_hash */
2516 0, /*tp_call*/
2517 0, /*tp_str*/
2518 0, /*tp_getattro*/
2519 0, /*tp_setattro*/
2520 0, /*tp_as_buffer*/
2521 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2522 0, /*tp_doc*/
2523 0, /*tp_traverse*/
2524 0, /*tp_clear*/
2525 0, /*tp_richcompare*/
2526 0, /*tp_weaklistoffset*/
2527 0, /*tp_iter*/
2528 0, /*tp_iternext*/
2529 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002530};
2531
Barry Warsawfa701a81997-01-16 00:15:11 +00002532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002533
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002534/** Timer Handler **/
2535
2536static void
Fred Drake509d79a2000-07-08 04:04:38 +00002537TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002538{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002539 TkttObject *v = (TkttObject *)clientData;
2540 PyObject *func = v->func;
2541 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 if (func == NULL)
2544 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002550 res = PyEval_CallObject(func, NULL);
2551 Py_DECREF(func);
2552 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 if (res == NULL) {
2555 errorInCmd = 1;
2556 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2557 }
2558 else
2559 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002561 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002562}
2563
2564static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002565Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 int milliseconds;
2568 PyObject *func;
2569 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2572 &milliseconds, &func))
2573 return NULL;
2574 if (!PyCallable_Check(func)) {
2575 PyErr_SetString(PyExc_TypeError, "bad argument list");
2576 return NULL;
2577 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 v = Tktt_New(func);
2582 if (v) {
2583 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2584 (ClientData)v);
2585 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002587 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002588}
2589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002590
Guido van Rossum18468821994-06-20 07:49:28 +00002591/** Event Loop **/
2592
Guido van Rossum18468821994-06-20 07:49:28 +00002593static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002594Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002595{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002596 int threshold = 0;
2597 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002598#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002600#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2603 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002605 CHECK_TCL_APPARTMENT;
2606 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002608 quitMainLoop = 0;
2609 while (Tk_GetNumMainWindows() > threshold &&
2610 !quitMainLoop &&
2611 !errorInCmd)
2612 {
2613 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002614
2615#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002616 if (self->threaded) {
2617 /* Allow other Python threads to run. */
2618 ENTER_TCL
2619 result = Tcl_DoOneEvent(0);
2620 LEAVE_TCL
2621 }
2622 else {
2623 Py_BEGIN_ALLOW_THREADS
2624 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2625 tcl_tstate = tstate;
2626 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2627 tcl_tstate = NULL;
2628 if(tcl_lock)PyThread_release_lock(tcl_lock);
2629 if (result == 0)
2630 Sleep(Tkinter_busywaitinterval);
2631 Py_END_ALLOW_THREADS
2632 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002633#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002635#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 if (PyErr_CheckSignals() != 0) {
2638 self->dispatching = 0;
2639 return NULL;
2640 }
2641 if (result < 0)
2642 break;
2643 }
2644 self->dispatching = 0;
2645 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002647 if (errorInCmd) {
2648 errorInCmd = 0;
2649 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2650 excInCmd = valInCmd = trbInCmd = NULL;
2651 return NULL;
2652 }
2653 Py_INCREF(Py_None);
2654 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002655}
2656
2657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002658Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002660 int flags = 0;
2661 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2664 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 ENTER_TCL
2667 rv = Tcl_DoOneEvent(flags);
2668 LEAVE_TCL
2669 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002670}
2671
2672static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002673Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002674{
2675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 if (!PyArg_ParseTuple(args, ":quit"))
2677 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002678
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002679 quitMainLoop = 1;
2680 Py_INCREF(Py_None);
2681 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002682}
2683
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002684static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002685Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002686{
2687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002688 if (!PyArg_ParseTuple(args, ":interpaddr"))
2689 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002690
Victor Stinnere1040e22013-09-05 00:22:24 +02002691 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002692}
2693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002694static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002695Tkapp_TkInit(PyObject *self, PyObject *args)
2696{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002697 Tcl_Interp *interp = Tkapp_Interp(self);
2698 const char * _tk_exists = NULL;
2699 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002700
Guilherme Polob681df42009-02-09 22:33:59 +00002701#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002702 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2703 * first call failed.
2704 * To avoid the deadlock, we just refuse the second call through
2705 * a static variable.
2706 */
2707 if (tk_load_failed) {
2708 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2709 return NULL;
2710 }
Guilherme Polob681df42009-02-09 22:33:59 +00002711#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 /* We want to guard against calling Tk_Init() multiple times */
2714 CHECK_TCL_APPARTMENT;
2715 ENTER_TCL
2716 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2717 ENTER_OVERLAP
2718 if (err == TCL_ERROR) {
2719 /* This sets an exception, but we cannot return right
2720 away because we need to exit the overlap first. */
2721 Tkinter_Error(self);
2722 } else {
2723 _tk_exists = Tkapp_Result(self);
2724 }
2725 LEAVE_OVERLAP_TCL
2726 if (err == TCL_ERROR) {
2727 return NULL;
2728 }
2729 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2730 if (Tk_Init(interp) == TCL_ERROR) {
2731 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002732#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002734#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 return NULL;
2736 }
2737 }
2738 Py_INCREF(Py_None);
2739 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002740}
Barry Warsawfa701a81997-01-16 00:15:11 +00002741
Martin v. Löwisffad6332002-11-26 09:28:05 +00002742static PyObject *
2743Tkapp_WantObjects(PyObject *self, PyObject *args)
2744{
2745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002746 int wantobjects = -1;
2747 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2748 return NULL;
2749 if (wantobjects == -1)
2750 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2751 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 Py_INCREF(Py_None);
2754 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002755}
2756
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002757static PyObject *
2758Tkapp_WillDispatch(PyObject *self, PyObject *args)
2759{
2760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002761 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002763 Py_INCREF(Py_None);
2764 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002765}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767
Guido van Rossum18468821994-06-20 07:49:28 +00002768/**** Tkapp Method List ****/
2769
2770static PyMethodDef Tkapp_methods[] =
2771{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2773 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2774 {"call", Tkapp_Call, METH_VARARGS},
2775 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2776 {"eval", Tkapp_Eval, METH_VARARGS},
2777 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2778 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2779 {"record", Tkapp_Record, METH_VARARGS},
2780 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2781 {"setvar", Tkapp_SetVar, METH_VARARGS},
2782 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2783 {"getvar", Tkapp_GetVar, METH_VARARGS},
2784 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2785 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2786 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2787 {"getint", Tkapp_GetInt, METH_VARARGS},
2788 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2789 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2790 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2791 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2792 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2793 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2794 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2795 {"split", Tkapp_Split, METH_VARARGS},
2796 {"merge", Tkapp_Merge, METH_VARARGS},
2797 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2798 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002799#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002800 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2801 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002802#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2804 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2805 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2806 {"quit", Tkapp_Quit, METH_VARARGS},
2807 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2808 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2809 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002810};
2811
Barry Warsawfa701a81997-01-16 00:15:11 +00002812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813
Guido van Rossum18468821994-06-20 07:49:28 +00002814/**** Tkapp Type Methods ****/
2815
2816static void
Fred Drake509d79a2000-07-08 04:04:38 +00002817Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002818{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 /*CHECK_TCL_APPARTMENT;*/
2820 ENTER_TCL
2821 Tcl_DeleteInterp(Tkapp_Interp(self));
2822 LEAVE_TCL
2823 PyObject_Del(self);
2824 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002825}
2826
Guido van Rossum18468821994-06-20 07:49:28 +00002827static PyTypeObject Tkapp_Type =
2828{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002829 PyVarObject_HEAD_INIT(NULL, 0)
2830 "tkapp", /*tp_name */
2831 sizeof(TkappObject), /*tp_basicsize */
2832 0, /*tp_itemsize */
2833 Tkapp_Dealloc, /*tp_dealloc */
2834 0, /*tp_print */
2835 0, /*tp_getattr */
2836 0, /*tp_setattr */
2837 0, /*tp_reserved */
2838 0, /*tp_repr */
2839 0, /*tp_as_number */
2840 0, /*tp_as_sequence */
2841 0, /*tp_as_mapping */
2842 0, /*tp_hash */
2843 0, /*tp_call*/
2844 0, /*tp_str*/
2845 0, /*tp_getattro*/
2846 0, /*tp_setattro*/
2847 0, /*tp_as_buffer*/
2848 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2849 0, /*tp_doc*/
2850 0, /*tp_traverse*/
2851 0, /*tp_clear*/
2852 0, /*tp_richcompare*/
2853 0, /*tp_weaklistoffset*/
2854 0, /*tp_iter*/
2855 0, /*tp_iternext*/
2856 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002857};
2858
Barry Warsawfa701a81997-01-16 00:15:11 +00002859
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002860
Guido van Rossum18468821994-06-20 07:49:28 +00002861/**** Tkinter Module ****/
2862
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002863typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 PyObject* tuple;
2865 int size; /* current size */
2866 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002867} FlattenContext;
2868
2869static int
2870_bump(FlattenContext* context, int size)
2871{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 /* expand tuple to hold (at least) size new items.
2873 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002877 if (maxsize < context->size + size)
2878 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002881
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002882 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002883}
2884
2885static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002886_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002887{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002891
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 if (depth > 1000) {
2893 PyErr_SetString(PyExc_ValueError,
2894 "nesting too deep in _flatten");
2895 return 0;
2896 } else if (PyList_Check(item)) {
2897 size = PyList_GET_SIZE(item);
2898 /* preallocate (assume no nesting) */
2899 if (context->size + size > context->maxsize &&
2900 !_bump(context, size))
2901 return 0;
2902 /* copy items to output tuple */
2903 for (i = 0; i < size; i++) {
2904 PyObject *o = PyList_GET_ITEM(item, i);
2905 if (PyList_Check(o) || PyTuple_Check(o)) {
2906 if (!_flatten1(context, o, depth + 1))
2907 return 0;
2908 } else if (o != Py_None) {
2909 if (context->size + 1 > context->maxsize &&
2910 !_bump(context, 1))
2911 return 0;
2912 Py_INCREF(o);
2913 PyTuple_SET_ITEM(context->tuple,
2914 context->size++, o);
2915 }
2916 }
2917 } else if (PyTuple_Check(item)) {
2918 /* same, for tuples */
2919 size = PyTuple_GET_SIZE(item);
2920 if (context->size + size > context->maxsize &&
2921 !_bump(context, size))
2922 return 0;
2923 for (i = 0; i < size; i++) {
2924 PyObject *o = PyTuple_GET_ITEM(item, i);
2925 if (PyList_Check(o) || PyTuple_Check(o)) {
2926 if (!_flatten1(context, o, depth + 1))
2927 return 0;
2928 } else if (o != Py_None) {
2929 if (context->size + 1 > context->maxsize &&
2930 !_bump(context, 1))
2931 return 0;
2932 Py_INCREF(o);
2933 PyTuple_SET_ITEM(context->tuple,
2934 context->size++, o);
2935 }
2936 }
2937 } else {
2938 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2939 return 0;
2940 }
2941 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002942}
2943
2944static PyObject *
2945Tkinter_Flatten(PyObject* self, PyObject* args)
2946{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002947 FlattenContext context;
2948 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002949
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2951 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 context.maxsize = PySequence_Size(item);
2954 if (context.maxsize < 0)
2955 return NULL;
2956 if (context.maxsize == 0)
2957 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002958
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 context.tuple = PyTuple_New(context.maxsize);
2960 if (!context.tuple)
2961 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002965 if (!_flatten1(&context, item,0))
2966 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002967
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002968 if (_PyTuple_Resize(&context.tuple, context.size))
2969 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002972}
2973
Guido van Rossum18468821994-06-20 07:49:28 +00002974static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002975Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002977 char *screenName = NULL;
2978 char *baseName = NULL; /* XXX this is not used anymore;
2979 try getting rid of it. */
2980 char *className = NULL;
2981 int interactive = 0;
2982 int wantobjects = 0;
2983 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2984 int sync = 0; /* pass -sync to wish */
2985 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002986
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002987 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002989 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2990 &screenName, &baseName, &className,
2991 &interactive, &wantobjects, &wantTk,
2992 &sync, &use))
2993 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 return (PyObject *) Tkapp_New(screenName, className,
2996 interactive, wantobjects, wantTk,
2997 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002998}
2999
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003000static PyObject *
3001Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3002{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003003 int new_val;
3004 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3005 return NULL;
3006 if (new_val < 0) {
3007 PyErr_SetString(PyExc_ValueError,
3008 "busywaitinterval must be >= 0");
3009 return NULL;
3010 }
3011 Tkinter_busywaitinterval = new_val;
3012 Py_INCREF(Py_None);
3013 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003014}
3015
3016static char setbusywaitinterval_doc[] =
3017"setbusywaitinterval(n) -> None\n\
3018\n\
3019Set the busy-wait interval in milliseconds between successive\n\
3020calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3021It should be set to a divisor of the maximum time between\n\
3022frames in an animation.";
3023
3024static PyObject *
3025Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003027 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003028}
3029
3030static char getbusywaitinterval_doc[] =
3031"getbusywaitinterval() -> int\n\
3032\n\
3033Return the current busy-wait interval between successive\n\
3034calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3035
Guido van Rossum18468821994-06-20 07:49:28 +00003036static PyMethodDef moduleMethods[] =
3037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003038 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3039 {"create", Tkinter_Create, METH_VARARGS},
3040 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3041 setbusywaitinterval_doc},
3042 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3043 METH_NOARGS, getbusywaitinterval_doc},
3044 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003045};
3046
Guido van Rossum7bf15641998-05-22 18:28:17 +00003047#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003048
3049static int stdin_ready = 0;
3050
Guido van Rossumad4db171998-06-13 13:56:28 +00003051#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003052static void
Fred Drake509d79a2000-07-08 04:04:38 +00003053MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003054{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003056}
Guido van Rossumad4db171998-06-13 13:56:28 +00003057#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003058
Martin v. Löwisa9656492003-03-30 08:44:58 +00003059#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003060static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003061#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003062
Guido van Rossum18468821994-06-20 07:49:28 +00003063static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003064EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003065{
Guido van Rossumad4db171998-06-13 13:56:28 +00003066#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003067 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003068#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003069#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003070 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003071#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003072 stdin_ready = 0;
3073 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003074#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003075 tfile = fileno(stdin);
3076 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003077#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003078 while (!errorInCmd && !stdin_ready) {
3079 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003080#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003081 if (_kbhit()) {
3082 stdin_ready = 1;
3083 break;
3084 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003085#endif
3086#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003087 Py_BEGIN_ALLOW_THREADS
3088 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3089 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003091 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003093 tcl_tstate = NULL;
3094 if(tcl_lock)PyThread_release_lock(tcl_lock);
3095 if (result == 0)
3096 Sleep(Tkinter_busywaitinterval);
3097 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003098#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003099 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003100#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003102 if (result < 0)
3103 break;
3104 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003105#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003106 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003107#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003108 if (errorInCmd) {
3109 errorInCmd = 0;
3110 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3111 excInCmd = valInCmd = trbInCmd = NULL;
3112 PyErr_Print();
3113 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003114#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003116#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003118}
Guido van Rossum18468821994-06-20 07:49:28 +00003119
Guido van Rossum00d93061998-05-28 23:06:38 +00003120#endif
3121
Guido van Rossum7bf15641998-05-22 18:28:17 +00003122static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003123EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003124{
Guido van Rossum00d93061998-05-28 23:06:38 +00003125#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003126 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003127#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003128 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003129#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 PyOS_InputHook = EventHook;
3131 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003132#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003133}
3134
3135static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003136DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003137{
Guido van Rossum00d93061998-05-28 23:06:38 +00003138#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003139 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3140 PyOS_InputHook = NULL;
3141 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003142#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003143}
3144
Barry Warsawfa701a81997-01-16 00:15:11 +00003145
3146/* all errors will be checked in one fell swoop in init_tkinter() */
3147static void
Fred Drake509d79a2000-07-08 04:04:38 +00003148ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003149{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 PyObject *v = PyLong_FromLong(val);
3151 if (v) {
3152 PyDict_SetItemString(d, name, v);
3153 Py_DECREF(v);
3154 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003155}
3156static void
Fred Drake509d79a2000-07-08 04:04:38 +00003157ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003158{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003159 PyObject *v = PyUnicode_FromString(val);
3160 if (v) {
3161 PyDict_SetItemString(d, name, v);
3162 Py_DECREF(v);
3163 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003164}
3165
3166
Martin v. Löwis1a214512008-06-11 05:26:20 +00003167static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003168 PyModuleDef_HEAD_INIT,
3169 "_tkinter",
3170 NULL,
3171 -1,
3172 moduleMethods,
3173 NULL,
3174 NULL,
3175 NULL,
3176 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003177};
3178
Mark Hammond62b1ab12002-07-23 06:31:15 +00003179PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003180PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003181{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003182 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003183
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003184 if (PyType_Ready(&Tkapp_Type) < 0)
3185 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003186
3187#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003189#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003190
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003191 m = PyModule_Create(&_tkintermodule);
3192 if (m == NULL)
3193 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003195 d = PyModule_GetDict(m);
3196 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3197 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003199 ins_long(d, "READABLE", TCL_READABLE);
3200 ins_long(d, "WRITABLE", TCL_WRITABLE);
3201 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3202 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3203 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3204 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3205 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3206 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3207 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3208 ins_string(d, "TK_VERSION", TK_VERSION);
3209 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003211 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003212
Jesus Ceaef86d122012-07-19 21:18:07 +02003213 if (PyType_Ready(&Tktt_Type) < 0) {
3214 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003215 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003216 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003217 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003219 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3220 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003221
3222#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003223 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3224 * start waking up. Note that Tcl_FindExecutable will do this, this
3225 * code must be above it! The original warning from
3226 * tkMacOSXAppInit.c is copied below.
3227 *
3228 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3229 * Tcl interpreter for now. It probably should work to do this
3230 * in the other order, but for now it doesn't seem to.
3231 *
3232 */
3233 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003234#endif
3235
3236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003237 /* This helps the dynamic loader; in Unicode aware Tcl versions
3238 it also helps Tcl find its encodings. */
3239 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3240 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003241 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003242 if (cexe)
3243 Tcl_FindExecutable(PyBytes_AsString(cexe));
3244 Py_XDECREF(cexe);
3245 Py_DECREF(uexe);
3246 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003248 if (PyErr_Occurred()) {
3249 Py_DECREF(m);
3250 return NULL;
3251 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003252
Guido van Rossum43ff8681998-07-14 18:02:13 +00003253#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003254 /* This was not a good idea; through <Destroy> bindings,
3255 Tcl_Finalize() may invoke Python code but at that point the
3256 interpreter and thread state have already been destroyed! */
3257 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003258#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003259 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003260}