blob: 4a7b284b267b1ea3511ec9ba266df1aa6ebe0327 [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
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300864#if PY_SIZE_MAX > INT_MAX
865#define CHECK_STRING_LENGTH(s) do { \
866 if (s != NULL && strlen(s) >= INT_MAX) { \
867 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
868 return NULL; \
869 } } while(0)
870#else
871#define CHECK_STRING_LENGTH(s)
872#endif
873
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000874static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000875AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000876{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000877 Tcl_Obj *result;
878 long longVal;
879 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 if (PyBytes_Check(value))
882 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
883 PyBytes_GET_SIZE(value));
884 else if (PyBool_Check(value))
885 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
886 else if (PyLong_CheckExact(value) &&
887 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
888 !overflow)) {
889 /* If there is an overflow in the long conversion,
890 fall through to default object handling. */
891 return Tcl_NewLongObj(longVal);
892 }
893 else if (PyFloat_Check(value))
894 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
895 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300896 Tcl_Obj **argv;
897 Py_ssize_t size, i;
898
899 size = PyTuple_Size(value);
900 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
901 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
902 return NULL;
903 }
904 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 if(!argv)
906 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300907 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000908 argv[i] = AsObj(PyTuple_GetItem(value,i));
909 result = Tcl_NewListObj(PyTuple_Size(value), argv);
910 ckfree(FREECAST argv);
911 return result;
912 }
913 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200914 void *inbuf;
915 Py_ssize_t size;
916 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000917 Tcl_UniChar *outbuf = NULL;
918 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200919 size_t allocsize;
920
921 if (PyUnicode_READY(value) == -1)
922 return NULL;
923
924 inbuf = PyUnicode_DATA(value);
925 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300926 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
927 PyErr_SetString(PyExc_OverflowError, "string is too long");
928 return NULL;
929 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200930 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200931 if (kind == sizeof(Tcl_UniChar))
932 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200933 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
934 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 /* Else overflow occurred, and we take the next exit */
936 if (!outbuf) {
937 PyErr_NoMemory();
938 return NULL;
939 }
940 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200941 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
942 /* We cannot test for sizeof(Tcl_UniChar) directly,
943 so we test for UTF-8 size instead. */
944#if TCL_UTF_MAX == 3
945 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200947 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100948 "character U+%x is above the range "
949 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100950 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000951 ckfree(FREECAST outbuf);
952 return NULL;
953 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300954#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200955 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000956 }
957 result = Tcl_NewUnicodeObj(outbuf, size);
958 ckfree(FREECAST outbuf);
959 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000960 }
961 else if(PyTclObject_Check(value)) {
962 Tcl_Obj *v = ((PyTclObject*)value)->value;
963 Tcl_IncrRefCount(v);
964 return v;
965 }
966 else {
967 PyObject *v = PyObject_Str(value);
968 if (!v)
969 return 0;
970 result = AsObj(v);
971 Py_DECREF(v);
972 return result;
973 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000974}
975
Martin v. Löwisffad6332002-11-26 09:28:05 +0000976static PyObject*
977FromObj(PyObject* tkapp, Tcl_Obj *value)
978{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000979 PyObject *result = NULL;
980 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200983 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000985
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000986 if (value->typePtr == app->BooleanType) {
987 result = value->internalRep.longValue ? Py_True : Py_False;
988 Py_INCREF(result);
989 return result;
990 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000991
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000992 if (value->typePtr == app->ByteArrayType) {
993 int size;
994 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
995 return PyBytes_FromStringAndSize(data, size);
996 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000998 if (value->typePtr == app->DoubleType) {
999 return PyFloat_FromDouble(value->internalRep.doubleValue);
1000 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001001
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 if (value->typePtr == app->IntType) {
1003 return PyLong_FromLong(value->internalRep.longValue);
1004 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001005
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 if (value->typePtr == app->ListType) {
1007 int size;
1008 int i, status;
1009 PyObject *elem;
1010 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1013 if (status == TCL_ERROR)
1014 return Tkinter_Error(tkapp);
1015 result = PyTuple_New(size);
1016 if (!result)
1017 return NULL;
1018 for (i = 0; i < size; i++) {
1019 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1020 value, i, &tcl_elem);
1021 if (status == TCL_ERROR) {
1022 Py_DECREF(result);
1023 return Tkinter_Error(tkapp);
1024 }
1025 elem = FromObj(tkapp, tcl_elem);
1026 if (!elem) {
1027 Py_DECREF(result);
1028 return NULL;
1029 }
1030 PyTuple_SetItem(result, i, elem);
1031 }
1032 return result;
1033 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 if (value->typePtr == app->ProcBodyType) {
1036 /* fall through: return tcl object. */
1037 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001039 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001040 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001041 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001042 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001046}
1047
Benjamin Peterson5879d412009-03-30 14:51:56 +00001048#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001049/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001050TCL_DECLARE_MUTEX(call_mutex)
1051
1052typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001053 Tcl_Event ev; /* Must be first */
1054 TkappObject *self;
1055 PyObject *args;
1056 int flags;
1057 PyObject **res;
1058 PyObject **exc_type, **exc_value, **exc_tb;
1059 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001060} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001061#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001062
1063void
1064Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001065{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001066 int i;
1067 for (i = 0; i < objc; i++)
1068 Tcl_DecrRefCount(objv[i]);
1069 if (objv != objStore)
1070 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001071}
Guido van Rossum18468821994-06-20 07:49:28 +00001072
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073/* Convert Python objects to Tcl objects. This must happen in the
1074 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001075
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001076static Tcl_Obj**
1077Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1078{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001080 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001081 if (args == NULL)
1082 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 else if (!PyTuple_Check(args)) {
1085 objv[0] = AsObj(args);
1086 if (objv[0] == 0)
1087 goto finally;
1088 objc = 1;
1089 Tcl_IncrRefCount(objv[0]);
1090 }
1091 else {
1092 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001095 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1096 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1097 return NULL;
1098 }
1099 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001100 if (objv == NULL) {
1101 PyErr_NoMemory();
1102 objc = 0;
1103 goto finally;
1104 }
1105 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001107 for (i = 0; i < objc; i++) {
1108 PyObject *v = PyTuple_GetItem(args, i);
1109 if (v == Py_None) {
1110 objc = i;
1111 break;
1112 }
1113 objv[i] = AsObj(v);
1114 if (!objv[i]) {
1115 /* Reset objc, so it attempts to clear
1116 objects only up to i. */
1117 objc = i;
1118 goto finally;
1119 }
1120 Tcl_IncrRefCount(objv[i]);
1121 }
1122 }
1123 *pobjc = objc;
1124 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001125finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001126 Tkapp_CallDeallocArgs(objv, objStore, objc);
1127 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001128}
Guido van Rossum212643f1998-04-29 16:22:14 +00001129
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001130/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001131
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001132static PyObject*
1133Tkapp_CallResult(TkappObject *self)
1134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001136 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 /* Not sure whether the IncrRef is necessary, but something
1139 may overwrite the interpreter result while we are
1140 converting it. */
1141 Tcl_IncrRefCount(value);
1142 res = FromObj((PyObject*)self, value);
1143 Tcl_DecrRefCount(value);
1144 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001145 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 }
1147 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001148}
Guido van Rossum632de272000-03-29 00:19:50 +00001149
Benjamin Peterson5879d412009-03-30 14:51:56 +00001150#ifdef WITH_THREAD
1151
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001152/* Tkapp_CallProc is the event procedure that is executed in the context of
1153 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1154 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001155
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156static int
1157Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1158{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 Tcl_Obj *objStore[ARGSZ];
1160 Tcl_Obj **objv;
1161 int objc;
1162 int i;
1163 ENTER_PYTHON
1164 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1165 if (!objv) {
1166 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1167 *(e->res) = NULL;
1168 }
1169 LEAVE_PYTHON
1170 if (!objv)
1171 goto done;
1172 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1173 ENTER_PYTHON
1174 if (i == TCL_ERROR) {
1175 *(e->res) = NULL;
1176 *(e->exc_type) = NULL;
1177 *(e->exc_tb) = NULL;
1178 *(e->exc_value) = PyObject_CallFunction(
1179 Tkinter_TclError, "s",
1180 Tcl_GetStringResult(e->self->interp));
1181 }
1182 else {
1183 *(e->res) = Tkapp_CallResult(e->self);
1184 }
1185 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001186
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001187 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001188done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001189 /* Wake up calling thread. */
1190 Tcl_MutexLock(&call_mutex);
1191 Tcl_ConditionNotify(e->done);
1192 Tcl_MutexUnlock(&call_mutex);
1193 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001194}
1195
Benjamin Peterson5879d412009-03-30 14:51:56 +00001196#endif
1197
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001198/* This is the main entry point for calling a Tcl command.
1199 It supports three cases, with regard to threading:
1200 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1201 the context of the calling thread.
1202 2. Tcl is threaded, caller of the command is in the interpreter thread:
1203 Execute the command in the calling thread. Since the Tcl lock will
1204 not be used, we can merge that with case 1.
1205 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1206 the interpreter thread. Allocation of Tcl objects needs to occur in the
1207 interpreter thread, so we ship the PyObject* args to the target thread,
1208 and perform processing there. */
1209
1210static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001211Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001212{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 Tcl_Obj *objStore[ARGSZ];
1214 Tcl_Obj **objv = NULL;
1215 int objc, i;
1216 PyObject *res = NULL;
1217 TkappObject *self = (TkappObject*)selfptr;
1218 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001220 /* If args is a single tuple, replace with contents of tuple */
1221 if (1 == PyTuple_Size(args)){
1222 PyObject* item = PyTuple_GetItem(args, 0);
1223 if (PyTuple_Check(item))
1224 args = item;
1225 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001226#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1228 /* We cannot call the command directly. Instead, we must
1229 marshal the parameters to the interpreter thread. */
1230 Tkapp_CallEvent *ev;
1231 Tcl_Condition cond = NULL;
1232 PyObject *exc_type, *exc_value, *exc_tb;
1233 if (!WaitForMainloop(self))
1234 return NULL;
1235 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1236 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1237 ev->self = self;
1238 ev->args = args;
1239 ev->res = &res;
1240 ev->exc_type = &exc_type;
1241 ev->exc_value = &exc_value;
1242 ev->exc_tb = &exc_tb;
1243 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001245 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 if (res == NULL) {
1248 if (exc_type)
1249 PyErr_Restore(exc_type, exc_value, exc_tb);
1250 else
1251 PyErr_SetObject(Tkinter_TclError, exc_value);
1252 }
1253 Tcl_ConditionFinalize(&cond);
1254 }
1255 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001256#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 objv = Tkapp_CallArgs(args, objStore, &objc);
1260 if (!objv)
1261 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001267 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 if (i == TCL_ERROR)
1270 Tkinter_Error(selfptr);
1271 else
1272 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 Tkapp_CallDeallocArgs(objv, objStore, objc);
1277 }
1278 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001279}
1280
1281
1282static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001283Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001284{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 char *script;
1286 PyObject *res = NULL;
1287 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 if (!PyArg_ParseTuple(args, "s:eval", &script))
1290 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001291
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001292 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 ENTER_TCL
1296 err = Tcl_Eval(Tkapp_Interp(self), script);
1297 ENTER_OVERLAP
1298 if (err == TCL_ERROR)
1299 res = Tkinter_Error(self);
1300 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001301 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 LEAVE_OVERLAP_TCL
1303 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001304}
1305
1306static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001307Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001308{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 char *fileName;
1310 PyObject *res = NULL;
1311 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1314 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001315
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001316 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 ENTER_TCL
1320 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1321 ENTER_OVERLAP
1322 if (err == TCL_ERROR)
1323 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001325 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 LEAVE_OVERLAP_TCL
1327 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001328}
1329
1330static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001331Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 char *script;
1334 PyObject *res = NULL;
1335 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001336
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001337 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001339
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001340 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 ENTER_TCL
1344 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1345 ENTER_OVERLAP
1346 if (err == TCL_ERROR)
1347 res = Tkinter_Error(self);
1348 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001349 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 LEAVE_OVERLAP_TCL
1351 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001352}
1353
1354static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001355Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1360 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001361 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 ENTER_TCL
1365 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1366 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001367
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001368 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001369}
1370
Barry Warsawfa701a81997-01-16 00:15:11 +00001371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372
Guido van Rossum18468821994-06-20 07:49:28 +00001373/** Tcl Variable **/
1374
Benjamin Peterson5879d412009-03-30 14:51:56 +00001375typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1376
1377#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378TCL_DECLARE_MUTEX(var_mutex)
1379
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001380typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 Tcl_Event ev; /* must be first */
1382 PyObject *self;
1383 PyObject *args;
1384 int flags;
1385 EventFunc func;
1386 PyObject **res;
1387 PyObject **exc_type;
1388 PyObject **exc_val;
1389 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001391#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001393static int
1394varname_converter(PyObject *in, void *_out)
1395{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001396 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 char **out = (char**)_out;
1398 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001399 if (PyBytes_Size(in) > INT_MAX) {
1400 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1401 return 0;
1402 }
1403 s = PyBytes_AsString(in);
1404 if (strlen(s) != PyBytes_Size(in)) {
1405 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1406 return 0;
1407 }
1408 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001409 return 1;
1410 }
1411 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001412 Py_ssize_t size;
1413 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001414 if (s == NULL) {
1415 return 0;
1416 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001417 if (size > INT_MAX) {
1418 PyErr_SetString(PyExc_OverflowError, "string is too long");
1419 return 0;
1420 }
1421 if (strlen(s) != size) {
1422 PyErr_SetString(PyExc_ValueError, "null character in string");
1423 return 0;
1424 }
1425 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 return 1;
1427 }
1428 if (PyTclObject_Check(in)) {
1429 *out = PyTclObject_TclString(in);
1430 return 1;
1431 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001432 PyErr_Format(PyExc_TypeError,
1433 "must be str, bytes or Tcl_Obj, not %.50s",
1434 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001436}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001437
Benjamin Peterson5879d412009-03-30 14:51:56 +00001438#ifdef WITH_THREAD
1439
Martin v. Löwis59683e82008-06-13 07:50:45 +00001440static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001441var_perform(VarEvent *ev)
1442{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1444 if (!*(ev->res)) {
1445 PyObject *exc, *val, *tb;
1446 PyErr_Fetch(&exc, &val, &tb);
1447 PyErr_NormalizeException(&exc, &val, &tb);
1448 *(ev->exc_type) = exc;
1449 *(ev->exc_val) = val;
1450 Py_DECREF(tb);
1451 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001452
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453}
1454
1455static int
1456var_proc(VarEvent* ev, int flags)
1457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001458 ENTER_PYTHON
1459 var_perform(ev);
1460 Tcl_MutexLock(&var_mutex);
1461 Tcl_ConditionNotify(ev->cond);
1462 Tcl_MutexUnlock(&var_mutex);
1463 LEAVE_PYTHON
1464 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001465}
1466
Benjamin Peterson5879d412009-03-30 14:51:56 +00001467#endif
1468
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001470var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001472#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 TkappObject *self = (TkappObject*)selfptr;
1474 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1475 TkappObject *self = (TkappObject*)selfptr;
1476 VarEvent *ev;
1477 PyObject *res, *exc_type, *exc_val;
1478 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001480 /* The current thread is not the interpreter thread. Marshal
1481 the call to the interpreter thread, then wait for
1482 completion. */
1483 if (!WaitForMainloop(self))
1484 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 ev->self = selfptr;
1489 ev->args = args;
1490 ev->flags = flags;
1491 ev->func = func;
1492 ev->res = &res;
1493 ev->exc_type = &exc_type;
1494 ev->exc_val = &exc_val;
1495 ev->cond = &cond;
1496 ev->ev.proc = (Tcl_EventProc*)var_proc;
1497 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1498 Tcl_ConditionFinalize(&cond);
1499 if (!res) {
1500 PyErr_SetObject(exc_type, exc_val);
1501 Py_DECREF(exc_type);
1502 Py_DECREF(exc_val);
1503 return NULL;
1504 }
1505 return res;
1506 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001507#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 /* Tcl is not threaded, or this is the interpreter thread. */
1509 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510}
1511
Guido van Rossum18468821994-06-20 07:49:28 +00001512static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001513SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001514{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515 char *name1, *name2;
1516 PyObject *newValue;
1517 PyObject *res = NULL;
1518 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001519
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001520 switch (PyTuple_GET_SIZE(args)) {
1521 case 2:
1522 if (!PyArg_ParseTuple(args, "O&O:setvar",
1523 varname_converter, &name1, &newValue))
1524 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 /* XXX Acquire tcl lock??? */
1526 newval = AsObj(newValue);
1527 if (newval == NULL)
1528 return NULL;
1529 ENTER_TCL
1530 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1531 newval, flags);
1532 ENTER_OVERLAP
1533 if (!ok)
1534 Tkinter_Error(self);
1535 else {
1536 res = Py_None;
1537 Py_INCREF(res);
1538 }
1539 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001540 break;
1541 case 3:
1542 if (!PyArg_ParseTuple(args, "ssO:setvar",
1543 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001545 CHECK_STRING_LENGTH(name1);
1546 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001547 /* XXX must hold tcl lock already??? */
1548 newval = AsObj(newValue);
1549 ENTER_TCL
1550 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1551 ENTER_OVERLAP
1552 if (!ok)
1553 Tkinter_Error(self);
1554 else {
1555 res = Py_None;
1556 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001558 LEAVE_OVERLAP_TCL
1559 break;
1560 default:
1561 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1562 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 }
1564 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001565}
1566
1567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001568Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001571}
1572
1573static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001574Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001575{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001577}
1578
Barry Warsawfa701a81997-01-16 00:15:11 +00001579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001580
Guido van Rossum18468821994-06-20 07:49:28 +00001581static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001582GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001583{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001584 char *name1, *name2=NULL;
1585 PyObject *res = NULL;
1586 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001588 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1589 varname_converter, &name1, &name2))
1590 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001591
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001592 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593 ENTER_TCL
1594 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1595 ENTER_OVERLAP
1596 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001597 PyErr_SetString(Tkinter_TclError,
1598 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 } else {
1600 if (((TkappObject*)self)->wantobjects) {
1601 res = FromObj(self, tres);
1602 }
1603 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001604 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605 }
1606 }
1607 LEAVE_OVERLAP_TCL
1608 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001609}
1610
1611static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001612Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001615}
1616
1617static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001618Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001619{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001620 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001621}
1622
Barry Warsawfa701a81997-01-16 00:15:11 +00001623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624
Guido van Rossum18468821994-06-20 07:49:28 +00001625static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001626UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001627{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628 char *name1, *name2=NULL;
1629 int code;
1630 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001632 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1633 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001634
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001635 CHECK_STRING_LENGTH(name1);
1636 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 ENTER_TCL
1638 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1639 ENTER_OVERLAP
1640 if (code == TCL_ERROR)
1641 res = Tkinter_Error(self);
1642 else {
1643 Py_INCREF(Py_None);
1644 res = Py_None;
1645 }
1646 LEAVE_OVERLAP_TCL
1647 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001648}
1649
1650static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001651Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001652{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001653 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001654}
1655
1656static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001657Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001658{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001659 return var_invoke(UnsetVar, self, args,
1660 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001661}
1662
Barry Warsawfa701a81997-01-16 00:15:11 +00001663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664
Guido van Rossum18468821994-06-20 07:49:28 +00001665/** Tcl to Python **/
1666
1667static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001668Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001669{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001670 char *s;
1671 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 if (PyTuple_Size(args) == 1) {
1674 PyObject* o = PyTuple_GetItem(args, 0);
1675 if (PyLong_Check(o)) {
1676 Py_INCREF(o);
1677 return o;
1678 }
1679 }
1680 if (!PyArg_ParseTuple(args, "s:getint", &s))
1681 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001682 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1684 return Tkinter_Error(self);
1685 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001686}
1687
1688static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001689Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001690{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001691 char *s;
1692 double 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 (PyFloat_Check(o)) {
1697 Py_INCREF(o);
1698 return o;
1699 }
1700 }
1701 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1702 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001703 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001704 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1705 return Tkinter_Error(self);
1706 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
1709static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001710Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 char *s;
1713 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715 if (PyTuple_Size(args) == 1) {
1716 PyObject *o = PyTuple_GetItem(args, 0);
1717 if (PyLong_Check(o)) {
1718 Py_INCREF(o);
1719 return o;
1720 }
1721 }
1722 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1723 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001724 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001725 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1726 return Tkinter_Error(self);
1727 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001728}
1729
1730static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001731Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001732{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 char *s;
1734 PyObject *res = NULL;
1735 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001737 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1738 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001739
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001740 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001741 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 ENTER_TCL
1744 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1745 ENTER_OVERLAP
1746 if (retval == TCL_ERROR)
1747 res = Tkinter_Error(self);
1748 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001749 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 LEAVE_OVERLAP_TCL
1751 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001752}
1753
1754static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001755Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001756{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 char *s;
1758 PyObject *res = NULL;
1759 int retval;
1760 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001762 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1763 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001764
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001765 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001766 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001767
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 ENTER_TCL
1769 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1770 ENTER_OVERLAP
1771 if (retval == TCL_ERROR)
1772 res = Tkinter_Error(self);
1773 else
1774 res = Py_BuildValue("l", 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_ExprDouble(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 double v;
1785 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1788 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001789 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001790 CHECK_TCL_APPARTMENT;
1791 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1792 ENTER_TCL
1793 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1794 ENTER_OVERLAP
1795 PyFPE_END_PROTECT(retval)
1796 if (retval == TCL_ERROR)
1797 res = Tkinter_Error(self);
1798 else
1799 res = Py_BuildValue("d", v);
1800 LEAVE_OVERLAP_TCL
1801 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001802}
1803
1804static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001805Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001806{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001807 char *s;
1808 PyObject *res = NULL;
1809 int retval;
1810 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001812 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1813 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001814 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001815 CHECK_TCL_APPARTMENT;
1816 ENTER_TCL
1817 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1818 ENTER_OVERLAP
1819 if (retval == TCL_ERROR)
1820 res = Tkinter_Error(self);
1821 else
1822 res = Py_BuildValue("i", v);
1823 LEAVE_OVERLAP_TCL
1824 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001825}
1826
Barry Warsawfa701a81997-01-16 00:15:11 +00001827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828
Guido van Rossum18468821994-06-20 07:49:28 +00001829static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001830Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001831{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001832 char *list;
1833 int argc;
1834 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001835 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001836 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001837
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001838 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1839 return NULL;
1840 if (PyTclObject_Check(arg)) {
1841 int objc;
1842 Tcl_Obj **objv;
1843 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1844 ((PyTclObject*)arg)->value,
1845 &objc, &objv) == TCL_ERROR) {
1846 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001848 if (!(v = PyTuple_New(objc)))
1849 return NULL;
1850 for (i = 0; i < objc; i++) {
1851 PyObject *s = FromObj(self, objv[i]);
1852 if (!s || PyTuple_SetItem(v, i, s)) {
1853 Py_DECREF(v);
1854 return NULL;
1855 }
1856 }
1857 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001858 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001859 if (PyTuple_Check(arg)) {
1860 Py_INCREF(arg);
1861 return arg;
1862 }
1863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1865 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001866
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001867 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 if (Tcl_SplitList(Tkapp_Interp(self), list,
1869 &argc, &argv) == TCL_ERROR) {
1870 PyMem_Free(list);
1871 return Tkinter_Error(self);
1872 }
Guido van Rossum18468821994-06-20 07:49:28 +00001873
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001874 if (!(v = PyTuple_New(argc)))
1875 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001878 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001879 if (!s || PyTuple_SetItem(v, i, s)) {
1880 Py_DECREF(v);
1881 v = NULL;
1882 goto finally;
1883 }
1884 }
Guido van Rossum18468821994-06-20 07:49:28 +00001885
Barry Warsawfa701a81997-01-16 00:15:11 +00001886 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001887 ckfree(FREECAST argv);
1888 PyMem_Free(list);
1889 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001890}
1891
1892static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001893Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001894{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001895 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001897
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001898 if (!PyArg_ParseTuple(args, "O:split", &arg))
1899 return NULL;
1900 if (PyTclObject_Check(arg)) {
1901 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1902 int objc;
1903 Tcl_Obj **objv;
1904 int i;
1905 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1906 &objc, &objv) == TCL_ERROR) {
1907 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001909 if (objc == 0)
1910 return PyUnicode_FromString("");
1911 if (objc == 1)
1912 return FromObj(self, objv[0]);
1913 if (!(v = PyTuple_New(objc)))
1914 return NULL;
1915 for (i = 0; i < objc; i++) {
1916 PyObject *s = FromObj(self, objv[i]);
1917 if (!s || PyTuple_SetItem(v, i, s)) {
1918 Py_DECREF(v);
1919 return NULL;
1920 }
1921 }
1922 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001923 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001924 if (PyTuple_Check(arg))
1925 return SplitObj(arg);
1926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001927 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1928 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001929 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 v = Split(list);
1931 PyMem_Free(list);
1932 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001933}
1934
Barry Warsawfa701a81997-01-16 00:15:11 +00001935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936
Guido van Rossum18468821994-06-20 07:49:28 +00001937/** Tcl Command **/
1938
Guido van Rossum00d93061998-05-28 23:06:38 +00001939/* Client data struct */
1940typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001941 PyObject *self;
1942 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001943} PythonCmd_ClientData;
1944
1945static int
Fred Drake509d79a2000-07-08 04:04:38 +00001946PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001947{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001948 errorInCmd = 1;
1949 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1950 LEAVE_PYTHON
1951 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001952}
1953
Guido van Rossum18468821994-06-20 07:49:28 +00001954/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001955 * function or method.
1956 */
Guido van Rossum18468821994-06-20 07:49:28 +00001957static int
Fred Drake509d79a2000-07-08 04:04:38 +00001958PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001959{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001961 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962 int i, rv;
1963 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001966
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001967 /* TBD: no error checking here since we know, via the
1968 * Tkapp_CreateCommand() that the client data is a two-tuple
1969 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001971
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 /* Create argument list (argv1, ..., argvN) */
1973 if (!(arg = PyTuple_New(argc - 1)))
1974 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001976 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001977 PyObject *s = unicodeFromTclString(argv[i + 1]);
1978 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 Py_DECREF(arg);
1980 return PythonCmd_Error(interp);
1981 }
1982 }
1983 res = PyEval_CallObject(func, arg);
1984 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001985
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001986 if (res == NULL)
1987 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 obj_res = AsObj(res);
1990 if (obj_res == NULL) {
1991 Py_DECREF(res);
1992 return PythonCmd_Error(interp);
1993 }
1994 else {
1995 Tcl_SetObjResult(interp, obj_res);
1996 rv = TCL_OK;
1997 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002004}
2005
2006static void
Fred Drake509d79a2000-07-08 04:04:38 +00002007PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002008{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002010
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002011 ENTER_PYTHON
2012 Py_XDECREF(data->self);
2013 Py_XDECREF(data->func);
2014 PyMem_DEL(data);
2015 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002016}
2017
Barry Warsawfa701a81997-01-16 00:15:11 +00002018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002019
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002020
Benjamin Peterson5879d412009-03-30 14:51:56 +00002021#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002022TCL_DECLARE_MUTEX(command_mutex)
2023
2024typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002025 Tcl_Event ev;
2026 Tcl_Interp* interp;
2027 char *name;
2028 int create;
2029 int *status;
2030 ClientData *data;
2031 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002032} CommandEvent;
2033
2034static int
2035Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002036{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002037 if (ev->create)
2038 *ev->status = Tcl_CreateCommand(
2039 ev->interp, ev->name, PythonCmd,
2040 ev->data, PythonCmdDelete) == NULL;
2041 else
2042 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2043 Tcl_MutexLock(&command_mutex);
2044 Tcl_ConditionNotify(ev->done);
2045 Tcl_MutexUnlock(&command_mutex);
2046 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002047}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002048#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002049
2050static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002051Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002052{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053 TkappObject *self = (TkappObject*)selfptr;
2054 PythonCmd_ClientData *data;
2055 char *cmdName;
2056 PyObject *func;
2057 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2060 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002061 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002062 if (!PyCallable_Check(func)) {
2063 PyErr_SetString(PyExc_TypeError, "command not callable");
2064 return NULL;
2065 }
Guido van Rossum18468821994-06-20 07:49:28 +00002066
Martin v. Löwisa9656492003-03-30 08:44:58 +00002067#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002068 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2069 !WaitForMainloop(self))
2070 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002071#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002073 data = PyMem_NEW(PythonCmd_ClientData, 1);
2074 if (!data)
2075 return PyErr_NoMemory();
2076 Py_INCREF(self);
2077 Py_INCREF(func);
2078 data->self = selfptr;
2079 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002080#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002081 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2082 Tcl_Condition cond = NULL;
2083 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2084 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2085 ev->interp = self->interp;
2086 ev->create = 1;
2087 ev->name = cmdName;
2088 ev->data = (ClientData)data;
2089 ev->status = &err;
2090 ev->done = &cond;
2091 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2092 Tcl_ConditionFinalize(&cond);
2093 }
2094 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002095#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002096 {
2097 ENTER_TCL
2098 err = Tcl_CreateCommand(
2099 Tkapp_Interp(self), cmdName, PythonCmd,
2100 (ClientData)data, PythonCmdDelete) == NULL;
2101 LEAVE_TCL
2102 }
2103 if (err) {
2104 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2105 PyMem_DEL(data);
2106 return NULL;
2107 }
Guido van Rossum18468821994-06-20 07:49:28 +00002108
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002109 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002110}
2111
Barry Warsawfa701a81997-01-16 00:15:11 +00002112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113
Guido van Rossum18468821994-06-20 07:49:28 +00002114static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002115Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002116{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002117 TkappObject *self = (TkappObject*)selfptr;
2118 char *cmdName;
2119 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002121 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2122 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002123 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002124
2125#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002126 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2127 Tcl_Condition cond = NULL;
2128 CommandEvent *ev;
2129 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2130 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2131 ev->interp = self->interp;
2132 ev->create = 0;
2133 ev->name = cmdName;
2134 ev->status = &err;
2135 ev->done = &cond;
2136 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2137 &command_mutex);
2138 Tcl_ConditionFinalize(&cond);
2139 }
2140 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002141#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 {
2143 ENTER_TCL
2144 err = Tcl_DeleteCommand(self->interp, cmdName);
2145 LEAVE_TCL
2146 }
2147 if (err == -1) {
2148 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2149 return NULL;
2150 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002151 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002152}
2153
Barry Warsawfa701a81997-01-16 00:15:11 +00002154
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002155
Guido van Rossum00d93061998-05-28 23:06:38 +00002156#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002157/** File Handler **/
2158
Guido van Rossum00d93061998-05-28 23:06:38 +00002159typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 PyObject *func;
2161 PyObject *file;
2162 int id;
2163 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002164} FileHandler_ClientData;
2165
2166static FileHandler_ClientData *HeadFHCD;
2167
2168static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002169NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002170{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 FileHandler_ClientData *p;
2172 p = PyMem_NEW(FileHandler_ClientData, 1);
2173 if (p != NULL) {
2174 Py_XINCREF(func);
2175 Py_XINCREF(file);
2176 p->func = func;
2177 p->file = file;
2178 p->id = id;
2179 p->next = HeadFHCD;
2180 HeadFHCD = p;
2181 }
2182 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002183}
2184
2185static void
Fred Drake509d79a2000-07-08 04:04:38 +00002186DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002187{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002188 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 pp = &HeadFHCD;
2191 while ((p = *pp) != NULL) {
2192 if (p->id == id) {
2193 *pp = p->next;
2194 Py_XDECREF(p->func);
2195 Py_XDECREF(p->file);
2196 PyMem_DEL(p);
2197 }
2198 else
2199 pp = &p->next;
2200 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002201}
2202
Guido van Rossuma597dde1995-01-10 20:56:29 +00002203static void
Fred Drake509d79a2000-07-08 04:04:38 +00002204FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002205{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2207 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002209 ENTER_PYTHON
2210 func = data->func;
2211 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002213 arg = Py_BuildValue("(Oi)", file, (long) mask);
2214 res = PyEval_CallObject(func, arg);
2215 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217 if (res == NULL) {
2218 errorInCmd = 1;
2219 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2220 }
2221 Py_XDECREF(res);
2222 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002223}
2224
Guido van Rossum18468821994-06-20 07:49:28 +00002225static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002226Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2227 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002228{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 FileHandler_ClientData *data;
2230 PyObject *file, *func;
2231 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2234 &file, &mask, &func))
2235 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 tfile = PyObject_AsFileDescriptor(file);
2240 if (tfile < 0)
2241 return NULL;
2242 if (!PyCallable_Check(func)) {
2243 PyErr_SetString(PyExc_TypeError, "bad argument list");
2244 return NULL;
2245 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 data = NewFHCD(func, file, tfile);
2248 if (data == NULL)
2249 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251 /* Ought to check for null Tcl_File object... */
2252 ENTER_TCL
2253 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2254 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002255 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002256}
2257
2258static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002259Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002260{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 PyObject *file;
2262 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2265 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 tfile = PyObject_AsFileDescriptor(file);
2270 if (tfile < 0)
2271 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 /* Ought to check for null Tcl_File object... */
2276 ENTER_TCL
2277 Tcl_DeleteFileHandler(tfile);
2278 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002279 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002280}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002281#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284/**** Tktt Object (timer token) ****/
2285
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002286static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002287
Guido van Rossum00d93061998-05-28 23:06:38 +00002288typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 PyObject_HEAD
2290 Tcl_TimerToken token;
2291 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002292} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002293
2294static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002295Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002296{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 TkttObject *v = (TkttObject *)self;
2298 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002300 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2301 return NULL;
2302 if (v->token != NULL) {
2303 Tcl_DeleteTimerHandler(v->token);
2304 v->token = NULL;
2305 }
2306 if (func != NULL) {
2307 v->func = NULL;
2308 Py_DECREF(func);
2309 Py_DECREF(v); /* See Tktt_New() */
2310 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002311 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002312}
2313
2314static PyMethodDef Tktt_methods[] =
2315{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2317 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002318};
2319
2320static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002321Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002323 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002324
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002325 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 if (v == NULL)
2327 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002328 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 Py_INCREF(func);
2331 v->token = NULL;
2332 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002334 /* Extra reference, deleted when called or when handler is deleted */
2335 Py_INCREF(v);
2336 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337}
2338
2339static void
Fred Drake509d79a2000-07-08 04:04:38 +00002340Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 TkttObject *v = (TkttObject *)self;
2343 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002344 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002349 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002350}
2351
Guido van Rossum597ac201998-05-12 14:36:19 +00002352static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002353Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002354{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002355 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002356 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2357 v,
2358 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359}
2360
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002361static PyType_Slot Tktt_Type_slots[] = {
2362 {Py_tp_dealloc, Tktt_Dealloc},
2363 {Py_tp_repr, Tktt_Repr},
2364 {Py_tp_methods, Tktt_methods},
2365 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366};
2367
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002368static PyType_Spec Tktt_Type_spec = {
2369 "tktimertoken",
2370 sizeof(TkttObject),
2371 0,
2372 Py_TPFLAGS_DEFAULT,
2373 Tktt_Type_slots,
2374};
Barry Warsawfa701a81997-01-16 00:15:11 +00002375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002376
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377/** Timer Handler **/
2378
2379static void
Fred Drake509d79a2000-07-08 04:04:38 +00002380TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 TkttObject *v = (TkttObject *)clientData;
2383 PyObject *func = v->func;
2384 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 if (func == NULL)
2387 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002391 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002393 res = PyEval_CallObject(func, NULL);
2394 Py_DECREF(func);
2395 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 if (res == NULL) {
2398 errorInCmd = 1;
2399 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2400 }
2401 else
2402 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002405}
2406
2407static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002408Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002409{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002410 int milliseconds;
2411 PyObject *func;
2412 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2415 &milliseconds, &func))
2416 return NULL;
2417 if (!PyCallable_Check(func)) {
2418 PyErr_SetString(PyExc_TypeError, "bad argument list");
2419 return NULL;
2420 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 v = Tktt_New(func);
2425 if (v) {
2426 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2427 (ClientData)v);
2428 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002431}
2432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002433
Guido van Rossum18468821994-06-20 07:49:28 +00002434/** Event Loop **/
2435
Guido van Rossum18468821994-06-20 07:49:28 +00002436static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002437Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002438{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439 int threshold = 0;
2440 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002441#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002443#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2446 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 CHECK_TCL_APPARTMENT;
2449 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 quitMainLoop = 0;
2452 while (Tk_GetNumMainWindows() > threshold &&
2453 !quitMainLoop &&
2454 !errorInCmd)
2455 {
2456 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002457
2458#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459 if (self->threaded) {
2460 /* Allow other Python threads to run. */
2461 ENTER_TCL
2462 result = Tcl_DoOneEvent(0);
2463 LEAVE_TCL
2464 }
2465 else {
2466 Py_BEGIN_ALLOW_THREADS
2467 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2468 tcl_tstate = tstate;
2469 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2470 tcl_tstate = NULL;
2471 if(tcl_lock)PyThread_release_lock(tcl_lock);
2472 if (result == 0)
2473 Sleep(Tkinter_busywaitinterval);
2474 Py_END_ALLOW_THREADS
2475 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002476#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002478#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480 if (PyErr_CheckSignals() != 0) {
2481 self->dispatching = 0;
2482 return NULL;
2483 }
2484 if (result < 0)
2485 break;
2486 }
2487 self->dispatching = 0;
2488 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 if (errorInCmd) {
2491 errorInCmd = 0;
2492 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2493 excInCmd = valInCmd = trbInCmd = NULL;
2494 return NULL;
2495 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002496 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002497}
2498
2499static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002500Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 int flags = 0;
2503 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2506 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 ENTER_TCL
2509 rv = Tcl_DoOneEvent(flags);
2510 LEAVE_TCL
2511 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002512}
2513
2514static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002515Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002516{
2517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 if (!PyArg_ParseTuple(args, ":quit"))
2519 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002522 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002523}
2524
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002525static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002526Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002527{
2528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002529 if (!PyArg_ParseTuple(args, ":interpaddr"))
2530 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002531
Victor Stinnere1040e22013-09-05 00:22:24 +02002532 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002533}
2534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002535static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002536Tkapp_TkInit(PyObject *self, PyObject *args)
2537{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002538 Tcl_Interp *interp = Tkapp_Interp(self);
2539 const char * _tk_exists = NULL;
2540 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002541
Guilherme Polob681df42009-02-09 22:33:59 +00002542#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2544 * first call failed.
2545 * To avoid the deadlock, we just refuse the second call through
2546 * a static variable.
2547 */
2548 if (tk_load_failed) {
2549 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2550 return NULL;
2551 }
Guilherme Polob681df42009-02-09 22:33:59 +00002552#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 /* We want to guard against calling Tk_Init() multiple times */
2555 CHECK_TCL_APPARTMENT;
2556 ENTER_TCL
2557 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2558 ENTER_OVERLAP
2559 if (err == TCL_ERROR) {
2560 /* This sets an exception, but we cannot return right
2561 away because we need to exit the overlap first. */
2562 Tkinter_Error(self);
2563 } else {
2564 _tk_exists = Tkapp_Result(self);
2565 }
2566 LEAVE_OVERLAP_TCL
2567 if (err == TCL_ERROR) {
2568 return NULL;
2569 }
2570 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2571 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002572 PyErr_SetString(Tkinter_TclError,
2573 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002574#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002575 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002576#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 return NULL;
2578 }
2579 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002580 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002581}
Barry Warsawfa701a81997-01-16 00:15:11 +00002582
Martin v. Löwisffad6332002-11-26 09:28:05 +00002583static PyObject *
2584Tkapp_WantObjects(PyObject *self, PyObject *args)
2585{
2586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002587 int wantobjects = -1;
2588 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2589 return NULL;
2590 if (wantobjects == -1)
2591 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2592 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002593
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002594 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002595}
2596
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002597static PyObject *
2598Tkapp_WillDispatch(PyObject *self, PyObject *args)
2599{
2600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002602
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002603 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002604}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002606
Guido van Rossum18468821994-06-20 07:49:28 +00002607/**** Tkapp Method List ****/
2608
2609static PyMethodDef Tkapp_methods[] =
2610{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2612 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2613 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002615 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2616 {"record", Tkapp_Record, METH_VARARGS},
2617 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2618 {"setvar", Tkapp_SetVar, METH_VARARGS},
2619 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2620 {"getvar", Tkapp_GetVar, METH_VARARGS},
2621 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2622 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2623 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2624 {"getint", Tkapp_GetInt, METH_VARARGS},
2625 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2626 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2627 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2628 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2629 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2630 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2631 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2632 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2634 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002635#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2637 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002638#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002639 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2640 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2641 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2642 {"quit", Tkapp_Quit, METH_VARARGS},
2643 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2644 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2645 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002646};
2647
Barry Warsawfa701a81997-01-16 00:15:11 +00002648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649
Guido van Rossum18468821994-06-20 07:49:28 +00002650/**** Tkapp Type Methods ****/
2651
2652static void
Fred Drake509d79a2000-07-08 04:04:38 +00002653Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002654{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002655 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002656 /*CHECK_TCL_APPARTMENT;*/
2657 ENTER_TCL
2658 Tcl_DeleteInterp(Tkapp_Interp(self));
2659 LEAVE_TCL
2660 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002661 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002662 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002663}
2664
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002665static PyType_Slot Tkapp_Type_slots[] = {
2666 {Py_tp_dealloc, Tkapp_Dealloc},
2667 {Py_tp_methods, Tkapp_methods},
2668 {0, 0}
2669};
2670
2671
2672static PyType_Spec Tkapp_Type_spec = {
2673 "tkapp",
2674 sizeof(TkappObject),
2675 0,
2676 Py_TPFLAGS_DEFAULT,
2677 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002678};
2679
Barry Warsawfa701a81997-01-16 00:15:11 +00002680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002681
Guido van Rossum18468821994-06-20 07:49:28 +00002682/**** Tkinter Module ****/
2683
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002684typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002685 PyObject* tuple;
2686 int size; /* current size */
2687 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002688} FlattenContext;
2689
2690static int
2691_bump(FlattenContext* context, int size)
2692{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002693 /* expand tuple to hold (at least) size new items.
2694 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002696 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 if (maxsize < context->size + size)
2699 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002701 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002702
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002704}
2705
2706static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002707_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002708{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002709 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002711 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 if (depth > 1000) {
2714 PyErr_SetString(PyExc_ValueError,
2715 "nesting too deep in _flatten");
2716 return 0;
2717 } else if (PyList_Check(item)) {
2718 size = PyList_GET_SIZE(item);
2719 /* preallocate (assume no nesting) */
2720 if (context->size + size > context->maxsize &&
2721 !_bump(context, size))
2722 return 0;
2723 /* copy items to output tuple */
2724 for (i = 0; i < size; i++) {
2725 PyObject *o = PyList_GET_ITEM(item, i);
2726 if (PyList_Check(o) || PyTuple_Check(o)) {
2727 if (!_flatten1(context, o, depth + 1))
2728 return 0;
2729 } else if (o != Py_None) {
2730 if (context->size + 1 > context->maxsize &&
2731 !_bump(context, 1))
2732 return 0;
2733 Py_INCREF(o);
2734 PyTuple_SET_ITEM(context->tuple,
2735 context->size++, o);
2736 }
2737 }
2738 } else if (PyTuple_Check(item)) {
2739 /* same, for tuples */
2740 size = PyTuple_GET_SIZE(item);
2741 if (context->size + size > context->maxsize &&
2742 !_bump(context, size))
2743 return 0;
2744 for (i = 0; i < size; i++) {
2745 PyObject *o = PyTuple_GET_ITEM(item, i);
2746 if (PyList_Check(o) || PyTuple_Check(o)) {
2747 if (!_flatten1(context, o, depth + 1))
2748 return 0;
2749 } else if (o != Py_None) {
2750 if (context->size + 1 > context->maxsize &&
2751 !_bump(context, 1))
2752 return 0;
2753 Py_INCREF(o);
2754 PyTuple_SET_ITEM(context->tuple,
2755 context->size++, o);
2756 }
2757 }
2758 } else {
2759 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2760 return 0;
2761 }
2762 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002763}
2764
2765static PyObject *
2766Tkinter_Flatten(PyObject* self, PyObject* args)
2767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002768 FlattenContext context;
2769 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002770
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002771 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2772 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002773
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 context.maxsize = PySequence_Size(item);
2775 if (context.maxsize < 0)
2776 return NULL;
2777 if (context.maxsize == 0)
2778 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780 context.tuple = PyTuple_New(context.maxsize);
2781 if (!context.tuple)
2782 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002783
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002784 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 if (!_flatten1(&context, item,0))
2787 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002789 if (_PyTuple_Resize(&context.tuple, context.size))
2790 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002792 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793}
2794
Guido van Rossum18468821994-06-20 07:49:28 +00002795static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002796Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002797{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 char *screenName = NULL;
2799 char *baseName = NULL; /* XXX this is not used anymore;
2800 try getting rid of it. */
2801 char *className = NULL;
2802 int interactive = 0;
2803 int wantobjects = 0;
2804 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2805 int sync = 0; /* pass -sync to wish */
2806 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002808 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2811 &screenName, &baseName, &className,
2812 &interactive, &wantobjects, &wantTk,
2813 &sync, &use))
2814 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002815 CHECK_STRING_LENGTH(screenName);
2816 CHECK_STRING_LENGTH(baseName);
2817 CHECK_STRING_LENGTH(className);
2818 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002819
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002820 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002821 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002823}
2824
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002825static PyObject *
2826Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2827{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 int new_val;
2829 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2830 return NULL;
2831 if (new_val < 0) {
2832 PyErr_SetString(PyExc_ValueError,
2833 "busywaitinterval must be >= 0");
2834 return NULL;
2835 }
2836 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002837 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002838}
2839
2840static char setbusywaitinterval_doc[] =
2841"setbusywaitinterval(n) -> None\n\
2842\n\
2843Set the busy-wait interval in milliseconds between successive\n\
2844calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2845It should be set to a divisor of the maximum time between\n\
2846frames in an animation.";
2847
2848static PyObject *
2849Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2850{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002852}
2853
2854static char getbusywaitinterval_doc[] =
2855"getbusywaitinterval() -> int\n\
2856\n\
2857Return the current busy-wait interval between successive\n\
2858calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2859
Guido van Rossum18468821994-06-20 07:49:28 +00002860static PyMethodDef moduleMethods[] =
2861{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002862 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2863 {"create", Tkinter_Create, METH_VARARGS},
2864 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2865 setbusywaitinterval_doc},
2866 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2867 METH_NOARGS, getbusywaitinterval_doc},
2868 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002869};
2870
Guido van Rossum7bf15641998-05-22 18:28:17 +00002871#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002872
2873static int stdin_ready = 0;
2874
Guido van Rossumad4db171998-06-13 13:56:28 +00002875#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002876static void
Fred Drake509d79a2000-07-08 04:04:38 +00002877MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002878{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002879 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002880}
Guido van Rossumad4db171998-06-13 13:56:28 +00002881#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002882
Martin v. Löwisa9656492003-03-30 08:44:58 +00002883#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002884static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002885#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002886
Guido van Rossum18468821994-06-20 07:49:28 +00002887static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002888EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002889{
Guido van Rossumad4db171998-06-13 13:56:28 +00002890#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002891 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002892#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002893#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002894 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002895#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002896 stdin_ready = 0;
2897 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002898#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002899 tfile = fileno(stdin);
2900 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002901#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002902 while (!errorInCmd && !stdin_ready) {
2903 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002904#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002905 if (_kbhit()) {
2906 stdin_ready = 1;
2907 break;
2908 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002909#endif
2910#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002911 Py_BEGIN_ALLOW_THREADS
2912 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2913 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002914
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002915 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002916
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 tcl_tstate = NULL;
2918 if(tcl_lock)PyThread_release_lock(tcl_lock);
2919 if (result == 0)
2920 Sleep(Tkinter_busywaitinterval);
2921 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002922#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002923 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002924#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 if (result < 0)
2927 break;
2928 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002929#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002930 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002931#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 if (errorInCmd) {
2933 errorInCmd = 0;
2934 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2935 excInCmd = valInCmd = trbInCmd = NULL;
2936 PyErr_Print();
2937 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002938#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002940#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002941 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002942}
Guido van Rossum18468821994-06-20 07:49:28 +00002943
Guido van Rossum00d93061998-05-28 23:06:38 +00002944#endif
2945
Guido van Rossum7bf15641998-05-22 18:28:17 +00002946static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002947EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002948{
Guido van Rossum00d93061998-05-28 23:06:38 +00002949#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002951#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002952 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002953#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002954 PyOS_InputHook = EventHook;
2955 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002956#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002957}
2958
2959static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002960DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002961{
Guido van Rossum00d93061998-05-28 23:06:38 +00002962#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2964 PyOS_InputHook = NULL;
2965 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002966#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002967}
2968
Barry Warsawfa701a81997-01-16 00:15:11 +00002969
Martin v. Löwis1a214512008-06-11 05:26:20 +00002970static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 PyModuleDef_HEAD_INIT,
2972 "_tkinter",
2973 NULL,
2974 -1,
2975 moduleMethods,
2976 NULL,
2977 NULL,
2978 NULL,
2979 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002980};
2981
Mark Hammond62b1ab12002-07-23 06:31:15 +00002982PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002983PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002984{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002985 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002986
Guido van Rossum00d93061998-05-28 23:06:38 +00002987#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002988 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002989 if (tcl_lock == NULL)
2990 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002991#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002992
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 m = PyModule_Create(&_tkintermodule);
2994 if (m == NULL)
2995 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002996
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002997 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2998 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002999 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003000 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003001 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003002 Py_INCREF(o);
3003 if (PyModule_AddObject(m, "TclError", o)) {
3004 Py_DECREF(o);
3005 Py_DECREF(m);
3006 return NULL;
3007 }
3008 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003009
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003010 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3011 Py_DECREF(m);
3012 return NULL;
3013 }
3014 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3015 Py_DECREF(m);
3016 return NULL;
3017 }
3018 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3019 Py_DECREF(m);
3020 return NULL;
3021 }
3022 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3023 Py_DECREF(m);
3024 return NULL;
3025 }
3026 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3027 Py_DECREF(m);
3028 return NULL;
3029 }
3030 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3031 Py_DECREF(m);
3032 return NULL;
3033 }
3034 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3035 Py_DECREF(m);
3036 return NULL;
3037 }
3038 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3039 Py_DECREF(m);
3040 return NULL;
3041 }
3042 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3043 Py_DECREF(m);
3044 return NULL;
3045 }
3046 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3047 Py_DECREF(m);
3048 return NULL;
3049 }
3050 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3051 Py_DECREF(m);
3052 return NULL;
3053 }
3054
3055 o = PyType_FromSpec(&Tkapp_Type_spec);
3056 if (o == NULL) {
3057 Py_DECREF(m);
3058 return NULL;
3059 }
3060 if (PyModule_AddObject(m, "TkappType", o)) {
3061 Py_DECREF(o);
3062 Py_DECREF(m);
3063 return NULL;
3064 }
3065 Tkapp_Type = o;
3066
3067 o = PyType_FromSpec(&Tktt_Type_spec);
3068 if (o == NULL) {
3069 Py_DECREF(m);
3070 return NULL;
3071 }
3072 if (PyModule_AddObject(m, "TkttType", o)) {
3073 Py_DECREF(o);
3074 Py_DECREF(m);
3075 return NULL;
3076 }
3077 Tktt_Type = o;
3078
3079 o = PyType_FromSpec(&PyTclObject_Type_spec);
3080 if (o == NULL) {
3081 Py_DECREF(m);
3082 return NULL;
3083 }
3084 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3085 Py_DECREF(o);
3086 Py_DECREF(m);
3087 return NULL;
3088 }
3089 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003090
3091#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003092 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3093 * start waking up. Note that Tcl_FindExecutable will do this, this
3094 * code must be above it! The original warning from
3095 * tkMacOSXAppInit.c is copied below.
3096 *
3097 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3098 * Tcl interpreter for now. It probably should work to do this
3099 * in the other order, but for now it doesn't seem to.
3100 *
3101 */
3102 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003103#endif
3104
3105
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003106 /* This helps the dynamic loader; in Unicode aware Tcl versions
3107 it also helps Tcl find its encodings. */
3108 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3109 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003110 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003111 if (cexe)
3112 Tcl_FindExecutable(PyBytes_AsString(cexe));
3113 Py_XDECREF(cexe);
3114 Py_DECREF(uexe);
3115 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003117 if (PyErr_Occurred()) {
3118 Py_DECREF(m);
3119 return NULL;
3120 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003121
Guido van Rossum43ff8681998-07-14 18:02:13 +00003122#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003123 /* This was not a good idea; through <Destroy> bindings,
3124 Tcl_Finalize() may invoke Python code but at that point the
3125 interpreter and thread state have already been destroyed! */
3126 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003127#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003128 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003129}