blob: 394fc8d2fcdc5b1e4e62e5759b3df6b04adde6d6 [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 Storchaka2b00c492014-05-21 17:12:21 +0300460 else if (PyList_Check(arg)) {
461 int i, size;
462 PyObject *elem, *newelem, *result;
463
464 size = PyList_GET_SIZE(arg);
465 result = PyTuple_New(size);
466 if (!result)
467 return NULL;
468 /* Recursively invoke SplitObj for all list items. */
469 for(i = 0; i < size; i++) {
470 elem = PyList_GET_ITEM(arg, i);
471 newelem = SplitObj(elem);
472 if (!newelem) {
473 Py_XDECREF(result);
474 return NULL;
475 }
476 PyTuple_SetItem(result, i, newelem);
477 }
478 return result;
479 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300480 else if (PyUnicode_Check(arg)) {
481 int argc;
482 char **argv;
483 char *list = PyUnicode_AsUTF8(arg);
484
485 if (list == NULL ||
486 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
487 Py_INCREF(arg);
488 return arg;
489 }
490 Tcl_Free(FREECAST argv);
491 if (argc > 1)
492 return Split(list);
493 /* Fall through, returning arg. */
494 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495 else if (PyBytes_Check(arg)) {
496 int argc;
497 char **argv;
498 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
501 Py_INCREF(arg);
502 return arg;
503 }
504 Tcl_Free(FREECAST argv);
505 if (argc > 1)
506 return Split(PyBytes_AsString(arg));
507 /* Fall through, returning arg. */
508 }
509 Py_INCREF(arg);
510 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000511}
Barry Warsawfa701a81997-01-16 00:15:11 +0000512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513
Guido van Rossum18468821994-06-20 07:49:28 +0000514/**** Tkapp Object ****/
515
516#ifndef WITH_APPINIT
517int
Fred Drake509d79a2000-07-08 04:04:38 +0000518Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000519{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 if (Tcl_Init(interp) == TCL_ERROR) {
523 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
524 return TCL_ERROR;
525 }
Guilherme Polob681df42009-02-09 22:33:59 +0000526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 _tkinter_skip_tk_init = Tcl_GetVar(interp,
528 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
529 if (_tkinter_skip_tk_init != NULL &&
530 strcmp(_tkinter_skip_tk_init, "1") == 0) {
531 return TCL_OK;
532 }
Guilherme Polob681df42009-02-09 22:33:59 +0000533
534#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 if (tk_load_failed) {
536 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
537 return TCL_ERROR;
538 }
Guilherme Polob681df42009-02-09 22:33:59 +0000539#endif
540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000542#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000544#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
546 return TCL_ERROR;
547 }
Guilherme Polob681df42009-02-09 22:33:59 +0000548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000550}
551#endif /* !WITH_APPINIT */
552
Guido van Rossum18468821994-06-20 07:49:28 +0000553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554
Barry Warsawfa701a81997-01-16 00:15:11 +0000555
556/* Initialize the Tk application; see the `main' function in
557 * `tkMain.c'.
558 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000559
Thomas Wouters58d05102000-07-24 14:43:35 +0000560static void EnableEventHook(void); /* Forward */
561static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000562
Barry Warsawfa701a81997-01-16 00:15:11 +0000563static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000564Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000565 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 TkappObject *v;
568 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000569
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300570 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 if (v == NULL)
572 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200573 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 v->interp = Tcl_CreateInterp();
576 v->wantobjects = wantobjects;
577 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
578 TCL_GLOBAL_ONLY) != NULL;
579 v->thread_id = Tcl_GetCurrentThread();
580 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000581
582#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300584 PyErr_SetString(PyExc_RuntimeError,
585 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 Py_DECREF(v);
587 return 0;
588 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000589#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000590#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 if (v->threaded && tcl_lock) {
592 /* If Tcl is threaded, we don't need the lock. */
593 PyThread_free_lock(tcl_lock);
594 tcl_lock = NULL;
595 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000596#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 v->BooleanType = Tcl_GetObjType("boolean");
599 v->ByteArrayType = Tcl_GetObjType("bytearray");
600 v->DoubleType = Tcl_GetObjType("double");
601 v->IntType = Tcl_GetObjType("int");
602 v->ListType = Tcl_GetObjType("list");
603 v->ProcBodyType = Tcl_GetObjType("procbody");
604 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 /* Delete the 'exit' command, which can screw things up */
607 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (screenName != NULL)
610 Tcl_SetVar2(v->interp, "env", "DISPLAY",
611 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 if (interactive)
614 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
615 else
616 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000617
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 /* This is used to get the application class for Tk 4.1 and up */
619 argv0 = (char*)ckalloc(strlen(className) + 1);
620 if (!argv0) {
621 PyErr_NoMemory();
622 Py_DECREF(v);
623 return NULL;
624 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200627 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
628 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
630 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 if (! wantTk) {
633 Tcl_SetVar(v->interp,
634 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
635 }
Guilherme Polob681df42009-02-09 22:33:59 +0000636#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 else if (tk_load_failed) {
638 Tcl_SetVar(v->interp,
639 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
640 }
Guilherme Polob681df42009-02-09 22:33:59 +0000641#endif
David Aschere2b4b322004-02-18 05:59:53 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 /* some initial arguments need to be in argv */
644 if (sync || use) {
645 char *args;
646 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 if (sync)
649 len += sizeof "-sync";
650 if (use)
651 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 args = (char*)ckalloc(len);
654 if (!args) {
655 PyErr_NoMemory();
656 Py_DECREF(v);
657 return NULL;
658 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 args[0] = '\0';
661 if (sync)
662 strcat(args, "-sync");
663 if (use) {
664 if (sync)
665 strcat(args, " ");
666 strcat(args, "-use ");
667 strcat(args, use);
668 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
671 ckfree(args);
672 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 if (Tcl_AppInit(v->interp) != TCL_OK) {
675 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000676#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 if (wantTk) {
678 const char *_tkinter_tk_failed;
679 _tkinter_tk_failed = Tcl_GetVar(v->interp,
680 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 if ( _tkinter_tk_failed != NULL &&
683 strcmp(_tkinter_tk_failed, "1") == 0) {
684 tk_load_failed = 1;
685 }
686 }
Guilherme Polob681df42009-02-09 22:33:59 +0000687#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 Py_DECREF((PyObject *)v);
689 return (TkappObject *)result;
690 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000695}
696
Barry Warsawfa701a81997-01-16 00:15:11 +0000697
Benjamin Peterson5879d412009-03-30 14:51:56 +0000698#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699static void
700Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000702{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 Py_BEGIN_ALLOW_THREADS;
704 Tcl_MutexLock(mutex);
705 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
706 Tcl_ThreadAlert(self->thread_id);
707 Tcl_ConditionWait(cond, mutex, NULL);
708 Tcl_MutexUnlock(mutex);
709 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000710}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000711#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713
Guido van Rossum18468821994-06-20 07:49:28 +0000714/** Tcl Eval **/
715
Martin v. Löwisffad6332002-11-26 09:28:05 +0000716typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 PyObject_HEAD
718 Tcl_Obj *value;
719 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000720} PyTclObject;
721
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300722static PyObject *PyTclObject_Type;
723#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000724
725static PyObject *
726newPyTclObject(Tcl_Obj *arg)
727{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300729 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 if (self == NULL)
731 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200732 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 Tcl_IncrRefCount(arg);
734 self->value = arg;
735 self->string = NULL;
736 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000737}
738
739static void
740PyTclObject_dealloc(PyTclObject *self)
741{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200742 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 Tcl_DecrRefCount(self->value);
744 Py_XDECREF(self->string);
745 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200746 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000747}
748
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000749static char*
750PyTclObject_TclString(PyObject *self)
751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000753}
754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000756PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000757"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000758
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000759static PyObject *
760PyTclObject_string(PyTclObject *self, void *ignored)
761{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200763 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 if (!self->string)
765 return NULL;
766 }
767 Py_INCREF(self->string);
768 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000769}
770
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000771static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000772PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000773{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200774 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 Py_INCREF(self->string);
776 return self->string;
777 }
778 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200779 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000780}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000781
Martin v. Löwisffad6332002-11-26 09:28:05 +0000782static PyObject *
783PyTclObject_repr(PyTclObject *self)
784{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300785 PyObject *repr, *str = PyTclObject_str(self, NULL);
786 if (str == NULL)
787 return NULL;
788 repr = PyUnicode_FromFormat("<%s object: %R>",
789 self->value->typePtr->name, str);
790 Py_DECREF(str);
791 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000792}
793
Mark Dickinson211c6252009-02-01 10:28:51 +0000794#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
795
796static PyObject *
797PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000798{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000799 int result;
800 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 /* neither argument should be NULL, unless something's gone wrong */
803 if (self == NULL || other == NULL) {
804 PyErr_BadInternalCall();
805 return NULL;
806 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000808 /* both arguments should be instances of PyTclObject */
809 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
810 v = Py_NotImplemented;
811 goto finished;
812 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 if (self == other)
815 /* fast path when self and other are identical */
816 result = 0;
817 else
818 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
819 Tcl_GetString(((PyTclObject *)other)->value));
820 /* Convert return value to a Boolean */
821 switch (op) {
822 case Py_EQ:
823 v = TEST_COND(result == 0);
824 break;
825 case Py_NE:
826 v = TEST_COND(result != 0);
827 break;
828 case Py_LE:
829 v = TEST_COND(result <= 0);
830 break;
831 case Py_GE:
832 v = TEST_COND(result >= 0);
833 break;
834 case Py_LT:
835 v = TEST_COND(result < 0);
836 break;
837 case Py_GT:
838 v = TEST_COND(result > 0);
839 break;
840 default:
841 PyErr_BadArgument();
842 return NULL;
843 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000844 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000845 Py_INCREF(v);
846 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000847}
848
Martin v. Löwis39195712003-01-04 00:33:13 +0000849PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
850
Martin v. Löwisffad6332002-11-26 09:28:05 +0000851static PyObject*
852get_typename(PyTclObject* obj, void* ignored)
853{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200854 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855}
856
Martin v. Löwis39195712003-01-04 00:33:13 +0000857
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 {"typename", (getter)get_typename, NULL, get_typename__doc__},
860 {"string", (getter)PyTclObject_string, NULL,
861 PyTclObject_string__doc__},
862 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000863};
864
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300865static PyType_Slot PyTclObject_Type_slots[] = {
866 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
867 {Py_tp_repr, (reprfunc)PyTclObject_repr},
868 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200869 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300870 {Py_tp_richcompare, PyTclObject_richcompare},
871 {Py_tp_getset, PyTclObject_getsetlist},
872 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000873};
874
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300875static PyType_Spec PyTclObject_Type_spec = {
876 "_tkinter.Tcl_Obj",
877 sizeof(PyTclObject),
878 0,
879 Py_TPFLAGS_DEFAULT,
880 PyTclObject_Type_slots,
881};
882
883
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300884#if PY_SIZE_MAX > INT_MAX
885#define CHECK_STRING_LENGTH(s) do { \
886 if (s != NULL && strlen(s) >= INT_MAX) { \
887 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
888 return NULL; \
889 } } while(0)
890#else
891#define CHECK_STRING_LENGTH(s)
892#endif
893
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000894static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000895AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000896{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 Tcl_Obj *result;
898 long longVal;
899 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000900
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 if (PyBytes_Check(value))
902 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
903 PyBytes_GET_SIZE(value));
904 else if (PyBool_Check(value))
905 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
906 else if (PyLong_CheckExact(value) &&
907 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
908 !overflow)) {
909 /* If there is an overflow in the long conversion,
910 fall through to default object handling. */
911 return Tcl_NewLongObj(longVal);
912 }
913 else if (PyFloat_Check(value))
914 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300915 else if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300916 Tcl_Obj **argv;
917 Py_ssize_t size, i;
918
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300919 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300920 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300921 PyErr_SetString(PyExc_OverflowError,
922 PyTuple_Check(value) ? "tuple is too long" :
923 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300924 return NULL;
925 }
926 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 if(!argv)
928 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300929 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300930 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
931 result = Tcl_NewListObj(size, argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 ckfree(FREECAST argv);
933 return result;
934 }
935 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200936 void *inbuf;
937 Py_ssize_t size;
938 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000939 Tcl_UniChar *outbuf = NULL;
940 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200941 size_t allocsize;
942
943 if (PyUnicode_READY(value) == -1)
944 return NULL;
945
946 inbuf = PyUnicode_DATA(value);
947 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300948 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
949 PyErr_SetString(PyExc_OverflowError, "string is too long");
950 return NULL;
951 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200952 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200953 if (kind == sizeof(Tcl_UniChar))
954 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200955 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
956 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 /* Else overflow occurred, and we take the next exit */
958 if (!outbuf) {
959 PyErr_NoMemory();
960 return NULL;
961 }
962 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200963 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
964 /* We cannot test for sizeof(Tcl_UniChar) directly,
965 so we test for UTF-8 size instead. */
966#if TCL_UTF_MAX == 3
967 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000968 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200969 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100970 "character U+%x is above the range "
971 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100972 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000973 ckfree(FREECAST outbuf);
974 return NULL;
975 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300976#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200977 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000978 }
979 result = Tcl_NewUnicodeObj(outbuf, size);
980 ckfree(FREECAST outbuf);
981 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 }
983 else if(PyTclObject_Check(value)) {
984 Tcl_Obj *v = ((PyTclObject*)value)->value;
985 Tcl_IncrRefCount(v);
986 return v;
987 }
988 else {
989 PyObject *v = PyObject_Str(value);
990 if (!v)
991 return 0;
992 result = AsObj(v);
993 Py_DECREF(v);
994 return result;
995 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000996}
997
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998static PyObject*
999FromObj(PyObject* tkapp, Tcl_Obj *value)
1000{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 PyObject *result = NULL;
1002 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001005 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 if (value->typePtr == app->BooleanType) {
1009 result = value->internalRep.longValue ? Py_True : Py_False;
1010 Py_INCREF(result);
1011 return result;
1012 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001014 if (value->typePtr == app->ByteArrayType) {
1015 int size;
1016 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1017 return PyBytes_FromStringAndSize(data, size);
1018 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001020 if (value->typePtr == app->DoubleType) {
1021 return PyFloat_FromDouble(value->internalRep.doubleValue);
1022 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 if (value->typePtr == app->IntType) {
1025 return PyLong_FromLong(value->internalRep.longValue);
1026 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001028 if (value->typePtr == app->ListType) {
1029 int size;
1030 int i, status;
1031 PyObject *elem;
1032 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1035 if (status == TCL_ERROR)
1036 return Tkinter_Error(tkapp);
1037 result = PyTuple_New(size);
1038 if (!result)
1039 return NULL;
1040 for (i = 0; i < size; i++) {
1041 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1042 value, i, &tcl_elem);
1043 if (status == TCL_ERROR) {
1044 Py_DECREF(result);
1045 return Tkinter_Error(tkapp);
1046 }
1047 elem = FromObj(tkapp, tcl_elem);
1048 if (!elem) {
1049 Py_DECREF(result);
1050 return NULL;
1051 }
1052 PyTuple_SetItem(result, i, elem);
1053 }
1054 return result;
1055 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 if (value->typePtr == app->ProcBodyType) {
1058 /* fall through: return tcl object. */
1059 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001061 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001062 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001063 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001064 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001065 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001066
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001067 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001068}
1069
Benjamin Peterson5879d412009-03-30 14:51:56 +00001070#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001071/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072TCL_DECLARE_MUTEX(call_mutex)
1073
1074typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001075 Tcl_Event ev; /* Must be first */
1076 TkappObject *self;
1077 PyObject *args;
1078 int flags;
1079 PyObject **res;
1080 PyObject **exc_type, **exc_value, **exc_tb;
1081 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001082} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001083#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084
1085void
1086Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001087{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001088 int i;
1089 for (i = 0; i < objc; i++)
1090 Tcl_DecrRefCount(objv[i]);
1091 if (objv != objStore)
1092 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001093}
Guido van Rossum18468821994-06-20 07:49:28 +00001094
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001095/* Convert Python objects to Tcl objects. This must happen in the
1096 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001097
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001098static Tcl_Obj**
1099Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1100{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001101 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001102 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001103 if (args == NULL)
1104 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001105
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001106 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001107 objv[0] = AsObj(args);
1108 if (objv[0] == 0)
1109 goto finally;
1110 objc = 1;
1111 Tcl_IncrRefCount(objv[0]);
1112 }
1113 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001114 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001115
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001116 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001117 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001118 PyErr_SetString(PyExc_OverflowError,
1119 PyTuple_Check(args) ? "tuple is too long" :
1120 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001121 return NULL;
1122 }
1123 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001124 if (objv == NULL) {
1125 PyErr_NoMemory();
1126 objc = 0;
1127 goto finally;
1128 }
1129 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001130
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001132 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 if (v == Py_None) {
1134 objc = i;
1135 break;
1136 }
1137 objv[i] = AsObj(v);
1138 if (!objv[i]) {
1139 /* Reset objc, so it attempts to clear
1140 objects only up to i. */
1141 objc = i;
1142 goto finally;
1143 }
1144 Tcl_IncrRefCount(objv[i]);
1145 }
1146 }
1147 *pobjc = objc;
1148 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001149finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001150 Tkapp_CallDeallocArgs(objv, objStore, objc);
1151 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001152}
Guido van Rossum212643f1998-04-29 16:22:14 +00001153
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001155
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156static PyObject*
1157Tkapp_CallResult(TkappObject *self)
1158{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001160 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001161 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 /* Not sure whether the IncrRef is necessary, but something
1163 may overwrite the interpreter result while we are
1164 converting it. */
1165 Tcl_IncrRefCount(value);
1166 res = FromObj((PyObject*)self, value);
1167 Tcl_DecrRefCount(value);
1168 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001169 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001170 }
1171 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001172}
Guido van Rossum632de272000-03-29 00:19:50 +00001173
Benjamin Peterson5879d412009-03-30 14:51:56 +00001174#ifdef WITH_THREAD
1175
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001176/* Tkapp_CallProc is the event procedure that is executed in the context of
1177 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1178 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001179
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001180static int
1181Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001183 Tcl_Obj *objStore[ARGSZ];
1184 Tcl_Obj **objv;
1185 int objc;
1186 int i;
1187 ENTER_PYTHON
1188 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1189 if (!objv) {
1190 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1191 *(e->res) = NULL;
1192 }
1193 LEAVE_PYTHON
1194 if (!objv)
1195 goto done;
1196 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1197 ENTER_PYTHON
1198 if (i == TCL_ERROR) {
1199 *(e->res) = NULL;
1200 *(e->exc_type) = NULL;
1201 *(e->exc_tb) = NULL;
1202 *(e->exc_value) = PyObject_CallFunction(
1203 Tkinter_TclError, "s",
1204 Tcl_GetStringResult(e->self->interp));
1205 }
1206 else {
1207 *(e->res) = Tkapp_CallResult(e->self);
1208 }
1209 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001212done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 /* Wake up calling thread. */
1214 Tcl_MutexLock(&call_mutex);
1215 Tcl_ConditionNotify(e->done);
1216 Tcl_MutexUnlock(&call_mutex);
1217 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001218}
1219
Benjamin Peterson5879d412009-03-30 14:51:56 +00001220#endif
1221
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001222/* This is the main entry point for calling a Tcl command.
1223 It supports three cases, with regard to threading:
1224 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1225 the context of the calling thread.
1226 2. Tcl is threaded, caller of the command is in the interpreter thread:
1227 Execute the command in the calling thread. Since the Tcl lock will
1228 not be used, we can merge that with case 1.
1229 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1230 the interpreter thread. Allocation of Tcl objects needs to occur in the
1231 interpreter thread, so we ship the PyObject* args to the target thread,
1232 and perform processing there. */
1233
1234static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001235Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 Tcl_Obj *objStore[ARGSZ];
1238 Tcl_Obj **objv = NULL;
1239 int objc, i;
1240 PyObject *res = NULL;
1241 TkappObject *self = (TkappObject*)selfptr;
1242 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 /* If args is a single tuple, replace with contents of tuple */
1245 if (1 == PyTuple_Size(args)){
1246 PyObject* item = PyTuple_GetItem(args, 0);
1247 if (PyTuple_Check(item))
1248 args = item;
1249 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001250#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001251 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1252 /* We cannot call the command directly. Instead, we must
1253 marshal the parameters to the interpreter thread. */
1254 Tkapp_CallEvent *ev;
1255 Tcl_Condition cond = NULL;
1256 PyObject *exc_type, *exc_value, *exc_tb;
1257 if (!WaitForMainloop(self))
1258 return NULL;
1259 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1260 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1261 ev->self = self;
1262 ev->args = args;
1263 ev->res = &res;
1264 ev->exc_type = &exc_type;
1265 ev->exc_value = &exc_value;
1266 ev->exc_tb = &exc_tb;
1267 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 if (res == NULL) {
1272 if (exc_type)
1273 PyErr_Restore(exc_type, exc_value, exc_tb);
1274 else
1275 PyErr_SetObject(Tkinter_TclError, exc_value);
1276 }
1277 Tcl_ConditionFinalize(&cond);
1278 }
1279 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001280#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001281 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 objv = Tkapp_CallArgs(args, objStore, &objc);
1284 if (!objv)
1285 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 if (i == TCL_ERROR)
1294 Tkinter_Error(selfptr);
1295 else
1296 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001300 Tkapp_CallDeallocArgs(objv, objStore, objc);
1301 }
1302 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001303}
1304
1305
1306static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001307Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001308{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 char *script;
1310 PyObject *res = NULL;
1311 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 if (!PyArg_ParseTuple(args, "s:eval", &script))
1314 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001315
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001316 CHECK_STRING_LENGTH(script);
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_Eval(Tkapp_Interp(self), script);
1321 ENTER_OVERLAP
1322 if (err == TCL_ERROR)
1323 res = Tkinter_Error(self);
1324 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_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 char *fileName;
1334 PyObject *res = NULL;
1335 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1338 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001339
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001340 CHECK_STRING_LENGTH(fileName);
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_EvalFile(Tkapp_Interp(self), fileName);
1345 ENTER_OVERLAP
1346 if (err == TCL_ERROR)
1347 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 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_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 char *script;
1358 PyObject *res = NULL;
1359 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001360
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001361 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001363
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001364 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 ENTER_TCL
1368 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1369 ENTER_OVERLAP
1370 if (err == TCL_ERROR)
1371 res = Tkinter_Error(self);
1372 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001373 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 LEAVE_OVERLAP_TCL
1375 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001376}
1377
1378static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001379Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001380{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1384 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001385 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001386 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 ENTER_TCL
1389 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1390 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001391
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001392 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001393}
1394
Barry Warsawfa701a81997-01-16 00:15:11 +00001395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396
Guido van Rossum18468821994-06-20 07:49:28 +00001397/** Tcl Variable **/
1398
Benjamin Peterson5879d412009-03-30 14:51:56 +00001399typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1400
1401#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001402TCL_DECLARE_MUTEX(var_mutex)
1403
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001404typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 Tcl_Event ev; /* must be first */
1406 PyObject *self;
1407 PyObject *args;
1408 int flags;
1409 EventFunc func;
1410 PyObject **res;
1411 PyObject **exc_type;
1412 PyObject **exc_val;
1413 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001414} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001415#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001416
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001417static int
1418varname_converter(PyObject *in, void *_out)
1419{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001420 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 char **out = (char**)_out;
1422 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001423 if (PyBytes_Size(in) > INT_MAX) {
1424 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1425 return 0;
1426 }
1427 s = PyBytes_AsString(in);
1428 if (strlen(s) != PyBytes_Size(in)) {
1429 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1430 return 0;
1431 }
1432 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 return 1;
1434 }
1435 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001436 Py_ssize_t size;
1437 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001438 if (s == NULL) {
1439 return 0;
1440 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001441 if (size > INT_MAX) {
1442 PyErr_SetString(PyExc_OverflowError, "string is too long");
1443 return 0;
1444 }
1445 if (strlen(s) != size) {
1446 PyErr_SetString(PyExc_ValueError, "null character in string");
1447 return 0;
1448 }
1449 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001450 return 1;
1451 }
1452 if (PyTclObject_Check(in)) {
1453 *out = PyTclObject_TclString(in);
1454 return 1;
1455 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001456 PyErr_Format(PyExc_TypeError,
1457 "must be str, bytes or Tcl_Obj, not %.50s",
1458 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001460}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001461
Benjamin Peterson5879d412009-03-30 14:51:56 +00001462#ifdef WITH_THREAD
1463
Martin v. Löwis59683e82008-06-13 07:50:45 +00001464static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001465var_perform(VarEvent *ev)
1466{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1468 if (!*(ev->res)) {
1469 PyObject *exc, *val, *tb;
1470 PyErr_Fetch(&exc, &val, &tb);
1471 PyErr_NormalizeException(&exc, &val, &tb);
1472 *(ev->exc_type) = exc;
1473 *(ev->exc_val) = val;
1474 Py_DECREF(tb);
1475 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001476
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001477}
1478
1479static int
1480var_proc(VarEvent* ev, int flags)
1481{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001482 ENTER_PYTHON
1483 var_perform(ev);
1484 Tcl_MutexLock(&var_mutex);
1485 Tcl_ConditionNotify(ev->cond);
1486 Tcl_MutexUnlock(&var_mutex);
1487 LEAVE_PYTHON
1488 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001489}
1490
Benjamin Peterson5879d412009-03-30 14:51:56 +00001491#endif
1492
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001494var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001496#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 TkappObject *self = (TkappObject*)selfptr;
1498 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1499 TkappObject *self = (TkappObject*)selfptr;
1500 VarEvent *ev;
1501 PyObject *res, *exc_type, *exc_val;
1502 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 /* The current thread is not the interpreter thread. Marshal
1505 the call to the interpreter thread, then wait for
1506 completion. */
1507 if (!WaitForMainloop(self))
1508 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 ev->self = selfptr;
1513 ev->args = args;
1514 ev->flags = flags;
1515 ev->func = func;
1516 ev->res = &res;
1517 ev->exc_type = &exc_type;
1518 ev->exc_val = &exc_val;
1519 ev->cond = &cond;
1520 ev->ev.proc = (Tcl_EventProc*)var_proc;
1521 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1522 Tcl_ConditionFinalize(&cond);
1523 if (!res) {
1524 PyErr_SetObject(exc_type, exc_val);
1525 Py_DECREF(exc_type);
1526 Py_DECREF(exc_val);
1527 return NULL;
1528 }
1529 return res;
1530 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001531#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001532 /* Tcl is not threaded, or this is the interpreter thread. */
1533 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534}
1535
Guido van Rossum18468821994-06-20 07:49:28 +00001536static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001537SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001538{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 char *name1, *name2;
1540 PyObject *newValue;
1541 PyObject *res = NULL;
1542 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001543
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001544 switch (PyTuple_GET_SIZE(args)) {
1545 case 2:
1546 if (!PyArg_ParseTuple(args, "O&O:setvar",
1547 varname_converter, &name1, &newValue))
1548 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 /* XXX Acquire tcl lock??? */
1550 newval = AsObj(newValue);
1551 if (newval == NULL)
1552 return NULL;
1553 ENTER_TCL
1554 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1555 newval, flags);
1556 ENTER_OVERLAP
1557 if (!ok)
1558 Tkinter_Error(self);
1559 else {
1560 res = Py_None;
1561 Py_INCREF(res);
1562 }
1563 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001564 break;
1565 case 3:
1566 if (!PyArg_ParseTuple(args, "ssO:setvar",
1567 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001569 CHECK_STRING_LENGTH(name1);
1570 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001571 /* XXX must hold tcl lock already??? */
1572 newval = AsObj(newValue);
1573 ENTER_TCL
1574 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1575 ENTER_OVERLAP
1576 if (!ok)
1577 Tkinter_Error(self);
1578 else {
1579 res = Py_None;
1580 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001582 LEAVE_OVERLAP_TCL
1583 break;
1584 default:
1585 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1586 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001587 }
1588 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001589}
1590
1591static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001592Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001594 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001595}
1596
1597static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001598Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001599{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001601}
1602
Barry Warsawfa701a81997-01-16 00:15:11 +00001603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001604
Guido van Rossum18468821994-06-20 07:49:28 +00001605static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001606GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001607{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 char *name1, *name2=NULL;
1609 PyObject *res = NULL;
1610 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1613 varname_converter, &name1, &name2))
1614 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001615
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001616 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001617 ENTER_TCL
1618 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1619 ENTER_OVERLAP
1620 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001621 PyErr_SetString(Tkinter_TclError,
1622 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001623 } else {
1624 if (((TkappObject*)self)->wantobjects) {
1625 res = FromObj(self, tres);
1626 }
1627 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001628 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 }
1630 }
1631 LEAVE_OVERLAP_TCL
1632 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001633}
1634
1635static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001636Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001637{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001639}
1640
1641static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001642Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001643{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001645}
1646
Barry Warsawfa701a81997-01-16 00:15:11 +00001647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001648
Guido van Rossum18468821994-06-20 07:49:28 +00001649static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001650UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001651{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001652 char *name1, *name2=NULL;
1653 int code;
1654 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001656 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1657 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001658
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001659 CHECK_STRING_LENGTH(name1);
1660 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001661 ENTER_TCL
1662 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1663 ENTER_OVERLAP
1664 if (code == TCL_ERROR)
1665 res = Tkinter_Error(self);
1666 else {
1667 Py_INCREF(Py_None);
1668 res = Py_None;
1669 }
1670 LEAVE_OVERLAP_TCL
1671 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001672}
1673
1674static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001675Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001676{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001677 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001678}
1679
1680static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001681Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001682{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001683 return var_invoke(UnsetVar, self, args,
1684 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
Barry Warsawfa701a81997-01-16 00:15:11 +00001687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001688
Guido van Rossum18468821994-06-20 07:49:28 +00001689/** Tcl to Python **/
1690
1691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001692Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001693{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001694 char *s;
1695 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001697 if (PyTuple_Size(args) == 1) {
1698 PyObject* o = PyTuple_GetItem(args, 0);
1699 if (PyLong_Check(o)) {
1700 Py_INCREF(o);
1701 return o;
1702 }
1703 }
1704 if (!PyArg_ParseTuple(args, "s:getint", &s))
1705 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001706 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001707 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1708 return Tkinter_Error(self);
1709 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001710}
1711
1712static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001713Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001714{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715 char *s;
1716 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718 if (PyTuple_Size(args) == 1) {
1719 PyObject *o = PyTuple_GetItem(args, 0);
1720 if (PyFloat_Check(o)) {
1721 Py_INCREF(o);
1722 return o;
1723 }
1724 }
1725 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1726 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001727 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001728 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1729 return Tkinter_Error(self);
1730 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001731}
1732
1733static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001734Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 char *s;
1737 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 if (PyTuple_Size(args) == 1) {
1740 PyObject *o = PyTuple_GetItem(args, 0);
1741 if (PyLong_Check(o)) {
1742 Py_INCREF(o);
1743 return o;
1744 }
1745 }
1746 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1747 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001748 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001749 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1750 return Tkinter_Error(self);
1751 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001752}
1753
1754static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001755Tkapp_ExprString(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;
Guido van Rossum18468821994-06-20 07:49:28 +00001760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001761 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1762 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001763
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001764 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001765 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 ENTER_TCL
1768 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1769 ENTER_OVERLAP
1770 if (retval == TCL_ERROR)
1771 res = Tkinter_Error(self);
1772 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001773 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 LEAVE_OVERLAP_TCL
1775 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001776}
1777
1778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001781 char *s;
1782 PyObject *res = NULL;
1783 int retval;
1784 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001786 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1787 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001788
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001789 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001790 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792 ENTER_TCL
1793 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1794 ENTER_OVERLAP
1795 if (retval == TCL_ERROR)
1796 res = Tkinter_Error(self);
1797 else
1798 res = Py_BuildValue("l", v);
1799 LEAVE_OVERLAP_TCL
1800 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001801}
1802
1803static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001804Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 char *s;
1807 PyObject *res = NULL;
1808 double v;
1809 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001811 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1812 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001813 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001814 CHECK_TCL_APPARTMENT;
1815 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1816 ENTER_TCL
1817 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1818 ENTER_OVERLAP
1819 PyFPE_END_PROTECT(retval)
1820 if (retval == TCL_ERROR)
1821 res = Tkinter_Error(self);
1822 else
1823 res = Py_BuildValue("d", v);
1824 LEAVE_OVERLAP_TCL
1825 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001826}
1827
1828static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001829Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001830{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001831 char *s;
1832 PyObject *res = NULL;
1833 int retval;
1834 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001835
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001836 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1837 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001838 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001839 CHECK_TCL_APPARTMENT;
1840 ENTER_TCL
1841 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1842 ENTER_OVERLAP
1843 if (retval == TCL_ERROR)
1844 res = Tkinter_Error(self);
1845 else
1846 res = Py_BuildValue("i", v);
1847 LEAVE_OVERLAP_TCL
1848 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001849}
1850
Barry Warsawfa701a81997-01-16 00:15:11 +00001851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852
Guido van Rossum18468821994-06-20 07:49:28 +00001853static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001854Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001855{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001856 char *list;
1857 int argc;
1858 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001859 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001861
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001862 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1863 return NULL;
1864 if (PyTclObject_Check(arg)) {
1865 int objc;
1866 Tcl_Obj **objv;
1867 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1868 ((PyTclObject*)arg)->value,
1869 &objc, &objv) == TCL_ERROR) {
1870 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001872 if (!(v = PyTuple_New(objc)))
1873 return NULL;
1874 for (i = 0; i < objc; i++) {
1875 PyObject *s = FromObj(self, objv[i]);
1876 if (!s || PyTuple_SetItem(v, i, s)) {
1877 Py_DECREF(v);
1878 return NULL;
1879 }
1880 }
1881 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001883 if (PyTuple_Check(arg)) {
1884 Py_INCREF(arg);
1885 return arg;
1886 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001887 if (PyList_Check(arg)) {
1888 return PySequence_Tuple(arg);
1889 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001891 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1892 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001893
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001894 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 if (Tcl_SplitList(Tkapp_Interp(self), list,
1896 &argc, &argv) == TCL_ERROR) {
1897 PyMem_Free(list);
1898 return Tkinter_Error(self);
1899 }
Guido van Rossum18468821994-06-20 07:49:28 +00001900
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001901 if (!(v = PyTuple_New(argc)))
1902 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001903
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001904 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001905 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001906 if (!s || PyTuple_SetItem(v, i, s)) {
1907 Py_DECREF(v);
1908 v = NULL;
1909 goto finally;
1910 }
1911 }
Guido van Rossum18468821994-06-20 07:49:28 +00001912
Barry Warsawfa701a81997-01-16 00:15:11 +00001913 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 ckfree(FREECAST argv);
1915 PyMem_Free(list);
1916 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001917}
1918
1919static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001920Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001921{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001922 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001923 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001924
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001925 if (!PyArg_ParseTuple(args, "O:split", &arg))
1926 return NULL;
1927 if (PyTclObject_Check(arg)) {
1928 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1929 int objc;
1930 Tcl_Obj **objv;
1931 int i;
1932 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1933 &objc, &objv) == TCL_ERROR) {
1934 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001936 if (objc == 0)
1937 return PyUnicode_FromString("");
1938 if (objc == 1)
1939 return FromObj(self, objv[0]);
1940 if (!(v = PyTuple_New(objc)))
1941 return NULL;
1942 for (i = 0; i < objc; i++) {
1943 PyObject *s = FromObj(self, objv[i]);
1944 if (!s || PyTuple_SetItem(v, i, s)) {
1945 Py_DECREF(v);
1946 return NULL;
1947 }
1948 }
1949 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001950 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001951 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001952 return SplitObj(arg);
1953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1955 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001956 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001957 v = Split(list);
1958 PyMem_Free(list);
1959 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001960}
1961
Barry Warsawfa701a81997-01-16 00:15:11 +00001962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001963
Guido van Rossum18468821994-06-20 07:49:28 +00001964/** Tcl Command **/
1965
Guido van Rossum00d93061998-05-28 23:06:38 +00001966/* Client data struct */
1967typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 PyObject *self;
1969 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001970} PythonCmd_ClientData;
1971
1972static int
Fred Drake509d79a2000-07-08 04:04:38 +00001973PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001974{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 errorInCmd = 1;
1976 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1977 LEAVE_PYTHON
1978 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001979}
1980
Guido van Rossum18468821994-06-20 07:49:28 +00001981/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001982 * function or method.
1983 */
Guido van Rossum18468821994-06-20 07:49:28 +00001984static int
Fred Drake509d79a2000-07-08 04:04:38 +00001985PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001986{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001987 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001988 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 int i, rv;
1990 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001991
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001992 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 /* TBD: no error checking here since we know, via the
1995 * Tkapp_CreateCommand() that the client data is a two-tuple
1996 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 /* Create argument list (argv1, ..., argvN) */
2000 if (!(arg = PyTuple_New(argc - 1)))
2001 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002004 PyObject *s = unicodeFromTclString(argv[i + 1]);
2005 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002006 Py_DECREF(arg);
2007 return PythonCmd_Error(interp);
2008 }
2009 }
2010 res = PyEval_CallObject(func, arg);
2011 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002013 if (res == NULL)
2014 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 obj_res = AsObj(res);
2017 if (obj_res == NULL) {
2018 Py_DECREF(res);
2019 return PythonCmd_Error(interp);
2020 }
2021 else {
2022 Tcl_SetObjResult(interp, obj_res);
2023 rv = TCL_OK;
2024 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002026 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002028 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002030 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002031}
2032
2033static void
Fred Drake509d79a2000-07-08 04:04:38 +00002034PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002035{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002036 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002037
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002038 ENTER_PYTHON
2039 Py_XDECREF(data->self);
2040 Py_XDECREF(data->func);
2041 PyMem_DEL(data);
2042 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002043}
2044
Barry Warsawfa701a81997-01-16 00:15:11 +00002045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002047
Benjamin Peterson5879d412009-03-30 14:51:56 +00002048#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002049TCL_DECLARE_MUTEX(command_mutex)
2050
2051typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002052 Tcl_Event ev;
2053 Tcl_Interp* interp;
2054 char *name;
2055 int create;
2056 int *status;
2057 ClientData *data;
2058 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002059} CommandEvent;
2060
2061static int
2062Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002063{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002064 if (ev->create)
2065 *ev->status = Tcl_CreateCommand(
2066 ev->interp, ev->name, PythonCmd,
2067 ev->data, PythonCmdDelete) == NULL;
2068 else
2069 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2070 Tcl_MutexLock(&command_mutex);
2071 Tcl_ConditionNotify(ev->done);
2072 Tcl_MutexUnlock(&command_mutex);
2073 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002074}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002075#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002076
2077static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002078Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002079{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 TkappObject *self = (TkappObject*)selfptr;
2081 PythonCmd_ClientData *data;
2082 char *cmdName;
2083 PyObject *func;
2084 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002085
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002086 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2087 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002088 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 if (!PyCallable_Check(func)) {
2090 PyErr_SetString(PyExc_TypeError, "command not callable");
2091 return NULL;
2092 }
Guido van Rossum18468821994-06-20 07:49:28 +00002093
Martin v. Löwisa9656492003-03-30 08:44:58 +00002094#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002095 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2096 !WaitForMainloop(self))
2097 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002098#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 data = PyMem_NEW(PythonCmd_ClientData, 1);
2101 if (!data)
2102 return PyErr_NoMemory();
2103 Py_INCREF(self);
2104 Py_INCREF(func);
2105 data->self = selfptr;
2106 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002107#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2109 Tcl_Condition cond = NULL;
2110 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2111 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2112 ev->interp = self->interp;
2113 ev->create = 1;
2114 ev->name = cmdName;
2115 ev->data = (ClientData)data;
2116 ev->status = &err;
2117 ev->done = &cond;
2118 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2119 Tcl_ConditionFinalize(&cond);
2120 }
2121 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002122#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 {
2124 ENTER_TCL
2125 err = Tcl_CreateCommand(
2126 Tkapp_Interp(self), cmdName, PythonCmd,
2127 (ClientData)data, PythonCmdDelete) == NULL;
2128 LEAVE_TCL
2129 }
2130 if (err) {
2131 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2132 PyMem_DEL(data);
2133 return NULL;
2134 }
Guido van Rossum18468821994-06-20 07:49:28 +00002135
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002136 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002137}
2138
Barry Warsawfa701a81997-01-16 00:15:11 +00002139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140
Guido van Rossum18468821994-06-20 07:49:28 +00002141static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002142Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002143{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 TkappObject *self = (TkappObject*)selfptr;
2145 char *cmdName;
2146 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002148 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2149 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002150 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002151
2152#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002153 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2154 Tcl_Condition cond = NULL;
2155 CommandEvent *ev;
2156 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2157 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2158 ev->interp = self->interp;
2159 ev->create = 0;
2160 ev->name = cmdName;
2161 ev->status = &err;
2162 ev->done = &cond;
2163 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2164 &command_mutex);
2165 Tcl_ConditionFinalize(&cond);
2166 }
2167 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002168#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002169 {
2170 ENTER_TCL
2171 err = Tcl_DeleteCommand(self->interp, cmdName);
2172 LEAVE_TCL
2173 }
2174 if (err == -1) {
2175 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2176 return NULL;
2177 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002178 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002179}
2180
Barry Warsawfa701a81997-01-16 00:15:11 +00002181
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002182
Guido van Rossum00d93061998-05-28 23:06:38 +00002183#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002184/** File Handler **/
2185
Guido van Rossum00d93061998-05-28 23:06:38 +00002186typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 PyObject *func;
2188 PyObject *file;
2189 int id;
2190 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002191} FileHandler_ClientData;
2192
2193static FileHandler_ClientData *HeadFHCD;
2194
2195static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002196NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002197{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198 FileHandler_ClientData *p;
2199 p = PyMem_NEW(FileHandler_ClientData, 1);
2200 if (p != NULL) {
2201 Py_XINCREF(func);
2202 Py_XINCREF(file);
2203 p->func = func;
2204 p->file = file;
2205 p->id = id;
2206 p->next = HeadFHCD;
2207 HeadFHCD = p;
2208 }
2209 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002210}
2211
2212static void
Fred Drake509d79a2000-07-08 04:04:38 +00002213DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002214{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002215 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217 pp = &HeadFHCD;
2218 while ((p = *pp) != NULL) {
2219 if (p->id == id) {
2220 *pp = p->next;
2221 Py_XDECREF(p->func);
2222 Py_XDECREF(p->file);
2223 PyMem_DEL(p);
2224 }
2225 else
2226 pp = &p->next;
2227 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002228}
2229
Guido van Rossuma597dde1995-01-10 20:56:29 +00002230static void
Fred Drake509d79a2000-07-08 04:04:38 +00002231FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002232{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2234 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002236 ENTER_PYTHON
2237 func = data->func;
2238 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002239
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002240 arg = Py_BuildValue("(Oi)", file, (long) mask);
2241 res = PyEval_CallObject(func, arg);
2242 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 if (res == NULL) {
2245 errorInCmd = 1;
2246 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2247 }
2248 Py_XDECREF(res);
2249 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002250}
2251
Guido van Rossum18468821994-06-20 07:49:28 +00002252static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002253Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2254 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002256 FileHandler_ClientData *data;
2257 PyObject *file, *func;
2258 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2261 &file, &mask, &func))
2262 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002266 tfile = PyObject_AsFileDescriptor(file);
2267 if (tfile < 0)
2268 return NULL;
2269 if (!PyCallable_Check(func)) {
2270 PyErr_SetString(PyExc_TypeError, "bad argument list");
2271 return NULL;
2272 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002274 data = NewFHCD(func, file, tfile);
2275 if (data == NULL)
2276 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002278 /* Ought to check for null Tcl_File object... */
2279 ENTER_TCL
2280 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2281 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002282 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002283}
2284
2285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002286Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002288 PyObject *file;
2289 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2292 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002296 tfile = PyObject_AsFileDescriptor(file);
2297 if (tfile < 0)
2298 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002300 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 /* Ought to check for null Tcl_File object... */
2303 ENTER_TCL
2304 Tcl_DeleteFileHandler(tfile);
2305 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002306 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002307}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002308#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002309
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002311/**** Tktt Object (timer token) ****/
2312
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002313static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314
Guido van Rossum00d93061998-05-28 23:06:38 +00002315typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 PyObject_HEAD
2317 Tcl_TimerToken token;
2318 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002319} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320
2321static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002322Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 TkttObject *v = (TkttObject *)self;
2325 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2328 return NULL;
2329 if (v->token != NULL) {
2330 Tcl_DeleteTimerHandler(v->token);
2331 v->token = NULL;
2332 }
2333 if (func != NULL) {
2334 v->func = NULL;
2335 Py_DECREF(func);
2336 Py_DECREF(v); /* See Tktt_New() */
2337 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002338 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339}
2340
2341static PyMethodDef Tktt_methods[] =
2342{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2344 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345};
2346
2347static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002348Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002351
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002352 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353 if (v == NULL)
2354 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002355 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 Py_INCREF(func);
2358 v->token = NULL;
2359 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 /* Extra reference, deleted when called or when handler is deleted */
2362 Py_INCREF(v);
2363 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002364}
2365
2366static void
Fred Drake509d79a2000-07-08 04:04:38 +00002367Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 TkttObject *v = (TkttObject *)self;
2370 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002371 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002376 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377}
2378
Guido van Rossum597ac201998-05-12 14:36:19 +00002379static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002380Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002382 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002383 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2384 v,
2385 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386}
2387
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002388static PyType_Slot Tktt_Type_slots[] = {
2389 {Py_tp_dealloc, Tktt_Dealloc},
2390 {Py_tp_repr, Tktt_Repr},
2391 {Py_tp_methods, Tktt_methods},
2392 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393};
2394
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002395static PyType_Spec Tktt_Type_spec = {
2396 "tktimertoken",
2397 sizeof(TkttObject),
2398 0,
2399 Py_TPFLAGS_DEFAULT,
2400 Tktt_Type_slots,
2401};
Barry Warsawfa701a81997-01-16 00:15:11 +00002402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404/** Timer Handler **/
2405
2406static void
Fred Drake509d79a2000-07-08 04:04:38 +00002407TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002408{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 TkttObject *v = (TkttObject *)clientData;
2410 PyObject *func = v->func;
2411 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 if (func == NULL)
2414 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002416 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 res = PyEval_CallObject(func, NULL);
2421 Py_DECREF(func);
2422 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 if (res == NULL) {
2425 errorInCmd = 1;
2426 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2427 }
2428 else
2429 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002431 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002432}
2433
2434static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002435Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002436{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002437 int milliseconds;
2438 PyObject *func;
2439 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002441 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2442 &milliseconds, &func))
2443 return NULL;
2444 if (!PyCallable_Check(func)) {
2445 PyErr_SetString(PyExc_TypeError, "bad argument list");
2446 return NULL;
2447 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002449 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 v = Tktt_New(func);
2452 if (v) {
2453 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2454 (ClientData)v);
2455 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002457 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002458}
2459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460
Guido van Rossum18468821994-06-20 07:49:28 +00002461/** Event Loop **/
2462
Guido van Rossum18468821994-06-20 07:49:28 +00002463static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002464Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002465{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002466 int threshold = 0;
2467 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002468#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002470#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002472 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2473 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 CHECK_TCL_APPARTMENT;
2476 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 quitMainLoop = 0;
2479 while (Tk_GetNumMainWindows() > threshold &&
2480 !quitMainLoop &&
2481 !errorInCmd)
2482 {
2483 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002484
2485#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 if (self->threaded) {
2487 /* Allow other Python threads to run. */
2488 ENTER_TCL
2489 result = Tcl_DoOneEvent(0);
2490 LEAVE_TCL
2491 }
2492 else {
2493 Py_BEGIN_ALLOW_THREADS
2494 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2495 tcl_tstate = tstate;
2496 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2497 tcl_tstate = NULL;
2498 if(tcl_lock)PyThread_release_lock(tcl_lock);
2499 if (result == 0)
2500 Sleep(Tkinter_busywaitinterval);
2501 Py_END_ALLOW_THREADS
2502 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002503#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002505#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002506
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002507 if (PyErr_CheckSignals() != 0) {
2508 self->dispatching = 0;
2509 return NULL;
2510 }
2511 if (result < 0)
2512 break;
2513 }
2514 self->dispatching = 0;
2515 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002517 if (errorInCmd) {
2518 errorInCmd = 0;
2519 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2520 excInCmd = valInCmd = trbInCmd = NULL;
2521 return NULL;
2522 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002523 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002524}
2525
2526static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002527Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002528{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002529 int flags = 0;
2530 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2533 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002535 ENTER_TCL
2536 rv = Tcl_DoOneEvent(flags);
2537 LEAVE_TCL
2538 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002539}
2540
2541static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002542Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002543{
2544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002545 if (!PyArg_ParseTuple(args, ":quit"))
2546 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002549 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002550}
2551
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002552static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002553Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002554{
2555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556 if (!PyArg_ParseTuple(args, ":interpaddr"))
2557 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002558
Victor Stinnere1040e22013-09-05 00:22:24 +02002559 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002560}
2561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002563Tkapp_TkInit(PyObject *self, PyObject *args)
2564{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002565 Tcl_Interp *interp = Tkapp_Interp(self);
2566 const char * _tk_exists = NULL;
2567 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002568
Guilherme Polob681df42009-02-09 22:33:59 +00002569#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2571 * first call failed.
2572 * To avoid the deadlock, we just refuse the second call through
2573 * a static variable.
2574 */
2575 if (tk_load_failed) {
2576 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2577 return NULL;
2578 }
Guilherme Polob681df42009-02-09 22:33:59 +00002579#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 /* We want to guard against calling Tk_Init() multiple times */
2582 CHECK_TCL_APPARTMENT;
2583 ENTER_TCL
2584 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2585 ENTER_OVERLAP
2586 if (err == TCL_ERROR) {
2587 /* This sets an exception, but we cannot return right
2588 away because we need to exit the overlap first. */
2589 Tkinter_Error(self);
2590 } else {
2591 _tk_exists = Tkapp_Result(self);
2592 }
2593 LEAVE_OVERLAP_TCL
2594 if (err == TCL_ERROR) {
2595 return NULL;
2596 }
2597 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2598 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002599 PyErr_SetString(Tkinter_TclError,
2600 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002601#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002603#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 return NULL;
2605 }
2606 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002607 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002608}
Barry Warsawfa701a81997-01-16 00:15:11 +00002609
Martin v. Löwisffad6332002-11-26 09:28:05 +00002610static PyObject *
2611Tkapp_WantObjects(PyObject *self, PyObject *args)
2612{
2613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614 int wantobjects = -1;
2615 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2616 return NULL;
2617 if (wantobjects == -1)
2618 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2619 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002620
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002621 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002622}
2623
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002624static PyObject *
2625Tkapp_WillDispatch(PyObject *self, PyObject *args)
2626{
2627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002629
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002630 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002631}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633
Guido van Rossum18468821994-06-20 07:49:28 +00002634/**** Tkapp Method List ****/
2635
2636static PyMethodDef Tkapp_methods[] =
2637{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002638 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2639 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2640 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002641 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002642 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2643 {"record", Tkapp_Record, METH_VARARGS},
2644 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2645 {"setvar", Tkapp_SetVar, METH_VARARGS},
2646 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2647 {"getvar", Tkapp_GetVar, METH_VARARGS},
2648 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2649 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2650 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2651 {"getint", Tkapp_GetInt, METH_VARARGS},
2652 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2653 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2654 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2655 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2656 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2657 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2658 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2659 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002660 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2661 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002662#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2664 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002665#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2667 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2668 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2669 {"quit", Tkapp_Quit, METH_VARARGS},
2670 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2671 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2672 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002673};
2674
Barry Warsawfa701a81997-01-16 00:15:11 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676
Guido van Rossum18468821994-06-20 07:49:28 +00002677/**** Tkapp Type Methods ****/
2678
2679static void
Fred Drake509d79a2000-07-08 04:04:38 +00002680Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002681{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002682 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002683 /*CHECK_TCL_APPARTMENT;*/
2684 ENTER_TCL
2685 Tcl_DeleteInterp(Tkapp_Interp(self));
2686 LEAVE_TCL
2687 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002688 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002689 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002690}
2691
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002692static PyType_Slot Tkapp_Type_slots[] = {
2693 {Py_tp_dealloc, Tkapp_Dealloc},
2694 {Py_tp_methods, Tkapp_methods},
2695 {0, 0}
2696};
2697
2698
2699static PyType_Spec Tkapp_Type_spec = {
2700 "tkapp",
2701 sizeof(TkappObject),
2702 0,
2703 Py_TPFLAGS_DEFAULT,
2704 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002705};
2706
Barry Warsawfa701a81997-01-16 00:15:11 +00002707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002708
Guido van Rossum18468821994-06-20 07:49:28 +00002709/**** Tkinter Module ****/
2710
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002711typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002712 PyObject* tuple;
2713 int size; /* current size */
2714 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002715} FlattenContext;
2716
2717static int
2718_bump(FlattenContext* context, int size)
2719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 /* expand tuple to hold (at least) size new items.
2721 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002722
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 if (maxsize < context->size + size)
2726 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002728 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002729
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002730 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731}
2732
2733static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002734_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002736 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002740 if (depth > 1000) {
2741 PyErr_SetString(PyExc_ValueError,
2742 "nesting too deep in _flatten");
2743 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002744 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2745 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002746 /* preallocate (assume no nesting) */
2747 if (context->size + size > context->maxsize &&
2748 !_bump(context, size))
2749 return 0;
2750 /* copy items to output tuple */
2751 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002752 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002753 if (PyList_Check(o) || PyTuple_Check(o)) {
2754 if (!_flatten1(context, o, depth + 1))
2755 return 0;
2756 } else if (o != Py_None) {
2757 if (context->size + 1 > context->maxsize &&
2758 !_bump(context, 1))
2759 return 0;
2760 Py_INCREF(o);
2761 PyTuple_SET_ITEM(context->tuple,
2762 context->size++, o);
2763 }
2764 }
2765 } else {
2766 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2767 return 0;
2768 }
2769 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002770}
2771
2772static PyObject *
2773Tkinter_Flatten(PyObject* self, PyObject* args)
2774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002775 FlattenContext context;
2776 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002778 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2779 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002780
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002781 context.maxsize = PySequence_Size(item);
2782 if (context.maxsize < 0)
2783 return NULL;
2784 if (context.maxsize == 0)
2785 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 context.tuple = PyTuple_New(context.maxsize);
2788 if (!context.tuple)
2789 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 if (!_flatten1(&context, item,0))
2794 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 if (_PyTuple_Resize(&context.tuple, context.size))
2797 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002798
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002800}
2801
Guido van Rossum18468821994-06-20 07:49:28 +00002802static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002803Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002804{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 char *screenName = NULL;
2806 char *baseName = NULL; /* XXX this is not used anymore;
2807 try getting rid of it. */
2808 char *className = NULL;
2809 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03002810 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2812 int sync = 0; /* pass -sync to wish */
2813 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2818 &screenName, &baseName, &className,
2819 &interactive, &wantobjects, &wantTk,
2820 &sync, &use))
2821 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002822 CHECK_STRING_LENGTH(screenName);
2823 CHECK_STRING_LENGTH(baseName);
2824 CHECK_STRING_LENGTH(className);
2825 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002826
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002827 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002828 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002829 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002830}
2831
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002832static PyObject *
2833Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 int new_val;
2836 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2837 return NULL;
2838 if (new_val < 0) {
2839 PyErr_SetString(PyExc_ValueError,
2840 "busywaitinterval must be >= 0");
2841 return NULL;
2842 }
2843 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002844 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002845}
2846
2847static char setbusywaitinterval_doc[] =
2848"setbusywaitinterval(n) -> None\n\
2849\n\
2850Set the busy-wait interval in milliseconds between successive\n\
2851calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2852It should be set to a divisor of the maximum time between\n\
2853frames in an animation.";
2854
2855static PyObject *
2856Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2857{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002858 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002859}
2860
2861static char getbusywaitinterval_doc[] =
2862"getbusywaitinterval() -> int\n\
2863\n\
2864Return the current busy-wait interval between successive\n\
2865calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2866
Guido van Rossum18468821994-06-20 07:49:28 +00002867static PyMethodDef moduleMethods[] =
2868{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2870 {"create", Tkinter_Create, METH_VARARGS},
2871 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2872 setbusywaitinterval_doc},
2873 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2874 METH_NOARGS, getbusywaitinterval_doc},
2875 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002876};
2877
Guido van Rossum7bf15641998-05-22 18:28:17 +00002878#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002879
2880static int stdin_ready = 0;
2881
Guido van Rossumad4db171998-06-13 13:56:28 +00002882#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002883static void
Fred Drake509d79a2000-07-08 04:04:38 +00002884MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002885{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002886 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002887}
Guido van Rossumad4db171998-06-13 13:56:28 +00002888#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002889
Martin v. Löwisa9656492003-03-30 08:44:58 +00002890#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002891static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002892#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002893
Guido van Rossum18468821994-06-20 07:49:28 +00002894static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002895EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002896{
Guido van Rossumad4db171998-06-13 13:56:28 +00002897#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002899#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002900#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002902#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 stdin_ready = 0;
2904 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002905#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906 tfile = fileno(stdin);
2907 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002908#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002909 while (!errorInCmd && !stdin_ready) {
2910 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002911#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002912 if (_kbhit()) {
2913 stdin_ready = 1;
2914 break;
2915 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002916#endif
2917#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918 Py_BEGIN_ALLOW_THREADS
2919 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2920 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002922 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002924 tcl_tstate = NULL;
2925 if(tcl_lock)PyThread_release_lock(tcl_lock);
2926 if (result == 0)
2927 Sleep(Tkinter_busywaitinterval);
2928 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002929#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002930 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002931#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933 if (result < 0)
2934 break;
2935 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002936#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002938#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 if (errorInCmd) {
2940 errorInCmd = 0;
2941 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2942 excInCmd = valInCmd = trbInCmd = NULL;
2943 PyErr_Print();
2944 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002945#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002947#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002949}
Guido van Rossum18468821994-06-20 07:49:28 +00002950
Guido van Rossum00d93061998-05-28 23:06:38 +00002951#endif
2952
Guido van Rossum7bf15641998-05-22 18:28:17 +00002953static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002954EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002955{
Guido van Rossum00d93061998-05-28 23:06:38 +00002956#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002957 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002958#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002960#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 PyOS_InputHook = EventHook;
2962 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002963#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002964}
2965
2966static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002967DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002968{
Guido van Rossum00d93061998-05-28 23:06:38 +00002969#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002970 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2971 PyOS_InputHook = NULL;
2972 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002973#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002974}
2975
Barry Warsawfa701a81997-01-16 00:15:11 +00002976
Martin v. Löwis1a214512008-06-11 05:26:20 +00002977static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002978 PyModuleDef_HEAD_INIT,
2979 "_tkinter",
2980 NULL,
2981 -1,
2982 moduleMethods,
2983 NULL,
2984 NULL,
2985 NULL,
2986 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002987};
2988
Mark Hammond62b1ab12002-07-23 06:31:15 +00002989PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002990PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002991{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002992 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002993
Guido van Rossum00d93061998-05-28 23:06:38 +00002994#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002996 if (tcl_lock == NULL)
2997 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002998#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002999
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003000 m = PyModule_Create(&_tkintermodule);
3001 if (m == NULL)
3002 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003003
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003004 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3005 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003006 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003007 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003008 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003009 Py_INCREF(o);
3010 if (PyModule_AddObject(m, "TclError", o)) {
3011 Py_DECREF(o);
3012 Py_DECREF(m);
3013 return NULL;
3014 }
3015 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003016
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003017 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3018 Py_DECREF(m);
3019 return NULL;
3020 }
3021 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3022 Py_DECREF(m);
3023 return NULL;
3024 }
3025 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3026 Py_DECREF(m);
3027 return NULL;
3028 }
3029 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3030 Py_DECREF(m);
3031 return NULL;
3032 }
3033 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3034 Py_DECREF(m);
3035 return NULL;
3036 }
3037 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3038 Py_DECREF(m);
3039 return NULL;
3040 }
3041 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3042 Py_DECREF(m);
3043 return NULL;
3044 }
3045 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3046 Py_DECREF(m);
3047 return NULL;
3048 }
3049 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3050 Py_DECREF(m);
3051 return NULL;
3052 }
3053 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3054 Py_DECREF(m);
3055 return NULL;
3056 }
3057 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3058 Py_DECREF(m);
3059 return NULL;
3060 }
3061
3062 o = PyType_FromSpec(&Tkapp_Type_spec);
3063 if (o == NULL) {
3064 Py_DECREF(m);
3065 return NULL;
3066 }
3067 if (PyModule_AddObject(m, "TkappType", o)) {
3068 Py_DECREF(o);
3069 Py_DECREF(m);
3070 return NULL;
3071 }
3072 Tkapp_Type = o;
3073
3074 o = PyType_FromSpec(&Tktt_Type_spec);
3075 if (o == NULL) {
3076 Py_DECREF(m);
3077 return NULL;
3078 }
3079 if (PyModule_AddObject(m, "TkttType", o)) {
3080 Py_DECREF(o);
3081 Py_DECREF(m);
3082 return NULL;
3083 }
3084 Tktt_Type = o;
3085
3086 o = PyType_FromSpec(&PyTclObject_Type_spec);
3087 if (o == NULL) {
3088 Py_DECREF(m);
3089 return NULL;
3090 }
3091 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3092 Py_DECREF(o);
3093 Py_DECREF(m);
3094 return NULL;
3095 }
3096 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003097
3098#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003099 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3100 * start waking up. Note that Tcl_FindExecutable will do this, this
3101 * code must be above it! The original warning from
3102 * tkMacOSXAppInit.c is copied below.
3103 *
3104 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3105 * Tcl interpreter for now. It probably should work to do this
3106 * in the other order, but for now it doesn't seem to.
3107 *
3108 */
3109 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003110#endif
3111
3112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003113 /* This helps the dynamic loader; in Unicode aware Tcl versions
3114 it also helps Tcl find its encodings. */
3115 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3116 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003117 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 if (cexe)
3119 Tcl_FindExecutable(PyBytes_AsString(cexe));
3120 Py_XDECREF(cexe);
3121 Py_DECREF(uexe);
3122 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 if (PyErr_Occurred()) {
3125 Py_DECREF(m);
3126 return NULL;
3127 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003128
Guido van Rossum43ff8681998-07-14 18:02:13 +00003129#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 /* This was not a good idea; through <Destroy> bindings,
3131 Tcl_Finalize() may invoke Python code but at that point the
3132 interpreter and thread state have already been destroyed! */
3133 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003134#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003136}