blob: ffb8ab08c95a4781d61e1dcccc5996e9eb65df9d [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. */
993 PyErr_SetString(PyExc_ValueError,
994 "unsupported character");
995 ckfree(FREECAST outbuf);
996 return NULL;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200997#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000998 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200999 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 }
1001 result = Tcl_NewUnicodeObj(outbuf, size);
1002 ckfree(FREECAST outbuf);
1003 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 }
1005 else if(PyTclObject_Check(value)) {
1006 Tcl_Obj *v = ((PyTclObject*)value)->value;
1007 Tcl_IncrRefCount(v);
1008 return v;
1009 }
1010 else {
1011 PyObject *v = PyObject_Str(value);
1012 if (!v)
1013 return 0;
1014 result = AsObj(v);
1015 Py_DECREF(v);
1016 return result;
1017 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001018}
1019
Martin v. Löwisffad6332002-11-26 09:28:05 +00001020static PyObject*
1021FromObj(PyObject* tkapp, Tcl_Obj *value)
1022{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001023 PyObject *result = NULL;
1024 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001026 if (value->typePtr == NULL) {
1027 return PyUnicode_FromStringAndSize(value->bytes,
1028 value->length);
1029 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 if (value->typePtr == app->BooleanType) {
1032 result = value->internalRep.longValue ? Py_True : Py_False;
1033 Py_INCREF(result);
1034 return result;
1035 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037 if (value->typePtr == app->ByteArrayType) {
1038 int size;
1039 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1040 return PyBytes_FromStringAndSize(data, size);
1041 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 if (value->typePtr == app->DoubleType) {
1044 return PyFloat_FromDouble(value->internalRep.doubleValue);
1045 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047 if (value->typePtr == app->IntType) {
1048 return PyLong_FromLong(value->internalRep.longValue);
1049 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 if (value->typePtr == app->ListType) {
1052 int size;
1053 int i, status;
1054 PyObject *elem;
1055 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1058 if (status == TCL_ERROR)
1059 return Tkinter_Error(tkapp);
1060 result = PyTuple_New(size);
1061 if (!result)
1062 return NULL;
1063 for (i = 0; i < size; i++) {
1064 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1065 value, i, &tcl_elem);
1066 if (status == TCL_ERROR) {
1067 Py_DECREF(result);
1068 return Tkinter_Error(tkapp);
1069 }
1070 elem = FromObj(tkapp, tcl_elem);
1071 if (!elem) {
1072 Py_DECREF(result);
1073 return NULL;
1074 }
1075 PyTuple_SetItem(result, i, elem);
1076 }
1077 return result;
1078 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001080 if (value->typePtr == app->ProcBodyType) {
1081 /* fall through: return tcl object. */
1082 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001085#if TCL_UTF_MAX==3
1086 return PyUnicode_FromKindAndData(
1087 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1088 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001089#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001090 return PyUnicode_FromKindAndData(
1091 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1092 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001093#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001097}
1098
Benjamin Peterson5879d412009-03-30 14:51:56 +00001099#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001100/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001101TCL_DECLARE_MUTEX(call_mutex)
1102
1103typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001104 Tcl_Event ev; /* Must be first */
1105 TkappObject *self;
1106 PyObject *args;
1107 int flags;
1108 PyObject **res;
1109 PyObject **exc_type, **exc_value, **exc_tb;
1110 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001111} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001112#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001113
1114void
1115Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001116{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001117 int i;
1118 for (i = 0; i < objc; i++)
1119 Tcl_DecrRefCount(objv[i]);
1120 if (objv != objStore)
1121 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001122}
Guido van Rossum18468821994-06-20 07:49:28 +00001123
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124/* Convert Python objects to Tcl objects. This must happen in the
1125 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001126
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001127static Tcl_Obj**
1128Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1129{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001130 Tcl_Obj **objv = objStore;
1131 int objc = 0, i;
1132 if (args == NULL)
1133 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 else if (!PyTuple_Check(args)) {
1136 objv[0] = AsObj(args);
1137 if (objv[0] == 0)
1138 goto finally;
1139 objc = 1;
1140 Tcl_IncrRefCount(objv[0]);
1141 }
1142 else {
1143 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 if (objc > ARGSZ) {
1146 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1147 if (objv == NULL) {
1148 PyErr_NoMemory();
1149 objc = 0;
1150 goto finally;
1151 }
1152 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001153
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001154 for (i = 0; i < objc; i++) {
1155 PyObject *v = PyTuple_GetItem(args, i);
1156 if (v == Py_None) {
1157 objc = i;
1158 break;
1159 }
1160 objv[i] = AsObj(v);
1161 if (!objv[i]) {
1162 /* Reset objc, so it attempts to clear
1163 objects only up to i. */
1164 objc = i;
1165 goto finally;
1166 }
1167 Tcl_IncrRefCount(objv[i]);
1168 }
1169 }
1170 *pobjc = objc;
1171 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001172finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001173 Tkapp_CallDeallocArgs(objv, objStore, objc);
1174 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175}
Guido van Rossum212643f1998-04-29 16:22:14 +00001176
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001178
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001179static PyObject*
1180Tkapp_CallResult(TkappObject *self)
1181{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001182 PyObject *res = NULL;
1183 if(self->wantobjects) {
1184 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1185 /* Not sure whether the IncrRef is necessary, but something
1186 may overwrite the interpreter result while we are
1187 converting it. */
1188 Tcl_IncrRefCount(value);
1189 res = FromObj((PyObject*)self, value);
1190 Tcl_DecrRefCount(value);
1191 } else {
1192 const char *s = Tcl_GetStringResult(self->interp);
1193 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001195 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1196 }
1197 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001198}
Guido van Rossum632de272000-03-29 00:19:50 +00001199
Benjamin Peterson5879d412009-03-30 14:51:56 +00001200#ifdef WITH_THREAD
1201
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001202/* Tkapp_CallProc is the event procedure that is executed in the context of
1203 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1204 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001205
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001206static int
1207Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1208{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001209 Tcl_Obj *objStore[ARGSZ];
1210 Tcl_Obj **objv;
1211 int objc;
1212 int i;
1213 ENTER_PYTHON
1214 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1215 if (!objv) {
1216 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1217 *(e->res) = NULL;
1218 }
1219 LEAVE_PYTHON
1220 if (!objv)
1221 goto done;
1222 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1223 ENTER_PYTHON
1224 if (i == TCL_ERROR) {
1225 *(e->res) = NULL;
1226 *(e->exc_type) = NULL;
1227 *(e->exc_tb) = NULL;
1228 *(e->exc_value) = PyObject_CallFunction(
1229 Tkinter_TclError, "s",
1230 Tcl_GetStringResult(e->self->interp));
1231 }
1232 else {
1233 *(e->res) = Tkapp_CallResult(e->self);
1234 }
1235 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001238done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 /* Wake up calling thread. */
1240 Tcl_MutexLock(&call_mutex);
1241 Tcl_ConditionNotify(e->done);
1242 Tcl_MutexUnlock(&call_mutex);
1243 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244}
1245
Benjamin Peterson5879d412009-03-30 14:51:56 +00001246#endif
1247
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248/* This is the main entry point for calling a Tcl command.
1249 It supports three cases, with regard to threading:
1250 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1251 the context of the calling thread.
1252 2. Tcl is threaded, caller of the command is in the interpreter thread:
1253 Execute the command in the calling thread. Since the Tcl lock will
1254 not be used, we can merge that with case 1.
1255 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1256 the interpreter thread. Allocation of Tcl objects needs to occur in the
1257 interpreter thread, so we ship the PyObject* args to the target thread,
1258 and perform processing there. */
1259
1260static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001261Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 Tcl_Obj *objStore[ARGSZ];
1264 Tcl_Obj **objv = NULL;
1265 int objc, i;
1266 PyObject *res = NULL;
1267 TkappObject *self = (TkappObject*)selfptr;
1268 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 /* If args is a single tuple, replace with contents of tuple */
1271 if (1 == PyTuple_Size(args)){
1272 PyObject* item = PyTuple_GetItem(args, 0);
1273 if (PyTuple_Check(item))
1274 args = item;
1275 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001276#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1278 /* We cannot call the command directly. Instead, we must
1279 marshal the parameters to the interpreter thread. */
1280 Tkapp_CallEvent *ev;
1281 Tcl_Condition cond = NULL;
1282 PyObject *exc_type, *exc_value, *exc_tb;
1283 if (!WaitForMainloop(self))
1284 return NULL;
1285 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1286 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1287 ev->self = self;
1288 ev->args = args;
1289 ev->res = &res;
1290 ev->exc_type = &exc_type;
1291 ev->exc_value = &exc_value;
1292 ev->exc_tb = &exc_tb;
1293 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 if (res == NULL) {
1298 if (exc_type)
1299 PyErr_Restore(exc_type, exc_value, exc_tb);
1300 else
1301 PyErr_SetObject(Tkinter_TclError, exc_value);
1302 }
1303 Tcl_ConditionFinalize(&cond);
1304 }
1305 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001306#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001307 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 objv = Tkapp_CallArgs(args, objStore, &objc);
1310 if (!objv)
1311 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 if (i == TCL_ERROR)
1320 Tkinter_Error(selfptr);
1321 else
1322 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 Tkapp_CallDeallocArgs(objv, objStore, objc);
1327 }
1328 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001329}
1330
1331
1332static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001333Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001334{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 /* Could do the same here as for Tkapp_Call(), but this is not used
1336 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1337 way for the user to do what all its Global* variants do (save and
1338 reset the scope pointer, call the local version, restore the saved
1339 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 char *cmd;
1342 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001343
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 cmd = Merge(args);
1347 if (cmd) {
1348 int err;
1349 ENTER_TCL
1350 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1351 ENTER_OVERLAP
1352 if (err == TCL_ERROR)
1353 res = Tkinter_Error(self);
1354 else
1355 res = PyUnicode_FromString(Tkapp_Result(self));
1356 LEAVE_OVERLAP_TCL
1357 ckfree(cmd);
1358 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001360 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001361}
1362
1363static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001364Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001365{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 char *script;
1367 PyObject *res = NULL;
1368 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 if (!PyArg_ParseTuple(args, "s:eval", &script))
1371 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001373 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 ENTER_TCL
1376 err = Tcl_Eval(Tkapp_Interp(self), script);
1377 ENTER_OVERLAP
1378 if (err == TCL_ERROR)
1379 res = Tkinter_Error(self);
1380 else
1381 res = PyUnicode_FromString(Tkapp_Result(self));
1382 LEAVE_OVERLAP_TCL
1383 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001384}
1385
1386static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001387Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001388{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001389 char *script;
1390 PyObject *res = NULL;
1391 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1394 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 ENTER_TCL
1399 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1400 ENTER_OVERLAP
1401 if (err == TCL_ERROR)
1402 res = Tkinter_Error(self);
1403 else
1404 res = PyUnicode_FromString(Tkapp_Result(self));
1405 LEAVE_OVERLAP_TCL
1406 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001407}
1408
1409static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001410Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001411{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001412 char *fileName;
1413 PyObject *res = NULL;
1414 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001416 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1417 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 ENTER_TCL
1422 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1423 ENTER_OVERLAP
1424 if (err == TCL_ERROR)
1425 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 else
1428 res = PyUnicode_FromString(Tkapp_Result(self));
1429 LEAVE_OVERLAP_TCL
1430 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001431}
1432
1433static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001434Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001435{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 char *script;
1437 PyObject *res = NULL;
1438 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001440 if (!PyArg_ParseTuple(args, "s", &script))
1441 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 ENTER_TCL
1446 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1447 ENTER_OVERLAP
1448 if (err == TCL_ERROR)
1449 res = Tkinter_Error(self);
1450 else
1451 res = PyUnicode_FromString(Tkapp_Result(self));
1452 LEAVE_OVERLAP_TCL
1453 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001454}
1455
1456static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001457Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001458{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1462 return NULL;
1463 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001465 ENTER_TCL
1466 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1467 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001469 Py_INCREF(Py_None);
1470 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001471}
1472
Barry Warsawfa701a81997-01-16 00:15:11 +00001473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474
Guido van Rossum18468821994-06-20 07:49:28 +00001475/** Tcl Variable **/
1476
Benjamin Peterson5879d412009-03-30 14:51:56 +00001477typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1478
1479#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480TCL_DECLARE_MUTEX(var_mutex)
1481
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 Tcl_Event ev; /* must be first */
1484 PyObject *self;
1485 PyObject *args;
1486 int flags;
1487 EventFunc func;
1488 PyObject **res;
1489 PyObject **exc_type;
1490 PyObject **exc_val;
1491 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001493#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001494
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001495static int
1496varname_converter(PyObject *in, void *_out)
1497{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 char **out = (char**)_out;
1499 if (PyBytes_Check(in)) {
1500 *out = PyBytes_AsString(in);
1501 return 1;
1502 }
1503 if (PyUnicode_Check(in)) {
1504 *out = _PyUnicode_AsString(in);
1505 return 1;
1506 }
1507 if (PyTclObject_Check(in)) {
1508 *out = PyTclObject_TclString(in);
1509 return 1;
1510 }
1511 /* XXX: Should give diagnostics. */
1512 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001513}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001514
Benjamin Peterson5879d412009-03-30 14:51:56 +00001515#ifdef WITH_THREAD
1516
Martin v. Löwis59683e82008-06-13 07:50:45 +00001517static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001518var_perform(VarEvent *ev)
1519{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1521 if (!*(ev->res)) {
1522 PyObject *exc, *val, *tb;
1523 PyErr_Fetch(&exc, &val, &tb);
1524 PyErr_NormalizeException(&exc, &val, &tb);
1525 *(ev->exc_type) = exc;
1526 *(ev->exc_val) = val;
1527 Py_DECREF(tb);
1528 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001529
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530}
1531
1532static int
1533var_proc(VarEvent* ev, int flags)
1534{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 ENTER_PYTHON
1536 var_perform(ev);
1537 Tcl_MutexLock(&var_mutex);
1538 Tcl_ConditionNotify(ev->cond);
1539 Tcl_MutexUnlock(&var_mutex);
1540 LEAVE_PYTHON
1541 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542}
1543
Benjamin Peterson5879d412009-03-30 14:51:56 +00001544#endif
1545
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001547var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001549#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 TkappObject *self = (TkappObject*)selfptr;
1551 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1552 TkappObject *self = (TkappObject*)selfptr;
1553 VarEvent *ev;
1554 PyObject *res, *exc_type, *exc_val;
1555 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001556
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 /* The current thread is not the interpreter thread. Marshal
1558 the call to the interpreter thread, then wait for
1559 completion. */
1560 if (!WaitForMainloop(self))
1561 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001562
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001564
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 ev->self = selfptr;
1566 ev->args = args;
1567 ev->flags = flags;
1568 ev->func = func;
1569 ev->res = &res;
1570 ev->exc_type = &exc_type;
1571 ev->exc_val = &exc_val;
1572 ev->cond = &cond;
1573 ev->ev.proc = (Tcl_EventProc*)var_proc;
1574 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1575 Tcl_ConditionFinalize(&cond);
1576 if (!res) {
1577 PyErr_SetObject(exc_type, exc_val);
1578 Py_DECREF(exc_type);
1579 Py_DECREF(exc_val);
1580 return NULL;
1581 }
1582 return res;
1583 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001584#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001585 /* Tcl is not threaded, or this is the interpreter thread. */
1586 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001587}
1588
Guido van Rossum18468821994-06-20 07:49:28 +00001589static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001590SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001591{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001592 char *name1, *name2;
1593 PyObject *newValue;
1594 PyObject *res = NULL;
1595 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 if (PyArg_ParseTuple(args, "O&O:setvar",
1598 varname_converter, &name1, &newValue)) {
1599 /* XXX Acquire tcl lock??? */
1600 newval = AsObj(newValue);
1601 if (newval == NULL)
1602 return NULL;
1603 ENTER_TCL
1604 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1605 newval, flags);
1606 ENTER_OVERLAP
1607 if (!ok)
1608 Tkinter_Error(self);
1609 else {
1610 res = Py_None;
1611 Py_INCREF(res);
1612 }
1613 LEAVE_OVERLAP_TCL
1614 }
1615 else {
1616 PyErr_Clear();
1617 if (PyArg_ParseTuple(args, "ssO:setvar",
1618 &name1, &name2, &newValue)) {
1619 /* XXX must hold tcl lock already??? */
1620 newval = AsObj(newValue);
1621 ENTER_TCL
1622 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1623 ENTER_OVERLAP
1624 if (!ok)
1625 Tkinter_Error(self);
1626 else {
1627 res = Py_None;
1628 Py_INCREF(res);
1629 }
1630 LEAVE_OVERLAP_TCL
1631 }
1632 else {
1633 return NULL;
1634 }
1635 }
1636 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001637}
1638
1639static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001640Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001641{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001642 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001643}
1644
1645static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001646Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001647{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001648 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001649}
1650
Barry Warsawfa701a81997-01-16 00:15:11 +00001651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001652
Guido van Rossum18468821994-06-20 07:49:28 +00001653static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001654GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001655{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001656 char *name1, *name2=NULL;
1657 PyObject *res = NULL;
1658 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1661 varname_converter, &name1, &name2))
1662 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 ENTER_TCL
1665 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1666 ENTER_OVERLAP
1667 if (tres == NULL) {
1668 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1669 } else {
1670 if (((TkappObject*)self)->wantobjects) {
1671 res = FromObj(self, tres);
1672 }
1673 else {
1674 res = PyUnicode_FromString(Tcl_GetString(tres));
1675 }
1676 }
1677 LEAVE_OVERLAP_TCL
1678 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001679}
1680
1681static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001682Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001683{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001684 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001690 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001691}
1692
Barry Warsawfa701a81997-01-16 00:15:11 +00001693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001694
Guido van Rossum18468821994-06-20 07:49:28 +00001695static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001696UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001697{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001698 char *name1, *name2=NULL;
1699 int code;
1700 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001702 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1703 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001705 ENTER_TCL
1706 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1707 ENTER_OVERLAP
1708 if (code == TCL_ERROR)
1709 res = Tkinter_Error(self);
1710 else {
1711 Py_INCREF(Py_None);
1712 res = Py_None;
1713 }
1714 LEAVE_OVERLAP_TCL
1715 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001716}
1717
1718static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001719Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001720{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001722}
1723
1724static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001725Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001726{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001728}
1729
Barry Warsawfa701a81997-01-16 00:15:11 +00001730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001731
Guido van Rossum18468821994-06-20 07:49:28 +00001732/** Tcl to Python **/
1733
1734static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001735Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001736{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001737 char *s;
1738 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001740 if (PyTuple_Size(args) == 1) {
1741 PyObject* o = PyTuple_GetItem(args, 0);
1742 if (PyLong_Check(o)) {
1743 Py_INCREF(o);
1744 return o;
1745 }
1746 }
1747 if (!PyArg_ParseTuple(args, "s:getint", &s))
1748 return NULL;
1749 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1750 return Tkinter_Error(self);
1751 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001752}
1753
1754static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001755Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 char *s;
1758 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001759
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 if (PyTuple_Size(args) == 1) {
1761 PyObject *o = PyTuple_GetItem(args, 0);
1762 if (PyFloat_Check(o)) {
1763 Py_INCREF(o);
1764 return o;
1765 }
1766 }
1767 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1768 return NULL;
1769 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1770 return Tkinter_Error(self);
1771 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001772}
1773
1774static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001775Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001776{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001777 char *s;
1778 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001780 if (PyTuple_Size(args) == 1) {
1781 PyObject *o = PyTuple_GetItem(args, 0);
1782 if (PyLong_Check(o)) {
1783 Py_INCREF(o);
1784 return o;
1785 }
1786 }
1787 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1788 return NULL;
1789 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1790 return Tkinter_Error(self);
1791 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001792}
1793
1794static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001795Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001796{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001797 char *s;
1798 PyObject *res = NULL;
1799 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001801 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1802 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001804 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001805
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 ENTER_TCL
1807 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1808 ENTER_OVERLAP
1809 if (retval == TCL_ERROR)
1810 res = Tkinter_Error(self);
1811 else
1812 res = Py_BuildValue("s", Tkapp_Result(self));
1813 LEAVE_OVERLAP_TCL
1814 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001815}
1816
1817static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001818Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001819{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001820 char *s;
1821 PyObject *res = NULL;
1822 int retval;
1823 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001824
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1826 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001830 ENTER_TCL
1831 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1832 ENTER_OVERLAP
1833 if (retval == TCL_ERROR)
1834 res = Tkinter_Error(self);
1835 else
1836 res = Py_BuildValue("l", v);
1837 LEAVE_OVERLAP_TCL
1838 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001839}
1840
1841static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001842Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001843{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001844 char *s;
1845 PyObject *res = NULL;
1846 double v;
1847 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1850 return NULL;
1851 CHECK_TCL_APPARTMENT;
1852 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1853 ENTER_TCL
1854 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1855 ENTER_OVERLAP
1856 PyFPE_END_PROTECT(retval)
1857 if (retval == TCL_ERROR)
1858 res = Tkinter_Error(self);
1859 else
1860 res = Py_BuildValue("d", v);
1861 LEAVE_OVERLAP_TCL
1862 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 char *s;
1869 PyObject *res = NULL;
1870 int retval;
1871 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1874 return NULL;
1875 CHECK_TCL_APPARTMENT;
1876 ENTER_TCL
1877 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1878 ENTER_OVERLAP
1879 if (retval == TCL_ERROR)
1880 res = Tkinter_Error(self);
1881 else
1882 res = Py_BuildValue("i", v);
1883 LEAVE_OVERLAP_TCL
1884 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001885}
1886
Barry Warsawfa701a81997-01-16 00:15:11 +00001887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888
Guido van Rossum18468821994-06-20 07:49:28 +00001889static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001890Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001891{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001892 char *list;
1893 int argc;
1894 char **argv;
1895 PyObject *v;
1896 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001897
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001898 if (PyTuple_Size(args) == 1) {
1899 v = PyTuple_GetItem(args, 0);
1900 if (PyTuple_Check(v)) {
1901 Py_INCREF(v);
1902 return v;
1903 }
1904 }
1905 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1906 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 if (Tcl_SplitList(Tkapp_Interp(self), list,
1909 &argc, &argv) == TCL_ERROR) {
1910 PyMem_Free(list);
1911 return Tkinter_Error(self);
1912 }
Guido van Rossum18468821994-06-20 07:49:28 +00001913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 if (!(v = PyTuple_New(argc)))
1915 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001916
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 for (i = 0; i < argc; i++) {
1918 PyObject *s = PyUnicode_FromString(argv[i]);
1919 if (!s || PyTuple_SetItem(v, i, s)) {
1920 Py_DECREF(v);
1921 v = NULL;
1922 goto finally;
1923 }
1924 }
Guido van Rossum18468821994-06-20 07:49:28 +00001925
Barry Warsawfa701a81997-01-16 00:15:11 +00001926 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001927 ckfree(FREECAST argv);
1928 PyMem_Free(list);
1929 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001930}
1931
1932static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001933Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001934{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 PyObject *v;
1936 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001938 if (PyTuple_Size(args) == 1) {
1939 PyObject* o = PyTuple_GetItem(args, 0);
1940 if (PyTuple_Check(o)) {
1941 o = SplitObj(o);
1942 return o;
1943 }
1944 }
1945 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1946 return NULL;
1947 v = Split(list);
1948 PyMem_Free(list);
1949 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001950}
1951
1952static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001953Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001954{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001955 char *s = Merge(args);
1956 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001958 if (s) {
1959 res = PyUnicode_FromString(s);
1960 ckfree(s);
1961 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001963 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001964}
1965
Barry Warsawfa701a81997-01-16 00:15:11 +00001966
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001967
Guido van Rossum18468821994-06-20 07:49:28 +00001968/** Tcl Command **/
1969
Guido van Rossum00d93061998-05-28 23:06:38 +00001970/* Client data struct */
1971typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 PyObject *self;
1973 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001974} PythonCmd_ClientData;
1975
1976static int
Fred Drake509d79a2000-07-08 04:04:38 +00001977PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001978{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 errorInCmd = 1;
1980 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1981 LEAVE_PYTHON
1982 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001983}
1984
Guido van Rossum18468821994-06-20 07:49:28 +00001985/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001986 * function or method.
1987 */
Guido van Rossum18468821994-06-20 07:49:28 +00001988static int
Fred Drake509d79a2000-07-08 04:04:38 +00001989PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001990{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001991 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001992 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 int i, rv;
1994 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 /* TBD: no error checking here since we know, via the
1999 * Tkapp_CreateCommand() that the client data is a two-tuple
2000 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 /* Create argument list (argv1, ..., argvN) */
2004 if (!(arg = PyTuple_New(argc - 1)))
2005 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002006
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002007 for (i = 0; i < (argc - 1); i++) {
2008 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002009 if (!s) {
2010 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2011 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2012 !strcmp(argv[i + 1], "\xC0\x80")) {
2013 PyErr_Clear();
2014 /* Convert to "strict" utf-8 null */
2015 s = PyUnicode_FromString("\0");
2016 } else {
2017 Py_DECREF(arg);
2018 return PythonCmd_Error(interp);
2019 }
2020 }
2021 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002022 Py_DECREF(arg);
2023 return PythonCmd_Error(interp);
2024 }
2025 }
2026 res = PyEval_CallObject(func, arg);
2027 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002029 if (res == NULL)
2030 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002032 obj_res = AsObj(res);
2033 if (obj_res == NULL) {
2034 Py_DECREF(res);
2035 return PythonCmd_Error(interp);
2036 }
2037 else {
2038 Tcl_SetObjResult(interp, obj_res);
2039 rv = TCL_OK;
2040 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002041
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002044 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002047}
2048
2049static void
Fred Drake509d79a2000-07-08 04:04:38 +00002050PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002051{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002052 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002053
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002054 ENTER_PYTHON
2055 Py_XDECREF(data->self);
2056 Py_XDECREF(data->func);
2057 PyMem_DEL(data);
2058 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002059}
2060
Barry Warsawfa701a81997-01-16 00:15:11 +00002061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002062
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002063
Benjamin Peterson5879d412009-03-30 14:51:56 +00002064#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002065TCL_DECLARE_MUTEX(command_mutex)
2066
2067typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002068 Tcl_Event ev;
2069 Tcl_Interp* interp;
2070 char *name;
2071 int create;
2072 int *status;
2073 ClientData *data;
2074 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002075} CommandEvent;
2076
2077static int
2078Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002079{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 if (ev->create)
2081 *ev->status = Tcl_CreateCommand(
2082 ev->interp, ev->name, PythonCmd,
2083 ev->data, PythonCmdDelete) == NULL;
2084 else
2085 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2086 Tcl_MutexLock(&command_mutex);
2087 Tcl_ConditionNotify(ev->done);
2088 Tcl_MutexUnlock(&command_mutex);
2089 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002090}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002091#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002092
2093static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002094Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002095{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002096 TkappObject *self = (TkappObject*)selfptr;
2097 PythonCmd_ClientData *data;
2098 char *cmdName;
2099 PyObject *func;
2100 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2103 return NULL;
2104 if (!PyCallable_Check(func)) {
2105 PyErr_SetString(PyExc_TypeError, "command not callable");
2106 return NULL;
2107 }
Guido van Rossum18468821994-06-20 07:49:28 +00002108
Martin v. Löwisa9656492003-03-30 08:44:58 +00002109#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2111 !WaitForMainloop(self))
2112 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002113#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 data = PyMem_NEW(PythonCmd_ClientData, 1);
2116 if (!data)
2117 return PyErr_NoMemory();
2118 Py_INCREF(self);
2119 Py_INCREF(func);
2120 data->self = selfptr;
2121 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002122#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2124 Tcl_Condition cond = NULL;
2125 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2126 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2127 ev->interp = self->interp;
2128 ev->create = 1;
2129 ev->name = cmdName;
2130 ev->data = (ClientData)data;
2131 ev->status = &err;
2132 ev->done = &cond;
2133 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2134 Tcl_ConditionFinalize(&cond);
2135 }
2136 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002137#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 {
2139 ENTER_TCL
2140 err = Tcl_CreateCommand(
2141 Tkapp_Interp(self), cmdName, PythonCmd,
2142 (ClientData)data, PythonCmdDelete) == NULL;
2143 LEAVE_TCL
2144 }
2145 if (err) {
2146 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2147 PyMem_DEL(data);
2148 return NULL;
2149 }
Guido van Rossum18468821994-06-20 07:49:28 +00002150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002151 Py_INCREF(Py_None);
2152 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002153}
2154
Barry Warsawfa701a81997-01-16 00:15:11 +00002155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002156
Guido van Rossum18468821994-06-20 07:49:28 +00002157static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002158Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002159{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 TkappObject *self = (TkappObject*)selfptr;
2161 char *cmdName;
2162 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002163
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2165 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002166
2167#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2169 Tcl_Condition cond = NULL;
2170 CommandEvent *ev;
2171 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2172 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2173 ev->interp = self->interp;
2174 ev->create = 0;
2175 ev->name = cmdName;
2176 ev->status = &err;
2177 ev->done = &cond;
2178 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2179 &command_mutex);
2180 Tcl_ConditionFinalize(&cond);
2181 }
2182 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002183#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002184 {
2185 ENTER_TCL
2186 err = Tcl_DeleteCommand(self->interp, cmdName);
2187 LEAVE_TCL
2188 }
2189 if (err == -1) {
2190 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2191 return NULL;
2192 }
2193 Py_INCREF(Py_None);
2194 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002195}
2196
Barry Warsawfa701a81997-01-16 00:15:11 +00002197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198
Guido van Rossum00d93061998-05-28 23:06:38 +00002199#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002200/** File Handler **/
2201
Guido van Rossum00d93061998-05-28 23:06:38 +00002202typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 PyObject *func;
2204 PyObject *file;
2205 int id;
2206 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002207} FileHandler_ClientData;
2208
2209static FileHandler_ClientData *HeadFHCD;
2210
2211static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002212NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002213{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002214 FileHandler_ClientData *p;
2215 p = PyMem_NEW(FileHandler_ClientData, 1);
2216 if (p != NULL) {
2217 Py_XINCREF(func);
2218 Py_XINCREF(file);
2219 p->func = func;
2220 p->file = file;
2221 p->id = id;
2222 p->next = HeadFHCD;
2223 HeadFHCD = p;
2224 }
2225 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002226}
2227
2228static void
Fred Drake509d79a2000-07-08 04:04:38 +00002229DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002230{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 pp = &HeadFHCD;
2234 while ((p = *pp) != NULL) {
2235 if (p->id == id) {
2236 *pp = p->next;
2237 Py_XDECREF(p->func);
2238 Py_XDECREF(p->file);
2239 PyMem_DEL(p);
2240 }
2241 else
2242 pp = &p->next;
2243 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002244}
2245
Guido van Rossuma597dde1995-01-10 20:56:29 +00002246static void
Fred Drake509d79a2000-07-08 04:04:38 +00002247FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002248{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002249 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2250 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002251
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 ENTER_PYTHON
2253 func = data->func;
2254 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002255
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002256 arg = Py_BuildValue("(Oi)", file, (long) mask);
2257 res = PyEval_CallObject(func, arg);
2258 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 if (res == NULL) {
2261 errorInCmd = 1;
2262 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2263 }
2264 Py_XDECREF(res);
2265 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002266}
2267
Guido van Rossum18468821994-06-20 07:49:28 +00002268static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002269Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2270 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002271{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 FileHandler_ClientData *data;
2273 PyObject *file, *func;
2274 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002276 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2277 &file, &mask, &func))
2278 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 tfile = PyObject_AsFileDescriptor(file);
2283 if (tfile < 0)
2284 return NULL;
2285 if (!PyCallable_Check(func)) {
2286 PyErr_SetString(PyExc_TypeError, "bad argument list");
2287 return NULL;
2288 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002290 data = NewFHCD(func, file, tfile);
2291 if (data == NULL)
2292 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 /* Ought to check for null Tcl_File object... */
2295 ENTER_TCL
2296 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2297 LEAVE_TCL
2298 Py_INCREF(Py_None);
2299 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002300}
2301
2302static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002303Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002304{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 PyObject *file;
2306 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2309 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 tfile = PyObject_AsFileDescriptor(file);
2314 if (tfile < 0)
2315 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 /* Ought to check for null Tcl_File object... */
2320 ENTER_TCL
2321 Tcl_DeleteFileHandler(tfile);
2322 LEAVE_TCL
2323 Py_INCREF(Py_None);
2324 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002325}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002326#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329/**** Tktt Object (timer token) ****/
2330
Jeremy Hylton938ace62002-07-17 16:30:39 +00002331static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002332
Guido van Rossum00d93061998-05-28 23:06:38 +00002333typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002334 PyObject_HEAD
2335 Tcl_TimerToken token;
2336 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002337} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002338
2339static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002340Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 TkttObject *v = (TkttObject *)self;
2343 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2346 return NULL;
2347 if (v->token != NULL) {
2348 Tcl_DeleteTimerHandler(v->token);
2349 v->token = NULL;
2350 }
2351 if (func != NULL) {
2352 v->func = NULL;
2353 Py_DECREF(func);
2354 Py_DECREF(v); /* See Tktt_New() */
2355 }
2356 Py_INCREF(Py_None);
2357 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358}
2359
2360static PyMethodDef Tktt_methods[] =
2361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2363 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002364};
2365
2366static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002367Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 v = PyObject_New(TkttObject, &Tktt_Type);
2372 if (v == NULL)
2373 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 Py_INCREF(func);
2376 v->token = NULL;
2377 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 /* Extra reference, deleted when called or when handler is deleted */
2380 Py_INCREF(v);
2381 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382}
2383
2384static void
Fred Drake509d79a2000-07-08 04:04:38 +00002385Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002387 TkttObject *v = (TkttObject *)self;
2388 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393}
2394
Guido van Rossum597ac201998-05-12 14:36:19 +00002395static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002396Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002399 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2400 v,
2401 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402}
2403
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404static PyTypeObject Tktt_Type =
2405{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 PyVarObject_HEAD_INIT(NULL, 0)
2407 "tktimertoken", /*tp_name */
2408 sizeof(TkttObject), /*tp_basicsize */
2409 0, /*tp_itemsize */
2410 Tktt_Dealloc, /*tp_dealloc */
2411 0, /*tp_print */
2412 0, /*tp_getattr */
2413 0, /*tp_setattr */
2414 0, /*tp_reserved */
2415 Tktt_Repr, /*tp_repr */
2416 0, /*tp_as_number */
2417 0, /*tp_as_sequence */
2418 0, /*tp_as_mapping */
2419 0, /*tp_hash */
2420 0, /*tp_call*/
2421 0, /*tp_str*/
2422 0, /*tp_getattro*/
2423 0, /*tp_setattro*/
2424 0, /*tp_as_buffer*/
2425 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2426 0, /*tp_doc*/
2427 0, /*tp_traverse*/
2428 0, /*tp_clear*/
2429 0, /*tp_richcompare*/
2430 0, /*tp_weaklistoffset*/
2431 0, /*tp_iter*/
2432 0, /*tp_iternext*/
2433 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434};
2435
Barry Warsawfa701a81997-01-16 00:15:11 +00002436
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002437
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002438/** Timer Handler **/
2439
2440static void
Fred Drake509d79a2000-07-08 04:04:38 +00002441TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002442{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 TkttObject *v = (TkttObject *)clientData;
2444 PyObject *func = v->func;
2445 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 if (func == NULL)
2448 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454 res = PyEval_CallObject(func, NULL);
2455 Py_DECREF(func);
2456 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458 if (res == NULL) {
2459 errorInCmd = 1;
2460 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2461 }
2462 else
2463 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002466}
2467
2468static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002469Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 int milliseconds;
2472 PyObject *func;
2473 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2476 &milliseconds, &func))
2477 return NULL;
2478 if (!PyCallable_Check(func)) {
2479 PyErr_SetString(PyExc_TypeError, "bad argument list");
2480 return NULL;
2481 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002483 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002485 v = Tktt_New(func);
2486 if (v) {
2487 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2488 (ClientData)v);
2489 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002491 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002492}
2493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494
Guido van Rossum18468821994-06-20 07:49:28 +00002495/** Event Loop **/
2496
Guido van Rossum18468821994-06-20 07:49:28 +00002497static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002498Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002499{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002500 int threshold = 0;
2501 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002502#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002504#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2507 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 CHECK_TCL_APPARTMENT;
2510 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 quitMainLoop = 0;
2513 while (Tk_GetNumMainWindows() > threshold &&
2514 !quitMainLoop &&
2515 !errorInCmd)
2516 {
2517 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002518
2519#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 if (self->threaded) {
2521 /* Allow other Python threads to run. */
2522 ENTER_TCL
2523 result = Tcl_DoOneEvent(0);
2524 LEAVE_TCL
2525 }
2526 else {
2527 Py_BEGIN_ALLOW_THREADS
2528 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2529 tcl_tstate = tstate;
2530 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2531 tcl_tstate = NULL;
2532 if(tcl_lock)PyThread_release_lock(tcl_lock);
2533 if (result == 0)
2534 Sleep(Tkinter_busywaitinterval);
2535 Py_END_ALLOW_THREADS
2536 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002537#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002538 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002539#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002541 if (PyErr_CheckSignals() != 0) {
2542 self->dispatching = 0;
2543 return NULL;
2544 }
2545 if (result < 0)
2546 break;
2547 }
2548 self->dispatching = 0;
2549 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002551 if (errorInCmd) {
2552 errorInCmd = 0;
2553 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2554 excInCmd = valInCmd = trbInCmd = NULL;
2555 return NULL;
2556 }
2557 Py_INCREF(Py_None);
2558 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002559}
2560
2561static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002562Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002563{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564 int flags = 0;
2565 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2568 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 ENTER_TCL
2571 rv = Tcl_DoOneEvent(flags);
2572 LEAVE_TCL
2573 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002574}
2575
2576static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002577Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002578{
2579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002580 if (!PyArg_ParseTuple(args, ":quit"))
2581 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 quitMainLoop = 1;
2584 Py_INCREF(Py_None);
2585 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002586}
2587
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002588static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002589Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002590{
2591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 if (!PyArg_ParseTuple(args, ":interpaddr"))
2593 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002595 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002596}
2597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002598static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002599Tkapp_TkInit(PyObject *self, PyObject *args)
2600{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 Tcl_Interp *interp = Tkapp_Interp(self);
2602 const char * _tk_exists = NULL;
2603 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002604
Guilherme Polob681df42009-02-09 22:33:59 +00002605#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002606 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2607 * first call failed.
2608 * To avoid the deadlock, we just refuse the second call through
2609 * a static variable.
2610 */
2611 if (tk_load_failed) {
2612 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2613 return NULL;
2614 }
Guilherme Polob681df42009-02-09 22:33:59 +00002615#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 /* We want to guard against calling Tk_Init() multiple times */
2618 CHECK_TCL_APPARTMENT;
2619 ENTER_TCL
2620 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2621 ENTER_OVERLAP
2622 if (err == TCL_ERROR) {
2623 /* This sets an exception, but we cannot return right
2624 away because we need to exit the overlap first. */
2625 Tkinter_Error(self);
2626 } else {
2627 _tk_exists = Tkapp_Result(self);
2628 }
2629 LEAVE_OVERLAP_TCL
2630 if (err == TCL_ERROR) {
2631 return NULL;
2632 }
2633 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2634 if (Tk_Init(interp) == TCL_ERROR) {
2635 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002636#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002638#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002639 return NULL;
2640 }
2641 }
2642 Py_INCREF(Py_None);
2643 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002644}
Barry Warsawfa701a81997-01-16 00:15:11 +00002645
Martin v. Löwisffad6332002-11-26 09:28:05 +00002646static PyObject *
2647Tkapp_WantObjects(PyObject *self, PyObject *args)
2648{
2649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002650 int wantobjects = -1;
2651 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2652 return NULL;
2653 if (wantobjects == -1)
2654 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2655 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002657 Py_INCREF(Py_None);
2658 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002659}
2660
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002661static PyObject *
2662Tkapp_WillDispatch(PyObject *self, PyObject *args)
2663{
2664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 Py_INCREF(Py_None);
2668 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002669}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671
Guido van Rossum18468821994-06-20 07:49:28 +00002672/**** Tkapp Method List ****/
2673
2674static PyMethodDef Tkapp_methods[] =
2675{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2677 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2678 {"call", Tkapp_Call, METH_VARARGS},
2679 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2680 {"eval", Tkapp_Eval, METH_VARARGS},
2681 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2682 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2683 {"record", Tkapp_Record, METH_VARARGS},
2684 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2685 {"setvar", Tkapp_SetVar, METH_VARARGS},
2686 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2687 {"getvar", Tkapp_GetVar, METH_VARARGS},
2688 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2689 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2690 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2691 {"getint", Tkapp_GetInt, METH_VARARGS},
2692 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2693 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2694 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2695 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2696 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2697 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2698 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2699 {"split", Tkapp_Split, METH_VARARGS},
2700 {"merge", Tkapp_Merge, METH_VARARGS},
2701 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2702 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002703#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2705 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002706#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002707 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2708 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2709 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2710 {"quit", Tkapp_Quit, METH_VARARGS},
2711 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2712 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2713 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002714};
2715
Barry Warsawfa701a81997-01-16 00:15:11 +00002716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002717
Guido van Rossum18468821994-06-20 07:49:28 +00002718/**** Tkapp Type Methods ****/
2719
2720static void
Fred Drake509d79a2000-07-08 04:04:38 +00002721Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002722{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 /*CHECK_TCL_APPARTMENT;*/
2724 ENTER_TCL
2725 Tcl_DeleteInterp(Tkapp_Interp(self));
2726 LEAVE_TCL
2727 PyObject_Del(self);
2728 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002729}
2730
Guido van Rossum18468821994-06-20 07:49:28 +00002731static PyTypeObject Tkapp_Type =
2732{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002733 PyVarObject_HEAD_INIT(NULL, 0)
2734 "tkapp", /*tp_name */
2735 sizeof(TkappObject), /*tp_basicsize */
2736 0, /*tp_itemsize */
2737 Tkapp_Dealloc, /*tp_dealloc */
2738 0, /*tp_print */
2739 0, /*tp_getattr */
2740 0, /*tp_setattr */
2741 0, /*tp_reserved */
2742 0, /*tp_repr */
2743 0, /*tp_as_number */
2744 0, /*tp_as_sequence */
2745 0, /*tp_as_mapping */
2746 0, /*tp_hash */
2747 0, /*tp_call*/
2748 0, /*tp_str*/
2749 0, /*tp_getattro*/
2750 0, /*tp_setattro*/
2751 0, /*tp_as_buffer*/
2752 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2753 0, /*tp_doc*/
2754 0, /*tp_traverse*/
2755 0, /*tp_clear*/
2756 0, /*tp_richcompare*/
2757 0, /*tp_weaklistoffset*/
2758 0, /*tp_iter*/
2759 0, /*tp_iternext*/
2760 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002761};
2762
Barry Warsawfa701a81997-01-16 00:15:11 +00002763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764
Guido van Rossum18468821994-06-20 07:49:28 +00002765/**** Tkinter Module ****/
2766
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002767typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002768 PyObject* tuple;
2769 int size; /* current size */
2770 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002771} FlattenContext;
2772
2773static int
2774_bump(FlattenContext* context, int size)
2775{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 /* expand tuple to hold (at least) size new items.
2777 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002781 if (maxsize < context->size + size)
2782 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002783
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002784 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002787}
2788
2789static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002790_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002791{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002792 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 if (depth > 1000) {
2797 PyErr_SetString(PyExc_ValueError,
2798 "nesting too deep in _flatten");
2799 return 0;
2800 } else if (PyList_Check(item)) {
2801 size = PyList_GET_SIZE(item);
2802 /* preallocate (assume no nesting) */
2803 if (context->size + size > context->maxsize &&
2804 !_bump(context, size))
2805 return 0;
2806 /* copy items to output tuple */
2807 for (i = 0; i < size; i++) {
2808 PyObject *o = PyList_GET_ITEM(item, i);
2809 if (PyList_Check(o) || PyTuple_Check(o)) {
2810 if (!_flatten1(context, o, depth + 1))
2811 return 0;
2812 } else if (o != Py_None) {
2813 if (context->size + 1 > context->maxsize &&
2814 !_bump(context, 1))
2815 return 0;
2816 Py_INCREF(o);
2817 PyTuple_SET_ITEM(context->tuple,
2818 context->size++, o);
2819 }
2820 }
2821 } else if (PyTuple_Check(item)) {
2822 /* same, for tuples */
2823 size = PyTuple_GET_SIZE(item);
2824 if (context->size + size > context->maxsize &&
2825 !_bump(context, size))
2826 return 0;
2827 for (i = 0; i < size; i++) {
2828 PyObject *o = PyTuple_GET_ITEM(item, i);
2829 if (PyList_Check(o) || PyTuple_Check(o)) {
2830 if (!_flatten1(context, o, depth + 1))
2831 return 0;
2832 } else if (o != Py_None) {
2833 if (context->size + 1 > context->maxsize &&
2834 !_bump(context, 1))
2835 return 0;
2836 Py_INCREF(o);
2837 PyTuple_SET_ITEM(context->tuple,
2838 context->size++, o);
2839 }
2840 }
2841 } else {
2842 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2843 return 0;
2844 }
2845 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002846}
2847
2848static PyObject *
2849Tkinter_Flatten(PyObject* self, PyObject* args)
2850{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 FlattenContext context;
2852 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002853
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002854 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2855 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002856
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002857 context.maxsize = PySequence_Size(item);
2858 if (context.maxsize < 0)
2859 return NULL;
2860 if (context.maxsize == 0)
2861 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002862
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002863 context.tuple = PyTuple_New(context.maxsize);
2864 if (!context.tuple)
2865 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002866
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002867 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002868
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 if (!_flatten1(&context, item,0))
2870 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 if (_PyTuple_Resize(&context.tuple, context.size))
2873 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002876}
2877
Guido van Rossum18468821994-06-20 07:49:28 +00002878static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002879Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002880{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002881 char *screenName = NULL;
2882 char *baseName = NULL; /* XXX this is not used anymore;
2883 try getting rid of it. */
2884 char *className = NULL;
2885 int interactive = 0;
2886 int wantobjects = 0;
2887 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2888 int sync = 0; /* pass -sync to wish */
2889 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002891 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002893 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2894 &screenName, &baseName, &className,
2895 &interactive, &wantobjects, &wantTk,
2896 &sync, &use))
2897 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002898
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002899 return (PyObject *) Tkapp_New(screenName, className,
2900 interactive, wantobjects, wantTk,
2901 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002902}
2903
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002904static PyObject *
2905Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2906{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002907 int new_val;
2908 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2909 return NULL;
2910 if (new_val < 0) {
2911 PyErr_SetString(PyExc_ValueError,
2912 "busywaitinterval must be >= 0");
2913 return NULL;
2914 }
2915 Tkinter_busywaitinterval = new_val;
2916 Py_INCREF(Py_None);
2917 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002918}
2919
2920static char setbusywaitinterval_doc[] =
2921"setbusywaitinterval(n) -> None\n\
2922\n\
2923Set the busy-wait interval in milliseconds between successive\n\
2924calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2925It should be set to a divisor of the maximum time between\n\
2926frames in an animation.";
2927
2928static PyObject *
2929Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2930{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002931 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002932}
2933
2934static char getbusywaitinterval_doc[] =
2935"getbusywaitinterval() -> int\n\
2936\n\
2937Return the current busy-wait interval between successive\n\
2938calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2939
Guido van Rossum18468821994-06-20 07:49:28 +00002940static PyMethodDef moduleMethods[] =
2941{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002942 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2943 {"create", Tkinter_Create, METH_VARARGS},
2944 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2945 setbusywaitinterval_doc},
2946 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2947 METH_NOARGS, getbusywaitinterval_doc},
2948 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002949};
2950
Guido van Rossum7bf15641998-05-22 18:28:17 +00002951#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002952
2953static int stdin_ready = 0;
2954
Guido van Rossumad4db171998-06-13 13:56:28 +00002955#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002956static void
Fred Drake509d79a2000-07-08 04:04:38 +00002957MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002958{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002960}
Guido van Rossumad4db171998-06-13 13:56:28 +00002961#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002962
Martin v. Löwisa9656492003-03-30 08:44:58 +00002963#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002964static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002965#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002966
Guido van Rossum18468821994-06-20 07:49:28 +00002967static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002968EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002969{
Guido van Rossumad4db171998-06-13 13:56:28 +00002970#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002972#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002973#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002974 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002975#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002976 stdin_ready = 0;
2977 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002978#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002979 tfile = fileno(stdin);
2980 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002981#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002982 while (!errorInCmd && !stdin_ready) {
2983 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002984#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002985 if (_kbhit()) {
2986 stdin_ready = 1;
2987 break;
2988 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002989#endif
2990#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002991 Py_BEGIN_ALLOW_THREADS
2992 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2993 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002997 tcl_tstate = NULL;
2998 if(tcl_lock)PyThread_release_lock(tcl_lock);
2999 if (result == 0)
3000 Sleep(Tkinter_busywaitinterval);
3001 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003002#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003003 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003004#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003005
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003006 if (result < 0)
3007 break;
3008 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003009#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003011#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 if (errorInCmd) {
3013 errorInCmd = 0;
3014 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3015 excInCmd = valInCmd = trbInCmd = NULL;
3016 PyErr_Print();
3017 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003018#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003019 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003020#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003022}
Guido van Rossum18468821994-06-20 07:49:28 +00003023
Guido van Rossum00d93061998-05-28 23:06:38 +00003024#endif
3025
Guido van Rossum7bf15641998-05-22 18:28:17 +00003026static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003027EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003028{
Guido van Rossum00d93061998-05-28 23:06:38 +00003029#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003030 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003031#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003032 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003033#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 PyOS_InputHook = EventHook;
3035 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003036#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003037}
3038
3039static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003040DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003041{
Guido van Rossum00d93061998-05-28 23:06:38 +00003042#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003043 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3044 PyOS_InputHook = NULL;
3045 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003046#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003047}
3048
Barry Warsawfa701a81997-01-16 00:15:11 +00003049
3050/* all errors will be checked in one fell swoop in init_tkinter() */
3051static void
Fred Drake509d79a2000-07-08 04:04:38 +00003052ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003053{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003054 PyObject *v = PyLong_FromLong(val);
3055 if (v) {
3056 PyDict_SetItemString(d, name, v);
3057 Py_DECREF(v);
3058 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003059}
3060static void
Fred Drake509d79a2000-07-08 04:04:38 +00003061ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003063 PyObject *v = PyUnicode_FromString(val);
3064 if (v) {
3065 PyDict_SetItemString(d, name, v);
3066 Py_DECREF(v);
3067 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003068}
3069
3070
Martin v. Löwis1a214512008-06-11 05:26:20 +00003071static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003072 PyModuleDef_HEAD_INIT,
3073 "_tkinter",
3074 NULL,
3075 -1,
3076 moduleMethods,
3077 NULL,
3078 NULL,
3079 NULL,
3080 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003081};
3082
Mark Hammond62b1ab12002-07-23 06:31:15 +00003083PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003084PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003085{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003086 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088 if (PyType_Ready(&Tkapp_Type) < 0)
3089 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003090
3091#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003092 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003093#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 m = PyModule_Create(&_tkintermodule);
3096 if (m == NULL)
3097 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003099 d = PyModule_GetDict(m);
3100 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3101 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003103 ins_long(d, "READABLE", TCL_READABLE);
3104 ins_long(d, "WRITABLE", TCL_WRITABLE);
3105 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3106 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3107 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3108 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3109 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3110 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3111 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3112 ins_string(d, "TK_VERSION", TK_VERSION);
3113 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 if (PyType_Ready(&Tktt_Type) < 0)
3118 return NULL;
3119 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003121 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3122 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003123
3124#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003125 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3126 * start waking up. Note that Tcl_FindExecutable will do this, this
3127 * code must be above it! The original warning from
3128 * tkMacOSXAppInit.c is copied below.
3129 *
3130 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3131 * Tcl interpreter for now. It probably should work to do this
3132 * in the other order, but for now it doesn't seem to.
3133 *
3134 */
3135 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003136#endif
3137
3138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003139 /* This helps the dynamic loader; in Unicode aware Tcl versions
3140 it also helps Tcl find its encodings. */
3141 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3142 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003143 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003144 if (cexe)
3145 Tcl_FindExecutable(PyBytes_AsString(cexe));
3146 Py_XDECREF(cexe);
3147 Py_DECREF(uexe);
3148 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 if (PyErr_Occurred()) {
3151 Py_DECREF(m);
3152 return NULL;
3153 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003154
Guido van Rossum43ff8681998-07-14 18:02:13 +00003155#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003156 /* This was not a good idea; through <Destroy> bindings,
3157 Tcl_Finalize() may invoke Python code but at that point the
3158 interpreter and thread state have already been destroyed! */
3159 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003160#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003161 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003162}