blob: ecad541b9543ed1dccf370ca478dc50a541531c0 [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);
Serhiy Storchaka369606d2013-09-23 23:20:07 +0300334 else if (PyUnicode_Check(value))
335 return PyUnicode_AsUTF8(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336 else {
337 PyObject *v = PyObject_Str(value);
338 if (v == NULL)
339 return NULL;
340 if (PyList_Append(tmp, v) != 0) {
341 Py_DECREF(v);
342 return NULL;
343 }
344 Py_DECREF(v);
Serhiy Storchaka369606d2013-09-23 23:20:07 +0300345 return PyUnicode_AsUTF8(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000346 }
Guido van Rossum18468821994-06-20 07:49:28 +0000347}
348
Barry Warsawfa701a81997-01-16 00:15:11 +0000349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000350
Guido van Rossum18468821994-06-20 07:49:28 +0000351#define ARGSZ 64
352
353static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000354Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000355{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 PyObject *tmp = NULL;
357 char *argvStore[ARGSZ];
358 char **argv = NULL;
359 int fvStore[ARGSZ];
360 int *fv = NULL;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300361 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000364 if (!(tmp = PyList_New(0)))
365 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000367 argv = argvStore;
368 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 if (args == NULL)
371 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 else if (!PyTuple_Check(args)) {
374 argc = 1;
375 fv[0] = 0;
376 if (!(argv[0] = AsString(args, tmp)))
377 goto finally;
378 }
379 else {
380 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 if (argc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300383 if (!CHECK_SIZE(argc, sizeof(char *))) {
384 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
385 goto finally;
386 }
387 argv = (char **)ckalloc((size_t)argc * sizeof(char *));
388 fv = (int *)ckalloc((size_t)argc * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 if (argv == NULL || fv == NULL) {
390 PyErr_NoMemory();
391 goto finally;
392 }
393 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 for (i = 0; i < argc; i++) {
396 PyObject *v = PyTuple_GetItem(args, i);
397 if (PyTuple_Check(v)) {
398 fv[i] = 1;
399 if (!(argv[i] = Merge(v)))
400 goto finally;
401 fvc++;
402 }
403 else if (v == Py_None) {
404 argc = i;
405 break;
406 }
407 else {
408 fv[i] = 0;
409 if (!(argv[i] = AsString(v, tmp)))
410 goto finally;
411 fvc++;
412 }
413 }
414 }
415 res = Tcl_Merge(argc, argv);
416 if (res == NULL)
417 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000418
Barry Warsawfa701a81997-01-16 00:15:11 +0000419 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 for (i = 0; i < fvc; i++)
421 if (fv[i]) {
422 ckfree(argv[i]);
423 }
424 if (argv != argvStore)
425 ckfree(FREECAST argv);
426 if (fv != fvStore)
427 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 Py_DECREF(tmp);
430 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000431}
432
Barry Warsawfa701a81997-01-16 00:15:11 +0000433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434
Guido van Rossum18468821994-06-20 07:49:28 +0000435static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000436Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000437{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 int argc;
439 char **argv;
440 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000442 if (list == NULL) {
443 Py_INCREF(Py_None);
444 return Py_None;
445 }
Guido van Rossum18468821994-06-20 07:49:28 +0000446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000447 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
448 /* Not a list.
449 * Could be a quoted string containing funnies, e.g. {"}.
450 * Return the string itself.
451 */
452 return PyUnicode_FromString(list);
453 }
Guido van Rossum18468821994-06-20 07:49:28 +0000454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 if (argc == 0)
456 v = PyUnicode_FromString("");
457 else if (argc == 1)
458 v = PyUnicode_FromString(argv[0]);
459 else if ((v = PyTuple_New(argc)) != NULL) {
460 int i;
461 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 for (i = 0; i < argc; i++) {
464 if ((w = Split(argv[i])) == NULL) {
465 Py_DECREF(v);
466 v = NULL;
467 break;
468 }
469 PyTuple_SetItem(v, i, w);
470 }
471 }
472 Tcl_Free(FREECAST argv);
473 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000474}
475
Martin v. Löwisffad6332002-11-26 09:28:05 +0000476/* In some cases, Tcl will still return strings that are supposed to be
477 lists. SplitObj walks through a nested tuple, finding string objects that
478 need to be split. */
479
Martin v. Löwis59683e82008-06-13 07:50:45 +0000480static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000481SplitObj(PyObject *arg)
482{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 if (PyTuple_Check(arg)) {
484 int i, size;
485 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 size = PyTuple_Size(arg);
488 result = NULL;
489 /* Recursively invoke SplitObj for all tuple items.
490 If this does not return a new object, no action is
491 needed. */
492 for(i = 0; i < size; i++) {
493 elem = PyTuple_GetItem(arg, i);
494 newelem = SplitObj(elem);
495 if (!newelem) {
496 Py_XDECREF(result);
497 return NULL;
498 }
499 if (!result) {
500 int k;
501 if (newelem == elem) {
502 Py_DECREF(newelem);
503 continue;
504 }
505 result = PyTuple_New(size);
506 if (!result)
507 return NULL;
508 for(k = 0; k < i; k++) {
509 elem = PyTuple_GetItem(arg, k);
510 Py_INCREF(elem);
511 PyTuple_SetItem(result, k, elem);
512 }
513 }
514 PyTuple_SetItem(result, i, newelem);
515 }
516 if (result)
517 return result;
518 /* Fall through, returning arg. */
519 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300520 else if (PyUnicode_Check(arg)) {
521 int argc;
522 char **argv;
523 char *list = PyUnicode_AsUTF8(arg);
524
525 if (list == NULL ||
526 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
527 Py_INCREF(arg);
528 return arg;
529 }
530 Tcl_Free(FREECAST argv);
531 if (argc > 1)
532 return Split(list);
533 /* Fall through, returning arg. */
534 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 else if (PyBytes_Check(arg)) {
536 int argc;
537 char **argv;
538 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000539
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
541 Py_INCREF(arg);
542 return arg;
543 }
544 Tcl_Free(FREECAST argv);
545 if (argc > 1)
546 return Split(PyBytes_AsString(arg));
547 /* Fall through, returning arg. */
548 }
549 Py_INCREF(arg);
550 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000551}
Barry Warsawfa701a81997-01-16 00:15:11 +0000552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553
Guido van Rossum18468821994-06-20 07:49:28 +0000554/**** Tkapp Object ****/
555
556#ifndef WITH_APPINIT
557int
Fred Drake509d79a2000-07-08 04:04:38 +0000558Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000559{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 if (Tcl_Init(interp) == TCL_ERROR) {
563 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
564 return TCL_ERROR;
565 }
Guilherme Polob681df42009-02-09 22:33:59 +0000566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 _tkinter_skip_tk_init = Tcl_GetVar(interp,
568 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
569 if (_tkinter_skip_tk_init != NULL &&
570 strcmp(_tkinter_skip_tk_init, "1") == 0) {
571 return TCL_OK;
572 }
Guilherme Polob681df42009-02-09 22:33:59 +0000573
574#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 if (tk_load_failed) {
576 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
577 return TCL_ERROR;
578 }
Guilherme Polob681df42009-02-09 22:33:59 +0000579#endif
580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000582#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000584#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000585 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
586 return TCL_ERROR;
587 }
Guilherme Polob681df42009-02-09 22:33:59 +0000588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000590}
591#endif /* !WITH_APPINIT */
592
Guido van Rossum18468821994-06-20 07:49:28 +0000593
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594
Barry Warsawfa701a81997-01-16 00:15:11 +0000595
596/* Initialize the Tk application; see the `main' function in
597 * `tkMain.c'.
598 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000599
Thomas Wouters58d05102000-07-24 14:43:35 +0000600static void EnableEventHook(void); /* Forward */
601static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000602
Barry Warsawfa701a81997-01-16 00:15:11 +0000603static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000604Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000606{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 TkappObject *v;
608 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 v = PyObject_New(TkappObject, &Tkapp_Type);
611 if (v == NULL)
612 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 v->interp = Tcl_CreateInterp();
615 v->wantobjects = wantobjects;
616 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
617 TCL_GLOBAL_ONLY) != NULL;
618 v->thread_id = Tcl_GetCurrentThread();
619 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000620
621#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 if (v->threaded) {
623 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
624 Py_DECREF(v);
625 return 0;
626 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000627#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000628#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 if (v->threaded && tcl_lock) {
630 /* If Tcl is threaded, we don't need the lock. */
631 PyThread_free_lock(tcl_lock);
632 tcl_lock = NULL;
633 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000634#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 v->BooleanType = Tcl_GetObjType("boolean");
637 v->ByteArrayType = Tcl_GetObjType("bytearray");
638 v->DoubleType = Tcl_GetObjType("double");
639 v->IntType = Tcl_GetObjType("int");
640 v->ListType = Tcl_GetObjType("list");
641 v->ProcBodyType = Tcl_GetObjType("procbody");
642 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 /* Delete the 'exit' command, which can screw things up */
645 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 if (screenName != NULL)
648 Tcl_SetVar2(v->interp, "env", "DISPLAY",
649 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 if (interactive)
652 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
653 else
654 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 /* This is used to get the application class for Tk 4.1 and up */
657 argv0 = (char*)ckalloc(strlen(className) + 1);
658 if (!argv0) {
659 PyErr_NoMemory();
660 Py_DECREF(v);
661 return NULL;
662 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200665 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
666 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
668 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 if (! wantTk) {
671 Tcl_SetVar(v->interp,
672 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
673 }
Guilherme Polob681df42009-02-09 22:33:59 +0000674#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 else if (tk_load_failed) {
676 Tcl_SetVar(v->interp,
677 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
678 }
Guilherme Polob681df42009-02-09 22:33:59 +0000679#endif
David Aschere2b4b322004-02-18 05:59:53 +0000680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 /* some initial arguments need to be in argv */
682 if (sync || use) {
683 char *args;
684 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 if (sync)
687 len += sizeof "-sync";
688 if (use)
689 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 args = (char*)ckalloc(len);
692 if (!args) {
693 PyErr_NoMemory();
694 Py_DECREF(v);
695 return NULL;
696 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 args[0] = '\0';
699 if (sync)
700 strcat(args, "-sync");
701 if (use) {
702 if (sync)
703 strcat(args, " ");
704 strcat(args, "-use ");
705 strcat(args, use);
706 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
709 ckfree(args);
710 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 if (Tcl_AppInit(v->interp) != TCL_OK) {
713 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000714#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 if (wantTk) {
716 const char *_tkinter_tk_failed;
717 _tkinter_tk_failed = Tcl_GetVar(v->interp,
718 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 if ( _tkinter_tk_failed != NULL &&
721 strcmp(_tkinter_tk_failed, "1") == 0) {
722 tk_load_failed = 1;
723 }
724 }
Guilherme Polob681df42009-02-09 22:33:59 +0000725#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 Py_DECREF((PyObject *)v);
727 return (TkappObject *)result;
728 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000729
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000733}
734
Barry Warsawfa701a81997-01-16 00:15:11 +0000735
Benjamin Peterson5879d412009-03-30 14:51:56 +0000736#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000737static void
738Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000739 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000740{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 Py_BEGIN_ALLOW_THREADS;
742 Tcl_MutexLock(mutex);
743 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
744 Tcl_ThreadAlert(self->thread_id);
745 Tcl_ConditionWait(cond, mutex, NULL);
746 Tcl_MutexUnlock(mutex);
747 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000748}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000749#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751
Guido van Rossum18468821994-06-20 07:49:28 +0000752/** Tcl Eval **/
753
Martin v. Löwisffad6332002-11-26 09:28:05 +0000754typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 PyObject_HEAD
756 Tcl_Obj *value;
757 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000758} PyTclObject;
759
Neal Norwitz227b5332006-03-22 09:28:35 +0000760static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000761#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000762
763static PyObject *
764newPyTclObject(Tcl_Obj *arg)
765{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 PyTclObject *self;
767 self = PyObject_New(PyTclObject, &PyTclObject_Type);
768 if (self == NULL)
769 return NULL;
770 Tcl_IncrRefCount(arg);
771 self->value = arg;
772 self->string = NULL;
773 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000774}
775
776static void
777PyTclObject_dealloc(PyTclObject *self)
778{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 Tcl_DecrRefCount(self->value);
780 Py_XDECREF(self->string);
781 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000782}
783
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000784static char*
785PyTclObject_TclString(PyObject *self)
786{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000788}
789
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000790/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000791PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000792"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000793
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000794static PyObject *
795PyTclObject_string(PyTclObject *self, void *ignored)
796{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 char *s;
798 int len;
799 if (!self->string) {
800 s = Tcl_GetStringFromObj(self->value, &len);
801 self->string = PyUnicode_FromStringAndSize(s, len);
802 if (!self->string)
803 return NULL;
804 }
805 Py_INCREF(self->string);
806 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000807}
808
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000809static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000810PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000811{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 char *s;
813 int len;
814 if (self->string && PyUnicode_Check(self->string)) {
815 Py_INCREF(self->string);
816 return self->string;
817 }
818 /* XXX Could chache result if it is non-ASCII. */
819 s = Tcl_GetStringFromObj(self->value, &len);
820 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000821}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000822
Martin v. Löwisffad6332002-11-26 09:28:05 +0000823static PyObject *
824PyTclObject_repr(PyTclObject *self)
825{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826 return PyUnicode_FromFormat("<%s object at %p>",
827 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000828}
829
Mark Dickinson211c6252009-02-01 10:28:51 +0000830#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
831
832static PyObject *
833PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 int result;
836 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000838 /* neither argument should be NULL, unless something's gone wrong */
839 if (self == NULL || other == NULL) {
840 PyErr_BadInternalCall();
841 return NULL;
842 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000844 /* both arguments should be instances of PyTclObject */
845 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
846 v = Py_NotImplemented;
847 goto finished;
848 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000849
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000850 if (self == other)
851 /* fast path when self and other are identical */
852 result = 0;
853 else
854 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
855 Tcl_GetString(((PyTclObject *)other)->value));
856 /* Convert return value to a Boolean */
857 switch (op) {
858 case Py_EQ:
859 v = TEST_COND(result == 0);
860 break;
861 case Py_NE:
862 v = TEST_COND(result != 0);
863 break;
864 case Py_LE:
865 v = TEST_COND(result <= 0);
866 break;
867 case Py_GE:
868 v = TEST_COND(result >= 0);
869 break;
870 case Py_LT:
871 v = TEST_COND(result < 0);
872 break;
873 case Py_GT:
874 v = TEST_COND(result > 0);
875 break;
876 default:
877 PyErr_BadArgument();
878 return NULL;
879 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000880 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 Py_INCREF(v);
882 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000883}
884
Martin v. Löwis39195712003-01-04 00:33:13 +0000885PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
886
Martin v. Löwisffad6332002-11-26 09:28:05 +0000887static PyObject*
888get_typename(PyTclObject* obj, void* ignored)
889{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000890 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000891}
892
Martin v. Löwis39195712003-01-04 00:33:13 +0000893
Martin v. Löwisffad6332002-11-26 09:28:05 +0000894static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 {"typename", (getter)get_typename, NULL, get_typename__doc__},
896 {"string", (getter)PyTclObject_string, NULL,
897 PyTclObject_string__doc__},
898 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000899};
900
Neal Norwitz227b5332006-03-22 09:28:35 +0000901static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000902 PyVarObject_HEAD_INIT(NULL, 0)
903 "_tkinter.Tcl_Obj", /*tp_name*/
904 sizeof(PyTclObject), /*tp_basicsize*/
905 0, /*tp_itemsize*/
906 /* methods */
907 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
908 0, /*tp_print*/
909 0, /*tp_getattr*/
910 0, /*tp_setattr*/
911 0, /*tp_reserved*/
912 (reprfunc)PyTclObject_repr, /*tp_repr*/
913 0, /*tp_as_number*/
914 0, /*tp_as_sequence*/
915 0, /*tp_as_mapping*/
916 0, /*tp_hash*/
917 0, /*tp_call*/
918 (reprfunc)PyTclObject_str, /*tp_str*/
919 PyObject_GenericGetAttr, /*tp_getattro*/
920 0, /*tp_setattro*/
921 0, /*tp_as_buffer*/
922 Py_TPFLAGS_DEFAULT, /*tp_flags*/
923 0, /*tp_doc*/
924 0, /*tp_traverse*/
925 0, /*tp_clear*/
926 PyTclObject_richcompare, /*tp_richcompare*/
927 0, /*tp_weaklistoffset*/
928 0, /*tp_iter*/
929 0, /*tp_iternext*/
930 0, /*tp_methods*/
931 0, /*tp_members*/
932 PyTclObject_getsetlist, /*tp_getset*/
933 0, /*tp_base*/
934 0, /*tp_dict*/
935 0, /*tp_descr_get*/
936 0, /*tp_descr_set*/
937 0, /*tp_dictoffset*/
938 0, /*tp_init*/
939 0, /*tp_alloc*/
940 0, /*tp_new*/
941 0, /*tp_free*/
942 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000943};
944
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000945static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000946AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000947{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 Tcl_Obj *result;
949 long longVal;
950 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 if (PyBytes_Check(value))
953 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
954 PyBytes_GET_SIZE(value));
955 else if (PyBool_Check(value))
956 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
957 else if (PyLong_CheckExact(value) &&
958 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
959 !overflow)) {
960 /* If there is an overflow in the long conversion,
961 fall through to default object handling. */
962 return Tcl_NewLongObj(longVal);
963 }
964 else if (PyFloat_Check(value))
965 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
966 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300967 Tcl_Obj **argv;
968 Py_ssize_t size, i;
969
970 size = PyTuple_Size(value);
971 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
972 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
973 return NULL;
974 }
975 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 if(!argv)
977 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300978 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000979 argv[i] = AsObj(PyTuple_GetItem(value,i));
980 result = Tcl_NewListObj(PyTuple_Size(value), argv);
981 ckfree(FREECAST argv);
982 return result;
983 }
984 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200985 void *inbuf;
986 Py_ssize_t size;
987 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 Tcl_UniChar *outbuf = NULL;
989 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200990 size_t allocsize;
991
992 if (PyUnicode_READY(value) == -1)
993 return NULL;
994
995 inbuf = PyUnicode_DATA(value);
996 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300997 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
998 PyErr_SetString(PyExc_OverflowError, "string is too long");
999 return NULL;
1000 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001001 kind = PyUnicode_KIND(value);
1002 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
1003 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 /* Else overflow occurred, and we take the next exit */
1005 if (!outbuf) {
1006 PyErr_NoMemory();
1007 return NULL;
1008 }
1009 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001010 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1011 /* We cannot test for sizeof(Tcl_UniChar) directly,
1012 so we test for UTF-8 size instead. */
1013#if TCL_UTF_MAX == 3
1014 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001015 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001016 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001017 "character U+%x is above the range "
1018 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001019 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001020 ckfree(FREECAST outbuf);
1021 return NULL;
1022 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001023#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001024 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 }
1026 result = Tcl_NewUnicodeObj(outbuf, size);
1027 ckfree(FREECAST outbuf);
1028 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 }
1030 else if(PyTclObject_Check(value)) {
1031 Tcl_Obj *v = ((PyTclObject*)value)->value;
1032 Tcl_IncrRefCount(v);
1033 return v;
1034 }
1035 else {
1036 PyObject *v = PyObject_Str(value);
1037 if (!v)
1038 return 0;
1039 result = AsObj(v);
1040 Py_DECREF(v);
1041 return result;
1042 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001043}
1044
Martin v. Löwisffad6332002-11-26 09:28:05 +00001045static PyObject*
1046FromObj(PyObject* tkapp, Tcl_Obj *value)
1047{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001048 PyObject *result = NULL;
1049 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 if (value->typePtr == NULL) {
1052 return PyUnicode_FromStringAndSize(value->bytes,
1053 value->length);
1054 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 if (value->typePtr == app->BooleanType) {
1057 result = value->internalRep.longValue ? Py_True : Py_False;
1058 Py_INCREF(result);
1059 return result;
1060 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 if (value->typePtr == app->ByteArrayType) {
1063 int size;
1064 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1065 return PyBytes_FromStringAndSize(data, size);
1066 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 if (value->typePtr == app->DoubleType) {
1069 return PyFloat_FromDouble(value->internalRep.doubleValue);
1070 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001072 if (value->typePtr == app->IntType) {
1073 return PyLong_FromLong(value->internalRep.longValue);
1074 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001075
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001076 if (value->typePtr == app->ListType) {
1077 int size;
1078 int i, status;
1079 PyObject *elem;
1080 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001081
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1083 if (status == TCL_ERROR)
1084 return Tkinter_Error(tkapp);
1085 result = PyTuple_New(size);
1086 if (!result)
1087 return NULL;
1088 for (i = 0; i < size; i++) {
1089 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1090 value, i, &tcl_elem);
1091 if (status == TCL_ERROR) {
1092 Py_DECREF(result);
1093 return Tkinter_Error(tkapp);
1094 }
1095 elem = FromObj(tkapp, tcl_elem);
1096 if (!elem) {
1097 Py_DECREF(result);
1098 return NULL;
1099 }
1100 PyTuple_SetItem(result, i, elem);
1101 }
1102 return result;
1103 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 if (value->typePtr == app->ProcBodyType) {
1106 /* fall through: return tcl object. */
1107 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001109 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001110#if TCL_UTF_MAX==3
1111 return PyUnicode_FromKindAndData(
1112 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1113 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001114#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001115 return PyUnicode_FromKindAndData(
1116 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1117 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001118#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001121 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001122}
1123
Benjamin Peterson5879d412009-03-30 14:51:56 +00001124#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001125/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126TCL_DECLARE_MUTEX(call_mutex)
1127
1128typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001129 Tcl_Event ev; /* Must be first */
1130 TkappObject *self;
1131 PyObject *args;
1132 int flags;
1133 PyObject **res;
1134 PyObject **exc_type, **exc_value, **exc_tb;
1135 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001136} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001137#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001138
1139void
1140Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001141{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001142 int i;
1143 for (i = 0; i < objc; i++)
1144 Tcl_DecrRefCount(objv[i]);
1145 if (objv != objStore)
1146 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001147}
Guido van Rossum18468821994-06-20 07:49:28 +00001148
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001149/* Convert Python objects to Tcl objects. This must happen in the
1150 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001151
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001152static Tcl_Obj**
1153Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001155 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001156 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 if (args == NULL)
1158 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 else if (!PyTuple_Check(args)) {
1161 objv[0] = AsObj(args);
1162 if (objv[0] == 0)
1163 goto finally;
1164 objc = 1;
1165 Tcl_IncrRefCount(objv[0]);
1166 }
1167 else {
1168 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001169
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001170 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001171 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1172 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1173 return NULL;
1174 }
1175 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001176 if (objv == NULL) {
1177 PyErr_NoMemory();
1178 objc = 0;
1179 goto finally;
1180 }
1181 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001183 for (i = 0; i < objc; i++) {
1184 PyObject *v = PyTuple_GetItem(args, i);
1185 if (v == Py_None) {
1186 objc = i;
1187 break;
1188 }
1189 objv[i] = AsObj(v);
1190 if (!objv[i]) {
1191 /* Reset objc, so it attempts to clear
1192 objects only up to i. */
1193 objc = i;
1194 goto finally;
1195 }
1196 Tcl_IncrRefCount(objv[i]);
1197 }
1198 }
1199 *pobjc = objc;
1200 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001201finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001202 Tkapp_CallDeallocArgs(objv, objStore, objc);
1203 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001204}
Guido van Rossum212643f1998-04-29 16:22:14 +00001205
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001206/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001207
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001208static PyObject*
1209Tkapp_CallResult(TkappObject *self)
1210{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 PyObject *res = NULL;
1212 if(self->wantobjects) {
1213 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1214 /* Not sure whether the IncrRef is necessary, but something
1215 may overwrite the interpreter result while we are
1216 converting it. */
1217 Tcl_IncrRefCount(value);
1218 res = FromObj((PyObject*)self, value);
1219 Tcl_DecrRefCount(value);
1220 } else {
Serhiy Storchaka31f477c2013-09-20 23:21:44 +03001221 res = PyUnicode_FromString(Tcl_GetStringResult(self->interp));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001222 }
1223 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224}
Guido van Rossum632de272000-03-29 00:19:50 +00001225
Benjamin Peterson5879d412009-03-30 14:51:56 +00001226#ifdef WITH_THREAD
1227
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001228/* Tkapp_CallProc is the event procedure that is executed in the context of
1229 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1230 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001231
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001232static int
1233Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1234{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 Tcl_Obj *objStore[ARGSZ];
1236 Tcl_Obj **objv;
1237 int objc;
1238 int i;
1239 ENTER_PYTHON
1240 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1241 if (!objv) {
1242 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1243 *(e->res) = NULL;
1244 }
1245 LEAVE_PYTHON
1246 if (!objv)
1247 goto done;
1248 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1249 ENTER_PYTHON
1250 if (i == TCL_ERROR) {
1251 *(e->res) = NULL;
1252 *(e->exc_type) = NULL;
1253 *(e->exc_tb) = NULL;
1254 *(e->exc_value) = PyObject_CallFunction(
1255 Tkinter_TclError, "s",
1256 Tcl_GetStringResult(e->self->interp));
1257 }
1258 else {
1259 *(e->res) = Tkapp_CallResult(e->self);
1260 }
1261 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001264done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 /* Wake up calling thread. */
1266 Tcl_MutexLock(&call_mutex);
1267 Tcl_ConditionNotify(e->done);
1268 Tcl_MutexUnlock(&call_mutex);
1269 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270}
1271
Benjamin Peterson5879d412009-03-30 14:51:56 +00001272#endif
1273
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001274/* This is the main entry point for calling a Tcl command.
1275 It supports three cases, with regard to threading:
1276 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1277 the context of the calling thread.
1278 2. Tcl is threaded, caller of the command is in the interpreter thread:
1279 Execute the command in the calling thread. Since the Tcl lock will
1280 not be used, we can merge that with case 1.
1281 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1282 the interpreter thread. Allocation of Tcl objects needs to occur in the
1283 interpreter thread, so we ship the PyObject* args to the target thread,
1284 and perform processing there. */
1285
1286static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001287Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 Tcl_Obj *objStore[ARGSZ];
1290 Tcl_Obj **objv = NULL;
1291 int objc, i;
1292 PyObject *res = NULL;
1293 TkappObject *self = (TkappObject*)selfptr;
1294 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001296 /* If args is a single tuple, replace with contents of tuple */
1297 if (1 == PyTuple_Size(args)){
1298 PyObject* item = PyTuple_GetItem(args, 0);
1299 if (PyTuple_Check(item))
1300 args = item;
1301 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001302#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1304 /* We cannot call the command directly. Instead, we must
1305 marshal the parameters to the interpreter thread. */
1306 Tkapp_CallEvent *ev;
1307 Tcl_Condition cond = NULL;
1308 PyObject *exc_type, *exc_value, *exc_tb;
1309 if (!WaitForMainloop(self))
1310 return NULL;
1311 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1312 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1313 ev->self = self;
1314 ev->args = args;
1315 ev->res = &res;
1316 ev->exc_type = &exc_type;
1317 ev->exc_value = &exc_value;
1318 ev->exc_tb = &exc_tb;
1319 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 if (res == NULL) {
1324 if (exc_type)
1325 PyErr_Restore(exc_type, exc_value, exc_tb);
1326 else
1327 PyErr_SetObject(Tkinter_TclError, exc_value);
1328 }
1329 Tcl_ConditionFinalize(&cond);
1330 }
1331 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001332#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 objv = Tkapp_CallArgs(args, objStore, &objc);
1336 if (!objv)
1337 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001345 if (i == TCL_ERROR)
1346 Tkinter_Error(selfptr);
1347 else
1348 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 Tkapp_CallDeallocArgs(objv, objStore, objc);
1353 }
1354 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001355}
1356
1357
1358static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001359Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001360{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 /* Could do the same here as for Tkapp_Call(), but this is not used
1362 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1363 way for the user to do what all its Global* variants do (save and
1364 reset the scope pointer, call the local version, restore the saved
1365 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 char *cmd;
1368 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001369
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001370 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1371 "globalcall is deprecated and will be removed in 3.4",
1372 1) < 0)
1373 return 0;
1374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 cmd = Merge(args);
1378 if (cmd) {
1379 int err;
1380 ENTER_TCL
1381 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1382 ENTER_OVERLAP
1383 if (err == TCL_ERROR)
1384 res = Tkinter_Error(self);
1385 else
1386 res = PyUnicode_FromString(Tkapp_Result(self));
1387 LEAVE_OVERLAP_TCL
1388 ckfree(cmd);
1389 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001392}
1393
1394static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001395Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001396{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 char *script;
1398 PyObject *res = NULL;
1399 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 if (!PyArg_ParseTuple(args, "s:eval", &script))
1402 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001404 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001406 ENTER_TCL
1407 err = Tcl_Eval(Tkapp_Interp(self), script);
1408 ENTER_OVERLAP
1409 if (err == TCL_ERROR)
1410 res = Tkinter_Error(self);
1411 else
1412 res = PyUnicode_FromString(Tkapp_Result(self));
1413 LEAVE_OVERLAP_TCL
1414 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001415}
1416
1417static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001418Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001419{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 char *script;
1421 PyObject *res = NULL;
1422 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001423
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001424 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1425 "globaleval is deprecated and will be removed in 3.4",
1426 1) < 0)
1427 return 0;
1428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001429 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1430 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 ENTER_TCL
1435 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1436 ENTER_OVERLAP
1437 if (err == TCL_ERROR)
1438 res = Tkinter_Error(self);
1439 else
1440 res = PyUnicode_FromString(Tkapp_Result(self));
1441 LEAVE_OVERLAP_TCL
1442 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001443}
1444
1445static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001446Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001447{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 char *fileName;
1449 PyObject *res = NULL;
1450 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1453 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001455 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 ENTER_TCL
1458 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1459 ENTER_OVERLAP
1460 if (err == TCL_ERROR)
1461 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 else
1464 res = PyUnicode_FromString(Tkapp_Result(self));
1465 LEAVE_OVERLAP_TCL
1466 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001467}
1468
1469static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001470Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001471{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 char *script;
1473 PyObject *res = NULL;
1474 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 if (!PyArg_ParseTuple(args, "s", &script))
1477 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 ENTER_TCL
1482 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1483 ENTER_OVERLAP
1484 if (err == TCL_ERROR)
1485 res = Tkinter_Error(self);
1486 else
1487 res = PyUnicode_FromString(Tkapp_Result(self));
1488 LEAVE_OVERLAP_TCL
1489 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001490}
1491
1492static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001493Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001494{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001495 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001496
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1498 return NULL;
1499 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001501 ENTER_TCL
1502 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1503 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505 Py_INCREF(Py_None);
1506 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001507}
1508
Barry Warsawfa701a81997-01-16 00:15:11 +00001509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510
Guido van Rossum18468821994-06-20 07:49:28 +00001511/** Tcl Variable **/
1512
Benjamin Peterson5879d412009-03-30 14:51:56 +00001513typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1514
1515#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001516TCL_DECLARE_MUTEX(var_mutex)
1517
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001518typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 Tcl_Event ev; /* must be first */
1520 PyObject *self;
1521 PyObject *args;
1522 int flags;
1523 EventFunc func;
1524 PyObject **res;
1525 PyObject **exc_type;
1526 PyObject **exc_val;
1527 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001529#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001531static int
1532varname_converter(PyObject *in, void *_out)
1533{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001534 char **out = (char**)_out;
1535 if (PyBytes_Check(in)) {
1536 *out = PyBytes_AsString(in);
1537 return 1;
1538 }
1539 if (PyUnicode_Check(in)) {
1540 *out = _PyUnicode_AsString(in);
1541 return 1;
1542 }
1543 if (PyTclObject_Check(in)) {
1544 *out = PyTclObject_TclString(in);
1545 return 1;
1546 }
1547 /* XXX: Should give diagnostics. */
1548 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001549}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001550
Benjamin Peterson5879d412009-03-30 14:51:56 +00001551#ifdef WITH_THREAD
1552
Martin v. Löwis59683e82008-06-13 07:50:45 +00001553static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554var_perform(VarEvent *ev)
1555{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001556 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1557 if (!*(ev->res)) {
1558 PyObject *exc, *val, *tb;
1559 PyErr_Fetch(&exc, &val, &tb);
1560 PyErr_NormalizeException(&exc, &val, &tb);
1561 *(ev->exc_type) = exc;
1562 *(ev->exc_val) = val;
1563 Py_DECREF(tb);
1564 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001565
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001566}
1567
1568static int
1569var_proc(VarEvent* ev, int flags)
1570{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 ENTER_PYTHON
1572 var_perform(ev);
1573 Tcl_MutexLock(&var_mutex);
1574 Tcl_ConditionNotify(ev->cond);
1575 Tcl_MutexUnlock(&var_mutex);
1576 LEAVE_PYTHON
1577 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001578}
1579
Benjamin Peterson5879d412009-03-30 14:51:56 +00001580#endif
1581
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001582static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001583var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001584{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001585#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001586 TkappObject *self = (TkappObject*)selfptr;
1587 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1588 TkappObject *self = (TkappObject*)selfptr;
1589 VarEvent *ev;
1590 PyObject *res, *exc_type, *exc_val;
1591 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593 /* The current thread is not the interpreter thread. Marshal
1594 the call to the interpreter thread, then wait for
1595 completion. */
1596 if (!WaitForMainloop(self))
1597 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 ev->self = selfptr;
1602 ev->args = args;
1603 ev->flags = flags;
1604 ev->func = func;
1605 ev->res = &res;
1606 ev->exc_type = &exc_type;
1607 ev->exc_val = &exc_val;
1608 ev->cond = &cond;
1609 ev->ev.proc = (Tcl_EventProc*)var_proc;
1610 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1611 Tcl_ConditionFinalize(&cond);
1612 if (!res) {
1613 PyErr_SetObject(exc_type, exc_val);
1614 Py_DECREF(exc_type);
1615 Py_DECREF(exc_val);
1616 return NULL;
1617 }
1618 return res;
1619 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001620#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001621 /* Tcl is not threaded, or this is the interpreter thread. */
1622 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001623}
1624
Guido van Rossum18468821994-06-20 07:49:28 +00001625static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001626SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628 char *name1, *name2;
1629 PyObject *newValue;
1630 PyObject *res = NULL;
1631 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 if (PyArg_ParseTuple(args, "O&O:setvar",
1634 varname_converter, &name1, &newValue)) {
1635 /* XXX Acquire tcl lock??? */
1636 newval = AsObj(newValue);
1637 if (newval == NULL)
1638 return NULL;
1639 ENTER_TCL
1640 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1641 newval, flags);
1642 ENTER_OVERLAP
1643 if (!ok)
1644 Tkinter_Error(self);
1645 else {
1646 res = Py_None;
1647 Py_INCREF(res);
1648 }
1649 LEAVE_OVERLAP_TCL
1650 }
1651 else {
1652 PyErr_Clear();
1653 if (PyArg_ParseTuple(args, "ssO:setvar",
1654 &name1, &name2, &newValue)) {
1655 /* XXX must hold tcl lock already??? */
1656 newval = AsObj(newValue);
1657 ENTER_TCL
1658 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1659 ENTER_OVERLAP
1660 if (!ok)
1661 Tkinter_Error(self);
1662 else {
1663 res = Py_None;
1664 Py_INCREF(res);
1665 }
1666 LEAVE_OVERLAP_TCL
1667 }
1668 else {
1669 return NULL;
1670 }
1671 }
1672 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001673}
1674
1675static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001676Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001677{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001679}
1680
1681static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001682Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001683{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001684 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
Barry Warsawfa701a81997-01-16 00:15:11 +00001687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001688
Guido van Rossum18468821994-06-20 07:49:28 +00001689static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001690GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001691{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692 char *name1, *name2=NULL;
1693 PyObject *res = NULL;
1694 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1697 varname_converter, &name1, &name2))
1698 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001700 ENTER_TCL
1701 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1702 ENTER_OVERLAP
1703 if (tres == NULL) {
1704 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1705 } else {
1706 if (((TkappObject*)self)->wantobjects) {
1707 res = FromObj(self, tres);
1708 }
1709 else {
1710 res = PyUnicode_FromString(Tcl_GetString(tres));
1711 }
1712 }
1713 LEAVE_OVERLAP_TCL
1714 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001715}
1716
1717static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001718Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001721}
1722
1723static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001724Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001725{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001727}
1728
Barry Warsawfa701a81997-01-16 00:15:11 +00001729
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001730
Guido van Rossum18468821994-06-20 07:49:28 +00001731static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001732UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001733{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001734 char *name1, *name2=NULL;
1735 int code;
1736 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1739 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001741 ENTER_TCL
1742 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1743 ENTER_OVERLAP
1744 if (code == TCL_ERROR)
1745 res = Tkinter_Error(self);
1746 else {
1747 Py_INCREF(Py_None);
1748 res = Py_None;
1749 }
1750 LEAVE_OVERLAP_TCL
1751 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001752}
1753
1754static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001755Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001758}
1759
1760static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001761Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001762{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
Barry Warsawfa701a81997-01-16 00:15:11 +00001766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767
Guido van Rossum18468821994-06-20 07:49:28 +00001768/** Tcl to Python **/
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 char *s;
1774 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 if (PyTuple_Size(args) == 1) {
1777 PyObject* o = PyTuple_GetItem(args, 0);
1778 if (PyLong_Check(o)) {
1779 Py_INCREF(o);
1780 return o;
1781 }
1782 }
1783 if (!PyArg_ParseTuple(args, "s:getint", &s))
1784 return NULL;
1785 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1786 return Tkinter_Error(self);
1787 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001788}
1789
1790static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001791Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001792{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001793 char *s;
1794 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001796 if (PyTuple_Size(args) == 1) {
1797 PyObject *o = PyTuple_GetItem(args, 0);
1798 if (PyFloat_Check(o)) {
1799 Py_INCREF(o);
1800 return o;
1801 }
1802 }
1803 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1804 return NULL;
1805 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1806 return Tkinter_Error(self);
1807 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001808}
1809
1810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001811Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001812{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 char *s;
1814 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 if (PyTuple_Size(args) == 1) {
1817 PyObject *o = PyTuple_GetItem(args, 0);
1818 if (PyLong_Check(o)) {
1819 Py_INCREF(o);
1820 return o;
1821 }
1822 }
1823 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1824 return NULL;
1825 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1826 return Tkinter_Error(self);
1827 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001828}
1829
1830static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001831Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001832{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001833 char *s;
1834 PyObject *res = NULL;
1835 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1838 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001840 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001841
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 ENTER_TCL
1843 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1844 ENTER_OVERLAP
1845 if (retval == TCL_ERROR)
1846 res = Tkinter_Error(self);
1847 else
1848 res = Py_BuildValue("s", Tkapp_Result(self));
1849 LEAVE_OVERLAP_TCL
1850 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001851}
1852
1853static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001854Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001855{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001856 char *s;
1857 PyObject *res = NULL;
1858 int retval;
1859 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001860
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1862 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001866 ENTER_TCL
1867 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1868 ENTER_OVERLAP
1869 if (retval == TCL_ERROR)
1870 res = Tkinter_Error(self);
1871 else
1872 res = Py_BuildValue("l", v);
1873 LEAVE_OVERLAP_TCL
1874 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001875}
1876
1877static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001878Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001879{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001880 char *s;
1881 PyObject *res = NULL;
1882 double v;
1883 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001884
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001885 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1886 return NULL;
1887 CHECK_TCL_APPARTMENT;
1888 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1889 ENTER_TCL
1890 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1891 ENTER_OVERLAP
1892 PyFPE_END_PROTECT(retval)
1893 if (retval == TCL_ERROR)
1894 res = Tkinter_Error(self);
1895 else
1896 res = Py_BuildValue("d", v);
1897 LEAVE_OVERLAP_TCL
1898 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001899}
1900
1901static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001902Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001903{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001904 char *s;
1905 PyObject *res = NULL;
1906 int retval;
1907 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001909 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1910 return NULL;
1911 CHECK_TCL_APPARTMENT;
1912 ENTER_TCL
1913 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1914 ENTER_OVERLAP
1915 if (retval == TCL_ERROR)
1916 res = Tkinter_Error(self);
1917 else
1918 res = Py_BuildValue("i", v);
1919 LEAVE_OVERLAP_TCL
1920 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001921}
1922
Barry Warsawfa701a81997-01-16 00:15:11 +00001923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924
Guido van Rossum18468821994-06-20 07:49:28 +00001925static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001926Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001927{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001928 char *list;
1929 int argc;
1930 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001931 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001933
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001934 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1935 return NULL;
1936 if (PyTclObject_Check(arg)) {
1937 int objc;
1938 Tcl_Obj **objv;
1939 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1940 ((PyTclObject*)arg)->value,
1941 &objc, &objv) == TCL_ERROR) {
1942 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001943 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001944 if (!(v = PyTuple_New(objc)))
1945 return NULL;
1946 for (i = 0; i < objc; i++) {
1947 PyObject *s = FromObj(self, objv[i]);
1948 if (!s || PyTuple_SetItem(v, i, s)) {
1949 Py_DECREF(v);
1950 return NULL;
1951 }
1952 }
1953 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001955 if (PyTuple_Check(arg)) {
1956 Py_INCREF(arg);
1957 return arg;
1958 }
1959
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1961 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001963 if (Tcl_SplitList(Tkapp_Interp(self), list,
1964 &argc, &argv) == TCL_ERROR) {
1965 PyMem_Free(list);
1966 return Tkinter_Error(self);
1967 }
Guido van Rossum18468821994-06-20 07:49:28 +00001968
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 if (!(v = PyTuple_New(argc)))
1970 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001971
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 for (i = 0; i < argc; i++) {
1973 PyObject *s = PyUnicode_FromString(argv[i]);
1974 if (!s || PyTuple_SetItem(v, i, s)) {
1975 Py_DECREF(v);
1976 v = NULL;
1977 goto finally;
1978 }
1979 }
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Barry Warsawfa701a81997-01-16 00:15:11 +00001981 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001982 ckfree(FREECAST argv);
1983 PyMem_Free(list);
1984 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001985}
1986
1987static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001988Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001989{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001990 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001991 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001992
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001993 if (!PyArg_ParseTuple(args, "O:split", &arg))
1994 return NULL;
1995 if (PyTclObject_Check(arg)) {
1996 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1997 int objc;
1998 Tcl_Obj **objv;
1999 int i;
2000 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2001 &objc, &objv) == TCL_ERROR) {
2002 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002004 if (objc == 0)
2005 return PyUnicode_FromString("");
2006 if (objc == 1)
2007 return FromObj(self, objv[0]);
2008 if (!(v = PyTuple_New(objc)))
2009 return NULL;
2010 for (i = 0; i < objc; i++) {
2011 PyObject *s = FromObj(self, objv[i]);
2012 if (!s || PyTuple_SetItem(v, i, s)) {
2013 Py_DECREF(v);
2014 return NULL;
2015 }
2016 }
2017 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002019 if (PyTuple_Check(arg))
2020 return SplitObj(arg);
2021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002022 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2023 return NULL;
2024 v = Split(list);
2025 PyMem_Free(list);
2026 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002027}
2028
2029static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002030Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002031{
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002032 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002034
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002035 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2036 "merge is deprecated and will be removed in 3.4",
2037 1) < 0)
2038 return 0;
2039
2040 s = Merge(args);
2041
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 if (s) {
2043 res = PyUnicode_FromString(s);
2044 ckfree(s);
2045 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002047 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002048}
2049
Barry Warsawfa701a81997-01-16 00:15:11 +00002050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051
Guido van Rossum18468821994-06-20 07:49:28 +00002052/** Tcl Command **/
2053
Guido van Rossum00d93061998-05-28 23:06:38 +00002054/* Client data struct */
2055typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002056 PyObject *self;
2057 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002058} PythonCmd_ClientData;
2059
2060static int
Fred Drake509d79a2000-07-08 04:04:38 +00002061PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 errorInCmd = 1;
2064 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2065 LEAVE_PYTHON
2066 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002067}
2068
Guido van Rossum18468821994-06-20 07:49:28 +00002069/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002070 * function or method.
2071 */
Guido van Rossum18468821994-06-20 07:49:28 +00002072static int
Fred Drake509d79a2000-07-08 04:04:38 +00002073PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002075 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002076 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002077 int i, rv;
2078 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002081
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002082 /* TBD: no error checking here since we know, via the
2083 * Tkapp_CreateCommand() that the client data is a two-tuple
2084 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002086
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 /* Create argument list (argv1, ..., argvN) */
2088 if (!(arg = PyTuple_New(argc - 1)))
2089 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002091 for (i = 0; i < (argc - 1); i++) {
2092 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002093 if (!s) {
2094 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2095 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2096 !strcmp(argv[i + 1], "\xC0\x80")) {
2097 PyErr_Clear();
2098 /* Convert to "strict" utf-8 null */
2099 s = PyUnicode_FromString("\0");
2100 } else {
2101 Py_DECREF(arg);
2102 return PythonCmd_Error(interp);
2103 }
2104 }
2105 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 Py_DECREF(arg);
2107 return PythonCmd_Error(interp);
2108 }
2109 }
2110 res = PyEval_CallObject(func, arg);
2111 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 if (res == NULL)
2114 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002115
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002116 obj_res = AsObj(res);
2117 if (obj_res == NULL) {
2118 Py_DECREF(res);
2119 return PythonCmd_Error(interp);
2120 }
2121 else {
2122 Tcl_SetObjResult(interp, obj_res);
2123 rv = TCL_OK;
2124 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002126 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002127
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002128 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002129
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002130 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002131}
2132
2133static void
Fred Drake509d79a2000-07-08 04:04:38 +00002134PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002135{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 ENTER_PYTHON
2139 Py_XDECREF(data->self);
2140 Py_XDECREF(data->func);
2141 PyMem_DEL(data);
2142 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002143}
2144
Barry Warsawfa701a81997-01-16 00:15:11 +00002145
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002146
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002147
Benjamin Peterson5879d412009-03-30 14:51:56 +00002148#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002149TCL_DECLARE_MUTEX(command_mutex)
2150
2151typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002152 Tcl_Event ev;
2153 Tcl_Interp* interp;
2154 char *name;
2155 int create;
2156 int *status;
2157 ClientData *data;
2158 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002159} CommandEvent;
2160
2161static int
2162Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164 if (ev->create)
2165 *ev->status = Tcl_CreateCommand(
2166 ev->interp, ev->name, PythonCmd,
2167 ev->data, PythonCmdDelete) == NULL;
2168 else
2169 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2170 Tcl_MutexLock(&command_mutex);
2171 Tcl_ConditionNotify(ev->done);
2172 Tcl_MutexUnlock(&command_mutex);
2173 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002174}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002175#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002176
2177static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002178Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002179{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002180 TkappObject *self = (TkappObject*)selfptr;
2181 PythonCmd_ClientData *data;
2182 char *cmdName;
2183 PyObject *func;
2184 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002185
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002186 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2187 return NULL;
2188 if (!PyCallable_Check(func)) {
2189 PyErr_SetString(PyExc_TypeError, "command not callable");
2190 return NULL;
2191 }
Guido van Rossum18468821994-06-20 07:49:28 +00002192
Martin v. Löwisa9656492003-03-30 08:44:58 +00002193#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2195 !WaitForMainloop(self))
2196 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002197#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 data = PyMem_NEW(PythonCmd_ClientData, 1);
2200 if (!data)
2201 return PyErr_NoMemory();
2202 Py_INCREF(self);
2203 Py_INCREF(func);
2204 data->self = selfptr;
2205 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002206#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2208 Tcl_Condition cond = NULL;
2209 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2210 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2211 ev->interp = self->interp;
2212 ev->create = 1;
2213 ev->name = cmdName;
2214 ev->data = (ClientData)data;
2215 ev->status = &err;
2216 ev->done = &cond;
2217 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2218 Tcl_ConditionFinalize(&cond);
2219 }
2220 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002221#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002222 {
2223 ENTER_TCL
2224 err = Tcl_CreateCommand(
2225 Tkapp_Interp(self), cmdName, PythonCmd,
2226 (ClientData)data, PythonCmdDelete) == NULL;
2227 LEAVE_TCL
2228 }
2229 if (err) {
2230 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2231 PyMem_DEL(data);
2232 return NULL;
2233 }
Guido van Rossum18468821994-06-20 07:49:28 +00002234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 Py_INCREF(Py_None);
2236 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002237}
2238
Barry Warsawfa701a81997-01-16 00:15:11 +00002239
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002240
Guido van Rossum18468821994-06-20 07:49:28 +00002241static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002242Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002243{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 TkappObject *self = (TkappObject*)selfptr;
2245 char *cmdName;
2246 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2249 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002250
2251#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2253 Tcl_Condition cond = NULL;
2254 CommandEvent *ev;
2255 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2256 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2257 ev->interp = self->interp;
2258 ev->create = 0;
2259 ev->name = cmdName;
2260 ev->status = &err;
2261 ev->done = &cond;
2262 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2263 &command_mutex);
2264 Tcl_ConditionFinalize(&cond);
2265 }
2266 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002267#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268 {
2269 ENTER_TCL
2270 err = Tcl_DeleteCommand(self->interp, cmdName);
2271 LEAVE_TCL
2272 }
2273 if (err == -1) {
2274 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2275 return NULL;
2276 }
2277 Py_INCREF(Py_None);
2278 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002279}
2280
Barry Warsawfa701a81997-01-16 00:15:11 +00002281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282
Guido van Rossum00d93061998-05-28 23:06:38 +00002283#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002284/** File Handler **/
2285
Guido van Rossum00d93061998-05-28 23:06:38 +00002286typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002287 PyObject *func;
2288 PyObject *file;
2289 int id;
2290 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002291} FileHandler_ClientData;
2292
2293static FileHandler_ClientData *HeadFHCD;
2294
2295static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002296NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 FileHandler_ClientData *p;
2299 p = PyMem_NEW(FileHandler_ClientData, 1);
2300 if (p != NULL) {
2301 Py_XINCREF(func);
2302 Py_XINCREF(file);
2303 p->func = func;
2304 p->file = file;
2305 p->id = id;
2306 p->next = HeadFHCD;
2307 HeadFHCD = p;
2308 }
2309 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002310}
2311
2312static void
Fred Drake509d79a2000-07-08 04:04:38 +00002313DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002314{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 pp = &HeadFHCD;
2318 while ((p = *pp) != NULL) {
2319 if (p->id == id) {
2320 *pp = p->next;
2321 Py_XDECREF(p->func);
2322 Py_XDECREF(p->file);
2323 PyMem_DEL(p);
2324 }
2325 else
2326 pp = &p->next;
2327 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002328}
2329
Guido van Rossuma597dde1995-01-10 20:56:29 +00002330static void
Fred Drake509d79a2000-07-08 04:04:38 +00002331FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2334 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 ENTER_PYTHON
2337 func = data->func;
2338 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 arg = Py_BuildValue("(Oi)", file, (long) mask);
2341 res = PyEval_CallObject(func, arg);
2342 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002343
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002344 if (res == NULL) {
2345 errorInCmd = 1;
2346 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2347 }
2348 Py_XDECREF(res);
2349 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002350}
2351
Guido van Rossum18468821994-06-20 07:49:28 +00002352static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002353Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2354 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002355{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002356 FileHandler_ClientData *data;
2357 PyObject *file, *func;
2358 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002360 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2361 &file, &mask, &func))
2362 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 tfile = PyObject_AsFileDescriptor(file);
2367 if (tfile < 0)
2368 return NULL;
2369 if (!PyCallable_Check(func)) {
2370 PyErr_SetString(PyExc_TypeError, "bad argument list");
2371 return NULL;
2372 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374 data = NewFHCD(func, file, tfile);
2375 if (data == NULL)
2376 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 /* Ought to check for null Tcl_File object... */
2379 ENTER_TCL
2380 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2381 LEAVE_TCL
2382 Py_INCREF(Py_None);
2383 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002384}
2385
2386static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002387Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002388{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 PyObject *file;
2390 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2393 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 tfile = PyObject_AsFileDescriptor(file);
2398 if (tfile < 0)
2399 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403 /* Ought to check for null Tcl_File object... */
2404 ENTER_TCL
2405 Tcl_DeleteFileHandler(tfile);
2406 LEAVE_TCL
2407 Py_INCREF(Py_None);
2408 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002409}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002410#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002413/**** Tktt Object (timer token) ****/
2414
Jeremy Hylton938ace62002-07-17 16:30:39 +00002415static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002416
Guido van Rossum00d93061998-05-28 23:06:38 +00002417typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 PyObject_HEAD
2419 Tcl_TimerToken token;
2420 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002421} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002422
2423static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002424Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 TkttObject *v = (TkttObject *)self;
2427 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2430 return NULL;
2431 if (v->token != NULL) {
2432 Tcl_DeleteTimerHandler(v->token);
2433 v->token = NULL;
2434 }
2435 if (func != NULL) {
2436 v->func = NULL;
2437 Py_DECREF(func);
2438 Py_DECREF(v); /* See Tktt_New() */
2439 }
2440 Py_INCREF(Py_None);
2441 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002442}
2443
2444static PyMethodDef Tktt_methods[] =
2445{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002446 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2447 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002448};
2449
2450static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002451Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002452{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002455 v = PyObject_New(TkttObject, &Tktt_Type);
2456 if (v == NULL)
2457 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459 Py_INCREF(func);
2460 v->token = NULL;
2461 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002463 /* Extra reference, deleted when called or when handler is deleted */
2464 Py_INCREF(v);
2465 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002466}
2467
2468static void
Fred Drake509d79a2000-07-08 04:04:38 +00002469Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 TkttObject *v = (TkttObject *)self;
2472 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002477}
2478
Guido van Rossum597ac201998-05-12 14:36:19 +00002479static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002480Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002481{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002483 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2484 v,
2485 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002486}
2487
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002488static PyTypeObject Tktt_Type =
2489{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 PyVarObject_HEAD_INIT(NULL, 0)
2491 "tktimertoken", /*tp_name */
2492 sizeof(TkttObject), /*tp_basicsize */
2493 0, /*tp_itemsize */
2494 Tktt_Dealloc, /*tp_dealloc */
2495 0, /*tp_print */
2496 0, /*tp_getattr */
2497 0, /*tp_setattr */
2498 0, /*tp_reserved */
2499 Tktt_Repr, /*tp_repr */
2500 0, /*tp_as_number */
2501 0, /*tp_as_sequence */
2502 0, /*tp_as_mapping */
2503 0, /*tp_hash */
2504 0, /*tp_call*/
2505 0, /*tp_str*/
2506 0, /*tp_getattro*/
2507 0, /*tp_setattro*/
2508 0, /*tp_as_buffer*/
2509 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2510 0, /*tp_doc*/
2511 0, /*tp_traverse*/
2512 0, /*tp_clear*/
2513 0, /*tp_richcompare*/
2514 0, /*tp_weaklistoffset*/
2515 0, /*tp_iter*/
2516 0, /*tp_iternext*/
2517 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002518};
2519
Barry Warsawfa701a81997-01-16 00:15:11 +00002520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002522/** Timer Handler **/
2523
2524static void
Fred Drake509d79a2000-07-08 04:04:38 +00002525TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002526{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002527 TkttObject *v = (TkttObject *)clientData;
2528 PyObject *func = v->func;
2529 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 if (func == NULL)
2532 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002533
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002538 res = PyEval_CallObject(func, NULL);
2539 Py_DECREF(func);
2540 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542 if (res == NULL) {
2543 errorInCmd = 1;
2544 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2545 }
2546 else
2547 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002549 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002550}
2551
2552static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002553Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002554{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002555 int milliseconds;
2556 PyObject *func;
2557 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2560 &milliseconds, &func))
2561 return NULL;
2562 if (!PyCallable_Check(func)) {
2563 PyErr_SetString(PyExc_TypeError, "bad argument list");
2564 return NULL;
2565 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002569 v = Tktt_New(func);
2570 if (v) {
2571 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2572 (ClientData)v);
2573 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002575 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002576}
2577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002578
Guido van Rossum18468821994-06-20 07:49:28 +00002579/** Event Loop **/
2580
Guido van Rossum18468821994-06-20 07:49:28 +00002581static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002582Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002583{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584 int threshold = 0;
2585 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002586#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002587 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002588#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002590 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2591 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002593 CHECK_TCL_APPARTMENT;
2594 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002596 quitMainLoop = 0;
2597 while (Tk_GetNumMainWindows() > threshold &&
2598 !quitMainLoop &&
2599 !errorInCmd)
2600 {
2601 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002602
2603#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 if (self->threaded) {
2605 /* Allow other Python threads to run. */
2606 ENTER_TCL
2607 result = Tcl_DoOneEvent(0);
2608 LEAVE_TCL
2609 }
2610 else {
2611 Py_BEGIN_ALLOW_THREADS
2612 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2613 tcl_tstate = tstate;
2614 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2615 tcl_tstate = NULL;
2616 if(tcl_lock)PyThread_release_lock(tcl_lock);
2617 if (result == 0)
2618 Sleep(Tkinter_busywaitinterval);
2619 Py_END_ALLOW_THREADS
2620 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002621#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002623#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 if (PyErr_CheckSignals() != 0) {
2626 self->dispatching = 0;
2627 return NULL;
2628 }
2629 if (result < 0)
2630 break;
2631 }
2632 self->dispatching = 0;
2633 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635 if (errorInCmd) {
2636 errorInCmd = 0;
2637 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2638 excInCmd = valInCmd = trbInCmd = NULL;
2639 return NULL;
2640 }
2641 Py_INCREF(Py_None);
2642 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002643}
2644
2645static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002646Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002647{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002648 int flags = 0;
2649 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002651 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2652 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002654 ENTER_TCL
2655 rv = Tcl_DoOneEvent(flags);
2656 LEAVE_TCL
2657 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002658}
2659
2660static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002661Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002662{
2663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002664 if (!PyArg_ParseTuple(args, ":quit"))
2665 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 quitMainLoop = 1;
2668 Py_INCREF(Py_None);
2669 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002670}
2671
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002672static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002673Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002674{
2675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 if (!PyArg_ParseTuple(args, ":interpaddr"))
2677 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002678
Victor Stinnere1040e22013-09-05 00:22:24 +02002679 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002680}
2681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002683Tkapp_TkInit(PyObject *self, PyObject *args)
2684{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002685 Tcl_Interp *interp = Tkapp_Interp(self);
2686 const char * _tk_exists = NULL;
2687 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002688
Guilherme Polob681df42009-02-09 22:33:59 +00002689#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2691 * first call failed.
2692 * To avoid the deadlock, we just refuse the second call through
2693 * a static variable.
2694 */
2695 if (tk_load_failed) {
2696 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2697 return NULL;
2698 }
Guilherme Polob681df42009-02-09 22:33:59 +00002699#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002701 /* We want to guard against calling Tk_Init() multiple times */
2702 CHECK_TCL_APPARTMENT;
2703 ENTER_TCL
2704 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2705 ENTER_OVERLAP
2706 if (err == TCL_ERROR) {
2707 /* This sets an exception, but we cannot return right
2708 away because we need to exit the overlap first. */
2709 Tkinter_Error(self);
2710 } else {
2711 _tk_exists = Tkapp_Result(self);
2712 }
2713 LEAVE_OVERLAP_TCL
2714 if (err == TCL_ERROR) {
2715 return NULL;
2716 }
2717 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2718 if (Tk_Init(interp) == TCL_ERROR) {
2719 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002720#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002721 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002722#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 return NULL;
2724 }
2725 }
2726 Py_INCREF(Py_None);
2727 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002728}
Barry Warsawfa701a81997-01-16 00:15:11 +00002729
Martin v. Löwisffad6332002-11-26 09:28:05 +00002730static PyObject *
2731Tkapp_WantObjects(PyObject *self, PyObject *args)
2732{
2733
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002734 int wantobjects = -1;
2735 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2736 return NULL;
2737 if (wantobjects == -1)
2738 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2739 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 Py_INCREF(Py_None);
2742 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002743}
2744
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002745static PyObject *
2746Tkapp_WillDispatch(PyObject *self, PyObject *args)
2747{
2748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002749 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751 Py_INCREF(Py_None);
2752 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002753}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755
Guido van Rossum18468821994-06-20 07:49:28 +00002756/**** Tkapp Method List ****/
2757
2758static PyMethodDef Tkapp_methods[] =
2759{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002760 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2761 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2762 {"call", Tkapp_Call, METH_VARARGS},
2763 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2764 {"eval", Tkapp_Eval, METH_VARARGS},
2765 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2766 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2767 {"record", Tkapp_Record, METH_VARARGS},
2768 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2769 {"setvar", Tkapp_SetVar, METH_VARARGS},
2770 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2771 {"getvar", Tkapp_GetVar, METH_VARARGS},
2772 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2773 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2774 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2775 {"getint", Tkapp_GetInt, METH_VARARGS},
2776 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2777 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2778 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2779 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2780 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2781 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2782 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2783 {"split", Tkapp_Split, METH_VARARGS},
2784 {"merge", Tkapp_Merge, METH_VARARGS},
2785 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2786 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002787#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2789 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002790#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2792 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2793 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2794 {"quit", Tkapp_Quit, METH_VARARGS},
2795 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2796 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2797 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002798};
2799
Barry Warsawfa701a81997-01-16 00:15:11 +00002800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801
Guido van Rossum18468821994-06-20 07:49:28 +00002802/**** Tkapp Type Methods ****/
2803
2804static void
Fred Drake509d79a2000-07-08 04:04:38 +00002805Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002806{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 /*CHECK_TCL_APPARTMENT;*/
2808 ENTER_TCL
2809 Tcl_DeleteInterp(Tkapp_Interp(self));
2810 LEAVE_TCL
2811 PyObject_Del(self);
2812 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002813}
2814
Guido van Rossum18468821994-06-20 07:49:28 +00002815static PyTypeObject Tkapp_Type =
2816{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 PyVarObject_HEAD_INIT(NULL, 0)
2818 "tkapp", /*tp_name */
2819 sizeof(TkappObject), /*tp_basicsize */
2820 0, /*tp_itemsize */
2821 Tkapp_Dealloc, /*tp_dealloc */
2822 0, /*tp_print */
2823 0, /*tp_getattr */
2824 0, /*tp_setattr */
2825 0, /*tp_reserved */
2826 0, /*tp_repr */
2827 0, /*tp_as_number */
2828 0, /*tp_as_sequence */
2829 0, /*tp_as_mapping */
2830 0, /*tp_hash */
2831 0, /*tp_call*/
2832 0, /*tp_str*/
2833 0, /*tp_getattro*/
2834 0, /*tp_setattro*/
2835 0, /*tp_as_buffer*/
2836 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2837 0, /*tp_doc*/
2838 0, /*tp_traverse*/
2839 0, /*tp_clear*/
2840 0, /*tp_richcompare*/
2841 0, /*tp_weaklistoffset*/
2842 0, /*tp_iter*/
2843 0, /*tp_iternext*/
2844 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002845};
2846
Barry Warsawfa701a81997-01-16 00:15:11 +00002847
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002848
Guido van Rossum18468821994-06-20 07:49:28 +00002849/**** Tkinter Module ****/
2850
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002851typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002852 PyObject* tuple;
2853 int size; /* current size */
2854 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002855} FlattenContext;
2856
2857static int
2858_bump(FlattenContext* context, int size)
2859{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002860 /* expand tuple to hold (at least) size new items.
2861 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002862
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002863 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002864
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002865 if (maxsize < context->size + size)
2866 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002867
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002868 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002869
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002871}
2872
2873static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002874_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002875{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002876 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 if (depth > 1000) {
2881 PyErr_SetString(PyExc_ValueError,
2882 "nesting too deep in _flatten");
2883 return 0;
2884 } else if (PyList_Check(item)) {
2885 size = PyList_GET_SIZE(item);
2886 /* preallocate (assume no nesting) */
2887 if (context->size + size > context->maxsize &&
2888 !_bump(context, size))
2889 return 0;
2890 /* copy items to output tuple */
2891 for (i = 0; i < size; i++) {
2892 PyObject *o = PyList_GET_ITEM(item, i);
2893 if (PyList_Check(o) || PyTuple_Check(o)) {
2894 if (!_flatten1(context, o, depth + 1))
2895 return 0;
2896 } else if (o != Py_None) {
2897 if (context->size + 1 > context->maxsize &&
2898 !_bump(context, 1))
2899 return 0;
2900 Py_INCREF(o);
2901 PyTuple_SET_ITEM(context->tuple,
2902 context->size++, o);
2903 }
2904 }
2905 } else if (PyTuple_Check(item)) {
2906 /* same, for tuples */
2907 size = PyTuple_GET_SIZE(item);
2908 if (context->size + size > context->maxsize &&
2909 !_bump(context, size))
2910 return 0;
2911 for (i = 0; i < size; i++) {
2912 PyObject *o = PyTuple_GET_ITEM(item, i);
2913 if (PyList_Check(o) || PyTuple_Check(o)) {
2914 if (!_flatten1(context, o, depth + 1))
2915 return 0;
2916 } else if (o != Py_None) {
2917 if (context->size + 1 > context->maxsize &&
2918 !_bump(context, 1))
2919 return 0;
2920 Py_INCREF(o);
2921 PyTuple_SET_ITEM(context->tuple,
2922 context->size++, o);
2923 }
2924 }
2925 } else {
2926 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2927 return 0;
2928 }
2929 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002930}
2931
2932static PyObject *
2933Tkinter_Flatten(PyObject* self, PyObject* args)
2934{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 FlattenContext context;
2936 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002938 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2939 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002940
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002941 context.maxsize = PySequence_Size(item);
2942 if (context.maxsize < 0)
2943 return NULL;
2944 if (context.maxsize == 0)
2945 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002947 context.tuple = PyTuple_New(context.maxsize);
2948 if (!context.tuple)
2949 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002950
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002951 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 if (!_flatten1(&context, item,0))
2954 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002956 if (_PyTuple_Resize(&context.tuple, context.size))
2957 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002958
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002960}
2961
Guido van Rossum18468821994-06-20 07:49:28 +00002962static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002963Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002964{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002965 char *screenName = NULL;
2966 char *baseName = NULL; /* XXX this is not used anymore;
2967 try getting rid of it. */
2968 char *className = NULL;
2969 int interactive = 0;
2970 int wantobjects = 0;
2971 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2972 int sync = 0; /* pass -sync to wish */
2973 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002975 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002976
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002977 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2978 &screenName, &baseName, &className,
2979 &interactive, &wantobjects, &wantTk,
2980 &sync, &use))
2981 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002982
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002983 return (PyObject *) Tkapp_New(screenName, className,
2984 interactive, wantobjects, wantTk,
2985 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002986}
2987
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002988static PyObject *
2989Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2990{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002991 int new_val;
2992 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2993 return NULL;
2994 if (new_val < 0) {
2995 PyErr_SetString(PyExc_ValueError,
2996 "busywaitinterval must be >= 0");
2997 return NULL;
2998 }
2999 Tkinter_busywaitinterval = new_val;
3000 Py_INCREF(Py_None);
3001 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003002}
3003
3004static char setbusywaitinterval_doc[] =
3005"setbusywaitinterval(n) -> None\n\
3006\n\
3007Set the busy-wait interval in milliseconds between successive\n\
3008calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3009It should be set to a divisor of the maximum time between\n\
3010frames in an animation.";
3011
3012static PyObject *
3013Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3014{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003015 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003016}
3017
3018static char getbusywaitinterval_doc[] =
3019"getbusywaitinterval() -> int\n\
3020\n\
3021Return the current busy-wait interval between successive\n\
3022calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3023
Guido van Rossum18468821994-06-20 07:49:28 +00003024static PyMethodDef moduleMethods[] =
3025{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003026 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3027 {"create", Tkinter_Create, METH_VARARGS},
3028 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3029 setbusywaitinterval_doc},
3030 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3031 METH_NOARGS, getbusywaitinterval_doc},
3032 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003033};
3034
Guido van Rossum7bf15641998-05-22 18:28:17 +00003035#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003036
3037static int stdin_ready = 0;
3038
Guido van Rossumad4db171998-06-13 13:56:28 +00003039#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003040static void
Fred Drake509d79a2000-07-08 04:04:38 +00003041MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003042{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003043 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003044}
Guido van Rossumad4db171998-06-13 13:56:28 +00003045#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003046
Martin v. Löwisa9656492003-03-30 08:44:58 +00003047#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003048static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003049#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003050
Guido van Rossum18468821994-06-20 07:49:28 +00003051static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003052EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003053{
Guido van Rossumad4db171998-06-13 13:56:28 +00003054#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003056#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003057#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003058 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003059#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003060 stdin_ready = 0;
3061 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003062#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003063 tfile = fileno(stdin);
3064 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003065#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003066 while (!errorInCmd && !stdin_ready) {
3067 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003068#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003069 if (_kbhit()) {
3070 stdin_ready = 1;
3071 break;
3072 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003073#endif
3074#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003075 Py_BEGIN_ALLOW_THREADS
3076 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3077 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003079 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003081 tcl_tstate = NULL;
3082 if(tcl_lock)PyThread_release_lock(tcl_lock);
3083 if (result == 0)
3084 Sleep(Tkinter_busywaitinterval);
3085 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003086#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003087 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003088#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003090 if (result < 0)
3091 break;
3092 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003093#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003094 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003095#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003096 if (errorInCmd) {
3097 errorInCmd = 0;
3098 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3099 excInCmd = valInCmd = trbInCmd = NULL;
3100 PyErr_Print();
3101 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003102#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003103 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003104#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003105 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003106}
Guido van Rossum18468821994-06-20 07:49:28 +00003107
Guido van Rossum00d93061998-05-28 23:06:38 +00003108#endif
3109
Guido van Rossum7bf15641998-05-22 18:28:17 +00003110static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003111EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003112{
Guido van Rossum00d93061998-05-28 23:06:38 +00003113#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003114 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003115#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003116 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003117#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 PyOS_InputHook = EventHook;
3119 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003120#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003121}
3122
3123static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003124DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003125{
Guido van Rossum00d93061998-05-28 23:06:38 +00003126#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3128 PyOS_InputHook = NULL;
3129 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003130#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003131}
3132
Barry Warsawfa701a81997-01-16 00:15:11 +00003133
3134/* all errors will be checked in one fell swoop in init_tkinter() */
3135static void
Fred Drake509d79a2000-07-08 04:04:38 +00003136ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003137{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003138 PyObject *v = PyLong_FromLong(val);
3139 if (v) {
3140 PyDict_SetItemString(d, name, v);
3141 Py_DECREF(v);
3142 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003143}
3144static void
Fred Drake509d79a2000-07-08 04:04:38 +00003145ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003146{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 PyObject *v = PyUnicode_FromString(val);
3148 if (v) {
3149 PyDict_SetItemString(d, name, v);
3150 Py_DECREF(v);
3151 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003152}
3153
3154
Martin v. Löwis1a214512008-06-11 05:26:20 +00003155static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003156 PyModuleDef_HEAD_INIT,
3157 "_tkinter",
3158 NULL,
3159 -1,
3160 moduleMethods,
3161 NULL,
3162 NULL,
3163 NULL,
3164 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003165};
3166
Mark Hammond62b1ab12002-07-23 06:31:15 +00003167PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003168PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003169{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003170 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003172 if (PyType_Ready(&Tkapp_Type) < 0)
3173 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003174
3175#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003176 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003177#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003179 m = PyModule_Create(&_tkintermodule);
3180 if (m == NULL)
3181 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003183 d = PyModule_GetDict(m);
3184 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3185 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003186
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003187 ins_long(d, "READABLE", TCL_READABLE);
3188 ins_long(d, "WRITABLE", TCL_WRITABLE);
3189 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3190 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3191 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3192 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3193 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3194 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3195 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3196 ins_string(d, "TK_VERSION", TK_VERSION);
3197 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003199 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003200
Jesus Ceaef86d122012-07-19 21:18:07 +02003201 if (PyType_Ready(&Tktt_Type) < 0) {
3202 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003203 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003204 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003205 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003207 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3208 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003209
3210#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003211 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3212 * start waking up. Note that Tcl_FindExecutable will do this, this
3213 * code must be above it! The original warning from
3214 * tkMacOSXAppInit.c is copied below.
3215 *
3216 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3217 * Tcl interpreter for now. It probably should work to do this
3218 * in the other order, but for now it doesn't seem to.
3219 *
3220 */
3221 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003222#endif
3223
3224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003225 /* This helps the dynamic loader; in Unicode aware Tcl versions
3226 it also helps Tcl find its encodings. */
3227 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3228 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003229 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003230 if (cexe)
3231 Tcl_FindExecutable(PyBytes_AsString(cexe));
3232 Py_XDECREF(cexe);
3233 Py_DECREF(uexe);
3234 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003236 if (PyErr_Occurred()) {
3237 Py_DECREF(m);
3238 return NULL;
3239 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003240
Guido van Rossum43ff8681998-07-14 18:02:13 +00003241#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003242 /* This was not a good idea; through <Destroy> bindings,
3243 Tcl_Finalize() may invoke Python code but at that point the
3244 interpreter and thread state have already been destroyed! */
3245 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003246#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003247 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003248}