blob: 630ce7214f1bf2f66d7b3a1bb81d481d032bb0b3 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
Christian Heimes217cfd12007-12-02 14:31:20 +000047#define PyBool_FromLong PyLong_FromLong
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000048#endif
49
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Guilherme Polo2d87e422009-04-10 22:19:09 +000070#include "tkinter.h"
71
Jason Tishlerbbe89612002-12-31 20:30:46 +000072/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#ifndef CONST84_RETURN
74#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000075#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#define CONST
77#endif
78
Guilherme Polo66917722009-02-09 22:35:27 +000079#if TK_VERSION_HEX < 0x08030102
80#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Jack Janseneddc1442003-11-20 01:44:59 +000083#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000084#define HAVE_CREATEFILEHANDLER
85#endif
86
Guido van Rossum00d93061998-05-28 23:06:38 +000087#ifdef HAVE_CREATEFILEHANDLER
88
Neal Norwitzd948a432006-01-08 01:08:55 +000089/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
90 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
91#ifndef TCL_UNIX_FD
92# ifdef TCL_WIN_SOCKET
93# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
94# else
95# define TCL_UNIX_FD 1
96# endif
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* Tcl_CreateFileHandler() changed several times; these macros deal with the
100 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
101 Unix, only because Jack added it back); when available on Windows, it only
102 applies to sockets. */
103
Guido van Rossum7bf15641998-05-22 18:28:17 +0000104#ifdef MS_WINDOWS
105#define FHANDLETYPE TCL_WIN_SOCKET
106#else
107#define FHANDLETYPE TCL_UNIX_FD
108#endif
109
Guido van Rossum00d93061998-05-28 23:06:38 +0000110/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
111 which uses this to handle Tcl events while the user is typing commands. */
112
113#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000114#define WAIT_FOR_STDIN
115#endif
116
Guido van Rossum00d93061998-05-28 23:06:38 +0000117#endif /* HAVE_CREATEFILEHANDLER */
118
Guido van Rossumad4db171998-06-13 13:56:28 +0000119#ifdef MS_WINDOWS
120#include <conio.h>
121#define WAIT_FOR_STDIN
122#endif
123
Guido van Rossum00d93061998-05-28 23:06:38 +0000124#ifdef WITH_THREAD
125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000126/* The threading situation is complicated. Tcl is not thread-safe, except
127 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000128 So we need to use a lock around all uses of Tcl. Previously, the Python
129 interpreter lock was used for this. However, this causes problems when
130 other Python threads need to run while Tcl is blocked waiting for events.
131
132 To solve this problem, a separate lock for Tcl is introduced. Holding it
133 is incompatible with holding Python's interpreter lock. The following four
134 macros manipulate both locks together.
135
136 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
137 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
138 that could call an event handler, or otherwise affect the state of a Tcl
139 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000140 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000141 released and the lock for Tcl has been acquired.
142
Guido van Rossum5e977831998-06-15 14:03:52 +0000143 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
144 (For example, when transferring data from the Tcl interpreter result to a
145 Python string object.) This can be done by using different macros to close
146 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
147 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
148 releases the Tcl lock.
149
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000150 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000151 handlers when the handler needs to use Python. Such event handlers are
152 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000153 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000154 the Python interpreter lock, restoring the appropriate thread state, and
155 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
156 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000157 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000158
159 These locks expand to several statements and brackets; they should not be
160 used in branches of if statements and the like.
161
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000162 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
163 only valid in the thread that created it, and all Tk activity must happen in this
164 thread, also. That means that the mainloop must be invoked in the thread that
165 created the interpreter. Invoking commands from other threads is possible;
166 _tkinter will queue an event for the interpreter thread, which will then
167 execute the command and pass back the result. If the main thread is not in the
168 mainloop, and invoking commands causes an exception; if the main loop is running
169 but not processing events, the command invocation will block.
170
171 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
172 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
173 threads. So we use the Tcl TLS API.
174
Guido van Rossum00d93061998-05-28 23:06:38 +0000175*/
176
Guido van Rossum65d5b571998-12-21 19:32:43 +0000177static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178
179#ifdef TCL_THREADS
180static Tcl_ThreadDataKey state_key;
181typedef PyThreadState *ThreadSpecificData;
182#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
183#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000184static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000185#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000186
187#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
189 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000190
191#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000192 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000193
Guido van Rossum62320c91998-06-15 04:36:09 +0000194#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000196
197#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000199
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
202 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
204#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 { PyThreadState *tstate = PyEval_SaveThread(); \
206 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000207
208#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 if (((TkappObject *)self)->threaded && \
210 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
211 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
212 return 0; \
213 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000214
215#else
216
217#define ENTER_TCL
218#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000219#define ENTER_OVERLAP
220#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000221#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000222#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000223#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000224
225#endif
226
Guido van Rossum97867b21996-08-08 19:09:53 +0000227#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000228#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000229#endif
230
Guido van Rossum18468821994-06-20 07:49:28 +0000231/**** Tkapp Object Declaration ****/
232
Jeremy Hylton938ace62002-07-17 16:30:39 +0000233static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000234
Guido van Rossum00d93061998-05-28 23:06:38 +0000235typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 PyObject_HEAD
237 Tcl_Interp *interp;
238 int wantobjects;
239 int threaded; /* True if tcl_platform[threaded] */
240 Tcl_ThreadId thread_id;
241 int dispatching;
242 /* We cannot include tclInt.h, as this is internal.
243 So we cache interesting types here. */
244 Tcl_ObjType *BooleanType;
245 Tcl_ObjType *ByteArrayType;
246 Tcl_ObjType *DoubleType;
247 Tcl_ObjType *IntType;
248 Tcl_ObjType *ListType;
249 Tcl_ObjType *ProcBodyType;
250 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000251} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000252
Christian Heimes90aa7642007-12-19 02:45:37 +0000253#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000254#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000255#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guido van Rossum35d43371997-08-02 00:09:09 +0000257#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000258(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000259
Barry Warsawfa701a81997-01-16 00:15:11 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262/**** Error Handling ****/
263
264static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000265static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000266static int errorInCmd = 0;
267static PyObject *excInCmd;
268static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000269static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guilherme Polob681df42009-02-09 22:33:59 +0000271#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000272static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000273#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275
Guido van Rossum18468821994-06-20 07:49:28 +0000276static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000277Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
280 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000281}
282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284
Guido van Rossum18468821994-06-20 07:49:28 +0000285/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000286
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000287static int Tkinter_busywaitinterval = 20;
288
Guido van Rossum00d93061998-05-28 23:06:38 +0000289#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000290#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000291
Guido van Rossum00d93061998-05-28 23:06:38 +0000292/* Millisecond sleep() for Unix platforms. */
293
294static void
Fred Drake509d79a2000-07-08 04:04:38 +0000295Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000296{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 /* XXX Too bad if you don't have select(). */
298 struct timeval t;
299 t.tv_sec = milli/1000;
300 t.tv_usec = (milli%1000) * 1000;
301 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000302}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000303#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000304
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000305/* Wait up to 1s for the mainloop to come up. */
306
307static int
308WaitForMainloop(TkappObject* self)
309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 int i;
311 for (i = 0; i < 10; i++) {
312 if (self->dispatching)
313 return 1;
314 Py_BEGIN_ALLOW_THREADS
315 Sleep(100);
316 Py_END_ALLOW_THREADS
317 }
318 if (self->dispatching)
319 return 1;
320 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
321 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000322}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000323#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325
Guido van Rossum18468821994-06-20 07:49:28 +0000326static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000327AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000328{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 if (PyBytes_Check(value))
330 return PyBytes_AsString(value);
331 else if (PyUnicode_Check(value)) {
332 PyObject *v = PyUnicode_AsUTF8String(value);
333 if (v == NULL)
334 return NULL;
335 if (PyList_Append(tmp, v) != 0) {
336 Py_DECREF(v);
337 return NULL;
338 }
339 Py_DECREF(v);
340 return PyBytes_AsString(v);
341 }
342 else {
343 PyObject *v = PyObject_Str(value);
344 if (v == NULL)
345 return NULL;
346 if (PyList_Append(tmp, v) != 0) {
347 Py_DECREF(v);
348 return NULL;
349 }
350 Py_DECREF(v);
351 return PyBytes_AsString(v);
352 }
Guido van Rossum18468821994-06-20 07:49:28 +0000353}
354
Barry Warsawfa701a81997-01-16 00:15:11 +0000355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356
Guido van Rossum18468821994-06-20 07:49:28 +0000357#define ARGSZ 64
358
359static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000360Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 PyObject *tmp = NULL;
363 char *argvStore[ARGSZ];
364 char **argv = NULL;
365 int fvStore[ARGSZ];
366 int *fv = NULL;
367 int argc = 0, fvc = 0, i;
368 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 if (!(tmp = PyList_New(0)))
371 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 argv = argvStore;
374 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 if (args == NULL)
377 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 else if (!PyTuple_Check(args)) {
380 argc = 1;
381 fv[0] = 0;
382 if (!(argv[0] = AsString(args, tmp)))
383 goto finally;
384 }
385 else {
386 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 if (argc > ARGSZ) {
389 argv = (char **)ckalloc(argc * sizeof(char *));
390 fv = (int *)ckalloc(argc * sizeof(int));
391 if (argv == NULL || fv == NULL) {
392 PyErr_NoMemory();
393 goto finally;
394 }
395 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 for (i = 0; i < argc; i++) {
398 PyObject *v = PyTuple_GetItem(args, i);
399 if (PyTuple_Check(v)) {
400 fv[i] = 1;
401 if (!(argv[i] = Merge(v)))
402 goto finally;
403 fvc++;
404 }
405 else if (v == Py_None) {
406 argc = i;
407 break;
408 }
409 else {
410 fv[i] = 0;
411 if (!(argv[i] = AsString(v, tmp)))
412 goto finally;
413 fvc++;
414 }
415 }
416 }
417 res = Tcl_Merge(argc, argv);
418 if (res == NULL)
419 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000420
Barry Warsawfa701a81997-01-16 00:15:11 +0000421 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 for (i = 0; i < fvc; i++)
423 if (fv[i]) {
424 ckfree(argv[i]);
425 }
426 if (argv != argvStore)
427 ckfree(FREECAST argv);
428 if (fv != fvStore)
429 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 Py_DECREF(tmp);
432 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000433}
434
Barry Warsawfa701a81997-01-16 00:15:11 +0000435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000436
Guido van Rossum18468821994-06-20 07:49:28 +0000437static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000438Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000439{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 int argc;
441 char **argv;
442 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000443
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 if (list == NULL) {
445 Py_INCREF(Py_None);
446 return Py_None;
447 }
Guido van Rossum18468821994-06-20 07:49:28 +0000448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
450 /* Not a list.
451 * Could be a quoted string containing funnies, e.g. {"}.
452 * Return the string itself.
453 */
454 return PyUnicode_FromString(list);
455 }
Guido van Rossum18468821994-06-20 07:49:28 +0000456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 if (argc == 0)
458 v = PyUnicode_FromString("");
459 else if (argc == 1)
460 v = PyUnicode_FromString(argv[0]);
461 else if ((v = PyTuple_New(argc)) != NULL) {
462 int i;
463 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000465 for (i = 0; i < argc; i++) {
466 if ((w = Split(argv[i])) == NULL) {
467 Py_DECREF(v);
468 v = NULL;
469 break;
470 }
471 PyTuple_SetItem(v, i, w);
472 }
473 }
474 Tcl_Free(FREECAST argv);
475 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000476}
477
Martin v. Löwisffad6332002-11-26 09:28:05 +0000478/* In some cases, Tcl will still return strings that are supposed to be
479 lists. SplitObj walks through a nested tuple, finding string objects that
480 need to be split. */
481
Martin v. Löwis59683e82008-06-13 07:50:45 +0000482static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000483SplitObj(PyObject *arg)
484{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 if (PyTuple_Check(arg)) {
486 int i, size;
487 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 size = PyTuple_Size(arg);
490 result = NULL;
491 /* Recursively invoke SplitObj for all tuple items.
492 If this does not return a new object, no action is
493 needed. */
494 for(i = 0; i < size; i++) {
495 elem = PyTuple_GetItem(arg, i);
496 newelem = SplitObj(elem);
497 if (!newelem) {
498 Py_XDECREF(result);
499 return NULL;
500 }
501 if (!result) {
502 int k;
503 if (newelem == elem) {
504 Py_DECREF(newelem);
505 continue;
506 }
507 result = PyTuple_New(size);
508 if (!result)
509 return NULL;
510 for(k = 0; k < i; k++) {
511 elem = PyTuple_GetItem(arg, k);
512 Py_INCREF(elem);
513 PyTuple_SetItem(result, k, elem);
514 }
515 }
516 PyTuple_SetItem(result, i, newelem);
517 }
518 if (result)
519 return result;
520 /* Fall through, returning arg. */
521 }
522 else if (PyBytes_Check(arg)) {
523 int argc;
524 char **argv;
525 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
528 Py_INCREF(arg);
529 return arg;
530 }
531 Tcl_Free(FREECAST argv);
532 if (argc > 1)
533 return Split(PyBytes_AsString(arg));
534 /* Fall through, returning arg. */
535 }
536 Py_INCREF(arg);
537 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000538}
Barry Warsawfa701a81997-01-16 00:15:11 +0000539
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540
Guido van Rossum18468821994-06-20 07:49:28 +0000541/**** Tkapp Object ****/
542
543#ifndef WITH_APPINIT
544int
Fred Drake509d79a2000-07-08 04:04:38 +0000545Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000546{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 if (Tcl_Init(interp) == TCL_ERROR) {
550 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
551 return TCL_ERROR;
552 }
Guilherme Polob681df42009-02-09 22:33:59 +0000553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 _tkinter_skip_tk_init = Tcl_GetVar(interp,
555 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
556 if (_tkinter_skip_tk_init != NULL &&
557 strcmp(_tkinter_skip_tk_init, "1") == 0) {
558 return TCL_OK;
559 }
Guilherme Polob681df42009-02-09 22:33:59 +0000560
561#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 if (tk_load_failed) {
563 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
564 return TCL_ERROR;
565 }
Guilherme Polob681df42009-02-09 22:33:59 +0000566#endif
567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000569#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000571#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
573 return TCL_ERROR;
574 }
Guilherme Polob681df42009-02-09 22:33:59 +0000575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000577}
578#endif /* !WITH_APPINIT */
579
Guido van Rossum18468821994-06-20 07:49:28 +0000580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581
Barry Warsawfa701a81997-01-16 00:15:11 +0000582
583/* Initialize the Tk application; see the `main' function in
584 * `tkMain.c'.
585 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000586
Thomas Wouters58d05102000-07-24 14:43:35 +0000587static void EnableEventHook(void); /* Forward */
588static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000589
Barry Warsawfa701a81997-01-16 00:15:11 +0000590static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000591Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 TkappObject *v;
595 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 v = PyObject_New(TkappObject, &Tkapp_Type);
598 if (v == NULL)
599 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 v->interp = Tcl_CreateInterp();
602 v->wantobjects = wantobjects;
603 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
604 TCL_GLOBAL_ONLY) != NULL;
605 v->thread_id = Tcl_GetCurrentThread();
606 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000607
608#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (v->threaded) {
610 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
611 Py_DECREF(v);
612 return 0;
613 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000614#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000615#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 if (v->threaded && tcl_lock) {
617 /* If Tcl is threaded, we don't need the lock. */
618 PyThread_free_lock(tcl_lock);
619 tcl_lock = NULL;
620 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000621#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 v->BooleanType = Tcl_GetObjType("boolean");
624 v->ByteArrayType = Tcl_GetObjType("bytearray");
625 v->DoubleType = Tcl_GetObjType("double");
626 v->IntType = Tcl_GetObjType("int");
627 v->ListType = Tcl_GetObjType("list");
628 v->ProcBodyType = Tcl_GetObjType("procbody");
629 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 /* Delete the 'exit' command, which can screw things up */
632 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 if (screenName != NULL)
635 Tcl_SetVar2(v->interp, "env", "DISPLAY",
636 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 if (interactive)
639 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
640 else
641 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 /* This is used to get the application class for Tk 4.1 and up */
644 argv0 = (char*)ckalloc(strlen(className) + 1);
645 if (!argv0) {
646 PyErr_NoMemory();
647 Py_DECREF(v);
648 return NULL;
649 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200652 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
653 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
655 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 if (! wantTk) {
658 Tcl_SetVar(v->interp,
659 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
660 }
Guilherme Polob681df42009-02-09 22:33:59 +0000661#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 else if (tk_load_failed) {
663 Tcl_SetVar(v->interp,
664 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
665 }
Guilherme Polob681df42009-02-09 22:33:59 +0000666#endif
David Aschere2b4b322004-02-18 05:59:53 +0000667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 /* some initial arguments need to be in argv */
669 if (sync || use) {
670 char *args;
671 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 if (sync)
674 len += sizeof "-sync";
675 if (use)
676 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 args = (char*)ckalloc(len);
679 if (!args) {
680 PyErr_NoMemory();
681 Py_DECREF(v);
682 return NULL;
683 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 args[0] = '\0';
686 if (sync)
687 strcat(args, "-sync");
688 if (use) {
689 if (sync)
690 strcat(args, " ");
691 strcat(args, "-use ");
692 strcat(args, use);
693 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
696 ckfree(args);
697 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 if (Tcl_AppInit(v->interp) != TCL_OK) {
700 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000701#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 if (wantTk) {
703 const char *_tkinter_tk_failed;
704 _tkinter_tk_failed = Tcl_GetVar(v->interp,
705 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 if ( _tkinter_tk_failed != NULL &&
708 strcmp(_tkinter_tk_failed, "1") == 0) {
709 tk_load_failed = 1;
710 }
711 }
Guilherme Polob681df42009-02-09 22:33:59 +0000712#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713 Py_DECREF((PyObject *)v);
714 return (TkappObject *)result;
715 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000720}
721
Barry Warsawfa701a81997-01-16 00:15:11 +0000722
Benjamin Peterson5879d412009-03-30 14:51:56 +0000723#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000724static void
725Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000727{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 Py_BEGIN_ALLOW_THREADS;
729 Tcl_MutexLock(mutex);
730 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
731 Tcl_ThreadAlert(self->thread_id);
732 Tcl_ConditionWait(cond, mutex, NULL);
733 Tcl_MutexUnlock(mutex);
734 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000735}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000736#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738
Guido van Rossum18468821994-06-20 07:49:28 +0000739/** Tcl Eval **/
740
Martin v. Löwisffad6332002-11-26 09:28:05 +0000741typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 PyObject_HEAD
743 Tcl_Obj *value;
744 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000745} PyTclObject;
746
Neal Norwitz227b5332006-03-22 09:28:35 +0000747static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000749
750static PyObject *
751newPyTclObject(Tcl_Obj *arg)
752{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753 PyTclObject *self;
754 self = PyObject_New(PyTclObject, &PyTclObject_Type);
755 if (self == NULL)
756 return NULL;
757 Tcl_IncrRefCount(arg);
758 self->value = arg;
759 self->string = NULL;
760 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000761}
762
763static void
764PyTclObject_dealloc(PyTclObject *self)
765{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 Tcl_DecrRefCount(self->value);
767 Py_XDECREF(self->string);
768 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000769}
770
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000771static char*
772PyTclObject_TclString(PyObject *self)
773{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000774 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000775}
776
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000777/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000778PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000779"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000780
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000781static PyObject *
782PyTclObject_string(PyTclObject *self, void *ignored)
783{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000784 char *s;
785 int len;
786 if (!self->string) {
787 s = Tcl_GetStringFromObj(self->value, &len);
788 self->string = PyUnicode_FromStringAndSize(s, len);
789 if (!self->string)
790 return NULL;
791 }
792 Py_INCREF(self->string);
793 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000794}
795
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000796static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000797PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000798{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000799 char *s;
800 int len;
801 if (self->string && PyUnicode_Check(self->string)) {
802 Py_INCREF(self->string);
803 return self->string;
804 }
805 /* XXX Could chache result if it is non-ASCII. */
806 s = Tcl_GetStringFromObj(self->value, &len);
807 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000808}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000809
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810static PyObject *
811PyTclObject_repr(PyTclObject *self)
812{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000813 return PyUnicode_FromFormat("<%s object at %p>",
814 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000815}
816
Mark Dickinson211c6252009-02-01 10:28:51 +0000817#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
818
819static PyObject *
820PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000821{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000822 int result;
823 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000824
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 /* neither argument should be NULL, unless something's gone wrong */
826 if (self == NULL || other == NULL) {
827 PyErr_BadInternalCall();
828 return NULL;
829 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000830
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000831 /* both arguments should be instances of PyTclObject */
832 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
833 v = Py_NotImplemented;
834 goto finished;
835 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 if (self == other)
838 /* fast path when self and other are identical */
839 result = 0;
840 else
841 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
842 Tcl_GetString(((PyTclObject *)other)->value));
843 /* Convert return value to a Boolean */
844 switch (op) {
845 case Py_EQ:
846 v = TEST_COND(result == 0);
847 break;
848 case Py_NE:
849 v = TEST_COND(result != 0);
850 break;
851 case Py_LE:
852 v = TEST_COND(result <= 0);
853 break;
854 case Py_GE:
855 v = TEST_COND(result >= 0);
856 break;
857 case Py_LT:
858 v = TEST_COND(result < 0);
859 break;
860 case Py_GT:
861 v = TEST_COND(result > 0);
862 break;
863 default:
864 PyErr_BadArgument();
865 return NULL;
866 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000867 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 Py_INCREF(v);
869 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000870}
871
Martin v. Löwis39195712003-01-04 00:33:13 +0000872PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
873
Martin v. Löwisffad6332002-11-26 09:28:05 +0000874static PyObject*
875get_typename(PyTclObject* obj, void* ignored)
876{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000877 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000878}
879
Martin v. Löwis39195712003-01-04 00:33:13 +0000880
Martin v. Löwisffad6332002-11-26 09:28:05 +0000881static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000882 {"typename", (getter)get_typename, NULL, get_typename__doc__},
883 {"string", (getter)PyTclObject_string, NULL,
884 PyTclObject_string__doc__},
885 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000886};
887
Neal Norwitz227b5332006-03-22 09:28:35 +0000888static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000889 PyVarObject_HEAD_INIT(NULL, 0)
890 "_tkinter.Tcl_Obj", /*tp_name*/
891 sizeof(PyTclObject), /*tp_basicsize*/
892 0, /*tp_itemsize*/
893 /* methods */
894 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
895 0, /*tp_print*/
896 0, /*tp_getattr*/
897 0, /*tp_setattr*/
898 0, /*tp_reserved*/
899 (reprfunc)PyTclObject_repr, /*tp_repr*/
900 0, /*tp_as_number*/
901 0, /*tp_as_sequence*/
902 0, /*tp_as_mapping*/
903 0, /*tp_hash*/
904 0, /*tp_call*/
905 (reprfunc)PyTclObject_str, /*tp_str*/
906 PyObject_GenericGetAttr, /*tp_getattro*/
907 0, /*tp_setattro*/
908 0, /*tp_as_buffer*/
909 Py_TPFLAGS_DEFAULT, /*tp_flags*/
910 0, /*tp_doc*/
911 0, /*tp_traverse*/
912 0, /*tp_clear*/
913 PyTclObject_richcompare, /*tp_richcompare*/
914 0, /*tp_weaklistoffset*/
915 0, /*tp_iter*/
916 0, /*tp_iternext*/
917 0, /*tp_methods*/
918 0, /*tp_members*/
919 PyTclObject_getsetlist, /*tp_getset*/
920 0, /*tp_base*/
921 0, /*tp_dict*/
922 0, /*tp_descr_get*/
923 0, /*tp_descr_set*/
924 0, /*tp_dictoffset*/
925 0, /*tp_init*/
926 0, /*tp_alloc*/
927 0, /*tp_new*/
928 0, /*tp_free*/
929 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000930};
931
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000932static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000933AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000934{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 Tcl_Obj *result;
936 long longVal;
937 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000939 if (PyBytes_Check(value))
940 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
941 PyBytes_GET_SIZE(value));
942 else if (PyBool_Check(value))
943 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
944 else if (PyLong_CheckExact(value) &&
945 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
946 !overflow)) {
947 /* If there is an overflow in the long conversion,
948 fall through to default object handling. */
949 return Tcl_NewLongObj(longVal);
950 }
951 else if (PyFloat_Check(value))
952 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
953 else if (PyTuple_Check(value)) {
954 Tcl_Obj **argv = (Tcl_Obj**)
955 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
956 int i;
957 if(!argv)
958 return 0;
959 for(i=0;i<PyTuple_Size(value);i++)
960 argv[i] = AsObj(PyTuple_GetItem(value,i));
961 result = Tcl_NewListObj(PyTuple_Size(value), argv);
962 ckfree(FREECAST argv);
963 return result;
964 }
965 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200966 void *inbuf;
967 Py_ssize_t size;
968 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000969 Tcl_UniChar *outbuf = NULL;
970 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200971 size_t allocsize;
972
973 if (PyUnicode_READY(value) == -1)
974 return NULL;
975
976 inbuf = PyUnicode_DATA(value);
977 size = PyUnicode_GET_LENGTH(value);
978 kind = PyUnicode_KIND(value);
979 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
980 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 /* Else overflow occurred, and we take the next exit */
982 if (!outbuf) {
983 PyErr_NoMemory();
984 return NULL;
985 }
986 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200987 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
988 /* We cannot test for sizeof(Tcl_UniChar) directly,
989 so we test for UTF-8 size instead. */
990#if TCL_UTF_MAX == 3
991 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000992 /* Tcl doesn't do UTF-16, yet. */
Victor Stinner7ab41922011-11-04 00:36:46 +0100993 PyErr_Format(PyExc_ValueError,
994 "character U+%x is above the range "
995 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100996 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 ckfree(FREECAST outbuf);
998 return NULL;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200999#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001001 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 }
1003 result = Tcl_NewUnicodeObj(outbuf, size);
1004 ckfree(FREECAST outbuf);
1005 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 }
1007 else if(PyTclObject_Check(value)) {
1008 Tcl_Obj *v = ((PyTclObject*)value)->value;
1009 Tcl_IncrRefCount(v);
1010 return v;
1011 }
1012 else {
1013 PyObject *v = PyObject_Str(value);
1014 if (!v)
1015 return 0;
1016 result = AsObj(v);
1017 Py_DECREF(v);
1018 return result;
1019 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001020}
1021
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022static PyObject*
1023FromObj(PyObject* tkapp, Tcl_Obj *value)
1024{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 PyObject *result = NULL;
1026 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001028 if (value->typePtr == NULL) {
1029 return PyUnicode_FromStringAndSize(value->bytes,
1030 value->length);
1031 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001032
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001033 if (value->typePtr == app->BooleanType) {
1034 result = value->internalRep.longValue ? Py_True : Py_False;
1035 Py_INCREF(result);
1036 return result;
1037 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001039 if (value->typePtr == app->ByteArrayType) {
1040 int size;
1041 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1042 return PyBytes_FromStringAndSize(data, size);
1043 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 if (value->typePtr == app->DoubleType) {
1046 return PyFloat_FromDouble(value->internalRep.doubleValue);
1047 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001049 if (value->typePtr == app->IntType) {
1050 return PyLong_FromLong(value->internalRep.longValue);
1051 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001053 if (value->typePtr == app->ListType) {
1054 int size;
1055 int i, status;
1056 PyObject *elem;
1057 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1060 if (status == TCL_ERROR)
1061 return Tkinter_Error(tkapp);
1062 result = PyTuple_New(size);
1063 if (!result)
1064 return NULL;
1065 for (i = 0; i < size; i++) {
1066 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1067 value, i, &tcl_elem);
1068 if (status == TCL_ERROR) {
1069 Py_DECREF(result);
1070 return Tkinter_Error(tkapp);
1071 }
1072 elem = FromObj(tkapp, tcl_elem);
1073 if (!elem) {
1074 Py_DECREF(result);
1075 return NULL;
1076 }
1077 PyTuple_SetItem(result, i, elem);
1078 }
1079 return result;
1080 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001081
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 if (value->typePtr == app->ProcBodyType) {
1083 /* fall through: return tcl object. */
1084 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001085
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001087#if TCL_UTF_MAX==3
1088 return PyUnicode_FromKindAndData(
1089 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1090 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001091#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001092 return PyUnicode_FromKindAndData(
1093 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1094 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001095#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001098 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001099}
1100
Benjamin Peterson5879d412009-03-30 14:51:56 +00001101#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001102/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001103TCL_DECLARE_MUTEX(call_mutex)
1104
1105typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 Tcl_Event ev; /* Must be first */
1107 TkappObject *self;
1108 PyObject *args;
1109 int flags;
1110 PyObject **res;
1111 PyObject **exc_type, **exc_value, **exc_tb;
1112 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001113} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001114#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001115
1116void
1117Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001118{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 int i;
1120 for (i = 0; i < objc; i++)
1121 Tcl_DecrRefCount(objv[i]);
1122 if (objv != objStore)
1123 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124}
Guido van Rossum18468821994-06-20 07:49:28 +00001125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126/* Convert Python objects to Tcl objects. This must happen in the
1127 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001128
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001129static Tcl_Obj**
1130Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1131{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 Tcl_Obj **objv = objStore;
1133 int objc = 0, i;
1134 if (args == NULL)
1135 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 else if (!PyTuple_Check(args)) {
1138 objv[0] = AsObj(args);
1139 if (objv[0] == 0)
1140 goto finally;
1141 objc = 1;
1142 Tcl_IncrRefCount(objv[0]);
1143 }
1144 else {
1145 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001147 if (objc > ARGSZ) {
1148 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1149 if (objv == NULL) {
1150 PyErr_NoMemory();
1151 objc = 0;
1152 goto finally;
1153 }
1154 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 for (i = 0; i < objc; i++) {
1157 PyObject *v = PyTuple_GetItem(args, i);
1158 if (v == Py_None) {
1159 objc = i;
1160 break;
1161 }
1162 objv[i] = AsObj(v);
1163 if (!objv[i]) {
1164 /* Reset objc, so it attempts to clear
1165 objects only up to i. */
1166 objc = i;
1167 goto finally;
1168 }
1169 Tcl_IncrRefCount(objv[i]);
1170 }
1171 }
1172 *pobjc = objc;
1173 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001174finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001175 Tkapp_CallDeallocArgs(objv, objStore, objc);
1176 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177}
Guido van Rossum212643f1998-04-29 16:22:14 +00001178
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001179/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001180
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181static PyObject*
1182Tkapp_CallResult(TkappObject *self)
1183{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001184 PyObject *res = NULL;
1185 if(self->wantobjects) {
1186 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1187 /* Not sure whether the IncrRef is necessary, but something
1188 may overwrite the interpreter result while we are
1189 converting it. */
1190 Tcl_IncrRefCount(value);
1191 res = FromObj((PyObject*)self, value);
1192 Tcl_DecrRefCount(value);
1193 } else {
1194 const char *s = Tcl_GetStringResult(self->interp);
1195 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001196
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001197 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1198 }
1199 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001200}
Guido van Rossum632de272000-03-29 00:19:50 +00001201
Benjamin Peterson5879d412009-03-30 14:51:56 +00001202#ifdef WITH_THREAD
1203
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001204/* Tkapp_CallProc is the event procedure that is executed in the context of
1205 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1206 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001207
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001208static int
1209Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1210{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 Tcl_Obj *objStore[ARGSZ];
1212 Tcl_Obj **objv;
1213 int objc;
1214 int i;
1215 ENTER_PYTHON
1216 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1217 if (!objv) {
1218 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1219 *(e->res) = NULL;
1220 }
1221 LEAVE_PYTHON
1222 if (!objv)
1223 goto done;
1224 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1225 ENTER_PYTHON
1226 if (i == TCL_ERROR) {
1227 *(e->res) = NULL;
1228 *(e->exc_type) = NULL;
1229 *(e->exc_tb) = NULL;
1230 *(e->exc_value) = PyObject_CallFunction(
1231 Tkinter_TclError, "s",
1232 Tcl_GetStringResult(e->self->interp));
1233 }
1234 else {
1235 *(e->res) = Tkapp_CallResult(e->self);
1236 }
1237 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001240done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 /* Wake up calling thread. */
1242 Tcl_MutexLock(&call_mutex);
1243 Tcl_ConditionNotify(e->done);
1244 Tcl_MutexUnlock(&call_mutex);
1245 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001246}
1247
Benjamin Peterson5879d412009-03-30 14:51:56 +00001248#endif
1249
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001250/* This is the main entry point for calling a Tcl command.
1251 It supports three cases, with regard to threading:
1252 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1253 the context of the calling thread.
1254 2. Tcl is threaded, caller of the command is in the interpreter thread:
1255 Execute the command in the calling thread. Since the Tcl lock will
1256 not be used, we can merge that with case 1.
1257 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1258 the interpreter thread. Allocation of Tcl objects needs to occur in the
1259 interpreter thread, so we ship the PyObject* args to the target thread,
1260 and perform processing there. */
1261
1262static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001263Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 Tcl_Obj *objStore[ARGSZ];
1266 Tcl_Obj **objv = NULL;
1267 int objc, i;
1268 PyObject *res = NULL;
1269 TkappObject *self = (TkappObject*)selfptr;
1270 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 /* If args is a single tuple, replace with contents of tuple */
1273 if (1 == PyTuple_Size(args)){
1274 PyObject* item = PyTuple_GetItem(args, 0);
1275 if (PyTuple_Check(item))
1276 args = item;
1277 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001278#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1280 /* We cannot call the command directly. Instead, we must
1281 marshal the parameters to the interpreter thread. */
1282 Tkapp_CallEvent *ev;
1283 Tcl_Condition cond = NULL;
1284 PyObject *exc_type, *exc_value, *exc_tb;
1285 if (!WaitForMainloop(self))
1286 return NULL;
1287 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1288 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1289 ev->self = self;
1290 ev->args = args;
1291 ev->res = &res;
1292 ev->exc_type = &exc_type;
1293 ev->exc_value = &exc_value;
1294 ev->exc_tb = &exc_tb;
1295 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001299 if (res == NULL) {
1300 if (exc_type)
1301 PyErr_Restore(exc_type, exc_value, exc_tb);
1302 else
1303 PyErr_SetObject(Tkinter_TclError, exc_value);
1304 }
1305 Tcl_ConditionFinalize(&cond);
1306 }
1307 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001308#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 objv = Tkapp_CallArgs(args, objStore, &objc);
1312 if (!objv)
1313 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 if (i == TCL_ERROR)
1322 Tkinter_Error(selfptr);
1323 else
1324 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 Tkapp_CallDeallocArgs(objv, objStore, objc);
1329 }
1330 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001331}
1332
1333
1334static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001335Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001336{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 /* Could do the same here as for Tkapp_Call(), but this is not used
1338 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1339 way for the user to do what all its Global* variants do (save and
1340 reset the scope pointer, call the local version, restore the saved
1341 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 char *cmd;
1344 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001345
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001346 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1347 "globalcall is deprecated and will be removed in 3.4",
1348 1) < 0)
1349 return 0;
1350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 cmd = Merge(args);
1354 if (cmd) {
1355 int err;
1356 ENTER_TCL
1357 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1358 ENTER_OVERLAP
1359 if (err == TCL_ERROR)
1360 res = Tkinter_Error(self);
1361 else
1362 res = PyUnicode_FromString(Tkapp_Result(self));
1363 LEAVE_OVERLAP_TCL
1364 ckfree(cmd);
1365 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001368}
1369
1370static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001371Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001373 char *script;
1374 PyObject *res = NULL;
1375 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 if (!PyArg_ParseTuple(args, "s:eval", &script))
1378 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001380 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 ENTER_TCL
1383 err = Tcl_Eval(Tkapp_Interp(self), script);
1384 ENTER_OVERLAP
1385 if (err == TCL_ERROR)
1386 res = Tkinter_Error(self);
1387 else
1388 res = PyUnicode_FromString(Tkapp_Result(self));
1389 LEAVE_OVERLAP_TCL
1390 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001391}
1392
1393static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001394Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001395{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 char *script;
1397 PyObject *res = NULL;
1398 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001399
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001400 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1401 "globaleval is deprecated and will be removed in 3.4",
1402 1) < 0)
1403 return 0;
1404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1406 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 ENTER_TCL
1411 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1412 ENTER_OVERLAP
1413 if (err == TCL_ERROR)
1414 res = Tkinter_Error(self);
1415 else
1416 res = PyUnicode_FromString(Tkapp_Result(self));
1417 LEAVE_OVERLAP_TCL
1418 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001419}
1420
1421static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001422Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001423{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 char *fileName;
1425 PyObject *res = NULL;
1426 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001428 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1429 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 ENTER_TCL
1434 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1435 ENTER_OVERLAP
1436 if (err == TCL_ERROR)
1437 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 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_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001447{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 char *script;
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", &script))
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_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1459 ENTER_OVERLAP
1460 if (err == TCL_ERROR)
1461 res = Tkinter_Error(self);
1462 else
1463 res = PyUnicode_FromString(Tkapp_Result(self));
1464 LEAVE_OVERLAP_TCL
1465 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001466}
1467
1468static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001469Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1474 return NULL;
1475 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001477 ENTER_TCL
1478 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1479 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 Py_INCREF(Py_None);
1482 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001483}
1484
Barry Warsawfa701a81997-01-16 00:15:11 +00001485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486
Guido van Rossum18468821994-06-20 07:49:28 +00001487/** Tcl Variable **/
1488
Benjamin Peterson5879d412009-03-30 14:51:56 +00001489typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1490
1491#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492TCL_DECLARE_MUTEX(var_mutex)
1493
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001494typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001495 Tcl_Event ev; /* must be first */
1496 PyObject *self;
1497 PyObject *args;
1498 int flags;
1499 EventFunc func;
1500 PyObject **res;
1501 PyObject **exc_type;
1502 PyObject **exc_val;
1503 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001505#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001506
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001507static int
1508varname_converter(PyObject *in, void *_out)
1509{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 char **out = (char**)_out;
1511 if (PyBytes_Check(in)) {
1512 *out = PyBytes_AsString(in);
1513 return 1;
1514 }
1515 if (PyUnicode_Check(in)) {
1516 *out = _PyUnicode_AsString(in);
1517 return 1;
1518 }
1519 if (PyTclObject_Check(in)) {
1520 *out = PyTclObject_TclString(in);
1521 return 1;
1522 }
1523 /* XXX: Should give diagnostics. */
1524 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001525}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001526
Benjamin Peterson5879d412009-03-30 14:51:56 +00001527#ifdef WITH_THREAD
1528
Martin v. Löwis59683e82008-06-13 07:50:45 +00001529static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530var_perform(VarEvent *ev)
1531{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001532 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1533 if (!*(ev->res)) {
1534 PyObject *exc, *val, *tb;
1535 PyErr_Fetch(&exc, &val, &tb);
1536 PyErr_NormalizeException(&exc, &val, &tb);
1537 *(ev->exc_type) = exc;
1538 *(ev->exc_val) = val;
1539 Py_DECREF(tb);
1540 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001541
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542}
1543
1544static int
1545var_proc(VarEvent* ev, int flags)
1546{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 ENTER_PYTHON
1548 var_perform(ev);
1549 Tcl_MutexLock(&var_mutex);
1550 Tcl_ConditionNotify(ev->cond);
1551 Tcl_MutexUnlock(&var_mutex);
1552 LEAVE_PYTHON
1553 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554}
1555
Benjamin Peterson5879d412009-03-30 14:51:56 +00001556#endif
1557
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001558static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001559var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001560{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001561#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001562 TkappObject *self = (TkappObject*)selfptr;
1563 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1564 TkappObject *self = (TkappObject*)selfptr;
1565 VarEvent *ev;
1566 PyObject *res, *exc_type, *exc_val;
1567 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 /* The current thread is not the interpreter thread. Marshal
1570 the call to the interpreter thread, then wait for
1571 completion. */
1572 if (!WaitForMainloop(self))
1573 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 ev->self = selfptr;
1578 ev->args = args;
1579 ev->flags = flags;
1580 ev->func = func;
1581 ev->res = &res;
1582 ev->exc_type = &exc_type;
1583 ev->exc_val = &exc_val;
1584 ev->cond = &cond;
1585 ev->ev.proc = (Tcl_EventProc*)var_proc;
1586 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1587 Tcl_ConditionFinalize(&cond);
1588 if (!res) {
1589 PyErr_SetObject(exc_type, exc_val);
1590 Py_DECREF(exc_type);
1591 Py_DECREF(exc_val);
1592 return NULL;
1593 }
1594 return res;
1595 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001596#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 /* Tcl is not threaded, or this is the interpreter thread. */
1598 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001599}
1600
Guido van Rossum18468821994-06-20 07:49:28 +00001601static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001602SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001603{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001604 char *name1, *name2;
1605 PyObject *newValue;
1606 PyObject *res = NULL;
1607 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001609 if (PyArg_ParseTuple(args, "O&O:setvar",
1610 varname_converter, &name1, &newValue)) {
1611 /* XXX Acquire tcl lock??? */
1612 newval = AsObj(newValue);
1613 if (newval == NULL)
1614 return NULL;
1615 ENTER_TCL
1616 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1617 newval, flags);
1618 ENTER_OVERLAP
1619 if (!ok)
1620 Tkinter_Error(self);
1621 else {
1622 res = Py_None;
1623 Py_INCREF(res);
1624 }
1625 LEAVE_OVERLAP_TCL
1626 }
1627 else {
1628 PyErr_Clear();
1629 if (PyArg_ParseTuple(args, "ssO:setvar",
1630 &name1, &name2, &newValue)) {
1631 /* XXX must hold tcl lock already??? */
1632 newval = AsObj(newValue);
1633 ENTER_TCL
1634 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1635 ENTER_OVERLAP
1636 if (!ok)
1637 Tkinter_Error(self);
1638 else {
1639 res = Py_None;
1640 Py_INCREF(res);
1641 }
1642 LEAVE_OVERLAP_TCL
1643 }
1644 else {
1645 return NULL;
1646 }
1647 }
1648 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001649}
1650
1651static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001652Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001653{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001655}
1656
1657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001658Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001661}
1662
Barry Warsawfa701a81997-01-16 00:15:11 +00001663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664
Guido van Rossum18468821994-06-20 07:49:28 +00001665static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001666GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001667{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 char *name1, *name2=NULL;
1669 PyObject *res = NULL;
1670 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1673 varname_converter, &name1, &name2))
1674 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001676 ENTER_TCL
1677 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1678 ENTER_OVERLAP
1679 if (tres == NULL) {
1680 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1681 } else {
1682 if (((TkappObject*)self)->wantobjects) {
1683 res = FromObj(self, tres);
1684 }
1685 else {
1686 res = PyUnicode_FromString(Tcl_GetString(tres));
1687 }
1688 }
1689 LEAVE_OVERLAP_TCL
1690 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001691}
1692
1693static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001694Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001695{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001697}
1698
1699static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001700Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001701{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001702 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001703}
1704
Barry Warsawfa701a81997-01-16 00:15:11 +00001705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001706
Guido van Rossum18468821994-06-20 07:49:28 +00001707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001710 char *name1, *name2=NULL;
1711 int code;
1712 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001714 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1715 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717 ENTER_TCL
1718 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1719 ENTER_OVERLAP
1720 if (code == TCL_ERROR)
1721 res = Tkinter_Error(self);
1722 else {
1723 Py_INCREF(Py_None);
1724 res = Py_None;
1725 }
1726 LEAVE_OVERLAP_TCL
1727 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001728}
1729
1730static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001731Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001732{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001734}
1735
1736static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001737Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001738{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001740}
1741
Barry Warsawfa701a81997-01-16 00:15:11 +00001742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743
Guido van Rossum18468821994-06-20 07:49:28 +00001744/** Tcl to Python **/
1745
1746static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001747Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001748{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001749 char *s;
1750 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001752 if (PyTuple_Size(args) == 1) {
1753 PyObject* o = PyTuple_GetItem(args, 0);
1754 if (PyLong_Check(o)) {
1755 Py_INCREF(o);
1756 return o;
1757 }
1758 }
1759 if (!PyArg_ParseTuple(args, "s:getint", &s))
1760 return NULL;
1761 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1762 return Tkinter_Error(self);
1763 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
1766static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001767Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001768{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 char *s;
1770 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001772 if (PyTuple_Size(args) == 1) {
1773 PyObject *o = PyTuple_GetItem(args, 0);
1774 if (PyFloat_Check(o)) {
1775 Py_INCREF(o);
1776 return o;
1777 }
1778 }
1779 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1780 return NULL;
1781 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1782 return Tkinter_Error(self);
1783 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001784}
1785
1786static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001787Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001788{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 char *s;
1790 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792 if (PyTuple_Size(args) == 1) {
1793 PyObject *o = PyTuple_GetItem(args, 0);
1794 if (PyLong_Check(o)) {
1795 Py_INCREF(o);
1796 return o;
1797 }
1798 }
1799 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1800 return NULL;
1801 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1802 return Tkinter_Error(self);
1803 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001804}
1805
1806static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001807Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001808{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001809 char *s;
1810 PyObject *res = NULL;
1811 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1814 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001817
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001818 ENTER_TCL
1819 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1820 ENTER_OVERLAP
1821 if (retval == TCL_ERROR)
1822 res = Tkinter_Error(self);
1823 else
1824 res = Py_BuildValue("s", Tkapp_Result(self));
1825 LEAVE_OVERLAP_TCL
1826 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001827}
1828
1829static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001830Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001831{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001832 char *s;
1833 PyObject *res = NULL;
1834 int retval;
1835 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1838 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +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_ExprLong(Tkapp_Interp(self), s, &v);
1844 ENTER_OVERLAP
1845 if (retval == TCL_ERROR)
1846 res = Tkinter_Error(self);
1847 else
1848 res = Py_BuildValue("l", v);
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_ExprDouble(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 double v;
1859 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001860
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1862 return NULL;
1863 CHECK_TCL_APPARTMENT;
1864 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1865 ENTER_TCL
1866 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1867 ENTER_OVERLAP
1868 PyFPE_END_PROTECT(retval)
1869 if (retval == TCL_ERROR)
1870 res = Tkinter_Error(self);
1871 else
1872 res = Py_BuildValue("d", 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_ExprBoolean(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 int retval;
1883 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001884
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001885 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1886 return NULL;
1887 CHECK_TCL_APPARTMENT;
1888 ENTER_TCL
1889 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1890 ENTER_OVERLAP
1891 if (retval == TCL_ERROR)
1892 res = Tkinter_Error(self);
1893 else
1894 res = Py_BuildValue("i", v);
1895 LEAVE_OVERLAP_TCL
1896 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001897}
1898
Barry Warsawfa701a81997-01-16 00:15:11 +00001899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900
Guido van Rossum18468821994-06-20 07:49:28 +00001901static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001902Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001903{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001904 char *list;
1905 int argc;
1906 char **argv;
1907 PyObject *v;
1908 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001910 if (PyTuple_Size(args) == 1) {
1911 v = PyTuple_GetItem(args, 0);
1912 if (PyTuple_Check(v)) {
1913 Py_INCREF(v);
1914 return v;
1915 }
1916 }
1917 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1918 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001919
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001920 if (Tcl_SplitList(Tkapp_Interp(self), list,
1921 &argc, &argv) == TCL_ERROR) {
1922 PyMem_Free(list);
1923 return Tkinter_Error(self);
1924 }
Guido van Rossum18468821994-06-20 07:49:28 +00001925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 if (!(v = PyTuple_New(argc)))
1927 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001928
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001929 for (i = 0; i < argc; i++) {
1930 PyObject *s = PyUnicode_FromString(argv[i]);
1931 if (!s || PyTuple_SetItem(v, i, s)) {
1932 Py_DECREF(v);
1933 v = NULL;
1934 goto finally;
1935 }
1936 }
Guido van Rossum18468821994-06-20 07:49:28 +00001937
Barry Warsawfa701a81997-01-16 00:15:11 +00001938 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 ckfree(FREECAST argv);
1940 PyMem_Free(list);
1941 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001942}
1943
1944static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001945Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001946{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001947 PyObject *v;
1948 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001949
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001950 if (PyTuple_Size(args) == 1) {
1951 PyObject* o = PyTuple_GetItem(args, 0);
1952 if (PyTuple_Check(o)) {
1953 o = SplitObj(o);
1954 return o;
1955 }
1956 }
1957 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1958 return NULL;
1959 v = Split(list);
1960 PyMem_Free(list);
1961 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001962}
1963
1964static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001965Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001966{
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001967 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001969
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001970 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1971 "merge is deprecated and will be removed in 3.4",
1972 1) < 0)
1973 return 0;
1974
1975 s = Merge(args);
1976
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 if (s) {
1978 res = PyUnicode_FromString(s);
1979 ckfree(s);
1980 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001981
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001982 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001983}
1984
Barry Warsawfa701a81997-01-16 00:15:11 +00001985
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001986
Guido van Rossum18468821994-06-20 07:49:28 +00001987/** Tcl Command **/
1988
Guido van Rossum00d93061998-05-28 23:06:38 +00001989/* Client data struct */
1990typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001991 PyObject *self;
1992 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001993} PythonCmd_ClientData;
1994
1995static int
Fred Drake509d79a2000-07-08 04:04:38 +00001996PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001997{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 errorInCmd = 1;
1999 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2000 LEAVE_PYTHON
2001 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002002}
2003
Guido van Rossum18468821994-06-20 07:49:28 +00002004/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002005 * function or method.
2006 */
Guido van Rossum18468821994-06-20 07:49:28 +00002007static int
Fred Drake509d79a2000-07-08 04:04:38 +00002008PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002009{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002011 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002012 int i, rv;
2013 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002016
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002017 /* TBD: no error checking here since we know, via the
2018 * Tkapp_CreateCommand() that the client data is a two-tuple
2019 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002022 /* Create argument list (argv1, ..., argvN) */
2023 if (!(arg = PyTuple_New(argc - 1)))
2024 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002026 for (i = 0; i < (argc - 1); i++) {
2027 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002028 if (!s) {
2029 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2030 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2031 !strcmp(argv[i + 1], "\xC0\x80")) {
2032 PyErr_Clear();
2033 /* Convert to "strict" utf-8 null */
2034 s = PyUnicode_FromString("\0");
2035 } else {
2036 Py_DECREF(arg);
2037 return PythonCmd_Error(interp);
2038 }
2039 }
2040 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 Py_DECREF(arg);
2042 return PythonCmd_Error(interp);
2043 }
2044 }
2045 res = PyEval_CallObject(func, arg);
2046 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 if (res == NULL)
2049 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051 obj_res = AsObj(res);
2052 if (obj_res == NULL) {
2053 Py_DECREF(res);
2054 return PythonCmd_Error(interp);
2055 }
2056 else {
2057 Tcl_SetObjResult(interp, obj_res);
2058 rv = TCL_OK;
2059 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002065 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002066}
2067
2068static void
Fred Drake509d79a2000-07-08 04:04:38 +00002069PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002070{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002073 ENTER_PYTHON
2074 Py_XDECREF(data->self);
2075 Py_XDECREF(data->func);
2076 PyMem_DEL(data);
2077 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002078}
2079
Barry Warsawfa701a81997-01-16 00:15:11 +00002080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002081
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002082
Benjamin Peterson5879d412009-03-30 14:51:56 +00002083#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084TCL_DECLARE_MUTEX(command_mutex)
2085
2086typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 Tcl_Event ev;
2088 Tcl_Interp* interp;
2089 char *name;
2090 int create;
2091 int *status;
2092 ClientData *data;
2093 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002094} CommandEvent;
2095
2096static int
2097Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002098{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002099 if (ev->create)
2100 *ev->status = Tcl_CreateCommand(
2101 ev->interp, ev->name, PythonCmd,
2102 ev->data, PythonCmdDelete) == NULL;
2103 else
2104 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2105 Tcl_MutexLock(&command_mutex);
2106 Tcl_ConditionNotify(ev->done);
2107 Tcl_MutexUnlock(&command_mutex);
2108 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002109}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002110#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002111
2112static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002113Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002114{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 TkappObject *self = (TkappObject*)selfptr;
2116 PythonCmd_ClientData *data;
2117 char *cmdName;
2118 PyObject *func;
2119 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002121 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2122 return NULL;
2123 if (!PyCallable_Check(func)) {
2124 PyErr_SetString(PyExc_TypeError, "command not callable");
2125 return NULL;
2126 }
Guido van Rossum18468821994-06-20 07:49:28 +00002127
Martin v. Löwisa9656492003-03-30 08:44:58 +00002128#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002129 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2130 !WaitForMainloop(self))
2131 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002132#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002134 data = PyMem_NEW(PythonCmd_ClientData, 1);
2135 if (!data)
2136 return PyErr_NoMemory();
2137 Py_INCREF(self);
2138 Py_INCREF(func);
2139 data->self = selfptr;
2140 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002141#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2143 Tcl_Condition cond = NULL;
2144 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2145 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2146 ev->interp = self->interp;
2147 ev->create = 1;
2148 ev->name = cmdName;
2149 ev->data = (ClientData)data;
2150 ev->status = &err;
2151 ev->done = &cond;
2152 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2153 Tcl_ConditionFinalize(&cond);
2154 }
2155 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002156#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002157 {
2158 ENTER_TCL
2159 err = Tcl_CreateCommand(
2160 Tkapp_Interp(self), cmdName, PythonCmd,
2161 (ClientData)data, PythonCmdDelete) == NULL;
2162 LEAVE_TCL
2163 }
2164 if (err) {
2165 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2166 PyMem_DEL(data);
2167 return NULL;
2168 }
Guido van Rossum18468821994-06-20 07:49:28 +00002169
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 Py_INCREF(Py_None);
2171 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002172}
2173
Barry Warsawfa701a81997-01-16 00:15:11 +00002174
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002175
Guido van Rossum18468821994-06-20 07:49:28 +00002176static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002177Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002178{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002179 TkappObject *self = (TkappObject*)selfptr;
2180 char *cmdName;
2181 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002183 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2184 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002185
2186#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2188 Tcl_Condition cond = NULL;
2189 CommandEvent *ev;
2190 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2191 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2192 ev->interp = self->interp;
2193 ev->create = 0;
2194 ev->name = cmdName;
2195 ev->status = &err;
2196 ev->done = &cond;
2197 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2198 &command_mutex);
2199 Tcl_ConditionFinalize(&cond);
2200 }
2201 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002202#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 {
2204 ENTER_TCL
2205 err = Tcl_DeleteCommand(self->interp, cmdName);
2206 LEAVE_TCL
2207 }
2208 if (err == -1) {
2209 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2210 return NULL;
2211 }
2212 Py_INCREF(Py_None);
2213 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002214}
2215
Barry Warsawfa701a81997-01-16 00:15:11 +00002216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217
Guido van Rossum00d93061998-05-28 23:06:38 +00002218#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002219/** File Handler **/
2220
Guido van Rossum00d93061998-05-28 23:06:38 +00002221typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002222 PyObject *func;
2223 PyObject *file;
2224 int id;
2225 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002226} FileHandler_ClientData;
2227
2228static FileHandler_ClientData *HeadFHCD;
2229
2230static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002231NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002232{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 FileHandler_ClientData *p;
2234 p = PyMem_NEW(FileHandler_ClientData, 1);
2235 if (p != NULL) {
2236 Py_XINCREF(func);
2237 Py_XINCREF(file);
2238 p->func = func;
2239 p->file = file;
2240 p->id = id;
2241 p->next = HeadFHCD;
2242 HeadFHCD = p;
2243 }
2244 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002245}
2246
2247static void
Fred Drake509d79a2000-07-08 04:04:38 +00002248DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002249{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002251
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 pp = &HeadFHCD;
2253 while ((p = *pp) != NULL) {
2254 if (p->id == id) {
2255 *pp = p->next;
2256 Py_XDECREF(p->func);
2257 Py_XDECREF(p->file);
2258 PyMem_DEL(p);
2259 }
2260 else
2261 pp = &p->next;
2262 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002263}
2264
Guido van Rossuma597dde1995-01-10 20:56:29 +00002265static void
Fred Drake509d79a2000-07-08 04:04:38 +00002266FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002267{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2269 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 ENTER_PYTHON
2272 func = data->func;
2273 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 arg = Py_BuildValue("(Oi)", file, (long) mask);
2276 res = PyEval_CallObject(func, arg);
2277 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 if (res == NULL) {
2280 errorInCmd = 1;
2281 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2282 }
2283 Py_XDECREF(res);
2284 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002285}
2286
Guido van Rossum18468821994-06-20 07:49:28 +00002287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002288Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2289 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 FileHandler_ClientData *data;
2292 PyObject *file, *func;
2293 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002295 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2296 &file, &mask, &func))
2297 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 tfile = PyObject_AsFileDescriptor(file);
2302 if (tfile < 0)
2303 return NULL;
2304 if (!PyCallable_Check(func)) {
2305 PyErr_SetString(PyExc_TypeError, "bad argument list");
2306 return NULL;
2307 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002309 data = NewFHCD(func, file, tfile);
2310 if (data == NULL)
2311 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 /* Ought to check for null Tcl_File object... */
2314 ENTER_TCL
2315 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2316 LEAVE_TCL
2317 Py_INCREF(Py_None);
2318 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002319}
2320
2321static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002322Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 PyObject *file;
2325 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2328 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 tfile = PyObject_AsFileDescriptor(file);
2333 if (tfile < 0)
2334 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338 /* Ought to check for null Tcl_File object... */
2339 ENTER_TCL
2340 Tcl_DeleteFileHandler(tfile);
2341 LEAVE_TCL
2342 Py_INCREF(Py_None);
2343 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002344}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002345#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002347
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348/**** Tktt Object (timer token) ****/
2349
Jeremy Hylton938ace62002-07-17 16:30:39 +00002350static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351
Guido van Rossum00d93061998-05-28 23:06:38 +00002352typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353 PyObject_HEAD
2354 Tcl_TimerToken token;
2355 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002356} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357
2358static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002359Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 TkttObject *v = (TkttObject *)self;
2362 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2365 return NULL;
2366 if (v->token != NULL) {
2367 Tcl_DeleteTimerHandler(v->token);
2368 v->token = NULL;
2369 }
2370 if (func != NULL) {
2371 v->func = NULL;
2372 Py_DECREF(func);
2373 Py_DECREF(v); /* See Tktt_New() */
2374 }
2375 Py_INCREF(Py_None);
2376 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377}
2378
2379static PyMethodDef Tktt_methods[] =
2380{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2382 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383};
2384
2385static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002386Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002387{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 v = PyObject_New(TkttObject, &Tktt_Type);
2391 if (v == NULL)
2392 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394 Py_INCREF(func);
2395 v->token = NULL;
2396 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 /* Extra reference, deleted when called or when handler is deleted */
2399 Py_INCREF(v);
2400 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002401}
2402
2403static void
Fred Drake509d79a2000-07-08 04:04:38 +00002404Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002405{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 TkttObject *v = (TkttObject *)self;
2407 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002412}
2413
Guido van Rossum597ac201998-05-12 14:36:19 +00002414static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002415Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002416{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002417 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002418 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2419 v,
2420 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002421}
2422
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423static PyTypeObject Tktt_Type =
2424{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002425 PyVarObject_HEAD_INIT(NULL, 0)
2426 "tktimertoken", /*tp_name */
2427 sizeof(TkttObject), /*tp_basicsize */
2428 0, /*tp_itemsize */
2429 Tktt_Dealloc, /*tp_dealloc */
2430 0, /*tp_print */
2431 0, /*tp_getattr */
2432 0, /*tp_setattr */
2433 0, /*tp_reserved */
2434 Tktt_Repr, /*tp_repr */
2435 0, /*tp_as_number */
2436 0, /*tp_as_sequence */
2437 0, /*tp_as_mapping */
2438 0, /*tp_hash */
2439 0, /*tp_call*/
2440 0, /*tp_str*/
2441 0, /*tp_getattro*/
2442 0, /*tp_setattro*/
2443 0, /*tp_as_buffer*/
2444 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2445 0, /*tp_doc*/
2446 0, /*tp_traverse*/
2447 0, /*tp_clear*/
2448 0, /*tp_richcompare*/
2449 0, /*tp_weaklistoffset*/
2450 0, /*tp_iter*/
2451 0, /*tp_iternext*/
2452 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002453};
2454
Barry Warsawfa701a81997-01-16 00:15:11 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002457/** Timer Handler **/
2458
2459static void
Fred Drake509d79a2000-07-08 04:04:38 +00002460TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002461{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 TkttObject *v = (TkttObject *)clientData;
2463 PyObject *func = v->func;
2464 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002466 if (func == NULL)
2467 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 res = PyEval_CallObject(func, NULL);
2474 Py_DECREF(func);
2475 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (res == NULL) {
2478 errorInCmd = 1;
2479 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2480 }
2481 else
2482 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002485}
2486
2487static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002488Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002489{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 int milliseconds;
2491 PyObject *func;
2492 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2495 &milliseconds, &func))
2496 return NULL;
2497 if (!PyCallable_Check(func)) {
2498 PyErr_SetString(PyExc_TypeError, "bad argument list");
2499 return NULL;
2500 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 v = Tktt_New(func);
2505 if (v) {
2506 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2507 (ClientData)v);
2508 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002511}
2512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002513
Guido van Rossum18468821994-06-20 07:49:28 +00002514/** Event Loop **/
2515
Guido van Rossum18468821994-06-20 07:49:28 +00002516static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002517Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002518{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002519 int threshold = 0;
2520 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002521#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002523#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002524
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002525 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2526 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528 CHECK_TCL_APPARTMENT;
2529 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 quitMainLoop = 0;
2532 while (Tk_GetNumMainWindows() > threshold &&
2533 !quitMainLoop &&
2534 !errorInCmd)
2535 {
2536 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002537
2538#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002539 if (self->threaded) {
2540 /* Allow other Python threads to run. */
2541 ENTER_TCL
2542 result = Tcl_DoOneEvent(0);
2543 LEAVE_TCL
2544 }
2545 else {
2546 Py_BEGIN_ALLOW_THREADS
2547 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2548 tcl_tstate = tstate;
2549 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2550 tcl_tstate = NULL;
2551 if(tcl_lock)PyThread_release_lock(tcl_lock);
2552 if (result == 0)
2553 Sleep(Tkinter_busywaitinterval);
2554 Py_END_ALLOW_THREADS
2555 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002556#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002557 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002558#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 if (PyErr_CheckSignals() != 0) {
2561 self->dispatching = 0;
2562 return NULL;
2563 }
2564 if (result < 0)
2565 break;
2566 }
2567 self->dispatching = 0;
2568 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 if (errorInCmd) {
2571 errorInCmd = 0;
2572 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2573 excInCmd = valInCmd = trbInCmd = NULL;
2574 return NULL;
2575 }
2576 Py_INCREF(Py_None);
2577 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002578}
2579
2580static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002581Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002582{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 int flags = 0;
2584 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002585
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002586 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2587 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 ENTER_TCL
2590 rv = Tcl_DoOneEvent(flags);
2591 LEAVE_TCL
2592 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002593}
2594
2595static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002596Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002597{
2598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 if (!PyArg_ParseTuple(args, ":quit"))
2600 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 quitMainLoop = 1;
2603 Py_INCREF(Py_None);
2604 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002605}
2606
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002607static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002608Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002609{
2610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 if (!PyArg_ParseTuple(args, ":interpaddr"))
2612 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002615}
2616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002618Tkapp_TkInit(PyObject *self, PyObject *args)
2619{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002620 Tcl_Interp *interp = Tkapp_Interp(self);
2621 const char * _tk_exists = NULL;
2622 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002623
Guilherme Polob681df42009-02-09 22:33:59 +00002624#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2626 * first call failed.
2627 * To avoid the deadlock, we just refuse the second call through
2628 * a static variable.
2629 */
2630 if (tk_load_failed) {
2631 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2632 return NULL;
2633 }
Guilherme Polob681df42009-02-09 22:33:59 +00002634#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 /* We want to guard against calling Tk_Init() multiple times */
2637 CHECK_TCL_APPARTMENT;
2638 ENTER_TCL
2639 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2640 ENTER_OVERLAP
2641 if (err == TCL_ERROR) {
2642 /* This sets an exception, but we cannot return right
2643 away because we need to exit the overlap first. */
2644 Tkinter_Error(self);
2645 } else {
2646 _tk_exists = Tkapp_Result(self);
2647 }
2648 LEAVE_OVERLAP_TCL
2649 if (err == TCL_ERROR) {
2650 return NULL;
2651 }
2652 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2653 if (Tk_Init(interp) == TCL_ERROR) {
2654 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002655#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002656 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002657#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 return NULL;
2659 }
2660 }
2661 Py_INCREF(Py_None);
2662 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002663}
Barry Warsawfa701a81997-01-16 00:15:11 +00002664
Martin v. Löwisffad6332002-11-26 09:28:05 +00002665static PyObject *
2666Tkapp_WantObjects(PyObject *self, PyObject *args)
2667{
2668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 int wantobjects = -1;
2670 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2671 return NULL;
2672 if (wantobjects == -1)
2673 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2674 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 Py_INCREF(Py_None);
2677 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002678}
2679
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002680static PyObject *
2681Tkapp_WillDispatch(PyObject *self, PyObject *args)
2682{
2683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002686 Py_INCREF(Py_None);
2687 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002688}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690
Guido van Rossum18468821994-06-20 07:49:28 +00002691/**** Tkapp Method List ****/
2692
2693static PyMethodDef Tkapp_methods[] =
2694{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2696 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2697 {"call", Tkapp_Call, METH_VARARGS},
2698 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2699 {"eval", Tkapp_Eval, METH_VARARGS},
2700 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2701 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2702 {"record", Tkapp_Record, METH_VARARGS},
2703 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2704 {"setvar", Tkapp_SetVar, METH_VARARGS},
2705 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2706 {"getvar", Tkapp_GetVar, METH_VARARGS},
2707 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2708 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2709 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2710 {"getint", Tkapp_GetInt, METH_VARARGS},
2711 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2712 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2713 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2714 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2715 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2716 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2717 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2718 {"split", Tkapp_Split, METH_VARARGS},
2719 {"merge", Tkapp_Merge, METH_VARARGS},
2720 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2721 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002722#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2724 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002725#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002726 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2727 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2728 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2729 {"quit", Tkapp_Quit, METH_VARARGS},
2730 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2731 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2732 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002733};
2734
Barry Warsawfa701a81997-01-16 00:15:11 +00002735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002736
Guido van Rossum18468821994-06-20 07:49:28 +00002737/**** Tkapp Type Methods ****/
2738
2739static void
Fred Drake509d79a2000-07-08 04:04:38 +00002740Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 /*CHECK_TCL_APPARTMENT;*/
2743 ENTER_TCL
2744 Tcl_DeleteInterp(Tkapp_Interp(self));
2745 LEAVE_TCL
2746 PyObject_Del(self);
2747 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002748}
2749
Guido van Rossum18468821994-06-20 07:49:28 +00002750static PyTypeObject Tkapp_Type =
2751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 PyVarObject_HEAD_INIT(NULL, 0)
2753 "tkapp", /*tp_name */
2754 sizeof(TkappObject), /*tp_basicsize */
2755 0, /*tp_itemsize */
2756 Tkapp_Dealloc, /*tp_dealloc */
2757 0, /*tp_print */
2758 0, /*tp_getattr */
2759 0, /*tp_setattr */
2760 0, /*tp_reserved */
2761 0, /*tp_repr */
2762 0, /*tp_as_number */
2763 0, /*tp_as_sequence */
2764 0, /*tp_as_mapping */
2765 0, /*tp_hash */
2766 0, /*tp_call*/
2767 0, /*tp_str*/
2768 0, /*tp_getattro*/
2769 0, /*tp_setattro*/
2770 0, /*tp_as_buffer*/
2771 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2772 0, /*tp_doc*/
2773 0, /*tp_traverse*/
2774 0, /*tp_clear*/
2775 0, /*tp_richcompare*/
2776 0, /*tp_weaklistoffset*/
2777 0, /*tp_iter*/
2778 0, /*tp_iternext*/
2779 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002780};
2781
Barry Warsawfa701a81997-01-16 00:15:11 +00002782
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002783
Guido van Rossum18468821994-06-20 07:49:28 +00002784/**** Tkinter Module ****/
2785
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002786typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 PyObject* tuple;
2788 int size; /* current size */
2789 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002790} FlattenContext;
2791
2792static int
2793_bump(FlattenContext* context, int size)
2794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 /* expand tuple to hold (at least) size new items.
2796 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002800 if (maxsize < context->size + size)
2801 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806}
2807
2808static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002809_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002810{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 if (depth > 1000) {
2816 PyErr_SetString(PyExc_ValueError,
2817 "nesting too deep in _flatten");
2818 return 0;
2819 } else if (PyList_Check(item)) {
2820 size = PyList_GET_SIZE(item);
2821 /* preallocate (assume no nesting) */
2822 if (context->size + size > context->maxsize &&
2823 !_bump(context, size))
2824 return 0;
2825 /* copy items to output tuple */
2826 for (i = 0; i < size; i++) {
2827 PyObject *o = PyList_GET_ITEM(item, i);
2828 if (PyList_Check(o) || PyTuple_Check(o)) {
2829 if (!_flatten1(context, o, depth + 1))
2830 return 0;
2831 } else if (o != Py_None) {
2832 if (context->size + 1 > context->maxsize &&
2833 !_bump(context, 1))
2834 return 0;
2835 Py_INCREF(o);
2836 PyTuple_SET_ITEM(context->tuple,
2837 context->size++, o);
2838 }
2839 }
2840 } else if (PyTuple_Check(item)) {
2841 /* same, for tuples */
2842 size = PyTuple_GET_SIZE(item);
2843 if (context->size + size > context->maxsize &&
2844 !_bump(context, size))
2845 return 0;
2846 for (i = 0; i < size; i++) {
2847 PyObject *o = PyTuple_GET_ITEM(item, i);
2848 if (PyList_Check(o) || PyTuple_Check(o)) {
2849 if (!_flatten1(context, o, depth + 1))
2850 return 0;
2851 } else if (o != Py_None) {
2852 if (context->size + 1 > context->maxsize &&
2853 !_bump(context, 1))
2854 return 0;
2855 Py_INCREF(o);
2856 PyTuple_SET_ITEM(context->tuple,
2857 context->size++, o);
2858 }
2859 }
2860 } else {
2861 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2862 return 0;
2863 }
2864 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002865}
2866
2867static PyObject *
2868Tkinter_Flatten(PyObject* self, PyObject* args)
2869{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 FlattenContext context;
2871 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002873 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2874 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002876 context.maxsize = PySequence_Size(item);
2877 if (context.maxsize < 0)
2878 return NULL;
2879 if (context.maxsize == 0)
2880 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002881
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002882 context.tuple = PyTuple_New(context.maxsize);
2883 if (!context.tuple)
2884 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002886 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 if (!_flatten1(&context, item,0))
2889 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002891 if (_PyTuple_Resize(&context.tuple, context.size))
2892 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002893
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002894 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002895}
2896
Guido van Rossum18468821994-06-20 07:49:28 +00002897static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002898Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002899{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 char *screenName = NULL;
2901 char *baseName = NULL; /* XXX this is not used anymore;
2902 try getting rid of it. */
2903 char *className = NULL;
2904 int interactive = 0;
2905 int wantobjects = 0;
2906 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2907 int sync = 0; /* pass -sync to wish */
2908 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002910 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002911
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002912 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2913 &screenName, &baseName, &className,
2914 &interactive, &wantobjects, &wantTk,
2915 &sync, &use))
2916 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002917
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918 return (PyObject *) Tkapp_New(screenName, className,
2919 interactive, wantobjects, wantTk,
2920 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002921}
2922
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002923static PyObject *
2924Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2925{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 int new_val;
2927 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2928 return NULL;
2929 if (new_val < 0) {
2930 PyErr_SetString(PyExc_ValueError,
2931 "busywaitinterval must be >= 0");
2932 return NULL;
2933 }
2934 Tkinter_busywaitinterval = new_val;
2935 Py_INCREF(Py_None);
2936 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002937}
2938
2939static char setbusywaitinterval_doc[] =
2940"setbusywaitinterval(n) -> None\n\
2941\n\
2942Set the busy-wait interval in milliseconds between successive\n\
2943calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2944It should be set to a divisor of the maximum time between\n\
2945frames in an animation.";
2946
2947static PyObject *
2948Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2949{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002951}
2952
2953static char getbusywaitinterval_doc[] =
2954"getbusywaitinterval() -> int\n\
2955\n\
2956Return the current busy-wait interval between successive\n\
2957calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2958
Guido van Rossum18468821994-06-20 07:49:28 +00002959static PyMethodDef moduleMethods[] =
2960{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2962 {"create", Tkinter_Create, METH_VARARGS},
2963 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2964 setbusywaitinterval_doc},
2965 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2966 METH_NOARGS, getbusywaitinterval_doc},
2967 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002968};
2969
Guido van Rossum7bf15641998-05-22 18:28:17 +00002970#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002971
2972static int stdin_ready = 0;
2973
Guido van Rossumad4db171998-06-13 13:56:28 +00002974#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002975static void
Fred Drake509d79a2000-07-08 04:04:38 +00002976MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002977{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002978 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002979}
Guido van Rossumad4db171998-06-13 13:56:28 +00002980#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002981
Martin v. Löwisa9656492003-03-30 08:44:58 +00002982#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002983static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002984#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002985
Guido van Rossum18468821994-06-20 07:49:28 +00002986static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002987EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002988{
Guido van Rossumad4db171998-06-13 13:56:28 +00002989#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002990 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002991#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002992#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002994#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 stdin_ready = 0;
2996 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002997#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 tfile = fileno(stdin);
2999 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003000#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003001 while (!errorInCmd && !stdin_ready) {
3002 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003003#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 if (_kbhit()) {
3005 stdin_ready = 1;
3006 break;
3007 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003008#endif
3009#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 Py_BEGIN_ALLOW_THREADS
3011 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3012 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003014 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 tcl_tstate = NULL;
3017 if(tcl_lock)PyThread_release_lock(tcl_lock);
3018 if (result == 0)
3019 Sleep(Tkinter_busywaitinterval);
3020 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003021#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003022 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003023#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003025 if (result < 0)
3026 break;
3027 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003028#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003030#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003031 if (errorInCmd) {
3032 errorInCmd = 0;
3033 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3034 excInCmd = valInCmd = trbInCmd = NULL;
3035 PyErr_Print();
3036 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003037#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003038 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003039#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003041}
Guido van Rossum18468821994-06-20 07:49:28 +00003042
Guido van Rossum00d93061998-05-28 23:06:38 +00003043#endif
3044
Guido van Rossum7bf15641998-05-22 18:28:17 +00003045static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003046EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003047{
Guido van Rossum00d93061998-05-28 23:06:38 +00003048#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003049 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003050#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003051 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003052#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 PyOS_InputHook = EventHook;
3054 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003055#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003056}
3057
3058static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003059DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003060{
Guido van Rossum00d93061998-05-28 23:06:38 +00003061#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003062 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3063 PyOS_InputHook = NULL;
3064 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003065#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003066}
3067
Barry Warsawfa701a81997-01-16 00:15:11 +00003068
3069/* all errors will be checked in one fell swoop in init_tkinter() */
3070static void
Fred Drake509d79a2000-07-08 04:04:38 +00003071ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003072{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003073 PyObject *v = PyLong_FromLong(val);
3074 if (v) {
3075 PyDict_SetItemString(d, name, v);
3076 Py_DECREF(v);
3077 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003078}
3079static void
Fred Drake509d79a2000-07-08 04:04:38 +00003080ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003081{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003082 PyObject *v = PyUnicode_FromString(val);
3083 if (v) {
3084 PyDict_SetItemString(d, name, v);
3085 Py_DECREF(v);
3086 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003087}
3088
3089
Martin v. Löwis1a214512008-06-11 05:26:20 +00003090static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003091 PyModuleDef_HEAD_INIT,
3092 "_tkinter",
3093 NULL,
3094 -1,
3095 moduleMethods,
3096 NULL,
3097 NULL,
3098 NULL,
3099 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003100};
3101
Mark Hammond62b1ab12002-07-23 06:31:15 +00003102PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003103PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003104{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003105 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003107 if (PyType_Ready(&Tkapp_Type) < 0)
3108 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003109
3110#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003111 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003112#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003114 m = PyModule_Create(&_tkintermodule);
3115 if (m == NULL)
3116 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 d = PyModule_GetDict(m);
3119 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3120 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 ins_long(d, "READABLE", TCL_READABLE);
3123 ins_long(d, "WRITABLE", TCL_WRITABLE);
3124 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3125 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3126 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3127 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3128 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3129 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3130 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3131 ins_string(d, "TK_VERSION", TK_VERSION);
3132 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003134 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003136 if (PyType_Ready(&Tktt_Type) < 0)
3137 return NULL;
3138 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003140 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3141 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003142
3143#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003144 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3145 * start waking up. Note that Tcl_FindExecutable will do this, this
3146 * code must be above it! The original warning from
3147 * tkMacOSXAppInit.c is copied below.
3148 *
3149 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3150 * Tcl interpreter for now. It probably should work to do this
3151 * in the other order, but for now it doesn't seem to.
3152 *
3153 */
3154 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003155#endif
3156
3157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 /* This helps the dynamic loader; in Unicode aware Tcl versions
3159 it also helps Tcl find its encodings. */
3160 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3161 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003162 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003163 if (cexe)
3164 Tcl_FindExecutable(PyBytes_AsString(cexe));
3165 Py_XDECREF(cexe);
3166 Py_DECREF(uexe);
3167 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003169 if (PyErr_Occurred()) {
3170 Py_DECREF(m);
3171 return NULL;
3172 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003173
Guido van Rossum43ff8681998-07-14 18:02:13 +00003174#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003175 /* This was not a good idea; through <Destroy> bindings,
3176 Tcl_Finalize() may invoke Python code but at that point the
3177 interpreter and thread state have already been destroyed! */
3178 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003179#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003180 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003181}