blob: af430fba9811081669a6faf690e988dc660b251f [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
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030036#define CHECK_SIZE(size, elemsize) \
37 ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
38
Martin v. Löwis71e25a02002-10-01 18:08:06 +000039/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
40 making _tkinter correct for this API means to break earlier
41 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
42 earlier versions. Once Tcl releases before 8.4 don't need to be supported
43 anymore, this should go. */
44#define USE_COMPAT_CONST
45
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000046/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
47 it always; if Tcl is not threaded, the thread functions in
48 Tcl are empty. */
49#define TCL_THREADS
50
Jack Jansencb852442001-12-09 23:15:56 +000051#ifdef TK_FRAMEWORK
52#include <Tcl/tcl.h>
53#include <Tk/tk.h>
54#else
Guido van Rossum18468821994-06-20 07:49:28 +000055#include <tcl.h>
56#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000057#endif
Guido van Rossum18468821994-06-20 07:49:28 +000058
Guilherme Polo2d87e422009-04-10 22:19:09 +000059#include "tkinter.h"
60
Jason Tishlerbbe89612002-12-31 20:30:46 +000061/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000062#ifndef CONST84_RETURN
63#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000064#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000065#define CONST
66#endif
67
Guilherme Polo66917722009-02-09 22:35:27 +000068#if TK_VERSION_HEX < 0x08030102
69#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000070#endif
71
Jack Janseneddc1442003-11-20 01:44:59 +000072#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000073#define HAVE_CREATEFILEHANDLER
74#endif
75
Guido van Rossum00d93061998-05-28 23:06:38 +000076#ifdef HAVE_CREATEFILEHANDLER
77
Neal Norwitzd948a432006-01-08 01:08:55 +000078/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
79 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
80#ifndef TCL_UNIX_FD
81# ifdef TCL_WIN_SOCKET
82# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
83# else
84# define TCL_UNIX_FD 1
85# endif
86#endif
87
Guido van Rossum00d93061998-05-28 23:06:38 +000088/* Tcl_CreateFileHandler() changed several times; these macros deal with the
89 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
90 Unix, only because Jack added it back); when available on Windows, it only
91 applies to sockets. */
92
Guido van Rossum7bf15641998-05-22 18:28:17 +000093#ifdef MS_WINDOWS
94#define FHANDLETYPE TCL_WIN_SOCKET
95#else
96#define FHANDLETYPE TCL_UNIX_FD
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
100 which uses this to handle Tcl events while the user is typing commands. */
101
102#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000103#define WAIT_FOR_STDIN
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106#endif /* HAVE_CREATEFILEHANDLER */
107
Guido van Rossumad4db171998-06-13 13:56:28 +0000108#ifdef MS_WINDOWS
109#include <conio.h>
110#define WAIT_FOR_STDIN
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113#ifdef WITH_THREAD
114
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000115/* The threading situation is complicated. Tcl is not thread-safe, except
116 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000117
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300118 So we need to use a lock around all uses of Tcl. Previously, the
119 Python interpreter lock was used for this. However, this causes
120 problems when other Python threads need to run while Tcl is blocked
121 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000122
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300123 To solve this problem, a separate lock for Tcl is introduced.
124 Holding it is incompatible with holding Python's interpreter lock.
125 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000126
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300127 ENTER_TCL and LEAVE_TCL are brackets, just like
128 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
129 used whenever a call into Tcl is made that could call an event
130 handler, or otherwise affect the state of a Tcl interpreter. These
131 assume that the surrounding code has the Python interpreter lock;
132 inside the brackets, the Python interpreter lock has been released
133 and the lock for Tcl has been acquired.
134
135 Sometimes, it is necessary to have both the Python lock and the Tcl
136 lock. (For example, when transferring data from the Tcl
137 interpreter result to a Python string object.) This can be done by
138 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
139 reacquires the Python lock (and restores the thread state) but
140 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
141 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000142
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000143 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300144 handlers when the handler needs to use Python. Such event handlers
145 are entered while the lock for Tcl is held; the event handler
146 presumably needs to use Python. ENTER_PYTHON releases the lock for
147 Tcl and acquires the Python interpreter lock, restoring the
148 appropriate thread state, and LEAVE_PYTHON releases the Python
149 interpreter lock and re-acquires the lock for Tcl. It is okay for
150 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
151 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000152
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300153 These locks expand to several statements and brackets; they should
154 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000155
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300156 If Tcl is threaded, this approach won't work anymore. The Tcl
157 interpreter is only valid in the thread that created it, and all Tk
158 activity must happen in this thread, also. That means that the
159 mainloop must be invoked in the thread that created the
160 interpreter. Invoking commands from other threads is possible;
161 _tkinter will queue an event for the interpreter thread, which will
162 then execute the command and pass back the result. If the main
163 thread is not in the mainloop, and invoking commands causes an
164 exception; if the main loop is running but not processing events,
165 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000166
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300167 In addition, for a threaded Tcl, a single global tcl_tstate won't
168 be sufficient anymore, since multiple Tcl interpreters may
169 simultaneously dispatch in different threads. So we use the Tcl TLS
170 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000171
Guido van Rossum00d93061998-05-28 23:06:38 +0000172*/
173
Guido van Rossum65d5b571998-12-21 19:32:43 +0000174static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000175
176#ifdef TCL_THREADS
177static Tcl_ThreadDataKey state_key;
178typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300179#define tcl_tstate \
180 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000182static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000183#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000184
185#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
187 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
189#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300190 tcl_tstate = NULL; \
191 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
Guido van Rossum62320c91998-06-15 04:36:09 +0000193#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000195
196#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000198
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000199#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300201 if(tcl_lock) \
202 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()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300211 PyErr_SetString(PyExc_RuntimeError, \
212 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 return 0; \
214 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#else
217
218#define ENTER_TCL
219#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000220#define ENTER_OVERLAP
221#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000222#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000223#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000224#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000225
226#endif
227
Guido van Rossum97867b21996-08-08 19:09:53 +0000228#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000229#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000230#endif
231
Guido van Rossum18468821994-06-20 07:49:28 +0000232/**** Tkapp Object Declaration ****/
233
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300234static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000235
Guido van Rossum00d93061998-05-28 23:06:38 +0000236typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 PyObject_HEAD
238 Tcl_Interp *interp;
239 int wantobjects;
240 int threaded; /* True if tcl_platform[threaded] */
241 Tcl_ThreadId thread_id;
242 int dispatching;
243 /* We cannot include tclInt.h, as this is internal.
244 So we cache interesting types here. */
245 Tcl_ObjType *BooleanType;
246 Tcl_ObjType *ByteArrayType;
247 Tcl_ObjType *DoubleType;
248 Tcl_ObjType *IntType;
249 Tcl_ObjType *ListType;
250 Tcl_ObjType *ProcBodyType;
251 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000252} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000253
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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326
Guido van Rossum18468821994-06-20 07:49:28 +0000327#define ARGSZ 64
328
Barry Warsawfa701a81997-01-16 00:15:11 +0000329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330
Guido van Rossum18468821994-06-20 07:49:28 +0000331static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200332unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
333{
334 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
335 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
336 /* Tcl encodes null character as \xc0\x80 */
337 if (memchr(s, '\xc0', size)) {
338 char *buf, *q;
339 const char *e = s + size;
340 PyErr_Clear();
341 q = buf = (char *)PyMem_Malloc(size);
342 if (buf == NULL)
343 return NULL;
344 while (s != e) {
345 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
346 *q++ = '\0';
347 s += 2;
348 }
349 else
350 *q++ = *s++;
351 }
352 s = buf;
353 size = q - s;
354 r = PyUnicode_DecodeUTF8(s, size, NULL);
355 PyMem_Free(buf);
356 }
357 }
358 return r;
359}
360
361static PyObject *
362unicodeFromTclString(const char *s)
363{
364 return unicodeFromTclStringAndSize(s, strlen(s));
365}
366
367static PyObject *
368unicodeFromTclObj(Tcl_Obj *value)
369{
370 int len;
371 char *s = Tcl_GetStringFromObj(value, &len);
372 return unicodeFromTclStringAndSize(s, len);
373}
374
375
376static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000377Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000378{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 int argc;
380 char **argv;
381 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300384 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 }
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
388 /* Not a list.
389 * Could be a quoted string containing funnies, e.g. {"}.
390 * Return the string itself.
391 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200392 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 }
Guido van Rossum18468821994-06-20 07:49:28 +0000394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 if (argc == 0)
396 v = PyUnicode_FromString("");
397 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200398 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000399 else if ((v = PyTuple_New(argc)) != NULL) {
400 int i;
401 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 for (i = 0; i < argc; i++) {
404 if ((w = Split(argv[i])) == NULL) {
405 Py_DECREF(v);
406 v = NULL;
407 break;
408 }
409 PyTuple_SetItem(v, i, w);
410 }
411 }
412 Tcl_Free(FREECAST argv);
413 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000414}
415
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300416/* In some cases, Tcl will still return strings that are supposed to
417 be lists. SplitObj walks through a nested tuple, finding string
418 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000419
Martin v. Löwis59683e82008-06-13 07:50:45 +0000420static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000421SplitObj(PyObject *arg)
422{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 if (PyTuple_Check(arg)) {
424 int i, size;
425 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000427 size = PyTuple_Size(arg);
428 result = NULL;
429 /* Recursively invoke SplitObj for all tuple items.
430 If this does not return a new object, no action is
431 needed. */
432 for(i = 0; i < size; i++) {
433 elem = PyTuple_GetItem(arg, i);
434 newelem = SplitObj(elem);
435 if (!newelem) {
436 Py_XDECREF(result);
437 return NULL;
438 }
439 if (!result) {
440 int k;
441 if (newelem == elem) {
442 Py_DECREF(newelem);
443 continue;
444 }
445 result = PyTuple_New(size);
446 if (!result)
447 return NULL;
448 for(k = 0; k < i; k++) {
449 elem = PyTuple_GetItem(arg, k);
450 Py_INCREF(elem);
451 PyTuple_SetItem(result, k, elem);
452 }
453 }
454 PyTuple_SetItem(result, i, newelem);
455 }
456 if (result)
457 return result;
458 /* Fall through, returning arg. */
459 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300460 else if (PyUnicode_Check(arg)) {
461 int argc;
462 char **argv;
463 char *list = PyUnicode_AsUTF8(arg);
464
465 if (list == NULL ||
466 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
467 Py_INCREF(arg);
468 return arg;
469 }
470 Tcl_Free(FREECAST argv);
471 if (argc > 1)
472 return Split(list);
473 /* Fall through, returning arg. */
474 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000475 else if (PyBytes_Check(arg)) {
476 int argc;
477 char **argv;
478 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
481 Py_INCREF(arg);
482 return arg;
483 }
484 Tcl_Free(FREECAST argv);
485 if (argc > 1)
486 return Split(PyBytes_AsString(arg));
487 /* Fall through, returning arg. */
488 }
489 Py_INCREF(arg);
490 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000491}
Barry Warsawfa701a81997-01-16 00:15:11 +0000492
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493
Guido van Rossum18468821994-06-20 07:49:28 +0000494/**** Tkapp Object ****/
495
496#ifndef WITH_APPINIT
497int
Fred Drake509d79a2000-07-08 04:04:38 +0000498Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000499{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 if (Tcl_Init(interp) == TCL_ERROR) {
503 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
504 return TCL_ERROR;
505 }
Guilherme Polob681df42009-02-09 22:33:59 +0000506
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000507 _tkinter_skip_tk_init = Tcl_GetVar(interp,
508 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
509 if (_tkinter_skip_tk_init != NULL &&
510 strcmp(_tkinter_skip_tk_init, "1") == 0) {
511 return TCL_OK;
512 }
Guilherme Polob681df42009-02-09 22:33:59 +0000513
514#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 if (tk_load_failed) {
516 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
517 return TCL_ERROR;
518 }
Guilherme Polob681df42009-02-09 22:33:59 +0000519#endif
520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000522#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000524#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
526 return TCL_ERROR;
527 }
Guilherme Polob681df42009-02-09 22:33:59 +0000528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000530}
531#endif /* !WITH_APPINIT */
532
Guido van Rossum18468821994-06-20 07:49:28 +0000533
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534
Barry Warsawfa701a81997-01-16 00:15:11 +0000535
536/* Initialize the Tk application; see the `main' function in
537 * `tkMain.c'.
538 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000539
Thomas Wouters58d05102000-07-24 14:43:35 +0000540static void EnableEventHook(void); /* Forward */
541static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000542
Barry Warsawfa701a81997-01-16 00:15:11 +0000543static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000544Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000546{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 TkappObject *v;
548 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000549
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300550 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 if (v == NULL)
552 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200553 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 v->interp = Tcl_CreateInterp();
556 v->wantobjects = wantobjects;
557 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
558 TCL_GLOBAL_ONLY) != NULL;
559 v->thread_id = Tcl_GetCurrentThread();
560 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000561
562#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300564 PyErr_SetString(PyExc_RuntimeError,
565 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 Py_DECREF(v);
567 return 0;
568 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000569#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000570#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 if (v->threaded && tcl_lock) {
572 /* If Tcl is threaded, we don't need the lock. */
573 PyThread_free_lock(tcl_lock);
574 tcl_lock = NULL;
575 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000576#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 v->BooleanType = Tcl_GetObjType("boolean");
579 v->ByteArrayType = Tcl_GetObjType("bytearray");
580 v->DoubleType = Tcl_GetObjType("double");
581 v->IntType = Tcl_GetObjType("int");
582 v->ListType = Tcl_GetObjType("list");
583 v->ProcBodyType = Tcl_GetObjType("procbody");
584 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000585
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 /* Delete the 'exit' command, which can screw things up */
587 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 if (screenName != NULL)
590 Tcl_SetVar2(v->interp, "env", "DISPLAY",
591 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (interactive)
594 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
595 else
596 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 /* This is used to get the application class for Tk 4.1 and up */
599 argv0 = (char*)ckalloc(strlen(className) + 1);
600 if (!argv0) {
601 PyErr_NoMemory();
602 Py_DECREF(v);
603 return NULL;
604 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200607 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
608 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
610 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 if (! wantTk) {
613 Tcl_SetVar(v->interp,
614 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
615 }
Guilherme Polob681df42009-02-09 22:33:59 +0000616#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000617 else if (tk_load_failed) {
618 Tcl_SetVar(v->interp,
619 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
620 }
Guilherme Polob681df42009-02-09 22:33:59 +0000621#endif
David Aschere2b4b322004-02-18 05:59:53 +0000622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 /* some initial arguments need to be in argv */
624 if (sync || use) {
625 char *args;
626 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 if (sync)
629 len += sizeof "-sync";
630 if (use)
631 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 args = (char*)ckalloc(len);
634 if (!args) {
635 PyErr_NoMemory();
636 Py_DECREF(v);
637 return NULL;
638 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 args[0] = '\0';
641 if (sync)
642 strcat(args, "-sync");
643 if (use) {
644 if (sync)
645 strcat(args, " ");
646 strcat(args, "-use ");
647 strcat(args, use);
648 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
651 ckfree(args);
652 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 if (Tcl_AppInit(v->interp) != TCL_OK) {
655 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000656#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 if (wantTk) {
658 const char *_tkinter_tk_failed;
659 _tkinter_tk_failed = Tcl_GetVar(v->interp,
660 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 if ( _tkinter_tk_failed != NULL &&
663 strcmp(_tkinter_tk_failed, "1") == 0) {
664 tk_load_failed = 1;
665 }
666 }
Guilherme Polob681df42009-02-09 22:33:59 +0000667#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 Py_DECREF((PyObject *)v);
669 return (TkappObject *)result;
670 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000675}
676
Barry Warsawfa701a81997-01-16 00:15:11 +0000677
Benjamin Peterson5879d412009-03-30 14:51:56 +0000678#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000679static void
680Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000682{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 Py_BEGIN_ALLOW_THREADS;
684 Tcl_MutexLock(mutex);
685 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
686 Tcl_ThreadAlert(self->thread_id);
687 Tcl_ConditionWait(cond, mutex, NULL);
688 Tcl_MutexUnlock(mutex);
689 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000690}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000691#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693
Guido van Rossum18468821994-06-20 07:49:28 +0000694/** Tcl Eval **/
695
Martin v. Löwisffad6332002-11-26 09:28:05 +0000696typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 PyObject_HEAD
698 Tcl_Obj *value;
699 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000700} PyTclObject;
701
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300702static PyObject *PyTclObject_Type;
703#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000704
705static PyObject *
706newPyTclObject(Tcl_Obj *arg)
707{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300709 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 if (self == NULL)
711 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200712 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713 Tcl_IncrRefCount(arg);
714 self->value = arg;
715 self->string = NULL;
716 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000717}
718
719static void
720PyTclObject_dealloc(PyTclObject *self)
721{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200722 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 Tcl_DecrRefCount(self->value);
724 Py_XDECREF(self->string);
725 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200726 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000727}
728
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000729static char*
730PyTclObject_TclString(PyObject *self)
731{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000733}
734
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000735/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000736PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000737"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000738
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000739static PyObject *
740PyTclObject_string(PyTclObject *self, void *ignored)
741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200743 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 if (!self->string)
745 return NULL;
746 }
747 Py_INCREF(self->string);
748 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000749}
750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000752PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000753{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200754 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 Py_INCREF(self->string);
756 return self->string;
757 }
758 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200759 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000760}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000761
Martin v. Löwisffad6332002-11-26 09:28:05 +0000762static PyObject *
763PyTclObject_repr(PyTclObject *self)
764{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300765 PyObject *repr, *str = PyTclObject_str(self, NULL);
766 if (str == NULL)
767 return NULL;
768 repr = PyUnicode_FromFormat("<%s object: %R>",
769 self->value->typePtr->name, str);
770 Py_DECREF(str);
771 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000772}
773
Mark Dickinson211c6252009-02-01 10:28:51 +0000774#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
775
776static PyObject *
777PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000778{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 int result;
780 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 /* neither argument should be NULL, unless something's gone wrong */
783 if (self == NULL || other == NULL) {
784 PyErr_BadInternalCall();
785 return NULL;
786 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000788 /* both arguments should be instances of PyTclObject */
789 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
790 v = Py_NotImplemented;
791 goto finished;
792 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000794 if (self == other)
795 /* fast path when self and other are identical */
796 result = 0;
797 else
798 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
799 Tcl_GetString(((PyTclObject *)other)->value));
800 /* Convert return value to a Boolean */
801 switch (op) {
802 case Py_EQ:
803 v = TEST_COND(result == 0);
804 break;
805 case Py_NE:
806 v = TEST_COND(result != 0);
807 break;
808 case Py_LE:
809 v = TEST_COND(result <= 0);
810 break;
811 case Py_GE:
812 v = TEST_COND(result >= 0);
813 break;
814 case Py_LT:
815 v = TEST_COND(result < 0);
816 break;
817 case Py_GT:
818 v = TEST_COND(result > 0);
819 break;
820 default:
821 PyErr_BadArgument();
822 return NULL;
823 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000824 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 Py_INCREF(v);
826 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000827}
828
Martin v. Löwis39195712003-01-04 00:33:13 +0000829PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
830
Martin v. Löwisffad6332002-11-26 09:28:05 +0000831static PyObject*
832get_typename(PyTclObject* obj, void* ignored)
833{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200834 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000835}
836
Martin v. Löwis39195712003-01-04 00:33:13 +0000837
Martin v. Löwisffad6332002-11-26 09:28:05 +0000838static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000839 {"typename", (getter)get_typename, NULL, get_typename__doc__},
840 {"string", (getter)PyTclObject_string, NULL,
841 PyTclObject_string__doc__},
842 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000843};
844
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300845static PyType_Slot PyTclObject_Type_slots[] = {
846 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
847 {Py_tp_repr, (reprfunc)PyTclObject_repr},
848 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200849 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300850 {Py_tp_richcompare, PyTclObject_richcompare},
851 {Py_tp_getset, PyTclObject_getsetlist},
852 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000853};
854
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300855static PyType_Spec PyTclObject_Type_spec = {
856 "_tkinter.Tcl_Obj",
857 sizeof(PyTclObject),
858 0,
859 Py_TPFLAGS_DEFAULT,
860 PyTclObject_Type_slots,
861};
862
863
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000864static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000865AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000866{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000867 Tcl_Obj *result;
868 long longVal;
869 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000870
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000871 if (PyBytes_Check(value))
872 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
873 PyBytes_GET_SIZE(value));
874 else if (PyBool_Check(value))
875 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
876 else if (PyLong_CheckExact(value) &&
877 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
878 !overflow)) {
879 /* If there is an overflow in the long conversion,
880 fall through to default object handling. */
881 return Tcl_NewLongObj(longVal);
882 }
883 else if (PyFloat_Check(value))
884 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
885 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300886 Tcl_Obj **argv;
887 Py_ssize_t size, i;
888
889 size = PyTuple_Size(value);
890 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
891 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
892 return NULL;
893 }
894 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 if(!argv)
896 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300897 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000898 argv[i] = AsObj(PyTuple_GetItem(value,i));
899 result = Tcl_NewListObj(PyTuple_Size(value), argv);
900 ckfree(FREECAST argv);
901 return result;
902 }
903 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200904 void *inbuf;
905 Py_ssize_t size;
906 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000907 Tcl_UniChar *outbuf = NULL;
908 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200909 size_t allocsize;
910
911 if (PyUnicode_READY(value) == -1)
912 return NULL;
913
914 inbuf = PyUnicode_DATA(value);
915 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300916 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
917 PyErr_SetString(PyExc_OverflowError, "string is too long");
918 return NULL;
919 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200920 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200921 if (kind == sizeof(Tcl_UniChar))
922 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200923 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
924 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 /* Else overflow occurred, and we take the next exit */
926 if (!outbuf) {
927 PyErr_NoMemory();
928 return NULL;
929 }
930 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200931 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
932 /* We cannot test for sizeof(Tcl_UniChar) directly,
933 so we test for UTF-8 size instead. */
934#if TCL_UTF_MAX == 3
935 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000936 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200937 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100938 "character U+%x is above the range "
939 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100940 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000941 ckfree(FREECAST outbuf);
942 return NULL;
943 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300944#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200945 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 }
947 result = Tcl_NewUnicodeObj(outbuf, size);
948 ckfree(FREECAST outbuf);
949 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000950 }
951 else if(PyTclObject_Check(value)) {
952 Tcl_Obj *v = ((PyTclObject*)value)->value;
953 Tcl_IncrRefCount(v);
954 return v;
955 }
956 else {
957 PyObject *v = PyObject_Str(value);
958 if (!v)
959 return 0;
960 result = AsObj(v);
961 Py_DECREF(v);
962 return result;
963 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000964}
965
Martin v. Löwisffad6332002-11-26 09:28:05 +0000966static PyObject*
967FromObj(PyObject* tkapp, Tcl_Obj *value)
968{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000969 PyObject *result = NULL;
970 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000971
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000972 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200973 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000974 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 if (value->typePtr == app->BooleanType) {
977 result = value->internalRep.longValue ? Py_True : Py_False;
978 Py_INCREF(result);
979 return result;
980 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 if (value->typePtr == app->ByteArrayType) {
983 int size;
984 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
985 return PyBytes_FromStringAndSize(data, size);
986 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000987
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 if (value->typePtr == app->DoubleType) {
989 return PyFloat_FromDouble(value->internalRep.doubleValue);
990 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000991
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000992 if (value->typePtr == app->IntType) {
993 return PyLong_FromLong(value->internalRep.longValue);
994 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000996 if (value->typePtr == app->ListType) {
997 int size;
998 int i, status;
999 PyObject *elem;
1000 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001001
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1003 if (status == TCL_ERROR)
1004 return Tkinter_Error(tkapp);
1005 result = PyTuple_New(size);
1006 if (!result)
1007 return NULL;
1008 for (i = 0; i < size; i++) {
1009 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1010 value, i, &tcl_elem);
1011 if (status == TCL_ERROR) {
1012 Py_DECREF(result);
1013 return Tkinter_Error(tkapp);
1014 }
1015 elem = FromObj(tkapp, tcl_elem);
1016 if (!elem) {
1017 Py_DECREF(result);
1018 return NULL;
1019 }
1020 PyTuple_SetItem(result, i, elem);
1021 }
1022 return result;
1023 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 if (value->typePtr == app->ProcBodyType) {
1026 /* fall through: return tcl object. */
1027 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001030 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001031 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001032 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001033 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036}
1037
Benjamin Peterson5879d412009-03-30 14:51:56 +00001038#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001039/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001040TCL_DECLARE_MUTEX(call_mutex)
1041
1042typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 Tcl_Event ev; /* Must be first */
1044 TkappObject *self;
1045 PyObject *args;
1046 int flags;
1047 PyObject **res;
1048 PyObject **exc_type, **exc_value, **exc_tb;
1049 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001050} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001051#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001052
1053void
1054Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001055{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 int i;
1057 for (i = 0; i < objc; i++)
1058 Tcl_DecrRefCount(objv[i]);
1059 if (objv != objStore)
1060 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001061}
Guido van Rossum18468821994-06-20 07:49:28 +00001062
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001063/* Convert Python objects to Tcl objects. This must happen in the
1064 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001065
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001066static Tcl_Obj**
1067Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001070 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001071 if (args == NULL)
1072 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 else if (!PyTuple_Check(args)) {
1075 objv[0] = AsObj(args);
1076 if (objv[0] == 0)
1077 goto finally;
1078 objc = 1;
1079 Tcl_IncrRefCount(objv[0]);
1080 }
1081 else {
1082 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001085 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1086 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1087 return NULL;
1088 }
1089 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001090 if (objv == NULL) {
1091 PyErr_NoMemory();
1092 objc = 0;
1093 goto finally;
1094 }
1095 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001097 for (i = 0; i < objc; i++) {
1098 PyObject *v = PyTuple_GetItem(args, i);
1099 if (v == Py_None) {
1100 objc = i;
1101 break;
1102 }
1103 objv[i] = AsObj(v);
1104 if (!objv[i]) {
1105 /* Reset objc, so it attempts to clear
1106 objects only up to i. */
1107 objc = i;
1108 goto finally;
1109 }
1110 Tcl_IncrRefCount(objv[i]);
1111 }
1112 }
1113 *pobjc = objc;
1114 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001115finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001116 Tkapp_CallDeallocArgs(objv, objStore, objc);
1117 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001118}
Guido van Rossum212643f1998-04-29 16:22:14 +00001119
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001120/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001121
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001122static PyObject*
1123Tkapp_CallResult(TkappObject *self)
1124{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001125 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001126 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001127 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 /* Not sure whether the IncrRef is necessary, but something
1129 may overwrite the interpreter result while we are
1130 converting it. */
1131 Tcl_IncrRefCount(value);
1132 res = FromObj((PyObject*)self, value);
1133 Tcl_DecrRefCount(value);
1134 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001135 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 }
1137 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001138}
Guido van Rossum632de272000-03-29 00:19:50 +00001139
Benjamin Peterson5879d412009-03-30 14:51:56 +00001140#ifdef WITH_THREAD
1141
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001142/* Tkapp_CallProc is the event procedure that is executed in the context of
1143 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1144 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001145
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001146static int
1147Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1148{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 Tcl_Obj *objStore[ARGSZ];
1150 Tcl_Obj **objv;
1151 int objc;
1152 int i;
1153 ENTER_PYTHON
1154 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1155 if (!objv) {
1156 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1157 *(e->res) = NULL;
1158 }
1159 LEAVE_PYTHON
1160 if (!objv)
1161 goto done;
1162 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1163 ENTER_PYTHON
1164 if (i == TCL_ERROR) {
1165 *(e->res) = NULL;
1166 *(e->exc_type) = NULL;
1167 *(e->exc_tb) = NULL;
1168 *(e->exc_value) = PyObject_CallFunction(
1169 Tkinter_TclError, "s",
1170 Tcl_GetStringResult(e->self->interp));
1171 }
1172 else {
1173 *(e->res) = Tkapp_CallResult(e->self);
1174 }
1175 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001176
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001177 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001178done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 /* Wake up calling thread. */
1180 Tcl_MutexLock(&call_mutex);
1181 Tcl_ConditionNotify(e->done);
1182 Tcl_MutexUnlock(&call_mutex);
1183 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001184}
1185
Benjamin Peterson5879d412009-03-30 14:51:56 +00001186#endif
1187
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001188/* This is the main entry point for calling a Tcl command.
1189 It supports three cases, with regard to threading:
1190 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1191 the context of the calling thread.
1192 2. Tcl is threaded, caller of the command is in the interpreter thread:
1193 Execute the command in the calling thread. Since the Tcl lock will
1194 not be used, we can merge that with case 1.
1195 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1196 the interpreter thread. Allocation of Tcl objects needs to occur in the
1197 interpreter thread, so we ship the PyObject* args to the target thread,
1198 and perform processing there. */
1199
1200static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001201Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001202{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001203 Tcl_Obj *objStore[ARGSZ];
1204 Tcl_Obj **objv = NULL;
1205 int objc, i;
1206 PyObject *res = NULL;
1207 TkappObject *self = (TkappObject*)selfptr;
1208 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001210 /* If args is a single tuple, replace with contents of tuple */
1211 if (1 == PyTuple_Size(args)){
1212 PyObject* item = PyTuple_GetItem(args, 0);
1213 if (PyTuple_Check(item))
1214 args = item;
1215 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001216#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001217 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1218 /* We cannot call the command directly. Instead, we must
1219 marshal the parameters to the interpreter thread. */
1220 Tkapp_CallEvent *ev;
1221 Tcl_Condition cond = NULL;
1222 PyObject *exc_type, *exc_value, *exc_tb;
1223 if (!WaitForMainloop(self))
1224 return NULL;
1225 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1226 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1227 ev->self = self;
1228 ev->args = args;
1229 ev->res = &res;
1230 ev->exc_type = &exc_type;
1231 ev->exc_value = &exc_value;
1232 ev->exc_tb = &exc_tb;
1233 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 if (res == NULL) {
1238 if (exc_type)
1239 PyErr_Restore(exc_type, exc_value, exc_tb);
1240 else
1241 PyErr_SetObject(Tkinter_TclError, exc_value);
1242 }
1243 Tcl_ConditionFinalize(&cond);
1244 }
1245 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001246#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001249 objv = Tkapp_CallArgs(args, objStore, &objc);
1250 if (!objv)
1251 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 if (i == TCL_ERROR)
1260 Tkinter_Error(selfptr);
1261 else
1262 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001266 Tkapp_CallDeallocArgs(objv, objStore, objc);
1267 }
1268 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001269}
1270
1271
1272static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001273Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001274{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 char *script;
1276 PyObject *res = NULL;
1277 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 if (!PyArg_ParseTuple(args, "s:eval", &script))
1280 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 ENTER_TCL
1285 err = Tcl_Eval(Tkapp_Interp(self), script);
1286 ENTER_OVERLAP
1287 if (err == TCL_ERROR)
1288 res = Tkinter_Error(self);
1289 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001290 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 LEAVE_OVERLAP_TCL
1292 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001293}
1294
1295static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001296Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 char *fileName;
1299 PyObject *res = NULL;
1300 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1303 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001305 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001307 ENTER_TCL
1308 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1309 ENTER_OVERLAP
1310 if (err == TCL_ERROR)
1311 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001313 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 LEAVE_OVERLAP_TCL
1315 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001316}
1317
1318static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001319Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001320{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 char *script;
1322 PyObject *res = NULL;
1323 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 if (!PyArg_ParseTuple(args, "s", &script))
1326 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001330 ENTER_TCL
1331 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1332 ENTER_OVERLAP
1333 if (err == TCL_ERROR)
1334 res = Tkinter_Error(self);
1335 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001336 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 LEAVE_OVERLAP_TCL
1338 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001339}
1340
1341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001342Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1347 return NULL;
1348 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 ENTER_TCL
1351 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1352 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001353
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001354 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001355}
1356
Barry Warsawfa701a81997-01-16 00:15:11 +00001357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001358
Guido van Rossum18468821994-06-20 07:49:28 +00001359/** Tcl Variable **/
1360
Benjamin Peterson5879d412009-03-30 14:51:56 +00001361typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1362
1363#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364TCL_DECLARE_MUTEX(var_mutex)
1365
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001366typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 Tcl_Event ev; /* must be first */
1368 PyObject *self;
1369 PyObject *args;
1370 int flags;
1371 EventFunc func;
1372 PyObject **res;
1373 PyObject **exc_type;
1374 PyObject **exc_val;
1375 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001377#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001379static int
1380varname_converter(PyObject *in, void *_out)
1381{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001382 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 char **out = (char**)_out;
1384 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001385 if (PyBytes_Size(in) > INT_MAX) {
1386 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1387 return 0;
1388 }
1389 s = PyBytes_AsString(in);
1390 if (strlen(s) != PyBytes_Size(in)) {
1391 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1392 return 0;
1393 }
1394 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 return 1;
1396 }
1397 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001398 Py_ssize_t size;
1399 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001400 if (s == NULL) {
1401 return 0;
1402 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001403 if (size > INT_MAX) {
1404 PyErr_SetString(PyExc_OverflowError, "string is too long");
1405 return 0;
1406 }
1407 if (strlen(s) != size) {
1408 PyErr_SetString(PyExc_ValueError, "null character in string");
1409 return 0;
1410 }
1411 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001412 return 1;
1413 }
1414 if (PyTclObject_Check(in)) {
1415 *out = PyTclObject_TclString(in);
1416 return 1;
1417 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001418 PyErr_Format(PyExc_TypeError,
1419 "must be str, bytes or Tcl_Obj, not %.50s",
1420 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001422}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001423
Benjamin Peterson5879d412009-03-30 14:51:56 +00001424#ifdef WITH_THREAD
1425
Martin v. Löwis59683e82008-06-13 07:50:45 +00001426static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001427var_perform(VarEvent *ev)
1428{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001429 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1430 if (!*(ev->res)) {
1431 PyObject *exc, *val, *tb;
1432 PyErr_Fetch(&exc, &val, &tb);
1433 PyErr_NormalizeException(&exc, &val, &tb);
1434 *(ev->exc_type) = exc;
1435 *(ev->exc_val) = val;
1436 Py_DECREF(tb);
1437 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001438
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439}
1440
1441static int
1442var_proc(VarEvent* ev, int flags)
1443{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001444 ENTER_PYTHON
1445 var_perform(ev);
1446 Tcl_MutexLock(&var_mutex);
1447 Tcl_ConditionNotify(ev->cond);
1448 Tcl_MutexUnlock(&var_mutex);
1449 LEAVE_PYTHON
1450 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451}
1452
Benjamin Peterson5879d412009-03-30 14:51:56 +00001453#endif
1454
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001456var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001458#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 TkappObject *self = (TkappObject*)selfptr;
1460 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1461 TkappObject *self = (TkappObject*)selfptr;
1462 VarEvent *ev;
1463 PyObject *res, *exc_type, *exc_val;
1464 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001466 /* The current thread is not the interpreter thread. Marshal
1467 the call to the interpreter thread, then wait for
1468 completion. */
1469 if (!WaitForMainloop(self))
1470 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 ev->self = selfptr;
1475 ev->args = args;
1476 ev->flags = flags;
1477 ev->func = func;
1478 ev->res = &res;
1479 ev->exc_type = &exc_type;
1480 ev->exc_val = &exc_val;
1481 ev->cond = &cond;
1482 ev->ev.proc = (Tcl_EventProc*)var_proc;
1483 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1484 Tcl_ConditionFinalize(&cond);
1485 if (!res) {
1486 PyErr_SetObject(exc_type, exc_val);
1487 Py_DECREF(exc_type);
1488 Py_DECREF(exc_val);
1489 return NULL;
1490 }
1491 return res;
1492 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001493#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 /* Tcl is not threaded, or this is the interpreter thread. */
1495 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001496}
1497
Guido van Rossum18468821994-06-20 07:49:28 +00001498static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001499SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001500{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001501 char *name1, *name2;
1502 PyObject *newValue;
1503 PyObject *res = NULL;
1504 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001505
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001506 switch (PyTuple_GET_SIZE(args)) {
1507 case 2:
1508 if (!PyArg_ParseTuple(args, "O&O:setvar",
1509 varname_converter, &name1, &newValue))
1510 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001511 /* XXX Acquire tcl lock??? */
1512 newval = AsObj(newValue);
1513 if (newval == NULL)
1514 return NULL;
1515 ENTER_TCL
1516 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1517 newval, flags);
1518 ENTER_OVERLAP
1519 if (!ok)
1520 Tkinter_Error(self);
1521 else {
1522 res = Py_None;
1523 Py_INCREF(res);
1524 }
1525 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001526 break;
1527 case 3:
1528 if (!PyArg_ParseTuple(args, "ssO:setvar",
1529 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001531 /* XXX must hold tcl lock already??? */
1532 newval = AsObj(newValue);
1533 ENTER_TCL
1534 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1535 ENTER_OVERLAP
1536 if (!ok)
1537 Tkinter_Error(self);
1538 else {
1539 res = Py_None;
1540 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001542 LEAVE_OVERLAP_TCL
1543 break;
1544 default:
1545 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1546 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 }
1548 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001549}
1550
1551static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001552Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001553{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001555}
1556
1557static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001558Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001559{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001561}
1562
Barry Warsawfa701a81997-01-16 00:15:11 +00001563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564
Guido van Rossum18468821994-06-20 07:49:28 +00001565static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001566GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001567{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 char *name1, *name2=NULL;
1569 PyObject *res = NULL;
1570 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1573 varname_converter, &name1, &name2))
1574 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 ENTER_TCL
1577 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1578 ENTER_OVERLAP
1579 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001580 PyErr_SetString(Tkinter_TclError,
1581 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001582 } else {
1583 if (((TkappObject*)self)->wantobjects) {
1584 res = FromObj(self, tres);
1585 }
1586 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001587 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001588 }
1589 }
1590 LEAVE_OVERLAP_TCL
1591 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001592}
1593
1594static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001595Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001598}
1599
1600static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001601Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001602{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001604}
1605
Barry Warsawfa701a81997-01-16 00:15:11 +00001606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607
Guido van Rossum18468821994-06-20 07:49:28 +00001608static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001609UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001610{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001611 char *name1, *name2=NULL;
1612 int code;
1613 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1616 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001617
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001618 ENTER_TCL
1619 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1620 ENTER_OVERLAP
1621 if (code == TCL_ERROR)
1622 res = Tkinter_Error(self);
1623 else {
1624 Py_INCREF(Py_None);
1625 res = Py_None;
1626 }
1627 LEAVE_OVERLAP_TCL
1628 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001629}
1630
1631static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001632Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001633{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001634 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001635}
1636
1637static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001638Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001639{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001640 return var_invoke(UnsetVar, self, args,
1641 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001642}
1643
Barry Warsawfa701a81997-01-16 00:15:11 +00001644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645
Guido van Rossum18468821994-06-20 07:49:28 +00001646/** Tcl to Python **/
1647
1648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001649Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001650{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001651 char *s;
1652 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 if (PyTuple_Size(args) == 1) {
1655 PyObject* o = PyTuple_GetItem(args, 0);
1656 if (PyLong_Check(o)) {
1657 Py_INCREF(o);
1658 return o;
1659 }
1660 }
1661 if (!PyArg_ParseTuple(args, "s:getint", &s))
1662 return NULL;
1663 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1664 return Tkinter_Error(self);
1665 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001666}
1667
1668static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001669Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001670{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001671 char *s;
1672 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674 if (PyTuple_Size(args) == 1) {
1675 PyObject *o = PyTuple_GetItem(args, 0);
1676 if (PyFloat_Check(o)) {
1677 Py_INCREF(o);
1678 return o;
1679 }
1680 }
1681 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1682 return NULL;
1683 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1684 return Tkinter_Error(self);
1685 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001686}
1687
1688static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001689Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001690{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001691 char *s;
1692 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001694 if (PyTuple_Size(args) == 1) {
1695 PyObject *o = PyTuple_GetItem(args, 0);
1696 if (PyLong_Check(o)) {
1697 Py_INCREF(o);
1698 return o;
1699 }
1700 }
1701 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1702 return NULL;
1703 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1704 return Tkinter_Error(self);
1705 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001706}
1707
1708static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001709Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001710{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001711 char *s;
1712 PyObject *res = NULL;
1713 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1716 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 ENTER_TCL
1721 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1722 ENTER_OVERLAP
1723 if (retval == TCL_ERROR)
1724 res = Tkinter_Error(self);
1725 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001726 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 LEAVE_OVERLAP_TCL
1728 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001729}
1730
1731static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001732Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001733{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001734 char *s;
1735 PyObject *res = NULL;
1736 int retval;
1737 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1740 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001744 ENTER_TCL
1745 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1746 ENTER_OVERLAP
1747 if (retval == TCL_ERROR)
1748 res = Tkinter_Error(self);
1749 else
1750 res = Py_BuildValue("l", v);
1751 LEAVE_OVERLAP_TCL
1752 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001753}
1754
1755static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001756Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001757{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 char *s;
1759 PyObject *res = NULL;
1760 double v;
1761 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1764 return NULL;
1765 CHECK_TCL_APPARTMENT;
1766 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1767 ENTER_TCL
1768 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1769 ENTER_OVERLAP
1770 PyFPE_END_PROTECT(retval)
1771 if (retval == TCL_ERROR)
1772 res = Tkinter_Error(self);
1773 else
1774 res = Py_BuildValue("d", v);
1775 LEAVE_OVERLAP_TCL
1776 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001777}
1778
1779static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001780Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001781{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 char *s;
1783 PyObject *res = NULL;
1784 int retval;
1785 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1788 return NULL;
1789 CHECK_TCL_APPARTMENT;
1790 ENTER_TCL
1791 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1792 ENTER_OVERLAP
1793 if (retval == TCL_ERROR)
1794 res = Tkinter_Error(self);
1795 else
1796 res = Py_BuildValue("i", v);
1797 LEAVE_OVERLAP_TCL
1798 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001799}
1800
Barry Warsawfa701a81997-01-16 00:15:11 +00001801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001802
Guido van Rossum18468821994-06-20 07:49:28 +00001803static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001804Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 char *list;
1807 int argc;
1808 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001809 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001810 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001811
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001812 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1813 return NULL;
1814 if (PyTclObject_Check(arg)) {
1815 int objc;
1816 Tcl_Obj **objv;
1817 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1818 ((PyTclObject*)arg)->value,
1819 &objc, &objv) == TCL_ERROR) {
1820 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001822 if (!(v = PyTuple_New(objc)))
1823 return NULL;
1824 for (i = 0; i < objc; i++) {
1825 PyObject *s = FromObj(self, objv[i]);
1826 if (!s || PyTuple_SetItem(v, i, s)) {
1827 Py_DECREF(v);
1828 return NULL;
1829 }
1830 }
1831 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001832 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001833 if (PyTuple_Check(arg)) {
1834 Py_INCREF(arg);
1835 return arg;
1836 }
1837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001838 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1839 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 if (Tcl_SplitList(Tkapp_Interp(self), list,
1842 &argc, &argv) == TCL_ERROR) {
1843 PyMem_Free(list);
1844 return Tkinter_Error(self);
1845 }
Guido van Rossum18468821994-06-20 07:49:28 +00001846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 if (!(v = PyTuple_New(argc)))
1848 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001849
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001850 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001851 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 if (!s || PyTuple_SetItem(v, i, s)) {
1853 Py_DECREF(v);
1854 v = NULL;
1855 goto finally;
1856 }
1857 }
Guido van Rossum18468821994-06-20 07:49:28 +00001858
Barry Warsawfa701a81997-01-16 00:15:11 +00001859 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860 ckfree(FREECAST argv);
1861 PyMem_Free(list);
1862 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001868 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001869 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001870
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001871 if (!PyArg_ParseTuple(args, "O:split", &arg))
1872 return NULL;
1873 if (PyTclObject_Check(arg)) {
1874 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1875 int objc;
1876 Tcl_Obj **objv;
1877 int i;
1878 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1879 &objc, &objv) == TCL_ERROR) {
1880 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001882 if (objc == 0)
1883 return PyUnicode_FromString("");
1884 if (objc == 1)
1885 return FromObj(self, objv[0]);
1886 if (!(v = PyTuple_New(objc)))
1887 return NULL;
1888 for (i = 0; i < objc; i++) {
1889 PyObject *s = FromObj(self, objv[i]);
1890 if (!s || PyTuple_SetItem(v, i, s)) {
1891 Py_DECREF(v);
1892 return NULL;
1893 }
1894 }
1895 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001897 if (PyTuple_Check(arg))
1898 return SplitObj(arg);
1899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1901 return NULL;
1902 v = Split(list);
1903 PyMem_Free(list);
1904 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001905}
1906
Barry Warsawfa701a81997-01-16 00:15:11 +00001907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908
Guido van Rossum18468821994-06-20 07:49:28 +00001909/** Tcl Command **/
1910
Guido van Rossum00d93061998-05-28 23:06:38 +00001911/* Client data struct */
1912typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001913 PyObject *self;
1914 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001915} PythonCmd_ClientData;
1916
1917static int
Fred Drake509d79a2000-07-08 04:04:38 +00001918PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001919{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001920 errorInCmd = 1;
1921 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1922 LEAVE_PYTHON
1923 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001924}
1925
Guido van Rossum18468821994-06-20 07:49:28 +00001926/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001927 * function or method.
1928 */
Guido van Rossum18468821994-06-20 07:49:28 +00001929static int
Fred Drake509d79a2000-07-08 04:04:38 +00001930PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001931{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001933 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001934 int i, rv;
1935 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001937 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 /* TBD: no error checking here since we know, via the
1940 * Tkapp_CreateCommand() that the client data is a two-tuple
1941 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001942 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 /* Create argument list (argv1, ..., argvN) */
1945 if (!(arg = PyTuple_New(argc - 1)))
1946 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001948 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001949 PyObject *s = unicodeFromTclString(argv[i + 1]);
1950 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 Py_DECREF(arg);
1952 return PythonCmd_Error(interp);
1953 }
1954 }
1955 res = PyEval_CallObject(func, arg);
1956 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001958 if (res == NULL)
1959 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001961 obj_res = AsObj(res);
1962 if (obj_res == NULL) {
1963 Py_DECREF(res);
1964 return PythonCmd_Error(interp);
1965 }
1966 else {
1967 Tcl_SetObjResult(interp, obj_res);
1968 rv = TCL_OK;
1969 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001972
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001973 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001976}
1977
1978static void
Fred Drake509d79a2000-07-08 04:04:38 +00001979PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001980{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001982
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001983 ENTER_PYTHON
1984 Py_XDECREF(data->self);
1985 Py_XDECREF(data->func);
1986 PyMem_DEL(data);
1987 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001988}
1989
Barry Warsawfa701a81997-01-16 00:15:11 +00001990
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001991
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001992
Benjamin Peterson5879d412009-03-30 14:51:56 +00001993#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001994TCL_DECLARE_MUTEX(command_mutex)
1995
1996typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 Tcl_Event ev;
1998 Tcl_Interp* interp;
1999 char *name;
2000 int create;
2001 int *status;
2002 ClientData *data;
2003 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002004} CommandEvent;
2005
2006static int
2007Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002008{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 if (ev->create)
2010 *ev->status = Tcl_CreateCommand(
2011 ev->interp, ev->name, PythonCmd,
2012 ev->data, PythonCmdDelete) == NULL;
2013 else
2014 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2015 Tcl_MutexLock(&command_mutex);
2016 Tcl_ConditionNotify(ev->done);
2017 Tcl_MutexUnlock(&command_mutex);
2018 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002019}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002020#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002021
2022static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002023Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002024{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002025 TkappObject *self = (TkappObject*)selfptr;
2026 PythonCmd_ClientData *data;
2027 char *cmdName;
2028 PyObject *func;
2029 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002031 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2032 return NULL;
2033 if (!PyCallable_Check(func)) {
2034 PyErr_SetString(PyExc_TypeError, "command not callable");
2035 return NULL;
2036 }
Guido van Rossum18468821994-06-20 07:49:28 +00002037
Martin v. Löwisa9656492003-03-30 08:44:58 +00002038#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2040 !WaitForMainloop(self))
2041 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002042#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002044 data = PyMem_NEW(PythonCmd_ClientData, 1);
2045 if (!data)
2046 return PyErr_NoMemory();
2047 Py_INCREF(self);
2048 Py_INCREF(func);
2049 data->self = selfptr;
2050 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002051#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002052 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2053 Tcl_Condition cond = NULL;
2054 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2055 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2056 ev->interp = self->interp;
2057 ev->create = 1;
2058 ev->name = cmdName;
2059 ev->data = (ClientData)data;
2060 ev->status = &err;
2061 ev->done = &cond;
2062 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2063 Tcl_ConditionFinalize(&cond);
2064 }
2065 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002066#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002067 {
2068 ENTER_TCL
2069 err = Tcl_CreateCommand(
2070 Tkapp_Interp(self), cmdName, PythonCmd,
2071 (ClientData)data, PythonCmdDelete) == NULL;
2072 LEAVE_TCL
2073 }
2074 if (err) {
2075 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2076 PyMem_DEL(data);
2077 return NULL;
2078 }
Guido van Rossum18468821994-06-20 07:49:28 +00002079
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002080 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002081}
2082
Barry Warsawfa701a81997-01-16 00:15:11 +00002083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084
Guido van Rossum18468821994-06-20 07:49:28 +00002085static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002086Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002087{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088 TkappObject *self = (TkappObject*)selfptr;
2089 char *cmdName;
2090 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002092 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2093 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002094
2095#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002096 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2097 Tcl_Condition cond = NULL;
2098 CommandEvent *ev;
2099 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2100 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2101 ev->interp = self->interp;
2102 ev->create = 0;
2103 ev->name = cmdName;
2104 ev->status = &err;
2105 ev->done = &cond;
2106 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2107 &command_mutex);
2108 Tcl_ConditionFinalize(&cond);
2109 }
2110 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002111#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002112 {
2113 ENTER_TCL
2114 err = Tcl_DeleteCommand(self->interp, cmdName);
2115 LEAVE_TCL
2116 }
2117 if (err == -1) {
2118 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2119 return NULL;
2120 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002121 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002122}
2123
Barry Warsawfa701a81997-01-16 00:15:11 +00002124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002125
Guido van Rossum00d93061998-05-28 23:06:38 +00002126#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002127/** File Handler **/
2128
Guido van Rossum00d93061998-05-28 23:06:38 +00002129typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002130 PyObject *func;
2131 PyObject *file;
2132 int id;
2133 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002134} FileHandler_ClientData;
2135
2136static FileHandler_ClientData *HeadFHCD;
2137
2138static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002139NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002140{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002141 FileHandler_ClientData *p;
2142 p = PyMem_NEW(FileHandler_ClientData, 1);
2143 if (p != NULL) {
2144 Py_XINCREF(func);
2145 Py_XINCREF(file);
2146 p->func = func;
2147 p->file = file;
2148 p->id = id;
2149 p->next = HeadFHCD;
2150 HeadFHCD = p;
2151 }
2152 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002153}
2154
2155static void
Fred Drake509d79a2000-07-08 04:04:38 +00002156DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002157{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 pp = &HeadFHCD;
2161 while ((p = *pp) != NULL) {
2162 if (p->id == id) {
2163 *pp = p->next;
2164 Py_XDECREF(p->func);
2165 Py_XDECREF(p->file);
2166 PyMem_DEL(p);
2167 }
2168 else
2169 pp = &p->next;
2170 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002171}
2172
Guido van Rossuma597dde1995-01-10 20:56:29 +00002173static void
Fred Drake509d79a2000-07-08 04:04:38 +00002174FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002175{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2177 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002179 ENTER_PYTHON
2180 func = data->func;
2181 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002183 arg = Py_BuildValue("(Oi)", file, (long) mask);
2184 res = PyEval_CallObject(func, arg);
2185 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002186
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 if (res == NULL) {
2188 errorInCmd = 1;
2189 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2190 }
2191 Py_XDECREF(res);
2192 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002193}
2194
Guido van Rossum18468821994-06-20 07:49:28 +00002195static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002196Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2197 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002198{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 FileHandler_ClientData *data;
2200 PyObject *file, *func;
2201 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2204 &file, &mask, &func))
2205 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002209 tfile = PyObject_AsFileDescriptor(file);
2210 if (tfile < 0)
2211 return NULL;
2212 if (!PyCallable_Check(func)) {
2213 PyErr_SetString(PyExc_TypeError, "bad argument list");
2214 return NULL;
2215 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217 data = NewFHCD(func, file, tfile);
2218 if (data == NULL)
2219 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002221 /* Ought to check for null Tcl_File object... */
2222 ENTER_TCL
2223 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2224 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002225 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002226}
2227
2228static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002229Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002230{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 PyObject *file;
2232 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2235 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 tfile = PyObject_AsFileDescriptor(file);
2240 if (tfile < 0)
2241 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002242
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002243 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002244
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002245 /* Ought to check for null Tcl_File object... */
2246 ENTER_TCL
2247 Tcl_DeleteFileHandler(tfile);
2248 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002249 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002250}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002251#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002253
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002254/**** Tktt Object (timer token) ****/
2255
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002256static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002257
Guido van Rossum00d93061998-05-28 23:06:38 +00002258typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002259 PyObject_HEAD
2260 Tcl_TimerToken token;
2261 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002262} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002263
2264static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002265Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002266{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 TkttObject *v = (TkttObject *)self;
2268 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002270 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2271 return NULL;
2272 if (v->token != NULL) {
2273 Tcl_DeleteTimerHandler(v->token);
2274 v->token = NULL;
2275 }
2276 if (func != NULL) {
2277 v->func = NULL;
2278 Py_DECREF(func);
2279 Py_DECREF(v); /* See Tktt_New() */
2280 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002281 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002282}
2283
2284static PyMethodDef Tktt_methods[] =
2285{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2287 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002288};
2289
2290static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002291Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002292{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002293 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002294
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002295 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002296 if (v == NULL)
2297 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002298 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002300 Py_INCREF(func);
2301 v->token = NULL;
2302 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 /* Extra reference, deleted when called or when handler is deleted */
2305 Py_INCREF(v);
2306 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002307}
2308
2309static void
Fred Drake509d79a2000-07-08 04:04:38 +00002310Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002311{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312 TkttObject *v = (TkttObject *)self;
2313 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002314 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002318 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002319 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320}
2321
Guido van Rossum597ac201998-05-12 14:36:19 +00002322static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002323Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002325 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002326 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2327 v,
2328 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329}
2330
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002331static PyType_Slot Tktt_Type_slots[] = {
2332 {Py_tp_dealloc, Tktt_Dealloc},
2333 {Py_tp_repr, Tktt_Repr},
2334 {Py_tp_methods, Tktt_methods},
2335 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002336};
2337
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002338static PyType_Spec Tktt_Type_spec = {
2339 "tktimertoken",
2340 sizeof(TkttObject),
2341 0,
2342 Py_TPFLAGS_DEFAULT,
2343 Tktt_Type_slots,
2344};
Barry Warsawfa701a81997-01-16 00:15:11 +00002345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347/** Timer Handler **/
2348
2349static void
Fred Drake509d79a2000-07-08 04:04:38 +00002350TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 TkttObject *v = (TkttObject *)clientData;
2353 PyObject *func = v->func;
2354 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002356 if (func == NULL)
2357 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002362
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 res = PyEval_CallObject(func, NULL);
2364 Py_DECREF(func);
2365 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002367 if (res == NULL) {
2368 errorInCmd = 1;
2369 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2370 }
2371 else
2372 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375}
2376
2377static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002378Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002379{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 int milliseconds;
2381 PyObject *func;
2382 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2385 &milliseconds, &func))
2386 return NULL;
2387 if (!PyCallable_Check(func)) {
2388 PyErr_SetString(PyExc_TypeError, "bad argument list");
2389 return NULL;
2390 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394 v = Tktt_New(func);
2395 if (v) {
2396 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2397 (ClientData)v);
2398 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002401}
2402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403
Guido van Rossum18468821994-06-20 07:49:28 +00002404/** Event Loop **/
2405
Guido van Rossum18468821994-06-20 07:49:28 +00002406static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002407Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002408{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 int threshold = 0;
2410 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002411#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002413#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2416 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 CHECK_TCL_APPARTMENT;
2419 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002421 quitMainLoop = 0;
2422 while (Tk_GetNumMainWindows() > threshold &&
2423 !quitMainLoop &&
2424 !errorInCmd)
2425 {
2426 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002427
2428#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 if (self->threaded) {
2430 /* Allow other Python threads to run. */
2431 ENTER_TCL
2432 result = Tcl_DoOneEvent(0);
2433 LEAVE_TCL
2434 }
2435 else {
2436 Py_BEGIN_ALLOW_THREADS
2437 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2438 tcl_tstate = tstate;
2439 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2440 tcl_tstate = NULL;
2441 if(tcl_lock)PyThread_release_lock(tcl_lock);
2442 if (result == 0)
2443 Sleep(Tkinter_busywaitinterval);
2444 Py_END_ALLOW_THREADS
2445 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002446#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002448#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 if (PyErr_CheckSignals() != 0) {
2451 self->dispatching = 0;
2452 return NULL;
2453 }
2454 if (result < 0)
2455 break;
2456 }
2457 self->dispatching = 0;
2458 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460 if (errorInCmd) {
2461 errorInCmd = 0;
2462 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2463 excInCmd = valInCmd = trbInCmd = NULL;
2464 return NULL;
2465 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002466 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002467}
2468
2469static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002470Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002471{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002472 int flags = 0;
2473 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2476 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 ENTER_TCL
2479 rv = Tcl_DoOneEvent(flags);
2480 LEAVE_TCL
2481 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002482}
2483
2484static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002485Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002486{
2487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 if (!PyArg_ParseTuple(args, ":quit"))
2489 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002491 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002492 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002493}
2494
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002495static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002496Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002497{
2498
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499 if (!PyArg_ParseTuple(args, ":interpaddr"))
2500 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002501
Victor Stinnere1040e22013-09-05 00:22:24 +02002502 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002503}
2504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002506Tkapp_TkInit(PyObject *self, PyObject *args)
2507{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 Tcl_Interp *interp = Tkapp_Interp(self);
2509 const char * _tk_exists = NULL;
2510 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002511
Guilherme Polob681df42009-02-09 22:33:59 +00002512#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002513 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2514 * first call failed.
2515 * To avoid the deadlock, we just refuse the second call through
2516 * a static variable.
2517 */
2518 if (tk_load_failed) {
2519 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2520 return NULL;
2521 }
Guilherme Polob681df42009-02-09 22:33:59 +00002522#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 /* We want to guard against calling Tk_Init() multiple times */
2525 CHECK_TCL_APPARTMENT;
2526 ENTER_TCL
2527 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2528 ENTER_OVERLAP
2529 if (err == TCL_ERROR) {
2530 /* This sets an exception, but we cannot return right
2531 away because we need to exit the overlap first. */
2532 Tkinter_Error(self);
2533 } else {
2534 _tk_exists = Tkapp_Result(self);
2535 }
2536 LEAVE_OVERLAP_TCL
2537 if (err == TCL_ERROR) {
2538 return NULL;
2539 }
2540 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2541 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002542 PyErr_SetString(Tkinter_TclError,
2543 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002544#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002545 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002546#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 return NULL;
2548 }
2549 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002550 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002551}
Barry Warsawfa701a81997-01-16 00:15:11 +00002552
Martin v. Löwisffad6332002-11-26 09:28:05 +00002553static PyObject *
2554Tkapp_WantObjects(PyObject *self, PyObject *args)
2555{
2556
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002557 int wantobjects = -1;
2558 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2559 return NULL;
2560 if (wantobjects == -1)
2561 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2562 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002563
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002564 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002565}
2566
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002567static PyObject *
2568Tkapp_WillDispatch(PyObject *self, PyObject *args)
2569{
2570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002572
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002573 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002574}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576
Guido van Rossum18468821994-06-20 07:49:28 +00002577/**** Tkapp Method List ****/
2578
2579static PyMethodDef Tkapp_methods[] =
2580{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2582 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2583 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2586 {"record", Tkapp_Record, METH_VARARGS},
2587 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2588 {"setvar", Tkapp_SetVar, METH_VARARGS},
2589 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2590 {"getvar", Tkapp_GetVar, METH_VARARGS},
2591 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2592 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2593 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2594 {"getint", Tkapp_GetInt, METH_VARARGS},
2595 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2596 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2597 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2598 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2599 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2600 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2601 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2602 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002603 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2604 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002605#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002606 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2607 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002608#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002609 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2610 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2611 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2612 {"quit", Tkapp_Quit, METH_VARARGS},
2613 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2614 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2615 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002616};
2617
Barry Warsawfa701a81997-01-16 00:15:11 +00002618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619
Guido van Rossum18468821994-06-20 07:49:28 +00002620/**** Tkapp Type Methods ****/
2621
2622static void
Fred Drake509d79a2000-07-08 04:04:38 +00002623Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002624{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002625 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 /*CHECK_TCL_APPARTMENT;*/
2627 ENTER_TCL
2628 Tcl_DeleteInterp(Tkapp_Interp(self));
2629 LEAVE_TCL
2630 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002631 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002633}
2634
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002635static PyType_Slot Tkapp_Type_slots[] = {
2636 {Py_tp_dealloc, Tkapp_Dealloc},
2637 {Py_tp_methods, Tkapp_methods},
2638 {0, 0}
2639};
2640
2641
2642static PyType_Spec Tkapp_Type_spec = {
2643 "tkapp",
2644 sizeof(TkappObject),
2645 0,
2646 Py_TPFLAGS_DEFAULT,
2647 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002648};
2649
Barry Warsawfa701a81997-01-16 00:15:11 +00002650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002651
Guido van Rossum18468821994-06-20 07:49:28 +00002652/**** Tkinter Module ****/
2653
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002654typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002655 PyObject* tuple;
2656 int size; /* current size */
2657 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002658} FlattenContext;
2659
2660static int
2661_bump(FlattenContext* context, int size)
2662{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 /* expand tuple to hold (at least) size new items.
2664 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 if (maxsize < context->size + size)
2669 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002673 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002674}
2675
2676static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002677_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002678{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002679 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002681 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002683 if (depth > 1000) {
2684 PyErr_SetString(PyExc_ValueError,
2685 "nesting too deep in _flatten");
2686 return 0;
2687 } else if (PyList_Check(item)) {
2688 size = PyList_GET_SIZE(item);
2689 /* preallocate (assume no nesting) */
2690 if (context->size + size > context->maxsize &&
2691 !_bump(context, size))
2692 return 0;
2693 /* copy items to output tuple */
2694 for (i = 0; i < size; i++) {
2695 PyObject *o = PyList_GET_ITEM(item, i);
2696 if (PyList_Check(o) || PyTuple_Check(o)) {
2697 if (!_flatten1(context, o, depth + 1))
2698 return 0;
2699 } else if (o != Py_None) {
2700 if (context->size + 1 > context->maxsize &&
2701 !_bump(context, 1))
2702 return 0;
2703 Py_INCREF(o);
2704 PyTuple_SET_ITEM(context->tuple,
2705 context->size++, o);
2706 }
2707 }
2708 } else if (PyTuple_Check(item)) {
2709 /* same, for tuples */
2710 size = PyTuple_GET_SIZE(item);
2711 if (context->size + size > context->maxsize &&
2712 !_bump(context, size))
2713 return 0;
2714 for (i = 0; i < size; i++) {
2715 PyObject *o = PyTuple_GET_ITEM(item, i);
2716 if (PyList_Check(o) || PyTuple_Check(o)) {
2717 if (!_flatten1(context, o, depth + 1))
2718 return 0;
2719 } else if (o != Py_None) {
2720 if (context->size + 1 > context->maxsize &&
2721 !_bump(context, 1))
2722 return 0;
2723 Py_INCREF(o);
2724 PyTuple_SET_ITEM(context->tuple,
2725 context->size++, o);
2726 }
2727 }
2728 } else {
2729 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2730 return 0;
2731 }
2732 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002733}
2734
2735static PyObject *
2736Tkinter_Flatten(PyObject* self, PyObject* args)
2737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 FlattenContext context;
2739 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2742 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002744 context.maxsize = PySequence_Size(item);
2745 if (context.maxsize < 0)
2746 return NULL;
2747 if (context.maxsize == 0)
2748 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002750 context.tuple = PyTuple_New(context.maxsize);
2751 if (!context.tuple)
2752 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 if (!_flatten1(&context, item,0))
2757 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002758
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002759 if (_PyTuple_Resize(&context.tuple, context.size))
2760 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002762 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002763}
2764
Guido van Rossum18468821994-06-20 07:49:28 +00002765static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002766Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002768 char *screenName = NULL;
2769 char *baseName = NULL; /* XXX this is not used anymore;
2770 try getting rid of it. */
2771 char *className = NULL;
2772 int interactive = 0;
2773 int wantobjects = 0;
2774 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2775 int sync = 0; /* pass -sync to wish */
2776 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002778 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2781 &screenName, &baseName, &className,
2782 &interactive, &wantobjects, &wantTk,
2783 &sync, &use))
2784 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002787 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002789}
2790
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002791static PyObject *
2792Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2793{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 int new_val;
2795 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2796 return NULL;
2797 if (new_val < 0) {
2798 PyErr_SetString(PyExc_ValueError,
2799 "busywaitinterval must be >= 0");
2800 return NULL;
2801 }
2802 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002803 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002804}
2805
2806static char setbusywaitinterval_doc[] =
2807"setbusywaitinterval(n) -> None\n\
2808\n\
2809Set the busy-wait interval in milliseconds between successive\n\
2810calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2811It should be set to a divisor of the maximum time between\n\
2812frames in an animation.";
2813
2814static PyObject *
2815Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2816{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002818}
2819
2820static char getbusywaitinterval_doc[] =
2821"getbusywaitinterval() -> int\n\
2822\n\
2823Return the current busy-wait interval between successive\n\
2824calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2825
Guido van Rossum18468821994-06-20 07:49:28 +00002826static PyMethodDef moduleMethods[] =
2827{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2829 {"create", Tkinter_Create, METH_VARARGS},
2830 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2831 setbusywaitinterval_doc},
2832 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2833 METH_NOARGS, getbusywaitinterval_doc},
2834 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002835};
2836
Guido van Rossum7bf15641998-05-22 18:28:17 +00002837#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002838
2839static int stdin_ready = 0;
2840
Guido van Rossumad4db171998-06-13 13:56:28 +00002841#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002842static void
Fred Drake509d79a2000-07-08 04:04:38 +00002843MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002844{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002845 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002846}
Guido van Rossumad4db171998-06-13 13:56:28 +00002847#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002848
Martin v. Löwisa9656492003-03-30 08:44:58 +00002849#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002850static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002851#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002852
Guido van Rossum18468821994-06-20 07:49:28 +00002853static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002854EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002855{
Guido van Rossumad4db171998-06-13 13:56:28 +00002856#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002857 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002858#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002859#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002860 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002861#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002862 stdin_ready = 0;
2863 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002864#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002865 tfile = fileno(stdin);
2866 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002867#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002868 while (!errorInCmd && !stdin_ready) {
2869 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002870#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 if (_kbhit()) {
2872 stdin_ready = 1;
2873 break;
2874 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002875#endif
2876#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002877 Py_BEGIN_ALLOW_THREADS
2878 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2879 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002881 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 tcl_tstate = NULL;
2884 if(tcl_lock)PyThread_release_lock(tcl_lock);
2885 if (result == 0)
2886 Sleep(Tkinter_busywaitinterval);
2887 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002888#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002889 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002890#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002891
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 if (result < 0)
2893 break;
2894 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002895#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002896 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002897#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 if (errorInCmd) {
2899 errorInCmd = 0;
2900 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2901 excInCmd = valInCmd = trbInCmd = NULL;
2902 PyErr_Print();
2903 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002904#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002905 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002906#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002907 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002908}
Guido van Rossum18468821994-06-20 07:49:28 +00002909
Guido van Rossum00d93061998-05-28 23:06:38 +00002910#endif
2911
Guido van Rossum7bf15641998-05-22 18:28:17 +00002912static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002913EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002914{
Guido van Rossum00d93061998-05-28 23:06:38 +00002915#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002916 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002917#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002919#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002920 PyOS_InputHook = EventHook;
2921 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002922#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002923}
2924
2925static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002926DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002927{
Guido van Rossum00d93061998-05-28 23:06:38 +00002928#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002929 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2930 PyOS_InputHook = NULL;
2931 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002932#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002933}
2934
Barry Warsawfa701a81997-01-16 00:15:11 +00002935
Martin v. Löwis1a214512008-06-11 05:26:20 +00002936static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 PyModuleDef_HEAD_INIT,
2938 "_tkinter",
2939 NULL,
2940 -1,
2941 moduleMethods,
2942 NULL,
2943 NULL,
2944 NULL,
2945 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002946};
2947
Mark Hammond62b1ab12002-07-23 06:31:15 +00002948PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002949PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002950{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002951 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002952
Guido van Rossum00d93061998-05-28 23:06:38 +00002953#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002954 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002955 if (tcl_lock == NULL)
2956 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002957#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002958
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 m = PyModule_Create(&_tkintermodule);
2960 if (m == NULL)
2961 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002962
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002963 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2964 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002965 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002966 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002967 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002968 Py_INCREF(o);
2969 if (PyModule_AddObject(m, "TclError", o)) {
2970 Py_DECREF(o);
2971 Py_DECREF(m);
2972 return NULL;
2973 }
2974 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002975
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002976 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2977 Py_DECREF(m);
2978 return NULL;
2979 }
2980 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2981 Py_DECREF(m);
2982 return NULL;
2983 }
2984 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2985 Py_DECREF(m);
2986 return NULL;
2987 }
2988 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2989 Py_DECREF(m);
2990 return NULL;
2991 }
2992 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
2993 Py_DECREF(m);
2994 return NULL;
2995 }
2996 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
2997 Py_DECREF(m);
2998 return NULL;
2999 }
3000 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3001 Py_DECREF(m);
3002 return NULL;
3003 }
3004 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3005 Py_DECREF(m);
3006 return NULL;
3007 }
3008 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3009 Py_DECREF(m);
3010 return NULL;
3011 }
3012 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3013 Py_DECREF(m);
3014 return NULL;
3015 }
3016 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3017 Py_DECREF(m);
3018 return NULL;
3019 }
3020
3021 o = PyType_FromSpec(&Tkapp_Type_spec);
3022 if (o == NULL) {
3023 Py_DECREF(m);
3024 return NULL;
3025 }
3026 if (PyModule_AddObject(m, "TkappType", o)) {
3027 Py_DECREF(o);
3028 Py_DECREF(m);
3029 return NULL;
3030 }
3031 Tkapp_Type = o;
3032
3033 o = PyType_FromSpec(&Tktt_Type_spec);
3034 if (o == NULL) {
3035 Py_DECREF(m);
3036 return NULL;
3037 }
3038 if (PyModule_AddObject(m, "TkttType", o)) {
3039 Py_DECREF(o);
3040 Py_DECREF(m);
3041 return NULL;
3042 }
3043 Tktt_Type = o;
3044
3045 o = PyType_FromSpec(&PyTclObject_Type_spec);
3046 if (o == NULL) {
3047 Py_DECREF(m);
3048 return NULL;
3049 }
3050 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3051 Py_DECREF(o);
3052 Py_DECREF(m);
3053 return NULL;
3054 }
3055 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003056
3057#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003058 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3059 * start waking up. Note that Tcl_FindExecutable will do this, this
3060 * code must be above it! The original warning from
3061 * tkMacOSXAppInit.c is copied below.
3062 *
3063 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3064 * Tcl interpreter for now. It probably should work to do this
3065 * in the other order, but for now it doesn't seem to.
3066 *
3067 */
3068 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003069#endif
3070
3071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003072 /* This helps the dynamic loader; in Unicode aware Tcl versions
3073 it also helps Tcl find its encodings. */
3074 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3075 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003076 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003077 if (cexe)
3078 Tcl_FindExecutable(PyBytes_AsString(cexe));
3079 Py_XDECREF(cexe);
3080 Py_DECREF(uexe);
3081 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003082
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003083 if (PyErr_Occurred()) {
3084 Py_DECREF(m);
3085 return NULL;
3086 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003087
Guido van Rossum43ff8681998-07-14 18:02:13 +00003088#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003089 /* This was not a good idea; through <Destroy> bindings,
3090 Tcl_Finalize() may invoke Python code but at that point the
3091 interpreter and thread state have already been destroyed! */
3092 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003093#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003094 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003095}