blob: abbe0ec7bbc5476fec3dc9085838cd470cedd3f5 [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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 cmd = Merge(args);
1349 if (cmd) {
1350 int err;
1351 ENTER_TCL
1352 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1353 ENTER_OVERLAP
1354 if (err == TCL_ERROR)
1355 res = Tkinter_Error(self);
1356 else
1357 res = PyUnicode_FromString(Tkapp_Result(self));
1358 LEAVE_OVERLAP_TCL
1359 ckfree(cmd);
1360 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001363}
1364
1365static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001366Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001367{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 char *script;
1369 PyObject *res = NULL;
1370 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 if (!PyArg_ParseTuple(args, "s:eval", &script))
1373 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 ENTER_TCL
1378 err = Tcl_Eval(Tkapp_Interp(self), script);
1379 ENTER_OVERLAP
1380 if (err == TCL_ERROR)
1381 res = Tkinter_Error(self);
1382 else
1383 res = PyUnicode_FromString(Tkapp_Result(self));
1384 LEAVE_OVERLAP_TCL
1385 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001386}
1387
1388static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001389Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001390{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 char *script;
1392 PyObject *res = NULL;
1393 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1396 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 ENTER_TCL
1401 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1402 ENTER_OVERLAP
1403 if (err == TCL_ERROR)
1404 res = Tkinter_Error(self);
1405 else
1406 res = PyUnicode_FromString(Tkapp_Result(self));
1407 LEAVE_OVERLAP_TCL
1408 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001409}
1410
1411static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001412Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001413{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 char *fileName;
1415 PyObject *res = NULL;
1416 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001418 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1419 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001423 ENTER_TCL
1424 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1425 ENTER_OVERLAP
1426 if (err == TCL_ERROR)
1427 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001429 else
1430 res = PyUnicode_FromString(Tkapp_Result(self));
1431 LEAVE_OVERLAP_TCL
1432 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001433}
1434
1435static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001436Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001437{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 char *script;
1439 PyObject *res = NULL;
1440 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001442 if (!PyArg_ParseTuple(args, "s", &script))
1443 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001447 ENTER_TCL
1448 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1449 ENTER_OVERLAP
1450 if (err == TCL_ERROR)
1451 res = Tkinter_Error(self);
1452 else
1453 res = PyUnicode_FromString(Tkapp_Result(self));
1454 LEAVE_OVERLAP_TCL
1455 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001456}
1457
1458static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001459Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001460{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1464 return NULL;
1465 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 ENTER_TCL
1468 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1469 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 Py_INCREF(Py_None);
1472 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001473}
1474
Barry Warsawfa701a81997-01-16 00:15:11 +00001475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476
Guido van Rossum18468821994-06-20 07:49:28 +00001477/** Tcl Variable **/
1478
Benjamin Peterson5879d412009-03-30 14:51:56 +00001479typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1480
1481#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482TCL_DECLARE_MUTEX(var_mutex)
1483
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 Tcl_Event ev; /* must be first */
1486 PyObject *self;
1487 PyObject *args;
1488 int flags;
1489 EventFunc func;
1490 PyObject **res;
1491 PyObject **exc_type;
1492 PyObject **exc_val;
1493 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001494} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001495#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001496
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001497static int
1498varname_converter(PyObject *in, void *_out)
1499{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001500 char **out = (char**)_out;
1501 if (PyBytes_Check(in)) {
1502 *out = PyBytes_AsString(in);
1503 return 1;
1504 }
1505 if (PyUnicode_Check(in)) {
1506 *out = _PyUnicode_AsString(in);
1507 return 1;
1508 }
1509 if (PyTclObject_Check(in)) {
1510 *out = PyTclObject_TclString(in);
1511 return 1;
1512 }
1513 /* XXX: Should give diagnostics. */
1514 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001515}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001516
Benjamin Peterson5879d412009-03-30 14:51:56 +00001517#ifdef WITH_THREAD
1518
Martin v. Löwis59683e82008-06-13 07:50:45 +00001519static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520var_perform(VarEvent *ev)
1521{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1523 if (!*(ev->res)) {
1524 PyObject *exc, *val, *tb;
1525 PyErr_Fetch(&exc, &val, &tb);
1526 PyErr_NormalizeException(&exc, &val, &tb);
1527 *(ev->exc_type) = exc;
1528 *(ev->exc_val) = val;
1529 Py_DECREF(tb);
1530 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001531
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532}
1533
1534static int
1535var_proc(VarEvent* ev, int flags)
1536{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 ENTER_PYTHON
1538 var_perform(ev);
1539 Tcl_MutexLock(&var_mutex);
1540 Tcl_ConditionNotify(ev->cond);
1541 Tcl_MutexUnlock(&var_mutex);
1542 LEAVE_PYTHON
1543 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544}
1545
Benjamin Peterson5879d412009-03-30 14:51:56 +00001546#endif
1547
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001549var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001550{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001551#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 TkappObject *self = (TkappObject*)selfptr;
1553 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1554 TkappObject *self = (TkappObject*)selfptr;
1555 VarEvent *ev;
1556 PyObject *res, *exc_type, *exc_val;
1557 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001559 /* The current thread is not the interpreter thread. Marshal
1560 the call to the interpreter thread, then wait for
1561 completion. */
1562 if (!WaitForMainloop(self))
1563 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001564
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001567 ev->self = selfptr;
1568 ev->args = args;
1569 ev->flags = flags;
1570 ev->func = func;
1571 ev->res = &res;
1572 ev->exc_type = &exc_type;
1573 ev->exc_val = &exc_val;
1574 ev->cond = &cond;
1575 ev->ev.proc = (Tcl_EventProc*)var_proc;
1576 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1577 Tcl_ConditionFinalize(&cond);
1578 if (!res) {
1579 PyErr_SetObject(exc_type, exc_val);
1580 Py_DECREF(exc_type);
1581 Py_DECREF(exc_val);
1582 return NULL;
1583 }
1584 return res;
1585 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001586#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001587 /* Tcl is not threaded, or this is the interpreter thread. */
1588 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001589}
1590
Guido van Rossum18468821994-06-20 07:49:28 +00001591static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001592SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001594 char *name1, *name2;
1595 PyObject *newValue;
1596 PyObject *res = NULL;
1597 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 if (PyArg_ParseTuple(args, "O&O:setvar",
1600 varname_converter, &name1, &newValue)) {
1601 /* XXX Acquire tcl lock??? */
1602 newval = AsObj(newValue);
1603 if (newval == NULL)
1604 return NULL;
1605 ENTER_TCL
1606 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1607 newval, flags);
1608 ENTER_OVERLAP
1609 if (!ok)
1610 Tkinter_Error(self);
1611 else {
1612 res = Py_None;
1613 Py_INCREF(res);
1614 }
1615 LEAVE_OVERLAP_TCL
1616 }
1617 else {
1618 PyErr_Clear();
1619 if (PyArg_ParseTuple(args, "ssO:setvar",
1620 &name1, &name2, &newValue)) {
1621 /* XXX must hold tcl lock already??? */
1622 newval = AsObj(newValue);
1623 ENTER_TCL
1624 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1625 ENTER_OVERLAP
1626 if (!ok)
1627 Tkinter_Error(self);
1628 else {
1629 res = Py_None;
1630 Py_INCREF(res);
1631 }
1632 LEAVE_OVERLAP_TCL
1633 }
1634 else {
1635 return NULL;
1636 }
1637 }
1638 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001639}
1640
1641static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001642Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001643{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001645}
1646
1647static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001648Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001649{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001650 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001651}
1652
Barry Warsawfa701a81997-01-16 00:15:11 +00001653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654
Guido van Rossum18468821994-06-20 07:49:28 +00001655static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001656GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001657{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 char *name1, *name2=NULL;
1659 PyObject *res = NULL;
1660 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001662 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1663 varname_converter, &name1, &name2))
1664 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666 ENTER_TCL
1667 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1668 ENTER_OVERLAP
1669 if (tres == NULL) {
1670 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1671 } else {
1672 if (((TkappObject*)self)->wantobjects) {
1673 res = FromObj(self, tres);
1674 }
1675 else {
1676 res = PyUnicode_FromString(Tcl_GetString(tres));
1677 }
1678 }
1679 LEAVE_OVERLAP_TCL
1680 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001681}
1682
1683static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001684Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001685{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001686 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001687}
1688
1689static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001690Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001691{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001693}
1694
Barry Warsawfa701a81997-01-16 00:15:11 +00001695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696
Guido van Rossum18468821994-06-20 07:49:28 +00001697static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001698UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001699{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001700 char *name1, *name2=NULL;
1701 int code;
1702 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001704 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1705 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001707 ENTER_TCL
1708 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1709 ENTER_OVERLAP
1710 if (code == TCL_ERROR)
1711 res = Tkinter_Error(self);
1712 else {
1713 Py_INCREF(Py_None);
1714 res = Py_None;
1715 }
1716 LEAVE_OVERLAP_TCL
1717 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001718}
1719
1720static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001721Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001722{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001723 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001724}
1725
1726static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001727Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001728{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001729 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001730}
1731
Barry Warsawfa701a81997-01-16 00:15:11 +00001732
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733
Guido van Rossum18468821994-06-20 07:49:28 +00001734/** Tcl to Python **/
1735
1736static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001737Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001738{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 char *s;
1740 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 if (PyTuple_Size(args) == 1) {
1743 PyObject* o = PyTuple_GetItem(args, 0);
1744 if (PyLong_Check(o)) {
1745 Py_INCREF(o);
1746 return o;
1747 }
1748 }
1749 if (!PyArg_ParseTuple(args, "s:getint", &s))
1750 return NULL;
1751 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1752 return Tkinter_Error(self);
1753 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001754}
1755
1756static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 char *s;
1760 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001762 if (PyTuple_Size(args) == 1) {
1763 PyObject *o = PyTuple_GetItem(args, 0);
1764 if (PyFloat_Check(o)) {
1765 Py_INCREF(o);
1766 return o;
1767 }
1768 }
1769 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1770 return NULL;
1771 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1772 return Tkinter_Error(self);
1773 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001774}
1775
1776static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001777Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001778{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 char *s;
1780 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 if (PyTuple_Size(args) == 1) {
1783 PyObject *o = PyTuple_GetItem(args, 0);
1784 if (PyLong_Check(o)) {
1785 Py_INCREF(o);
1786 return o;
1787 }
1788 }
1789 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1790 return NULL;
1791 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1792 return Tkinter_Error(self);
1793 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
1796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001799 char *s;
1800 PyObject *res = NULL;
1801 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001803 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1804 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001805
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 ENTER_TCL
1809 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1810 ENTER_OVERLAP
1811 if (retval == TCL_ERROR)
1812 res = Tkinter_Error(self);
1813 else
1814 res = Py_BuildValue("s", Tkapp_Result(self));
1815 LEAVE_OVERLAP_TCL
1816 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001817}
1818
1819static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001820Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001821{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 char *s;
1823 PyObject *res = NULL;
1824 int retval;
1825 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001826
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001827 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1828 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001830 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001832 ENTER_TCL
1833 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1834 ENTER_OVERLAP
1835 if (retval == TCL_ERROR)
1836 res = Tkinter_Error(self);
1837 else
1838 res = Py_BuildValue("l", v);
1839 LEAVE_OVERLAP_TCL
1840 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001841}
1842
1843static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001844Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001845{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001846 char *s;
1847 PyObject *res = NULL;
1848 double v;
1849 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001851 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1852 return NULL;
1853 CHECK_TCL_APPARTMENT;
1854 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1855 ENTER_TCL
1856 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1857 ENTER_OVERLAP
1858 PyFPE_END_PROTECT(retval)
1859 if (retval == TCL_ERROR)
1860 res = Tkinter_Error(self);
1861 else
1862 res = Py_BuildValue("d", v);
1863 LEAVE_OVERLAP_TCL
1864 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001865}
1866
1867static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001868Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001869{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001870 char *s;
1871 PyObject *res = NULL;
1872 int retval;
1873 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001875 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1876 return NULL;
1877 CHECK_TCL_APPARTMENT;
1878 ENTER_TCL
1879 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1880 ENTER_OVERLAP
1881 if (retval == TCL_ERROR)
1882 res = Tkinter_Error(self);
1883 else
1884 res = Py_BuildValue("i", v);
1885 LEAVE_OVERLAP_TCL
1886 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001887}
1888
Barry Warsawfa701a81997-01-16 00:15:11 +00001889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890
Guido van Rossum18468821994-06-20 07:49:28 +00001891static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001892Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001893{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001894 char *list;
1895 int argc;
1896 char **argv;
1897 PyObject *v;
1898 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900 if (PyTuple_Size(args) == 1) {
1901 v = PyTuple_GetItem(args, 0);
1902 if (PyTuple_Check(v)) {
1903 Py_INCREF(v);
1904 return v;
1905 }
1906 }
1907 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1908 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001910 if (Tcl_SplitList(Tkapp_Interp(self), list,
1911 &argc, &argv) == TCL_ERROR) {
1912 PyMem_Free(list);
1913 return Tkinter_Error(self);
1914 }
Guido van Rossum18468821994-06-20 07:49:28 +00001915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001916 if (!(v = PyTuple_New(argc)))
1917 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001918
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001919 for (i = 0; i < argc; i++) {
1920 PyObject *s = PyUnicode_FromString(argv[i]);
1921 if (!s || PyTuple_SetItem(v, i, s)) {
1922 Py_DECREF(v);
1923 v = NULL;
1924 goto finally;
1925 }
1926 }
Guido van Rossum18468821994-06-20 07:49:28 +00001927
Barry Warsawfa701a81997-01-16 00:15:11 +00001928 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001929 ckfree(FREECAST argv);
1930 PyMem_Free(list);
1931 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001932}
1933
1934static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001935Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001936{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001937 PyObject *v;
1938 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 if (PyTuple_Size(args) == 1) {
1941 PyObject* o = PyTuple_GetItem(args, 0);
1942 if (PyTuple_Check(o)) {
1943 o = SplitObj(o);
1944 return o;
1945 }
1946 }
1947 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1948 return NULL;
1949 v = Split(list);
1950 PyMem_Free(list);
1951 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001952}
1953
1954static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001955Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001956{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001957 char *s = Merge(args);
1958 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001959
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 if (s) {
1961 res = PyUnicode_FromString(s);
1962 ckfree(s);
1963 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001966}
1967
Barry Warsawfa701a81997-01-16 00:15:11 +00001968
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969
Guido van Rossum18468821994-06-20 07:49:28 +00001970/** Tcl Command **/
1971
Guido van Rossum00d93061998-05-28 23:06:38 +00001972/* Client data struct */
1973typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974 PyObject *self;
1975 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001976} PythonCmd_ClientData;
1977
1978static int
Fred Drake509d79a2000-07-08 04:04:38 +00001979PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001980{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 errorInCmd = 1;
1982 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1983 LEAVE_PYTHON
1984 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001985}
1986
Guido van Rossum18468821994-06-20 07:49:28 +00001987/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001988 * function or method.
1989 */
Guido van Rossum18468821994-06-20 07:49:28 +00001990static int
Fred Drake509d79a2000-07-08 04:04:38 +00001991PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001994 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 int i, rv;
1996 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001999
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002000 /* TBD: no error checking here since we know, via the
2001 * Tkapp_CreateCommand() that the client data is a two-tuple
2002 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 /* Create argument list (argv1, ..., argvN) */
2006 if (!(arg = PyTuple_New(argc - 1)))
2007 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002008
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 for (i = 0; i < (argc - 1); i++) {
2010 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002011 if (!s) {
2012 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2013 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2014 !strcmp(argv[i + 1], "\xC0\x80")) {
2015 PyErr_Clear();
2016 /* Convert to "strict" utf-8 null */
2017 s = PyUnicode_FromString("\0");
2018 } else {
2019 Py_DECREF(arg);
2020 return PythonCmd_Error(interp);
2021 }
2022 }
2023 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002024 Py_DECREF(arg);
2025 return PythonCmd_Error(interp);
2026 }
2027 }
2028 res = PyEval_CallObject(func, arg);
2029 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002031 if (res == NULL)
2032 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002034 obj_res = AsObj(res);
2035 if (obj_res == NULL) {
2036 Py_DECREF(res);
2037 return PythonCmd_Error(interp);
2038 }
2039 else {
2040 Tcl_SetObjResult(interp, obj_res);
2041 rv = TCL_OK;
2042 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002044 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002049}
2050
2051static void
Fred Drake509d79a2000-07-08 04:04:38 +00002052PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002053{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002054 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002056 ENTER_PYTHON
2057 Py_XDECREF(data->self);
2058 Py_XDECREF(data->func);
2059 PyMem_DEL(data);
2060 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002061}
2062
Barry Warsawfa701a81997-01-16 00:15:11 +00002063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002064
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002065
Benjamin Peterson5879d412009-03-30 14:51:56 +00002066#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002067TCL_DECLARE_MUTEX(command_mutex)
2068
2069typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002070 Tcl_Event ev;
2071 Tcl_Interp* interp;
2072 char *name;
2073 int create;
2074 int *status;
2075 ClientData *data;
2076 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002077} CommandEvent;
2078
2079static int
2080Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002081{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002082 if (ev->create)
2083 *ev->status = Tcl_CreateCommand(
2084 ev->interp, ev->name, PythonCmd,
2085 ev->data, PythonCmdDelete) == NULL;
2086 else
2087 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2088 Tcl_MutexLock(&command_mutex);
2089 Tcl_ConditionNotify(ev->done);
2090 Tcl_MutexUnlock(&command_mutex);
2091 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002092}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002093#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002094
2095static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002096Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002097{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002098 TkappObject *self = (TkappObject*)selfptr;
2099 PythonCmd_ClientData *data;
2100 char *cmdName;
2101 PyObject *func;
2102 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2105 return NULL;
2106 if (!PyCallable_Check(func)) {
2107 PyErr_SetString(PyExc_TypeError, "command not callable");
2108 return NULL;
2109 }
Guido van Rossum18468821994-06-20 07:49:28 +00002110
Martin v. Löwisa9656492003-03-30 08:44:58 +00002111#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002112 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2113 !WaitForMainloop(self))
2114 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002115#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002117 data = PyMem_NEW(PythonCmd_ClientData, 1);
2118 if (!data)
2119 return PyErr_NoMemory();
2120 Py_INCREF(self);
2121 Py_INCREF(func);
2122 data->self = selfptr;
2123 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002124#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002125 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2126 Tcl_Condition cond = NULL;
2127 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2128 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2129 ev->interp = self->interp;
2130 ev->create = 1;
2131 ev->name = cmdName;
2132 ev->data = (ClientData)data;
2133 ev->status = &err;
2134 ev->done = &cond;
2135 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2136 Tcl_ConditionFinalize(&cond);
2137 }
2138 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002139#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 {
2141 ENTER_TCL
2142 err = Tcl_CreateCommand(
2143 Tkapp_Interp(self), cmdName, PythonCmd,
2144 (ClientData)data, PythonCmdDelete) == NULL;
2145 LEAVE_TCL
2146 }
2147 if (err) {
2148 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2149 PyMem_DEL(data);
2150 return NULL;
2151 }
Guido van Rossum18468821994-06-20 07:49:28 +00002152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002153 Py_INCREF(Py_None);
2154 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002155}
2156
Barry Warsawfa701a81997-01-16 00:15:11 +00002157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158
Guido van Rossum18468821994-06-20 07:49:28 +00002159static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002160Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002161{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002162 TkappObject *self = (TkappObject*)selfptr;
2163 char *cmdName;
2164 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2167 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002168
2169#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2171 Tcl_Condition cond = NULL;
2172 CommandEvent *ev;
2173 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2174 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2175 ev->interp = self->interp;
2176 ev->create = 0;
2177 ev->name = cmdName;
2178 ev->status = &err;
2179 ev->done = &cond;
2180 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2181 &command_mutex);
2182 Tcl_ConditionFinalize(&cond);
2183 }
2184 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002185#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002186 {
2187 ENTER_TCL
2188 err = Tcl_DeleteCommand(self->interp, cmdName);
2189 LEAVE_TCL
2190 }
2191 if (err == -1) {
2192 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2193 return NULL;
2194 }
2195 Py_INCREF(Py_None);
2196 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002197}
2198
Barry Warsawfa701a81997-01-16 00:15:11 +00002199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200
Guido van Rossum00d93061998-05-28 23:06:38 +00002201#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002202/** File Handler **/
2203
Guido van Rossum00d93061998-05-28 23:06:38 +00002204typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 PyObject *func;
2206 PyObject *file;
2207 int id;
2208 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002209} FileHandler_ClientData;
2210
2211static FileHandler_ClientData *HeadFHCD;
2212
2213static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002214NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002215{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002216 FileHandler_ClientData *p;
2217 p = PyMem_NEW(FileHandler_ClientData, 1);
2218 if (p != NULL) {
2219 Py_XINCREF(func);
2220 Py_XINCREF(file);
2221 p->func = func;
2222 p->file = file;
2223 p->id = id;
2224 p->next = HeadFHCD;
2225 HeadFHCD = p;
2226 }
2227 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002228}
2229
2230static void
Fred Drake509d79a2000-07-08 04:04:38 +00002231DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002232{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 pp = &HeadFHCD;
2236 while ((p = *pp) != NULL) {
2237 if (p->id == id) {
2238 *pp = p->next;
2239 Py_XDECREF(p->func);
2240 Py_XDECREF(p->file);
2241 PyMem_DEL(p);
2242 }
2243 else
2244 pp = &p->next;
2245 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002246}
2247
Guido van Rossuma597dde1995-01-10 20:56:29 +00002248static void
Fred Drake509d79a2000-07-08 04:04:38 +00002249FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002250{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2252 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002253
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002254 ENTER_PYTHON
2255 func = data->func;
2256 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 arg = Py_BuildValue("(Oi)", file, (long) mask);
2259 res = PyEval_CallObject(func, arg);
2260 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002262 if (res == NULL) {
2263 errorInCmd = 1;
2264 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2265 }
2266 Py_XDECREF(res);
2267 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002268}
2269
Guido van Rossum18468821994-06-20 07:49:28 +00002270static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002271Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2272 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002273{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002274 FileHandler_ClientData *data;
2275 PyObject *file, *func;
2276 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002278 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2279 &file, &mask, &func))
2280 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002284 tfile = PyObject_AsFileDescriptor(file);
2285 if (tfile < 0)
2286 return NULL;
2287 if (!PyCallable_Check(func)) {
2288 PyErr_SetString(PyExc_TypeError, "bad argument list");
2289 return NULL;
2290 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 data = NewFHCD(func, file, tfile);
2293 if (data == NULL)
2294 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002296 /* Ought to check for null Tcl_File object... */
2297 ENTER_TCL
2298 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2299 LEAVE_TCL
2300 Py_INCREF(Py_None);
2301 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002302}
2303
2304static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002305Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002306{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 PyObject *file;
2308 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002309
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2311 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 tfile = PyObject_AsFileDescriptor(file);
2316 if (tfile < 0)
2317 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321 /* Ought to check for null Tcl_File object... */
2322 ENTER_TCL
2323 Tcl_DeleteFileHandler(tfile);
2324 LEAVE_TCL
2325 Py_INCREF(Py_None);
2326 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002327}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002328#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331/**** Tktt Object (timer token) ****/
2332
Jeremy Hylton938ace62002-07-17 16:30:39 +00002333static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Guido van Rossum00d93061998-05-28 23:06:38 +00002335typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 PyObject_HEAD
2337 Tcl_TimerToken token;
2338 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002339} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340
2341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002342Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002344 TkttObject *v = (TkttObject *)self;
2345 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002347 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2348 return NULL;
2349 if (v->token != NULL) {
2350 Tcl_DeleteTimerHandler(v->token);
2351 v->token = NULL;
2352 }
2353 if (func != NULL) {
2354 v->func = NULL;
2355 Py_DECREF(func);
2356 Py_DECREF(v); /* See Tktt_New() */
2357 }
2358 Py_INCREF(Py_None);
2359 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360}
2361
2362static PyMethodDef Tktt_methods[] =
2363{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2365 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366};
2367
2368static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002369Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373 v = PyObject_New(TkttObject, &Tktt_Type);
2374 if (v == NULL)
2375 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 Py_INCREF(func);
2378 v->token = NULL;
2379 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 /* Extra reference, deleted when called or when handler is deleted */
2382 Py_INCREF(v);
2383 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384}
2385
2386static void
Fred Drake509d79a2000-07-08 04:04:38 +00002387Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 TkttObject *v = (TkttObject *)self;
2390 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395}
2396
Guido van Rossum597ac201998-05-12 14:36:19 +00002397static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002398Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002401 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2402 v,
2403 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404}
2405
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406static PyTypeObject Tktt_Type =
2407{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002408 PyVarObject_HEAD_INIT(NULL, 0)
2409 "tktimertoken", /*tp_name */
2410 sizeof(TkttObject), /*tp_basicsize */
2411 0, /*tp_itemsize */
2412 Tktt_Dealloc, /*tp_dealloc */
2413 0, /*tp_print */
2414 0, /*tp_getattr */
2415 0, /*tp_setattr */
2416 0, /*tp_reserved */
2417 Tktt_Repr, /*tp_repr */
2418 0, /*tp_as_number */
2419 0, /*tp_as_sequence */
2420 0, /*tp_as_mapping */
2421 0, /*tp_hash */
2422 0, /*tp_call*/
2423 0, /*tp_str*/
2424 0, /*tp_getattro*/
2425 0, /*tp_setattro*/
2426 0, /*tp_as_buffer*/
2427 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2428 0, /*tp_doc*/
2429 0, /*tp_traverse*/
2430 0, /*tp_clear*/
2431 0, /*tp_richcompare*/
2432 0, /*tp_weaklistoffset*/
2433 0, /*tp_iter*/
2434 0, /*tp_iternext*/
2435 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002436};
2437
Barry Warsawfa701a81997-01-16 00:15:11 +00002438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002440/** Timer Handler **/
2441
2442static void
Fred Drake509d79a2000-07-08 04:04:38 +00002443TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002444{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 TkttObject *v = (TkttObject *)clientData;
2446 PyObject *func = v->func;
2447 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002449 if (func == NULL)
2450 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456 res = PyEval_CallObject(func, NULL);
2457 Py_DECREF(func);
2458 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460 if (res == NULL) {
2461 errorInCmd = 1;
2462 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2463 }
2464 else
2465 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002468}
2469
2470static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002471Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 int milliseconds;
2474 PyObject *func;
2475 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2478 &milliseconds, &func))
2479 return NULL;
2480 if (!PyCallable_Check(func)) {
2481 PyErr_SetString(PyExc_TypeError, "bad argument list");
2482 return NULL;
2483 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002485 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002487 v = Tktt_New(func);
2488 if (v) {
2489 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2490 (ClientData)v);
2491 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002492
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002493 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002494}
2495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002496
Guido van Rossum18468821994-06-20 07:49:28 +00002497/** Event Loop **/
2498
Guido van Rossum18468821994-06-20 07:49:28 +00002499static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002500Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 int threshold = 0;
2503 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002504#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002506#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2509 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002511 CHECK_TCL_APPARTMENT;
2512 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 quitMainLoop = 0;
2515 while (Tk_GetNumMainWindows() > threshold &&
2516 !quitMainLoop &&
2517 !errorInCmd)
2518 {
2519 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002520
2521#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 if (self->threaded) {
2523 /* Allow other Python threads to run. */
2524 ENTER_TCL
2525 result = Tcl_DoOneEvent(0);
2526 LEAVE_TCL
2527 }
2528 else {
2529 Py_BEGIN_ALLOW_THREADS
2530 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2531 tcl_tstate = tstate;
2532 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2533 tcl_tstate = NULL;
2534 if(tcl_lock)PyThread_release_lock(tcl_lock);
2535 if (result == 0)
2536 Sleep(Tkinter_busywaitinterval);
2537 Py_END_ALLOW_THREADS
2538 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002539#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002540 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002541#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 if (PyErr_CheckSignals() != 0) {
2544 self->dispatching = 0;
2545 return NULL;
2546 }
2547 if (result < 0)
2548 break;
2549 }
2550 self->dispatching = 0;
2551 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002553 if (errorInCmd) {
2554 errorInCmd = 0;
2555 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2556 excInCmd = valInCmd = trbInCmd = NULL;
2557 return NULL;
2558 }
2559 Py_INCREF(Py_None);
2560 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002561}
2562
2563static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002564Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002566 int flags = 0;
2567 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002569 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2570 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 ENTER_TCL
2573 rv = Tcl_DoOneEvent(flags);
2574 LEAVE_TCL
2575 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002576}
2577
2578static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002579Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002580{
2581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002582 if (!PyArg_ParseTuple(args, ":quit"))
2583 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002584
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 quitMainLoop = 1;
2586 Py_INCREF(Py_None);
2587 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002588}
2589
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002590static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002591Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002592{
2593
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002594 if (!PyArg_ParseTuple(args, ":interpaddr"))
2595 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002598}
2599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002600static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002601Tkapp_TkInit(PyObject *self, PyObject *args)
2602{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002603 Tcl_Interp *interp = Tkapp_Interp(self);
2604 const char * _tk_exists = NULL;
2605 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002606
Guilherme Polob681df42009-02-09 22:33:59 +00002607#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002608 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2609 * first call failed.
2610 * To avoid the deadlock, we just refuse the second call through
2611 * a static variable.
2612 */
2613 if (tk_load_failed) {
2614 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2615 return NULL;
2616 }
Guilherme Polob681df42009-02-09 22:33:59 +00002617#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 /* We want to guard against calling Tk_Init() multiple times */
2620 CHECK_TCL_APPARTMENT;
2621 ENTER_TCL
2622 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2623 ENTER_OVERLAP
2624 if (err == TCL_ERROR) {
2625 /* This sets an exception, but we cannot return right
2626 away because we need to exit the overlap first. */
2627 Tkinter_Error(self);
2628 } else {
2629 _tk_exists = Tkapp_Result(self);
2630 }
2631 LEAVE_OVERLAP_TCL
2632 if (err == TCL_ERROR) {
2633 return NULL;
2634 }
2635 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2636 if (Tk_Init(interp) == TCL_ERROR) {
2637 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002638#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002639 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002640#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002641 return NULL;
2642 }
2643 }
2644 Py_INCREF(Py_None);
2645 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002646}
Barry Warsawfa701a81997-01-16 00:15:11 +00002647
Martin v. Löwisffad6332002-11-26 09:28:05 +00002648static PyObject *
2649Tkapp_WantObjects(PyObject *self, PyObject *args)
2650{
2651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002652 int wantobjects = -1;
2653 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2654 return NULL;
2655 if (wantobjects == -1)
2656 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2657 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 Py_INCREF(Py_None);
2660 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002661}
2662
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002663static PyObject *
2664Tkapp_WillDispatch(PyObject *self, PyObject *args)
2665{
2666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 Py_INCREF(Py_None);
2670 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002671}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673
Guido van Rossum18468821994-06-20 07:49:28 +00002674/**** Tkapp Method List ****/
2675
2676static PyMethodDef Tkapp_methods[] =
2677{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2679 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2680 {"call", Tkapp_Call, METH_VARARGS},
2681 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2682 {"eval", Tkapp_Eval, METH_VARARGS},
2683 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2684 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2685 {"record", Tkapp_Record, METH_VARARGS},
2686 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2687 {"setvar", Tkapp_SetVar, METH_VARARGS},
2688 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2689 {"getvar", Tkapp_GetVar, METH_VARARGS},
2690 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2691 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2692 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2693 {"getint", Tkapp_GetInt, METH_VARARGS},
2694 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2695 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2696 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2697 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2698 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2699 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2700 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2701 {"split", Tkapp_Split, METH_VARARGS},
2702 {"merge", Tkapp_Merge, METH_VARARGS},
2703 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2704 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002705#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2707 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002708#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002709 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2710 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2711 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2712 {"quit", Tkapp_Quit, METH_VARARGS},
2713 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2714 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2715 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002716};
2717
Barry Warsawfa701a81997-01-16 00:15:11 +00002718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719
Guido van Rossum18468821994-06-20 07:49:28 +00002720/**** Tkapp Type Methods ****/
2721
2722static void
Fred Drake509d79a2000-07-08 04:04:38 +00002723Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002724{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 /*CHECK_TCL_APPARTMENT;*/
2726 ENTER_TCL
2727 Tcl_DeleteInterp(Tkapp_Interp(self));
2728 LEAVE_TCL
2729 PyObject_Del(self);
2730 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002731}
2732
Guido van Rossum18468821994-06-20 07:49:28 +00002733static PyTypeObject Tkapp_Type =
2734{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 PyVarObject_HEAD_INIT(NULL, 0)
2736 "tkapp", /*tp_name */
2737 sizeof(TkappObject), /*tp_basicsize */
2738 0, /*tp_itemsize */
2739 Tkapp_Dealloc, /*tp_dealloc */
2740 0, /*tp_print */
2741 0, /*tp_getattr */
2742 0, /*tp_setattr */
2743 0, /*tp_reserved */
2744 0, /*tp_repr */
2745 0, /*tp_as_number */
2746 0, /*tp_as_sequence */
2747 0, /*tp_as_mapping */
2748 0, /*tp_hash */
2749 0, /*tp_call*/
2750 0, /*tp_str*/
2751 0, /*tp_getattro*/
2752 0, /*tp_setattro*/
2753 0, /*tp_as_buffer*/
2754 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2755 0, /*tp_doc*/
2756 0, /*tp_traverse*/
2757 0, /*tp_clear*/
2758 0, /*tp_richcompare*/
2759 0, /*tp_weaklistoffset*/
2760 0, /*tp_iter*/
2761 0, /*tp_iternext*/
2762 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002763};
2764
Barry Warsawfa701a81997-01-16 00:15:11 +00002765
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002766
Guido van Rossum18468821994-06-20 07:49:28 +00002767/**** Tkinter Module ****/
2768
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002769typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 PyObject* tuple;
2771 int size; /* current size */
2772 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002773} FlattenContext;
2774
2775static int
2776_bump(FlattenContext* context, int size)
2777{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002778 /* expand tuple to hold (at least) size new items.
2779 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002781 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002782
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002783 if (maxsize < context->size + size)
2784 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002789}
2790
2791static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002792_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 if (depth > 1000) {
2799 PyErr_SetString(PyExc_ValueError,
2800 "nesting too deep in _flatten");
2801 return 0;
2802 } else if (PyList_Check(item)) {
2803 size = PyList_GET_SIZE(item);
2804 /* preallocate (assume no nesting) */
2805 if (context->size + size > context->maxsize &&
2806 !_bump(context, size))
2807 return 0;
2808 /* copy items to output tuple */
2809 for (i = 0; i < size; i++) {
2810 PyObject *o = PyList_GET_ITEM(item, i);
2811 if (PyList_Check(o) || PyTuple_Check(o)) {
2812 if (!_flatten1(context, o, depth + 1))
2813 return 0;
2814 } else if (o != Py_None) {
2815 if (context->size + 1 > context->maxsize &&
2816 !_bump(context, 1))
2817 return 0;
2818 Py_INCREF(o);
2819 PyTuple_SET_ITEM(context->tuple,
2820 context->size++, o);
2821 }
2822 }
2823 } else if (PyTuple_Check(item)) {
2824 /* same, for tuples */
2825 size = PyTuple_GET_SIZE(item);
2826 if (context->size + size > context->maxsize &&
2827 !_bump(context, size))
2828 return 0;
2829 for (i = 0; i < size; i++) {
2830 PyObject *o = PyTuple_GET_ITEM(item, i);
2831 if (PyList_Check(o) || PyTuple_Check(o)) {
2832 if (!_flatten1(context, o, depth + 1))
2833 return 0;
2834 } else if (o != Py_None) {
2835 if (context->size + 1 > context->maxsize &&
2836 !_bump(context, 1))
2837 return 0;
2838 Py_INCREF(o);
2839 PyTuple_SET_ITEM(context->tuple,
2840 context->size++, o);
2841 }
2842 }
2843 } else {
2844 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2845 return 0;
2846 }
2847 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002848}
2849
2850static PyObject *
2851Tkinter_Flatten(PyObject* self, PyObject* args)
2852{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002853 FlattenContext context;
2854 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002855
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2857 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002858
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 context.maxsize = PySequence_Size(item);
2860 if (context.maxsize < 0)
2861 return NULL;
2862 if (context.maxsize == 0)
2863 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002864
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002865 context.tuple = PyTuple_New(context.maxsize);
2866 if (!context.tuple)
2867 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002868
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002870
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 if (!_flatten1(&context, item,0))
2872 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002873
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002874 if (_PyTuple_Resize(&context.tuple, context.size))
2875 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002877 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002878}
2879
Guido van Rossum18468821994-06-20 07:49:28 +00002880static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002881Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002882{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 char *screenName = NULL;
2884 char *baseName = NULL; /* XXX this is not used anymore;
2885 try getting rid of it. */
2886 char *className = NULL;
2887 int interactive = 0;
2888 int wantobjects = 0;
2889 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2890 int sync = 0; /* pass -sync to wish */
2891 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002893 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002895 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2896 &screenName, &baseName, &className,
2897 &interactive, &wantobjects, &wantTk,
2898 &sync, &use))
2899 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002900
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901 return (PyObject *) Tkapp_New(screenName, className,
2902 interactive, wantobjects, wantTk,
2903 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002904}
2905
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002906static PyObject *
2907Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2908{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002909 int new_val;
2910 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2911 return NULL;
2912 if (new_val < 0) {
2913 PyErr_SetString(PyExc_ValueError,
2914 "busywaitinterval must be >= 0");
2915 return NULL;
2916 }
2917 Tkinter_busywaitinterval = new_val;
2918 Py_INCREF(Py_None);
2919 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002920}
2921
2922static char setbusywaitinterval_doc[] =
2923"setbusywaitinterval(n) -> None\n\
2924\n\
2925Set the busy-wait interval in milliseconds between successive\n\
2926calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2927It should be set to a divisor of the maximum time between\n\
2928frames in an animation.";
2929
2930static PyObject *
2931Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2932{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002934}
2935
2936static char getbusywaitinterval_doc[] =
2937"getbusywaitinterval() -> int\n\
2938\n\
2939Return the current busy-wait interval between successive\n\
2940calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2941
Guido van Rossum18468821994-06-20 07:49:28 +00002942static PyMethodDef moduleMethods[] =
2943{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002944 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2945 {"create", Tkinter_Create, METH_VARARGS},
2946 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2947 setbusywaitinterval_doc},
2948 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2949 METH_NOARGS, getbusywaitinterval_doc},
2950 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002951};
2952
Guido van Rossum7bf15641998-05-22 18:28:17 +00002953#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002954
2955static int stdin_ready = 0;
2956
Guido van Rossumad4db171998-06-13 13:56:28 +00002957#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002958static void
Fred Drake509d79a2000-07-08 04:04:38 +00002959MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002960{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002962}
Guido van Rossumad4db171998-06-13 13:56:28 +00002963#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002964
Martin v. Löwisa9656492003-03-30 08:44:58 +00002965#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002966static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002967#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002968
Guido van Rossum18468821994-06-20 07:49:28 +00002969static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002970EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002971{
Guido van Rossumad4db171998-06-13 13:56:28 +00002972#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002974#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002975#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002976 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002977#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002978 stdin_ready = 0;
2979 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002980#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002981 tfile = fileno(stdin);
2982 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002983#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002984 while (!errorInCmd && !stdin_ready) {
2985 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002986#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002987 if (_kbhit()) {
2988 stdin_ready = 1;
2989 break;
2990 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002991#endif
2992#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 Py_BEGIN_ALLOW_THREADS
2994 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2995 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002997 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002999 tcl_tstate = NULL;
3000 if(tcl_lock)PyThread_release_lock(tcl_lock);
3001 if (result == 0)
3002 Sleep(Tkinter_busywaitinterval);
3003 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003004#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003005 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003006#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008 if (result < 0)
3009 break;
3010 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003011#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003013#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003014 if (errorInCmd) {
3015 errorInCmd = 0;
3016 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3017 excInCmd = valInCmd = trbInCmd = NULL;
3018 PyErr_Print();
3019 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003020#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003022#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003024}
Guido van Rossum18468821994-06-20 07:49:28 +00003025
Guido van Rossum00d93061998-05-28 23:06:38 +00003026#endif
3027
Guido van Rossum7bf15641998-05-22 18:28:17 +00003028static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003029EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003030{
Guido van Rossum00d93061998-05-28 23:06:38 +00003031#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003032 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003033#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003035#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003036 PyOS_InputHook = EventHook;
3037 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003038#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003039}
3040
3041static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003042DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003043{
Guido van Rossum00d93061998-05-28 23:06:38 +00003044#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3046 PyOS_InputHook = NULL;
3047 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003048#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003049}
3050
Barry Warsawfa701a81997-01-16 00:15:11 +00003051
3052/* all errors will be checked in one fell swoop in init_tkinter() */
3053static void
Fred Drake509d79a2000-07-08 04:04:38 +00003054ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003055{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003056 PyObject *v = PyLong_FromLong(val);
3057 if (v) {
3058 PyDict_SetItemString(d, name, v);
3059 Py_DECREF(v);
3060 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003061}
3062static void
Fred Drake509d79a2000-07-08 04:04:38 +00003063ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003064{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003065 PyObject *v = PyUnicode_FromString(val);
3066 if (v) {
3067 PyDict_SetItemString(d, name, v);
3068 Py_DECREF(v);
3069 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003070}
3071
3072
Martin v. Löwis1a214512008-06-11 05:26:20 +00003073static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003074 PyModuleDef_HEAD_INIT,
3075 "_tkinter",
3076 NULL,
3077 -1,
3078 moduleMethods,
3079 NULL,
3080 NULL,
3081 NULL,
3082 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003083};
3084
Mark Hammond62b1ab12002-07-23 06:31:15 +00003085PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003086PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003087{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003090 if (PyType_Ready(&Tkapp_Type) < 0)
3091 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003092
3093#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003094 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003095#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003097 m = PyModule_Create(&_tkintermodule);
3098 if (m == NULL)
3099 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003100
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 d = PyModule_GetDict(m);
3102 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3103 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003105 ins_long(d, "READABLE", TCL_READABLE);
3106 ins_long(d, "WRITABLE", TCL_WRITABLE);
3107 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3108 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3109 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3110 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3111 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3112 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3113 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3114 ins_string(d, "TK_VERSION", TK_VERSION);
3115 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003119 if (PyType_Ready(&Tktt_Type) < 0)
3120 return NULL;
3121 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003123 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3124 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003125
3126#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3128 * start waking up. Note that Tcl_FindExecutable will do this, this
3129 * code must be above it! The original warning from
3130 * tkMacOSXAppInit.c is copied below.
3131 *
3132 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3133 * Tcl interpreter for now. It probably should work to do this
3134 * in the other order, but for now it doesn't seem to.
3135 *
3136 */
3137 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003138#endif
3139
3140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 /* This helps the dynamic loader; in Unicode aware Tcl versions
3142 it also helps Tcl find its encodings. */
3143 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3144 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003145 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003146 if (cexe)
3147 Tcl_FindExecutable(PyBytes_AsString(cexe));
3148 Py_XDECREF(cexe);
3149 Py_DECREF(uexe);
3150 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003152 if (PyErr_Occurred()) {
3153 Py_DECREF(m);
3154 return NULL;
3155 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003156
Guido van Rossum43ff8681998-07-14 18:02:13 +00003157#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 /* This was not a good idea; through <Destroy> bindings,
3159 Tcl_Finalize() may invoke Python code but at that point the
3160 interpreter and thread state have already been destroyed! */
3161 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003162#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003163 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003164}