blob: 07175944ec052c1d14d1c83872a0c27fc0ee9c31 [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
Serhiy Storchaka6716d602014-07-30 19:19:21 +030012 Only Tcl/Tk 8.4 and later are supported. Older versions are not
13 supported. Use Python 3.4 or older if you cannot upgrade your
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000014 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öwisb5bfb9f2002-12-12 17:07:58 +000039/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
40 it always; if Tcl is not threaded, the thread functions in
41 Tcl are empty. */
42#define TCL_THREADS
43
Jack Jansencb852442001-12-09 23:15:56 +000044#ifdef TK_FRAMEWORK
45#include <Tcl/tcl.h>
46#include <Tk/tk.h>
47#else
Guido van Rossum18468821994-06-20 07:49:28 +000048#include <tcl.h>
49#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000050#endif
Guido van Rossum18468821994-06-20 07:49:28 +000051
Guilherme Polo2d87e422009-04-10 22:19:09 +000052#include "tkinter.h"
53
Serhiy Storchaka6716d602014-07-30 19:19:21 +030054#if TK_VERSION_HEX < 0x08040002
55#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000056#endif
57
Jack Janseneddc1442003-11-20 01:44:59 +000058#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000059#define HAVE_CREATEFILEHANDLER
60#endif
61
Guido van Rossum00d93061998-05-28 23:06:38 +000062#ifdef HAVE_CREATEFILEHANDLER
63
Neal Norwitzd948a432006-01-08 01:08:55 +000064/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
65 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
66#ifndef TCL_UNIX_FD
67# ifdef TCL_WIN_SOCKET
68# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
69# else
70# define TCL_UNIX_FD 1
71# endif
72#endif
73
Guido van Rossum00d93061998-05-28 23:06:38 +000074/* Tcl_CreateFileHandler() changed several times; these macros deal with the
75 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
76 Unix, only because Jack added it back); when available on Windows, it only
77 applies to sockets. */
78
Guido van Rossum7bf15641998-05-22 18:28:17 +000079#ifdef MS_WINDOWS
80#define FHANDLETYPE TCL_WIN_SOCKET
81#else
82#define FHANDLETYPE TCL_UNIX_FD
83#endif
84
Guido van Rossum00d93061998-05-28 23:06:38 +000085/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
86 which uses this to handle Tcl events while the user is typing commands. */
87
88#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000089#define WAIT_FOR_STDIN
90#endif
91
Guido van Rossum00d93061998-05-28 23:06:38 +000092#endif /* HAVE_CREATEFILEHANDLER */
93
Guido van Rossumad4db171998-06-13 13:56:28 +000094#ifdef MS_WINDOWS
95#include <conio.h>
96#define WAIT_FOR_STDIN
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef WITH_THREAD
100
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000101/* The threading situation is complicated. Tcl is not thread-safe, except
102 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000103
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300104 So we need to use a lock around all uses of Tcl. Previously, the
105 Python interpreter lock was used for this. However, this causes
106 problems when other Python threads need to run while Tcl is blocked
107 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000108
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300109 To solve this problem, a separate lock for Tcl is introduced.
110 Holding it is incompatible with holding Python's interpreter lock.
111 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000112
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300113 ENTER_TCL and LEAVE_TCL are brackets, just like
114 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
115 used whenever a call into Tcl is made that could call an event
116 handler, or otherwise affect the state of a Tcl interpreter. These
117 assume that the surrounding code has the Python interpreter lock;
118 inside the brackets, the Python interpreter lock has been released
119 and the lock for Tcl has been acquired.
120
121 Sometimes, it is necessary to have both the Python lock and the Tcl
122 lock. (For example, when transferring data from the Tcl
123 interpreter result to a Python string object.) This can be done by
124 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
125 reacquires the Python lock (and restores the thread state) but
126 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
127 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000128
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000129 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300130 handlers when the handler needs to use Python. Such event handlers
131 are entered while the lock for Tcl is held; the event handler
132 presumably needs to use Python. ENTER_PYTHON releases the lock for
133 Tcl and acquires the Python interpreter lock, restoring the
134 appropriate thread state, and LEAVE_PYTHON releases the Python
135 interpreter lock and re-acquires the lock for Tcl. It is okay for
136 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
137 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000138
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300139 These locks expand to several statements and brackets; they should
140 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000141
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300142 If Tcl is threaded, this approach won't work anymore. The Tcl
143 interpreter is only valid in the thread that created it, and all Tk
144 activity must happen in this thread, also. That means that the
145 mainloop must be invoked in the thread that created the
146 interpreter. Invoking commands from other threads is possible;
147 _tkinter will queue an event for the interpreter thread, which will
148 then execute the command and pass back the result. If the main
149 thread is not in the mainloop, and invoking commands causes an
150 exception; if the main loop is running but not processing events,
151 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300153 In addition, for a threaded Tcl, a single global tcl_tstate won't
154 be sufficient anymore, since multiple Tcl interpreters may
155 simultaneously dispatch in different threads. So we use the Tcl TLS
156 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000157
Guido van Rossum00d93061998-05-28 23:06:38 +0000158*/
159
Guido van Rossum65d5b571998-12-21 19:32:43 +0000160static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000161
162#ifdef TCL_THREADS
163static Tcl_ThreadDataKey state_key;
164typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300165#define tcl_tstate \
166 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000167#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000168static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000169#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
173 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000174
175#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300176 tcl_tstate = NULL; \
177 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000178
Guido van Rossum62320c91998-06-15 04:36:09 +0000179#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000181
182#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000184
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000185#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300187 if(tcl_lock) \
188 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000189
190#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 { PyThreadState *tstate = PyEval_SaveThread(); \
192 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000193
194#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 if (((TkappObject *)self)->threaded && \
196 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300197 PyErr_SetString(PyExc_RuntimeError, \
198 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 return 0; \
200 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000201
202#else
203
204#define ENTER_TCL
205#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP
207#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000208#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000209#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000210#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000211
212#endif
213
Guido van Rossum97867b21996-08-08 19:09:53 +0000214#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000215#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000216#endif
217
Guido van Rossum18468821994-06-20 07:49:28 +0000218/**** Tkapp Object Declaration ****/
219
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300220static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000221
Guido van Rossum00d93061998-05-28 23:06:38 +0000222typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 PyObject_HEAD
224 Tcl_Interp *interp;
225 int wantobjects;
226 int threaded; /* True if tcl_platform[threaded] */
227 Tcl_ThreadId thread_id;
228 int dispatching;
229 /* We cannot include tclInt.h, as this is internal.
230 So we cache interesting types here. */
Zachary Ware037605b2014-08-05 11:54:34 -0500231 const Tcl_ObjType *BooleanType;
232 const Tcl_ObjType *ByteArrayType;
233 const Tcl_ObjType *DoubleType;
234 const Tcl_ObjType *IntType;
235 const Tcl_ObjType *ListType;
236 const Tcl_ObjType *ProcBodyType;
237 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000238} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000239
Guido van Rossum18468821994-06-20 07:49:28 +0000240#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000241#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000242
Guido van Rossum35d43371997-08-02 00:09:09 +0000243#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000244(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000245
Barry Warsawfa701a81997-01-16 00:15:11 +0000246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247
Guido van Rossum18468821994-06-20 07:49:28 +0000248/**** Error Handling ****/
249
250static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000251static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000252static int errorInCmd = 0;
253static PyObject *excInCmd;
254static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000255static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guilherme Polob681df42009-02-09 22:33:59 +0000257#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000258static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000259#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000263Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000264{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
266 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000267}
268
Barry Warsawfa701a81997-01-16 00:15:11 +0000269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270
Guido van Rossum18468821994-06-20 07:49:28 +0000271/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000272
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000273static int Tkinter_busywaitinterval = 20;
274
Guido van Rossum00d93061998-05-28 23:06:38 +0000275#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000276#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000277
Guido van Rossum00d93061998-05-28 23:06:38 +0000278/* Millisecond sleep() for Unix platforms. */
279
280static void
Fred Drake509d79a2000-07-08 04:04:38 +0000281Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000282{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283 /* XXX Too bad if you don't have select(). */
284 struct timeval t;
285 t.tv_sec = milli/1000;
286 t.tv_usec = (milli%1000) * 1000;
287 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000288}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000289#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000290
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000291/* Wait up to 1s for the mainloop to come up. */
292
293static int
294WaitForMainloop(TkappObject* self)
295{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 int i;
297 for (i = 0; i < 10; i++) {
298 if (self->dispatching)
299 return 1;
300 Py_BEGIN_ALLOW_THREADS
301 Sleep(100);
302 Py_END_ALLOW_THREADS
303 }
304 if (self->dispatching)
305 return 1;
306 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
307 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000308}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000309#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312
Guido van Rossum18468821994-06-20 07:49:28 +0000313#define ARGSZ 64
314
Barry Warsawfa701a81997-01-16 00:15:11 +0000315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316
Guido van Rossum18468821994-06-20 07:49:28 +0000317static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200318unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
319{
320 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
321 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
322 /* Tcl encodes null character as \xc0\x80 */
323 if (memchr(s, '\xc0', size)) {
324 char *buf, *q;
325 const char *e = s + size;
326 PyErr_Clear();
327 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300328 if (buf == NULL) {
329 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200330 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300331 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200332 while (s != e) {
333 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
334 *q++ = '\0';
335 s += 2;
336 }
337 else
338 *q++ = *s++;
339 }
340 s = buf;
341 size = q - s;
342 r = PyUnicode_DecodeUTF8(s, size, NULL);
343 PyMem_Free(buf);
344 }
345 }
346 return r;
347}
348
349static PyObject *
350unicodeFromTclString(const char *s)
351{
352 return unicodeFromTclStringAndSize(s, strlen(s));
353}
354
355static PyObject *
356unicodeFromTclObj(Tcl_Obj *value)
357{
358 int len;
359 char *s = Tcl_GetStringFromObj(value, &len);
360 return unicodeFromTclStringAndSize(s, len);
361}
362
363
364static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300365Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000366{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000367 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300368 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300372 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 }
Guido van Rossum18468821994-06-20 07:49:28 +0000374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000375 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
376 /* Not a list.
377 * Could be a quoted string containing funnies, e.g. {"}.
378 * Return the string itself.
379 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200380 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 }
Guido van Rossum18468821994-06-20 07:49:28 +0000382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 if (argc == 0)
384 v = PyUnicode_FromString("");
385 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200386 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 else if ((v = PyTuple_New(argc)) != NULL) {
388 int i;
389 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 for (i = 0; i < argc; i++) {
392 if ((w = Split(argv[i])) == NULL) {
393 Py_DECREF(v);
394 v = NULL;
395 break;
396 }
397 PyTuple_SetItem(v, i, w);
398 }
399 }
400 Tcl_Free(FREECAST argv);
401 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000402}
403
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300404/* In some cases, Tcl will still return strings that are supposed to
405 be lists. SplitObj walks through a nested tuple, finding string
406 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000407
Martin v. Löwis59683e82008-06-13 07:50:45 +0000408static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000409SplitObj(PyObject *arg)
410{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 if (PyTuple_Check(arg)) {
412 int i, size;
413 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 size = PyTuple_Size(arg);
416 result = NULL;
417 /* Recursively invoke SplitObj for all tuple items.
418 If this does not return a new object, no action is
419 needed. */
420 for(i = 0; i < size; i++) {
421 elem = PyTuple_GetItem(arg, i);
422 newelem = SplitObj(elem);
423 if (!newelem) {
424 Py_XDECREF(result);
425 return NULL;
426 }
427 if (!result) {
428 int k;
429 if (newelem == elem) {
430 Py_DECREF(newelem);
431 continue;
432 }
433 result = PyTuple_New(size);
434 if (!result)
435 return NULL;
436 for(k = 0; k < i; k++) {
437 elem = PyTuple_GetItem(arg, k);
438 Py_INCREF(elem);
439 PyTuple_SetItem(result, k, elem);
440 }
441 }
442 PyTuple_SetItem(result, i, newelem);
443 }
444 if (result)
445 return result;
446 /* Fall through, returning arg. */
447 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300448 else if (PyList_Check(arg)) {
449 int i, size;
450 PyObject *elem, *newelem, *result;
451
452 size = PyList_GET_SIZE(arg);
453 result = PyTuple_New(size);
454 if (!result)
455 return NULL;
456 /* Recursively invoke SplitObj for all list items. */
457 for(i = 0; i < size; i++) {
458 elem = PyList_GET_ITEM(arg, i);
459 newelem = SplitObj(elem);
460 if (!newelem) {
461 Py_XDECREF(result);
462 return NULL;
463 }
464 PyTuple_SetItem(result, i, newelem);
465 }
466 return result;
467 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300468 else if (PyUnicode_Check(arg)) {
469 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300470 const char **argv;
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300471 char *list = PyUnicode_AsUTF8(arg);
472
473 if (list == NULL ||
474 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
475 Py_INCREF(arg);
476 return arg;
477 }
478 Tcl_Free(FREECAST argv);
479 if (argc > 1)
480 return Split(list);
481 /* Fall through, returning arg. */
482 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 else if (PyBytes_Check(arg)) {
484 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300485 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
489 Py_INCREF(arg);
490 return arg;
491 }
492 Tcl_Free(FREECAST argv);
493 if (argc > 1)
494 return Split(PyBytes_AsString(arg));
495 /* Fall through, returning arg. */
496 }
497 Py_INCREF(arg);
498 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000499}
Barry Warsawfa701a81997-01-16 00:15:11 +0000500
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000501
Guido van Rossum18468821994-06-20 07:49:28 +0000502/**** Tkapp Object ****/
503
504#ifndef WITH_APPINIT
505int
Fred Drake509d79a2000-07-08 04:04:38 +0000506Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000507{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 if (Tcl_Init(interp) == TCL_ERROR) {
511 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
512 return TCL_ERROR;
513 }
Guilherme Polob681df42009-02-09 22:33:59 +0000514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 _tkinter_skip_tk_init = Tcl_GetVar(interp,
516 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
517 if (_tkinter_skip_tk_init != NULL &&
518 strcmp(_tkinter_skip_tk_init, "1") == 0) {
519 return TCL_OK;
520 }
Guilherme Polob681df42009-02-09 22:33:59 +0000521
522#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 if (tk_load_failed) {
524 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
525 return TCL_ERROR;
526 }
Guilherme Polob681df42009-02-09 22:33:59 +0000527#endif
528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000530#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000532#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
534 return TCL_ERROR;
535 }
Guilherme Polob681df42009-02-09 22:33:59 +0000536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000538}
539#endif /* !WITH_APPINIT */
540
Guido van Rossum18468821994-06-20 07:49:28 +0000541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542
Barry Warsawfa701a81997-01-16 00:15:11 +0000543
544/* Initialize the Tk application; see the `main' function in
545 * `tkMain.c'.
546 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000547
Thomas Wouters58d05102000-07-24 14:43:35 +0000548static void EnableEventHook(void); /* Forward */
549static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000550
Barry Warsawfa701a81997-01-16 00:15:11 +0000551static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300552Tkapp_New(const char *screenName, const char *className,
553 int interactive, int wantobjects, int wantTk, int sync,
554 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000555{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 TkappObject *v;
557 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000558
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300559 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 if (v == NULL)
561 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200562 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 v->interp = Tcl_CreateInterp();
565 v->wantobjects = wantobjects;
566 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
567 TCL_GLOBAL_ONLY) != NULL;
568 v->thread_id = Tcl_GetCurrentThread();
569 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000570
571#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300573 PyErr_SetString(PyExc_RuntimeError,
574 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 Py_DECREF(v);
576 return 0;
577 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000578#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000579#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 if (v->threaded && tcl_lock) {
581 /* If Tcl is threaded, we don't need the lock. */
582 PyThread_free_lock(tcl_lock);
583 tcl_lock = NULL;
584 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000585#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 v->BooleanType = Tcl_GetObjType("boolean");
588 v->ByteArrayType = Tcl_GetObjType("bytearray");
589 v->DoubleType = Tcl_GetObjType("double");
590 v->IntType = Tcl_GetObjType("int");
591 v->ListType = Tcl_GetObjType("list");
592 v->ProcBodyType = Tcl_GetObjType("procbody");
593 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 /* Delete the 'exit' command, which can screw things up */
596 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 if (screenName != NULL)
599 Tcl_SetVar2(v->interp, "env", "DISPLAY",
600 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 if (interactive)
603 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
604 else
605 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 /* This is used to get the application class for Tk 4.1 and up */
608 argv0 = (char*)ckalloc(strlen(className) + 1);
609 if (!argv0) {
610 PyErr_NoMemory();
611 Py_DECREF(v);
612 return NULL;
613 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200616 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
617 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
619 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000620
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 if (! wantTk) {
622 Tcl_SetVar(v->interp,
623 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
624 }
Guilherme Polob681df42009-02-09 22:33:59 +0000625#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 else if (tk_load_failed) {
627 Tcl_SetVar(v->interp,
628 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
629 }
Guilherme Polob681df42009-02-09 22:33:59 +0000630#endif
David Aschere2b4b322004-02-18 05:59:53 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 /* some initial arguments need to be in argv */
633 if (sync || use) {
634 char *args;
635 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 if (sync)
638 len += sizeof "-sync";
639 if (use)
640 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 args = (char*)ckalloc(len);
643 if (!args) {
644 PyErr_NoMemory();
645 Py_DECREF(v);
646 return NULL;
647 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 args[0] = '\0';
650 if (sync)
651 strcat(args, "-sync");
652 if (use) {
653 if (sync)
654 strcat(args, " ");
655 strcat(args, "-use ");
656 strcat(args, use);
657 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
660 ckfree(args);
661 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 if (Tcl_AppInit(v->interp) != TCL_OK) {
664 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000665#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 if (wantTk) {
667 const char *_tkinter_tk_failed;
668 _tkinter_tk_failed = Tcl_GetVar(v->interp,
669 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 if ( _tkinter_tk_failed != NULL &&
672 strcmp(_tkinter_tk_failed, "1") == 0) {
673 tk_load_failed = 1;
674 }
675 }
Guilherme Polob681df42009-02-09 22:33:59 +0000676#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 Py_DECREF((PyObject *)v);
678 return (TkappObject *)result;
679 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000684}
685
Barry Warsawfa701a81997-01-16 00:15:11 +0000686
Benjamin Peterson5879d412009-03-30 14:51:56 +0000687#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000688static void
689Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000691{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 Py_BEGIN_ALLOW_THREADS;
693 Tcl_MutexLock(mutex);
694 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
695 Tcl_ThreadAlert(self->thread_id);
696 Tcl_ConditionWait(cond, mutex, NULL);
697 Tcl_MutexUnlock(mutex);
698 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000700#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702
Guido van Rossum18468821994-06-20 07:49:28 +0000703/** Tcl Eval **/
704
Martin v. Löwisffad6332002-11-26 09:28:05 +0000705typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 PyObject_HEAD
707 Tcl_Obj *value;
708 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000709} PyTclObject;
710
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300711static PyObject *PyTclObject_Type;
712#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000713
714static PyObject *
715newPyTclObject(Tcl_Obj *arg)
716{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300718 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 if (self == NULL)
720 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200721 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 Tcl_IncrRefCount(arg);
723 self->value = arg;
724 self->string = NULL;
725 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000726}
727
728static void
729PyTclObject_dealloc(PyTclObject *self)
730{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200731 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 Tcl_DecrRefCount(self->value);
733 Py_XDECREF(self->string);
734 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200735 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000736}
737
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000738static char*
739PyTclObject_TclString(PyObject *self)
740{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000742}
743
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000744/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000745PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000746"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000747
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000748static PyObject *
749PyTclObject_string(PyTclObject *self, void *ignored)
750{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200752 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753 if (!self->string)
754 return NULL;
755 }
756 Py_INCREF(self->string);
757 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000758}
759
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000760static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000761PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000762{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200763 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 Py_INCREF(self->string);
765 return self->string;
766 }
767 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200768 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000769}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000770
Martin v. Löwisffad6332002-11-26 09:28:05 +0000771static PyObject *
772PyTclObject_repr(PyTclObject *self)
773{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300774 PyObject *repr, *str = PyTclObject_str(self, NULL);
775 if (str == NULL)
776 return NULL;
777 repr = PyUnicode_FromFormat("<%s object: %R>",
778 self->value->typePtr->name, str);
779 Py_DECREF(str);
780 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000781}
782
Mark Dickinson211c6252009-02-01 10:28:51 +0000783#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
784
785static PyObject *
786PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000787{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000788 int result;
789 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 /* neither argument should be NULL, unless something's gone wrong */
792 if (self == NULL || other == NULL) {
793 PyErr_BadInternalCall();
794 return NULL;
795 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 /* both arguments should be instances of PyTclObject */
798 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
799 v = Py_NotImplemented;
800 goto finished;
801 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 if (self == other)
804 /* fast path when self and other are identical */
805 result = 0;
806 else
807 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
808 Tcl_GetString(((PyTclObject *)other)->value));
809 /* Convert return value to a Boolean */
810 switch (op) {
811 case Py_EQ:
812 v = TEST_COND(result == 0);
813 break;
814 case Py_NE:
815 v = TEST_COND(result != 0);
816 break;
817 case Py_LE:
818 v = TEST_COND(result <= 0);
819 break;
820 case Py_GE:
821 v = TEST_COND(result >= 0);
822 break;
823 case Py_LT:
824 v = TEST_COND(result < 0);
825 break;
826 case Py_GT:
827 v = TEST_COND(result > 0);
828 break;
829 default:
830 PyErr_BadArgument();
831 return NULL;
832 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000833 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000834 Py_INCREF(v);
835 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000836}
837
Martin v. Löwis39195712003-01-04 00:33:13 +0000838PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
839
Martin v. Löwisffad6332002-11-26 09:28:05 +0000840static PyObject*
841get_typename(PyTclObject* obj, void* ignored)
842{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200843 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000844}
845
Martin v. Löwis39195712003-01-04 00:33:13 +0000846
Martin v. Löwisffad6332002-11-26 09:28:05 +0000847static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 {"typename", (getter)get_typename, NULL, get_typename__doc__},
849 {"string", (getter)PyTclObject_string, NULL,
850 PyTclObject_string__doc__},
851 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000852};
853
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300854static PyType_Slot PyTclObject_Type_slots[] = {
855 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
856 {Py_tp_repr, (reprfunc)PyTclObject_repr},
857 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200858 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300859 {Py_tp_richcompare, PyTclObject_richcompare},
860 {Py_tp_getset, PyTclObject_getsetlist},
861 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862};
863
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300864static PyType_Spec PyTclObject_Type_spec = {
865 "_tkinter.Tcl_Obj",
866 sizeof(PyTclObject),
867 0,
868 Py_TPFLAGS_DEFAULT,
869 PyTclObject_Type_slots,
870};
871
872
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300873#if PY_SIZE_MAX > INT_MAX
874#define CHECK_STRING_LENGTH(s) do { \
875 if (s != NULL && strlen(s) >= INT_MAX) { \
876 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
877 return NULL; \
878 } } while(0)
879#else
880#define CHECK_STRING_LENGTH(s)
881#endif
882
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000883static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000884AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000885{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000886 Tcl_Obj *result;
887 long longVal;
888 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000890 if (PyBytes_Check(value))
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300891 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
892 PyBytes_GET_SIZE(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000893 else if (PyBool_Check(value))
894 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
895 else if (PyLong_CheckExact(value) &&
896 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
897 !overflow)) {
898 /* If there is an overflow in the long conversion,
899 fall through to default object handling. */
900 return Tcl_NewLongObj(longVal);
901 }
902 else if (PyFloat_Check(value))
903 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300904 else if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300905 Tcl_Obj **argv;
906 Py_ssize_t size, i;
907
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300908 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300909 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300910 PyErr_SetString(PyExc_OverflowError,
911 PyTuple_Check(value) ? "tuple is too long" :
912 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300913 return NULL;
914 }
915 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 if(!argv)
917 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300918 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300919 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
920 result = Tcl_NewListObj(size, argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000921 ckfree(FREECAST argv);
922 return result;
923 }
924 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200925 void *inbuf;
926 Py_ssize_t size;
927 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000928 Tcl_UniChar *outbuf = NULL;
929 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200930 size_t allocsize;
931
932 if (PyUnicode_READY(value) == -1)
933 return NULL;
934
935 inbuf = PyUnicode_DATA(value);
936 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300937 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
938 PyErr_SetString(PyExc_OverflowError, "string is too long");
939 return NULL;
940 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200941 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200942 if (kind == sizeof(Tcl_UniChar))
943 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200944 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
945 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 /* Else overflow occurred, and we take the next exit */
947 if (!outbuf) {
948 PyErr_NoMemory();
949 return NULL;
950 }
951 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200952 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
953 /* We cannot test for sizeof(Tcl_UniChar) directly,
954 so we test for UTF-8 size instead. */
955#if TCL_UTF_MAX == 3
956 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200958 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100959 "character U+%x is above the range "
960 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100961 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 ckfree(FREECAST outbuf);
963 return NULL;
964 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300965#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200966 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000967 }
968 result = Tcl_NewUnicodeObj(outbuf, size);
969 ckfree(FREECAST outbuf);
970 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000971 }
972 else if(PyTclObject_Check(value)) {
973 Tcl_Obj *v = ((PyTclObject*)value)->value;
974 Tcl_IncrRefCount(v);
975 return v;
976 }
977 else {
978 PyObject *v = PyObject_Str(value);
979 if (!v)
980 return 0;
981 result = AsObj(v);
982 Py_DECREF(v);
983 return result;
984 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000985}
986
Martin v. Löwisffad6332002-11-26 09:28:05 +0000987static PyObject*
988FromObj(PyObject* tkapp, Tcl_Obj *value)
989{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000990 PyObject *result = NULL;
991 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000992
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000993 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200994 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000995 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 if (value->typePtr == app->BooleanType) {
998 result = value->internalRep.longValue ? Py_True : Py_False;
999 Py_INCREF(result);
1000 return result;
1001 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001003 if (value->typePtr == app->ByteArrayType) {
1004 int size;
1005 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1006 return PyBytes_FromStringAndSize(data, size);
1007 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 if (value->typePtr == app->DoubleType) {
1010 return PyFloat_FromDouble(value->internalRep.doubleValue);
1011 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 if (value->typePtr == app->IntType) {
1014 return PyLong_FromLong(value->internalRep.longValue);
1015 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001017 if (value->typePtr == app->ListType) {
1018 int size;
1019 int i, status;
1020 PyObject *elem;
1021 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001023 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1024 if (status == TCL_ERROR)
1025 return Tkinter_Error(tkapp);
1026 result = PyTuple_New(size);
1027 if (!result)
1028 return NULL;
1029 for (i = 0; i < size; i++) {
1030 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1031 value, i, &tcl_elem);
1032 if (status == TCL_ERROR) {
1033 Py_DECREF(result);
1034 return Tkinter_Error(tkapp);
1035 }
1036 elem = FromObj(tkapp, tcl_elem);
1037 if (!elem) {
1038 Py_DECREF(result);
1039 return NULL;
1040 }
1041 PyTuple_SetItem(result, i, elem);
1042 }
1043 return result;
1044 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001046 if (value->typePtr == app->ProcBodyType) {
1047 /* fall through: return tcl object. */
1048 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001049
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001050 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001051 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001052 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001053 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001057}
1058
Benjamin Peterson5879d412009-03-30 14:51:56 +00001059#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001060/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001061TCL_DECLARE_MUTEX(call_mutex)
1062
1063typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 Tcl_Event ev; /* Must be first */
1065 TkappObject *self;
1066 PyObject *args;
1067 int flags;
1068 PyObject **res;
1069 PyObject **exc_type, **exc_value, **exc_tb;
1070 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001071} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001072#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073
1074void
1075Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001076{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 int i;
1078 for (i = 0; i < objc; i++)
1079 Tcl_DecrRefCount(objv[i]);
1080 if (objv != objStore)
1081 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001082}
Guido van Rossum18468821994-06-20 07:49:28 +00001083
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084/* Convert Python objects to Tcl objects. This must happen in the
1085 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001086
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001087static Tcl_Obj**
1088Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1089{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001090 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001091 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092 if (args == NULL)
1093 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001094
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001095 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 objv[0] = AsObj(args);
1097 if (objv[0] == 0)
1098 goto finally;
1099 objc = 1;
1100 Tcl_IncrRefCount(objv[0]);
1101 }
1102 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001103 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001106 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001107 PyErr_SetString(PyExc_OverflowError,
1108 PyTuple_Check(args) ? "tuple is too long" :
1109 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001110 return NULL;
1111 }
1112 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001113 if (objv == NULL) {
1114 PyErr_NoMemory();
1115 objc = 0;
1116 goto finally;
1117 }
1118 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001119
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001120 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001121 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001122 if (v == Py_None) {
1123 objc = i;
1124 break;
1125 }
1126 objv[i] = AsObj(v);
1127 if (!objv[i]) {
1128 /* Reset objc, so it attempts to clear
1129 objects only up to i. */
1130 objc = i;
1131 goto finally;
1132 }
1133 Tcl_IncrRefCount(objv[i]);
1134 }
1135 }
1136 *pobjc = objc;
1137 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001138finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 Tkapp_CallDeallocArgs(objv, objStore, objc);
1140 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001141}
Guido van Rossum212643f1998-04-29 16:22:14 +00001142
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001143/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001144
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145static PyObject*
1146Tkapp_CallResult(TkappObject *self)
1147{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001149 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001150 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 /* Not sure whether the IncrRef is necessary, but something
1152 may overwrite the interpreter result while we are
1153 converting it. */
1154 Tcl_IncrRefCount(value);
1155 res = FromObj((PyObject*)self, value);
1156 Tcl_DecrRefCount(value);
1157 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001158 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 }
1160 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001161}
Guido van Rossum632de272000-03-29 00:19:50 +00001162
Benjamin Peterson5879d412009-03-30 14:51:56 +00001163#ifdef WITH_THREAD
1164
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165/* Tkapp_CallProc is the event procedure that is executed in the context of
1166 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1167 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001168
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001169static int
1170Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1171{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001172 Tcl_Obj *objStore[ARGSZ];
1173 Tcl_Obj **objv;
1174 int objc;
1175 int i;
1176 ENTER_PYTHON
1177 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1178 if (!objv) {
1179 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1180 *(e->res) = NULL;
1181 }
1182 LEAVE_PYTHON
1183 if (!objv)
1184 goto done;
1185 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1186 ENTER_PYTHON
1187 if (i == TCL_ERROR) {
1188 *(e->res) = NULL;
1189 *(e->exc_type) = NULL;
1190 *(e->exc_tb) = NULL;
1191 *(e->exc_value) = PyObject_CallFunction(
1192 Tkinter_TclError, "s",
1193 Tcl_GetStringResult(e->self->interp));
1194 }
1195 else {
1196 *(e->res) = Tkapp_CallResult(e->self);
1197 }
1198 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001200 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001201done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001202 /* Wake up calling thread. */
1203 Tcl_MutexLock(&call_mutex);
1204 Tcl_ConditionNotify(e->done);
1205 Tcl_MutexUnlock(&call_mutex);
1206 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001207}
1208
Benjamin Peterson5879d412009-03-30 14:51:56 +00001209#endif
1210
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211/* This is the main entry point for calling a Tcl command.
1212 It supports three cases, with regard to threading:
1213 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1214 the context of the calling thread.
1215 2. Tcl is threaded, caller of the command is in the interpreter thread:
1216 Execute the command in the calling thread. Since the Tcl lock will
1217 not be used, we can merge that with case 1.
1218 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1219 the interpreter thread. Allocation of Tcl objects needs to occur in the
1220 interpreter thread, so we ship the PyObject* args to the target thread,
1221 and perform processing there. */
1222
1223static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001224Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 Tcl_Obj *objStore[ARGSZ];
1227 Tcl_Obj **objv = NULL;
1228 int objc, i;
1229 PyObject *res = NULL;
1230 TkappObject *self = (TkappObject*)selfptr;
1231 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 /* If args is a single tuple, replace with contents of tuple */
1234 if (1 == PyTuple_Size(args)){
1235 PyObject* item = PyTuple_GetItem(args, 0);
1236 if (PyTuple_Check(item))
1237 args = item;
1238 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001239#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001240 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1241 /* We cannot call the command directly. Instead, we must
1242 marshal the parameters to the interpreter thread. */
1243 Tkapp_CallEvent *ev;
1244 Tcl_Condition cond = NULL;
1245 PyObject *exc_type, *exc_value, *exc_tb;
1246 if (!WaitForMainloop(self))
1247 return NULL;
1248 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1249 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1250 ev->self = self;
1251 ev->args = args;
1252 ev->res = &res;
1253 ev->exc_type = &exc_type;
1254 ev->exc_value = &exc_value;
1255 ev->exc_tb = &exc_tb;
1256 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001258 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 if (res == NULL) {
1261 if (exc_type)
1262 PyErr_Restore(exc_type, exc_value, exc_tb);
1263 else
1264 PyErr_SetObject(Tkinter_TclError, exc_value);
1265 }
1266 Tcl_ConditionFinalize(&cond);
1267 }
1268 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001269#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 objv = Tkapp_CallArgs(args, objStore, &objc);
1273 if (!objv)
1274 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 if (i == TCL_ERROR)
1283 Tkinter_Error(selfptr);
1284 else
1285 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 Tkapp_CallDeallocArgs(objv, objStore, objc);
1290 }
1291 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001292}
1293
1294
1295static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001296Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 char *script;
1299 PyObject *res = NULL;
1300 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 if (!PyArg_ParseTuple(args, "s:eval", &script))
1303 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001304
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001305 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 ENTER_TCL
1309 err = Tcl_Eval(Tkapp_Interp(self), script);
1310 ENTER_OVERLAP
1311 if (err == TCL_ERROR)
1312 res = Tkinter_Error(self);
1313 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001314 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 LEAVE_OVERLAP_TCL
1316 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001317}
1318
1319static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001320Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001321{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 char *fileName;
1323 PyObject *res = NULL;
1324 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1327 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001328
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001329 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001330 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001332 ENTER_TCL
1333 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1334 ENTER_OVERLAP
1335 if (err == TCL_ERROR)
1336 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001338 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 LEAVE_OVERLAP_TCL
1340 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001341}
1342
1343static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001344Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001345{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 char *script;
1347 PyObject *res = NULL;
1348 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001349
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001350 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001352
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001353 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001354 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001356 ENTER_TCL
1357 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1358 ENTER_OVERLAP
1359 if (err == TCL_ERROR)
1360 res = Tkinter_Error(self);
1361 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001362 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 LEAVE_OVERLAP_TCL
1364 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001365}
1366
1367static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001368Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1373 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001374 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 ENTER_TCL
1378 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1379 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001380
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001381 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001382}
1383
Barry Warsawfa701a81997-01-16 00:15:11 +00001384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385
Guido van Rossum18468821994-06-20 07:49:28 +00001386/** Tcl Variable **/
1387
Benjamin Peterson5879d412009-03-30 14:51:56 +00001388typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1389
1390#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001391TCL_DECLARE_MUTEX(var_mutex)
1392
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001393typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001394 Tcl_Event ev; /* must be first */
1395 PyObject *self;
1396 PyObject *args;
1397 int flags;
1398 EventFunc func;
1399 PyObject **res;
1400 PyObject **exc_type;
1401 PyObject **exc_val;
1402 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001403} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001404#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001406static int
1407varname_converter(PyObject *in, void *_out)
1408{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001409 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 char **out = (char**)_out;
1411 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001412 if (PyBytes_Size(in) > INT_MAX) {
1413 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1414 return 0;
1415 }
1416 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001417 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001418 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1419 return 0;
1420 }
1421 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001422 return 1;
1423 }
1424 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001425 Py_ssize_t size;
1426 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001427 if (s == NULL) {
1428 return 0;
1429 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001430 if (size > INT_MAX) {
1431 PyErr_SetString(PyExc_OverflowError, "string is too long");
1432 return 0;
1433 }
Victor Stinner706768c2014-08-16 01:03:39 +02001434 if (strlen(s) != (size_t)size) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001435 PyErr_SetString(PyExc_ValueError, "null character in string");
1436 return 0;
1437 }
1438 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 return 1;
1440 }
1441 if (PyTclObject_Check(in)) {
1442 *out = PyTclObject_TclString(in);
1443 return 1;
1444 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001445 PyErr_Format(PyExc_TypeError,
1446 "must be str, bytes or Tcl_Obj, not %.50s",
1447 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001449}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001450
Benjamin Peterson5879d412009-03-30 14:51:56 +00001451#ifdef WITH_THREAD
1452
Martin v. Löwis59683e82008-06-13 07:50:45 +00001453static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454var_perform(VarEvent *ev)
1455{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001456 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1457 if (!*(ev->res)) {
1458 PyObject *exc, *val, *tb;
1459 PyErr_Fetch(&exc, &val, &tb);
1460 PyErr_NormalizeException(&exc, &val, &tb);
1461 *(ev->exc_type) = exc;
1462 *(ev->exc_val) = val;
1463 Py_DECREF(tb);
1464 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001465
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001466}
1467
1468static int
1469var_proc(VarEvent* ev, int flags)
1470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 ENTER_PYTHON
1472 var_perform(ev);
1473 Tcl_MutexLock(&var_mutex);
1474 Tcl_ConditionNotify(ev->cond);
1475 Tcl_MutexUnlock(&var_mutex);
1476 LEAVE_PYTHON
1477 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001478}
1479
Benjamin Peterson5879d412009-03-30 14:51:56 +00001480#endif
1481
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001483var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001485#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 TkappObject *self = (TkappObject*)selfptr;
1487 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1488 TkappObject *self = (TkappObject*)selfptr;
1489 VarEvent *ev;
1490 PyObject *res, *exc_type, *exc_val;
1491 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001492
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001493 /* The current thread is not the interpreter thread. Marshal
1494 the call to the interpreter thread, then wait for
1495 completion. */
1496 if (!WaitForMainloop(self))
1497 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001498
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001499 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001500
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001501 ev->self = selfptr;
1502 ev->args = args;
1503 ev->flags = flags;
1504 ev->func = func;
1505 ev->res = &res;
1506 ev->exc_type = &exc_type;
1507 ev->exc_val = &exc_val;
1508 ev->cond = &cond;
1509 ev->ev.proc = (Tcl_EventProc*)var_proc;
1510 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1511 Tcl_ConditionFinalize(&cond);
1512 if (!res) {
1513 PyErr_SetObject(exc_type, exc_val);
1514 Py_DECREF(exc_type);
1515 Py_DECREF(exc_val);
1516 return NULL;
1517 }
1518 return res;
1519 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001520#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001521 /* Tcl is not threaded, or this is the interpreter thread. */
1522 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001523}
1524
Guido van Rossum18468821994-06-20 07:49:28 +00001525static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001526SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001527{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001528 char *name1, *name2;
1529 PyObject *newValue;
1530 PyObject *res = NULL;
1531 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001532
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001533 switch (PyTuple_GET_SIZE(args)) {
1534 case 2:
1535 if (!PyArg_ParseTuple(args, "O&O:setvar",
1536 varname_converter, &name1, &newValue))
1537 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 /* XXX Acquire tcl lock??? */
1539 newval = AsObj(newValue);
1540 if (newval == NULL)
1541 return NULL;
1542 ENTER_TCL
1543 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1544 newval, flags);
1545 ENTER_OVERLAP
1546 if (!ok)
1547 Tkinter_Error(self);
1548 else {
1549 res = Py_None;
1550 Py_INCREF(res);
1551 }
1552 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001553 break;
1554 case 3:
1555 if (!PyArg_ParseTuple(args, "ssO:setvar",
1556 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001558 CHECK_STRING_LENGTH(name1);
1559 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001560 /* XXX must hold tcl lock already??? */
1561 newval = AsObj(newValue);
1562 ENTER_TCL
1563 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1564 ENTER_OVERLAP
1565 if (!ok)
1566 Tkinter_Error(self);
1567 else {
1568 res = Py_None;
1569 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001571 LEAVE_OVERLAP_TCL
1572 break;
1573 default:
1574 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1575 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 }
1577 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001578}
1579
1580static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001581Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001582{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001584}
1585
1586static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001587Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001588{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001589 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001590}
1591
Barry Warsawfa701a81997-01-16 00:15:11 +00001592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593
Guido van Rossum18468821994-06-20 07:49:28 +00001594static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001595GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 char *name1, *name2=NULL;
1598 PyObject *res = NULL;
1599 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1602 varname_converter, &name1, &name2))
1603 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001604
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001605 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 ENTER_TCL
1607 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1608 ENTER_OVERLAP
1609 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001610 PyErr_SetString(Tkinter_TclError,
1611 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 } else {
1613 if (((TkappObject*)self)->wantobjects) {
1614 res = FromObj(self, tres);
1615 }
1616 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001617 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001618 }
1619 }
1620 LEAVE_OVERLAP_TCL
1621 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001622}
1623
1624static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001625Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001626{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001627 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001628}
1629
1630static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001631Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001632{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001634}
1635
Barry Warsawfa701a81997-01-16 00:15:11 +00001636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637
Guido van Rossum18468821994-06-20 07:49:28 +00001638static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001639UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001640{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 char *name1, *name2=NULL;
1642 int code;
1643 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1646 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001647
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001648 CHECK_STRING_LENGTH(name1);
1649 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001650 ENTER_TCL
1651 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1652 ENTER_OVERLAP
1653 if (code == TCL_ERROR)
1654 res = Tkinter_Error(self);
1655 else {
1656 Py_INCREF(Py_None);
1657 res = Py_None;
1658 }
1659 LEAVE_OVERLAP_TCL
1660 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001661}
1662
1663static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001664Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001665{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001667}
1668
1669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001671{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001672 return var_invoke(UnsetVar, self, args,
1673 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001674}
1675
Barry Warsawfa701a81997-01-16 00:15:11 +00001676
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001677
Guido van Rossum18468821994-06-20 07:49:28 +00001678/** Tcl to Python **/
1679
1680static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001681Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001682{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 char *s;
1684 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001686 if (PyTuple_Size(args) == 1) {
1687 PyObject* o = PyTuple_GetItem(args, 0);
1688 if (PyLong_Check(o)) {
1689 Py_INCREF(o);
1690 return o;
1691 }
1692 }
1693 if (!PyArg_ParseTuple(args, "s:getint", &s))
1694 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001695 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1697 return Tkinter_Error(self);
1698 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001699}
1700
1701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001704 char *s;
1705 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001707 if (PyTuple_Size(args) == 1) {
1708 PyObject *o = PyTuple_GetItem(args, 0);
1709 if (PyFloat_Check(o)) {
1710 Py_INCREF(o);
1711 return o;
1712 }
1713 }
1714 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1715 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001716 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1718 return Tkinter_Error(self);
1719 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001720}
1721
1722static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001723Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001724{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001725 char *s;
1726 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001728 if (PyTuple_Size(args) == 1) {
1729 PyObject *o = PyTuple_GetItem(args, 0);
1730 if (PyLong_Check(o)) {
1731 Py_INCREF(o);
1732 return o;
1733 }
1734 }
1735 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1736 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001737 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1739 return Tkinter_Error(self);
1740 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001741}
1742
1743static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001744Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 char *s;
1747 PyObject *res = NULL;
1748 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1751 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001752
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001753 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001754 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 ENTER_TCL
1757 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1758 ENTER_OVERLAP
1759 if (retval == TCL_ERROR)
1760 res = Tkinter_Error(self);
1761 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001762 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 LEAVE_OVERLAP_TCL
1764 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001765}
1766
1767static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001768Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001769{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001770 char *s;
1771 PyObject *res = NULL;
1772 int retval;
1773 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001774
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1776 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001777
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001778 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001780
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001781 ENTER_TCL
1782 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1783 ENTER_OVERLAP
1784 if (retval == TCL_ERROR)
1785 res = Tkinter_Error(self);
1786 else
1787 res = Py_BuildValue("l", v);
1788 LEAVE_OVERLAP_TCL
1789 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001790}
1791
1792static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001793Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001795 char *s;
1796 PyObject *res = NULL;
1797 double v;
1798 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001800 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1801 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001802 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001803 CHECK_TCL_APPARTMENT;
1804 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1805 ENTER_TCL
1806 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1807 ENTER_OVERLAP
1808 PyFPE_END_PROTECT(retval)
1809 if (retval == TCL_ERROR)
1810 res = Tkinter_Error(self);
1811 else
1812 res = Py_BuildValue("d", v);
1813 LEAVE_OVERLAP_TCL
1814 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001815}
1816
1817static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001818Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001819{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001820 char *s;
1821 PyObject *res = NULL;
1822 int retval;
1823 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001824
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1826 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001827 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828 CHECK_TCL_APPARTMENT;
1829 ENTER_TCL
1830 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1831 ENTER_OVERLAP
1832 if (retval == TCL_ERROR)
1833 res = Tkinter_Error(self);
1834 else
1835 res = Py_BuildValue("i", v);
1836 LEAVE_OVERLAP_TCL
1837 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001838}
1839
Barry Warsawfa701a81997-01-16 00:15:11 +00001840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841
Guido van Rossum18468821994-06-20 07:49:28 +00001842static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001843Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001844{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001845 char *list;
1846 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001847 const char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001848 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001850
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001851 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1852 return NULL;
1853 if (PyTclObject_Check(arg)) {
1854 int objc;
1855 Tcl_Obj **objv;
1856 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1857 ((PyTclObject*)arg)->value,
1858 &objc, &objv) == TCL_ERROR) {
1859 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001861 if (!(v = PyTuple_New(objc)))
1862 return NULL;
1863 for (i = 0; i < objc; i++) {
1864 PyObject *s = FromObj(self, objv[i]);
1865 if (!s || PyTuple_SetItem(v, i, s)) {
1866 Py_DECREF(v);
1867 return NULL;
1868 }
1869 }
1870 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001872 if (PyTuple_Check(arg)) {
1873 Py_INCREF(arg);
1874 return arg;
1875 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001876 if (PyList_Check(arg)) {
1877 return PySequence_Tuple(arg);
1878 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001880 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1881 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001882
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001883 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 if (Tcl_SplitList(Tkapp_Interp(self), list,
1885 &argc, &argv) == TCL_ERROR) {
1886 PyMem_Free(list);
1887 return Tkinter_Error(self);
1888 }
Guido van Rossum18468821994-06-20 07:49:28 +00001889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890 if (!(v = PyTuple_New(argc)))
1891 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001893 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001894 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 if (!s || PyTuple_SetItem(v, i, s)) {
1896 Py_DECREF(v);
1897 v = NULL;
1898 goto finally;
1899 }
1900 }
Guido van Rossum18468821994-06-20 07:49:28 +00001901
Barry Warsawfa701a81997-01-16 00:15:11 +00001902 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 ckfree(FREECAST argv);
1904 PyMem_Free(list);
1905 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001906}
1907
1908static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001909Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001910{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001911 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001912 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001913
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001914 if (!PyArg_ParseTuple(args, "O:split", &arg))
1915 return NULL;
1916 if (PyTclObject_Check(arg)) {
1917 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1918 int objc;
1919 Tcl_Obj **objv;
1920 int i;
1921 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1922 &objc, &objv) == TCL_ERROR) {
1923 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001925 if (objc == 0)
1926 return PyUnicode_FromString("");
1927 if (objc == 1)
1928 return FromObj(self, objv[0]);
1929 if (!(v = PyTuple_New(objc)))
1930 return NULL;
1931 for (i = 0; i < objc; i++) {
1932 PyObject *s = FromObj(self, objv[i]);
1933 if (!s || PyTuple_SetItem(v, i, s)) {
1934 Py_DECREF(v);
1935 return NULL;
1936 }
1937 }
1938 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001940 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001941 return SplitObj(arg);
1942
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001943 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1944 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001945 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001946 v = Split(list);
1947 PyMem_Free(list);
1948 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001949}
1950
Barry Warsawfa701a81997-01-16 00:15:11 +00001951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001952
Guido van Rossum18468821994-06-20 07:49:28 +00001953/** Tcl Command **/
1954
Guido van Rossum00d93061998-05-28 23:06:38 +00001955/* Client data struct */
1956typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001957 PyObject *self;
1958 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001959} PythonCmd_ClientData;
1960
1961static int
Fred Drake509d79a2000-07-08 04:04:38 +00001962PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001963{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 errorInCmd = 1;
1965 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1966 LEAVE_PYTHON
1967 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001968}
1969
Guido van Rossum18468821994-06-20 07:49:28 +00001970/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001971 * function or method.
1972 */
Guido van Rossum18468821994-06-20 07:49:28 +00001973static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001974PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001975{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001976 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001977 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001978 int i, rv;
1979 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001982
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001983 /* TBD: no error checking here since we know, via the
1984 * Tkapp_CreateCommand() that the client data is a two-tuple
1985 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001986 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001987
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 /* Create argument list (argv1, ..., argvN) */
1989 if (!(arg = PyTuple_New(argc - 1)))
1990 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001991
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001992 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001993 PyObject *s = unicodeFromTclString(argv[i + 1]);
1994 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 Py_DECREF(arg);
1996 return PythonCmd_Error(interp);
1997 }
1998 }
1999 res = PyEval_CallObject(func, arg);
2000 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002001
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002002 if (res == NULL)
2003 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 obj_res = AsObj(res);
2006 if (obj_res == NULL) {
2007 Py_DECREF(res);
2008 return PythonCmd_Error(interp);
2009 }
2010 else {
2011 Tcl_SetObjResult(interp, obj_res);
2012 rv = TCL_OK;
2013 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002016
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002017 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002019 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002020}
2021
2022static void
Fred Drake509d79a2000-07-08 04:04:38 +00002023PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002024{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002025 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002026
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 ENTER_PYTHON
2028 Py_XDECREF(data->self);
2029 Py_XDECREF(data->func);
2030 PyMem_DEL(data);
2031 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002032}
2033
Barry Warsawfa701a81997-01-16 00:15:11 +00002034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002036
Benjamin Peterson5879d412009-03-30 14:51:56 +00002037#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002038TCL_DECLARE_MUTEX(command_mutex)
2039
2040typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 Tcl_Event ev;
2042 Tcl_Interp* interp;
2043 char *name;
2044 int create;
2045 int *status;
2046 ClientData *data;
2047 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002048} CommandEvent;
2049
2050static int
2051Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002052{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002053 if (ev->create)
2054 *ev->status = Tcl_CreateCommand(
2055 ev->interp, ev->name, PythonCmd,
2056 ev->data, PythonCmdDelete) == NULL;
2057 else
2058 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2059 Tcl_MutexLock(&command_mutex);
2060 Tcl_ConditionNotify(ev->done);
2061 Tcl_MutexUnlock(&command_mutex);
2062 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002063}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002064#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002065
2066static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002067Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 TkappObject *self = (TkappObject*)selfptr;
2070 PythonCmd_ClientData *data;
2071 char *cmdName;
2072 PyObject *func;
2073 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002074
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002075 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2076 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002077 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002078 if (!PyCallable_Check(func)) {
2079 PyErr_SetString(PyExc_TypeError, "command not callable");
2080 return NULL;
2081 }
Guido van Rossum18468821994-06-20 07:49:28 +00002082
Martin v. Löwisa9656492003-03-30 08:44:58 +00002083#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2085 !WaitForMainloop(self))
2086 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002087#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002088
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 data = PyMem_NEW(PythonCmd_ClientData, 1);
2090 if (!data)
2091 return PyErr_NoMemory();
2092 Py_INCREF(self);
2093 Py_INCREF(func);
2094 data->self = selfptr;
2095 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002096#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002097 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2098 Tcl_Condition cond = NULL;
2099 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2100 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2101 ev->interp = self->interp;
2102 ev->create = 1;
2103 ev->name = cmdName;
2104 ev->data = (ClientData)data;
2105 ev->status = &err;
2106 ev->done = &cond;
2107 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2108 Tcl_ConditionFinalize(&cond);
2109 }
2110 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002111#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002112 {
2113 ENTER_TCL
2114 err = Tcl_CreateCommand(
2115 Tkapp_Interp(self), cmdName, PythonCmd,
2116 (ClientData)data, PythonCmdDelete) == NULL;
2117 LEAVE_TCL
2118 }
2119 if (err) {
2120 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2121 PyMem_DEL(data);
2122 return NULL;
2123 }
Guido van Rossum18468821994-06-20 07:49:28 +00002124
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002125 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002126}
2127
Barry Warsawfa701a81997-01-16 00:15:11 +00002128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002129
Guido van Rossum18468821994-06-20 07:49:28 +00002130static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002131Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002133 TkappObject *self = (TkappObject*)selfptr;
2134 char *cmdName;
2135 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002137 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2138 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002139 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002140
2141#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2143 Tcl_Condition cond = NULL;
2144 CommandEvent *ev;
2145 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2146 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2147 ev->interp = self->interp;
2148 ev->create = 0;
2149 ev->name = cmdName;
2150 ev->status = &err;
2151 ev->done = &cond;
2152 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2153 &command_mutex);
2154 Tcl_ConditionFinalize(&cond);
2155 }
2156 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002157#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 {
2159 ENTER_TCL
2160 err = Tcl_DeleteCommand(self->interp, cmdName);
2161 LEAVE_TCL
2162 }
2163 if (err == -1) {
2164 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2165 return NULL;
2166 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002167 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002168}
2169
Barry Warsawfa701a81997-01-16 00:15:11 +00002170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171
Guido van Rossum00d93061998-05-28 23:06:38 +00002172#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002173/** File Handler **/
2174
Guido van Rossum00d93061998-05-28 23:06:38 +00002175typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 PyObject *func;
2177 PyObject *file;
2178 int id;
2179 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002180} FileHandler_ClientData;
2181
2182static FileHandler_ClientData *HeadFHCD;
2183
2184static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002185NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002186{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 FileHandler_ClientData *p;
2188 p = PyMem_NEW(FileHandler_ClientData, 1);
2189 if (p != NULL) {
2190 Py_XINCREF(func);
2191 Py_XINCREF(file);
2192 p->func = func;
2193 p->file = file;
2194 p->id = id;
2195 p->next = HeadFHCD;
2196 HeadFHCD = p;
2197 }
2198 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002199}
2200
2201static void
Fred Drake509d79a2000-07-08 04:04:38 +00002202DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002203{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002204 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 pp = &HeadFHCD;
2207 while ((p = *pp) != NULL) {
2208 if (p->id == id) {
2209 *pp = p->next;
2210 Py_XDECREF(p->func);
2211 Py_XDECREF(p->file);
2212 PyMem_DEL(p);
2213 }
2214 else
2215 pp = &p->next;
2216 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002217}
2218
Guido van Rossuma597dde1995-01-10 20:56:29 +00002219static void
Fred Drake509d79a2000-07-08 04:04:38 +00002220FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002221{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002222 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2223 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002225 ENTER_PYTHON
2226 func = data->func;
2227 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 arg = Py_BuildValue("(Oi)", file, (long) mask);
2230 res = PyEval_CallObject(func, arg);
2231 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 if (res == NULL) {
2234 errorInCmd = 1;
2235 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2236 }
2237 Py_XDECREF(res);
2238 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002239}
2240
Guido van Rossum18468821994-06-20 07:49:28 +00002241static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002242Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2243 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002244{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002245 FileHandler_ClientData *data;
2246 PyObject *file, *func;
2247 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002249 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2250 &file, &mask, &func))
2251 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002253 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 tfile = PyObject_AsFileDescriptor(file);
2256 if (tfile < 0)
2257 return NULL;
2258 if (!PyCallable_Check(func)) {
2259 PyErr_SetString(PyExc_TypeError, "bad argument list");
2260 return NULL;
2261 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002263 data = NewFHCD(func, file, tfile);
2264 if (data == NULL)
2265 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 /* Ought to check for null Tcl_File object... */
2268 ENTER_TCL
2269 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2270 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002271 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002272}
2273
2274static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002275Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002276{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 PyObject *file;
2278 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2281 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285 tfile = PyObject_AsFileDescriptor(file);
2286 if (tfile < 0)
2287 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 /* Ought to check for null Tcl_File object... */
2292 ENTER_TCL
2293 Tcl_DeleteFileHandler(tfile);
2294 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002295 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002296}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002297#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002300/**** Tktt Object (timer token) ****/
2301
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002302static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002303
Guido van Rossum00d93061998-05-28 23:06:38 +00002304typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 PyObject_HEAD
2306 Tcl_TimerToken token;
2307 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002308} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002309
2310static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002311Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002312{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 TkttObject *v = (TkttObject *)self;
2314 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2317 return NULL;
2318 if (v->token != NULL) {
2319 Tcl_DeleteTimerHandler(v->token);
2320 v->token = NULL;
2321 }
2322 if (func != NULL) {
2323 v->func = NULL;
2324 Py_DECREF(func);
2325 Py_DECREF(v); /* See Tktt_New() */
2326 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002327 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328}
2329
2330static PyMethodDef Tktt_methods[] =
2331{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2333 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334};
2335
2336static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002337Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002338{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002339 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002340
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002341 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 if (v == NULL)
2343 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002344 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346 Py_INCREF(func);
2347 v->token = NULL;
2348 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 /* Extra reference, deleted when called or when handler is deleted */
2351 Py_INCREF(v);
2352 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353}
2354
2355static void
Fred Drake509d79a2000-07-08 04:04:38 +00002356Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 TkttObject *v = (TkttObject *)self;
2359 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002360 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002365 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366}
2367
Guido van Rossum597ac201998-05-12 14:36:19 +00002368static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002369Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002372 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2373 v,
2374 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375}
2376
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002377static PyType_Slot Tktt_Type_slots[] = {
2378 {Py_tp_dealloc, Tktt_Dealloc},
2379 {Py_tp_repr, Tktt_Repr},
2380 {Py_tp_methods, Tktt_methods},
2381 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382};
2383
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002384static PyType_Spec Tktt_Type_spec = {
2385 "tktimertoken",
2386 sizeof(TkttObject),
2387 0,
2388 Py_TPFLAGS_DEFAULT,
2389 Tktt_Type_slots,
2390};
Barry Warsawfa701a81997-01-16 00:15:11 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393/** Timer Handler **/
2394
2395static void
Fred Drake509d79a2000-07-08 04:04:38 +00002396TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 TkttObject *v = (TkttObject *)clientData;
2399 PyObject *func = v->func;
2400 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002402 if (func == NULL)
2403 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 res = PyEval_CallObject(func, NULL);
2410 Py_DECREF(func);
2411 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 if (res == NULL) {
2414 errorInCmd = 1;
2415 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2416 }
2417 else
2418 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002421}
2422
2423static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002424Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 int milliseconds;
2427 PyObject *func;
2428 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2431 &milliseconds, &func))
2432 return NULL;
2433 if (!PyCallable_Check(func)) {
2434 PyErr_SetString(PyExc_TypeError, "bad argument list");
2435 return NULL;
2436 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 v = Tktt_New(func);
2441 if (v) {
2442 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2443 (ClientData)v);
2444 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002446 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002447}
2448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002449
Guido van Rossum18468821994-06-20 07:49:28 +00002450/** Event Loop **/
2451
Guido van Rossum18468821994-06-20 07:49:28 +00002452static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002453Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002454{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002455 int threshold = 0;
2456 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002457#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002459#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2462 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 CHECK_TCL_APPARTMENT;
2465 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 quitMainLoop = 0;
2468 while (Tk_GetNumMainWindows() > threshold &&
2469 !quitMainLoop &&
2470 !errorInCmd)
2471 {
2472 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002473
2474#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 if (self->threaded) {
2476 /* Allow other Python threads to run. */
2477 ENTER_TCL
2478 result = Tcl_DoOneEvent(0);
2479 LEAVE_TCL
2480 }
2481 else {
2482 Py_BEGIN_ALLOW_THREADS
2483 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2484 tcl_tstate = tstate;
2485 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2486 tcl_tstate = NULL;
2487 if(tcl_lock)PyThread_release_lock(tcl_lock);
2488 if (result == 0)
2489 Sleep(Tkinter_busywaitinterval);
2490 Py_END_ALLOW_THREADS
2491 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002492#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002493 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002494#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002496 if (PyErr_CheckSignals() != 0) {
2497 self->dispatching = 0;
2498 return NULL;
2499 }
2500 if (result < 0)
2501 break;
2502 }
2503 self->dispatching = 0;
2504 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 if (errorInCmd) {
2507 errorInCmd = 0;
2508 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2509 excInCmd = valInCmd = trbInCmd = NULL;
2510 return NULL;
2511 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002512 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002513}
2514
2515static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002516Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002517{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 int flags = 0;
2519 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2522 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 ENTER_TCL
2525 rv = Tcl_DoOneEvent(flags);
2526 LEAVE_TCL
2527 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002528}
2529
2530static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002531Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002532{
2533
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 if (!PyArg_ParseTuple(args, ":quit"))
2535 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002538 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002539}
2540
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002541static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002542Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002543{
2544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002545 if (!PyArg_ParseTuple(args, ":interpaddr"))
2546 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002547
Victor Stinnere1040e22013-09-05 00:22:24 +02002548 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002549}
2550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002551static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002552Tkapp_TkInit(PyObject *self, PyObject *args)
2553{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 Tcl_Interp *interp = Tkapp_Interp(self);
2555 const char * _tk_exists = NULL;
2556 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002557
Guilherme Polob681df42009-02-09 22:33:59 +00002558#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2560 * first call failed.
2561 * To avoid the deadlock, we just refuse the second call through
2562 * a static variable.
2563 */
2564 if (tk_load_failed) {
2565 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2566 return NULL;
2567 }
Guilherme Polob681df42009-02-09 22:33:59 +00002568#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 /* We want to guard against calling Tk_Init() multiple times */
2571 CHECK_TCL_APPARTMENT;
2572 ENTER_TCL
2573 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2574 ENTER_OVERLAP
2575 if (err == TCL_ERROR) {
2576 /* This sets an exception, but we cannot return right
2577 away because we need to exit the overlap first. */
2578 Tkinter_Error(self);
2579 } else {
2580 _tk_exists = Tkapp_Result(self);
2581 }
2582 LEAVE_OVERLAP_TCL
2583 if (err == TCL_ERROR) {
2584 return NULL;
2585 }
2586 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2587 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002588 PyErr_SetString(Tkinter_TclError,
2589 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002590#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002591 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002592#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002593 return NULL;
2594 }
2595 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002596 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002597}
Barry Warsawfa701a81997-01-16 00:15:11 +00002598
Martin v. Löwisffad6332002-11-26 09:28:05 +00002599static PyObject *
2600Tkapp_WantObjects(PyObject *self, PyObject *args)
2601{
2602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002603 int wantobjects = -1;
2604 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2605 return NULL;
2606 if (wantobjects == -1)
2607 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2608 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002609
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002610 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002611}
2612
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002613static PyObject *
2614Tkapp_WillDispatch(PyObject *self, PyObject *args)
2615{
2616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002618
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002619 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002620}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622
Guido van Rossum18468821994-06-20 07:49:28 +00002623/**** Tkapp Method List ****/
2624
2625static PyMethodDef Tkapp_methods[] =
2626{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002627 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2628 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2629 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2632 {"record", Tkapp_Record, METH_VARARGS},
2633 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2634 {"setvar", Tkapp_SetVar, METH_VARARGS},
2635 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2636 {"getvar", Tkapp_GetVar, METH_VARARGS},
2637 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2638 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2639 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2640 {"getint", Tkapp_GetInt, METH_VARARGS},
2641 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2642 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2643 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2644 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2645 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2646 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2647 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2648 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2650 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002651#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002652 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2653 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002654#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002655 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2656 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2657 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2658 {"quit", Tkapp_Quit, METH_VARARGS},
2659 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2660 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2661 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002662};
2663
Barry Warsawfa701a81997-01-16 00:15:11 +00002664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665
Guido van Rossum18468821994-06-20 07:49:28 +00002666/**** Tkapp Type Methods ****/
2667
2668static void
Fred Drake509d79a2000-07-08 04:04:38 +00002669Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002670{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002671 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002672 /*CHECK_TCL_APPARTMENT;*/
2673 ENTER_TCL
2674 Tcl_DeleteInterp(Tkapp_Interp(self));
2675 LEAVE_TCL
2676 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002677 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002679}
2680
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002681static PyType_Slot Tkapp_Type_slots[] = {
2682 {Py_tp_dealloc, Tkapp_Dealloc},
2683 {Py_tp_methods, Tkapp_methods},
2684 {0, 0}
2685};
2686
2687
2688static PyType_Spec Tkapp_Type_spec = {
2689 "tkapp",
2690 sizeof(TkappObject),
2691 0,
2692 Py_TPFLAGS_DEFAULT,
2693 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002694};
2695
Barry Warsawfa701a81997-01-16 00:15:11 +00002696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002697
Guido van Rossum18468821994-06-20 07:49:28 +00002698/**** Tkinter Module ****/
2699
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002700typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002701 PyObject* tuple;
2702 int size; /* current size */
2703 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002704} FlattenContext;
2705
2706static int
2707_bump(FlattenContext* context, int size)
2708{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002709 /* expand tuple to hold (at least) size new items.
2710 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002712 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002714 if (maxsize < context->size + size)
2715 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002717 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002720}
2721
2722static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002723_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002724{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002729 if (depth > 1000) {
2730 PyErr_SetString(PyExc_ValueError,
2731 "nesting too deep in _flatten");
2732 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002733 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2734 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 /* preallocate (assume no nesting) */
2736 if (context->size + size > context->maxsize &&
2737 !_bump(context, size))
2738 return 0;
2739 /* copy items to output tuple */
2740 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002741 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 if (PyList_Check(o) || PyTuple_Check(o)) {
2743 if (!_flatten1(context, o, depth + 1))
2744 return 0;
2745 } else if (o != Py_None) {
2746 if (context->size + 1 > context->maxsize &&
2747 !_bump(context, 1))
2748 return 0;
2749 Py_INCREF(o);
2750 PyTuple_SET_ITEM(context->tuple,
2751 context->size++, o);
2752 }
2753 }
2754 } else {
2755 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2756 return 0;
2757 }
2758 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002759}
2760
2761static PyObject *
2762Tkinter_Flatten(PyObject* self, PyObject* args)
2763{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764 FlattenContext context;
2765 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002766
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2768 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002769
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 context.maxsize = PySequence_Size(item);
2771 if (context.maxsize < 0)
2772 return NULL;
2773 if (context.maxsize == 0)
2774 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 context.tuple = PyTuple_New(context.maxsize);
2777 if (!context.tuple)
2778 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002782 if (!_flatten1(&context, item,0))
2783 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 if (_PyTuple_Resize(&context.tuple, context.size))
2786 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002789}
2790
Guido van Rossum18468821994-06-20 07:49:28 +00002791static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002792Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002793{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 char *screenName = NULL;
2795 char *baseName = NULL; /* XXX this is not used anymore;
2796 try getting rid of it. */
2797 char *className = NULL;
2798 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03002799 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002800 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2801 int sync = 0; /* pass -sync to wish */
2802 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002804 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002805
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002806 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2807 &screenName, &baseName, &className,
2808 &interactive, &wantobjects, &wantTk,
2809 &sync, &use))
2810 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002811 CHECK_STRING_LENGTH(screenName);
2812 CHECK_STRING_LENGTH(baseName);
2813 CHECK_STRING_LENGTH(className);
2814 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002817 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002818 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002819}
2820
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002821static PyObject *
2822Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2823{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002824 int new_val;
2825 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2826 return NULL;
2827 if (new_val < 0) {
2828 PyErr_SetString(PyExc_ValueError,
2829 "busywaitinterval must be >= 0");
2830 return NULL;
2831 }
2832 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002833 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002834}
2835
2836static char setbusywaitinterval_doc[] =
2837"setbusywaitinterval(n) -> None\n\
2838\n\
2839Set the busy-wait interval in milliseconds between successive\n\
2840calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2841It should be set to a divisor of the maximum time between\n\
2842frames in an animation.";
2843
2844static PyObject *
2845Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2846{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002847 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002848}
2849
2850static char getbusywaitinterval_doc[] =
2851"getbusywaitinterval() -> int\n\
2852\n\
2853Return the current busy-wait interval between successive\n\
2854calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2855
Guido van Rossum18468821994-06-20 07:49:28 +00002856static PyMethodDef moduleMethods[] =
2857{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002858 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2859 {"create", Tkinter_Create, METH_VARARGS},
2860 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2861 setbusywaitinterval_doc},
2862 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2863 METH_NOARGS, getbusywaitinterval_doc},
2864 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002865};
2866
Guido van Rossum7bf15641998-05-22 18:28:17 +00002867#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002868
2869static int stdin_ready = 0;
2870
Guido van Rossumad4db171998-06-13 13:56:28 +00002871#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002872static void
Fred Drake509d79a2000-07-08 04:04:38 +00002873MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002874{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002876}
Guido van Rossumad4db171998-06-13 13:56:28 +00002877#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002878
Martin v. Löwisa9656492003-03-30 08:44:58 +00002879#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002880static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002881#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002882
Guido van Rossum18468821994-06-20 07:49:28 +00002883static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002884EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002885{
Guido van Rossumad4db171998-06-13 13:56:28 +00002886#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002887 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002888#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002889#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002891#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 stdin_ready = 0;
2893 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002894#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002895 tfile = fileno(stdin);
2896 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002897#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 while (!errorInCmd && !stdin_ready) {
2899 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002900#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901 if (_kbhit()) {
2902 stdin_ready = 1;
2903 break;
2904 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002905#endif
2906#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002907 Py_BEGIN_ALLOW_THREADS
2908 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2909 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002911 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002912
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002913 tcl_tstate = NULL;
2914 if(tcl_lock)PyThread_release_lock(tcl_lock);
2915 if (result == 0)
2916 Sleep(Tkinter_busywaitinterval);
2917 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002918#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002919 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002920#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002922 if (result < 0)
2923 break;
2924 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002925#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002927#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002928 if (errorInCmd) {
2929 errorInCmd = 0;
2930 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2931 excInCmd = valInCmd = trbInCmd = NULL;
2932 PyErr_Print();
2933 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002934#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002936#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002938}
Guido van Rossum18468821994-06-20 07:49:28 +00002939
Guido van Rossum00d93061998-05-28 23:06:38 +00002940#endif
2941
Guido van Rossum7bf15641998-05-22 18:28:17 +00002942static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002943EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002944{
Guido van Rossum00d93061998-05-28 23:06:38 +00002945#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002947#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002949#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 PyOS_InputHook = EventHook;
2951 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002952#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002953}
2954
2955static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002956DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002957{
Guido van Rossum00d93061998-05-28 23:06:38 +00002958#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2960 PyOS_InputHook = NULL;
2961 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002962#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002963}
2964
Barry Warsawfa701a81997-01-16 00:15:11 +00002965
Martin v. Löwis1a214512008-06-11 05:26:20 +00002966static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002967 PyModuleDef_HEAD_INIT,
2968 "_tkinter",
2969 NULL,
2970 -1,
2971 moduleMethods,
2972 NULL,
2973 NULL,
2974 NULL,
2975 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002976};
2977
Mark Hammond62b1ab12002-07-23 06:31:15 +00002978PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002979PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002980{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002981 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002982
Guido van Rossum00d93061998-05-28 23:06:38 +00002983#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002984 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002985 if (tcl_lock == NULL)
2986 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002987#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002989 m = PyModule_Create(&_tkintermodule);
2990 if (m == NULL)
2991 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002992
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002993 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2994 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002995 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002996 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002997 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002998 Py_INCREF(o);
2999 if (PyModule_AddObject(m, "TclError", o)) {
3000 Py_DECREF(o);
3001 Py_DECREF(m);
3002 return NULL;
3003 }
3004 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003005
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003006 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3007 Py_DECREF(m);
3008 return NULL;
3009 }
3010 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3011 Py_DECREF(m);
3012 return NULL;
3013 }
3014 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3015 Py_DECREF(m);
3016 return NULL;
3017 }
3018 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3019 Py_DECREF(m);
3020 return NULL;
3021 }
3022 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3023 Py_DECREF(m);
3024 return NULL;
3025 }
3026 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3027 Py_DECREF(m);
3028 return NULL;
3029 }
3030 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3031 Py_DECREF(m);
3032 return NULL;
3033 }
3034 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3035 Py_DECREF(m);
3036 return NULL;
3037 }
3038 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3039 Py_DECREF(m);
3040 return NULL;
3041 }
3042 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3043 Py_DECREF(m);
3044 return NULL;
3045 }
3046 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3047 Py_DECREF(m);
3048 return NULL;
3049 }
3050
3051 o = PyType_FromSpec(&Tkapp_Type_spec);
3052 if (o == NULL) {
3053 Py_DECREF(m);
3054 return NULL;
3055 }
3056 if (PyModule_AddObject(m, "TkappType", o)) {
3057 Py_DECREF(o);
3058 Py_DECREF(m);
3059 return NULL;
3060 }
3061 Tkapp_Type = o;
3062
3063 o = PyType_FromSpec(&Tktt_Type_spec);
3064 if (o == NULL) {
3065 Py_DECREF(m);
3066 return NULL;
3067 }
3068 if (PyModule_AddObject(m, "TkttType", o)) {
3069 Py_DECREF(o);
3070 Py_DECREF(m);
3071 return NULL;
3072 }
3073 Tktt_Type = o;
3074
3075 o = PyType_FromSpec(&PyTclObject_Type_spec);
3076 if (o == NULL) {
3077 Py_DECREF(m);
3078 return NULL;
3079 }
3080 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3081 Py_DECREF(o);
3082 Py_DECREF(m);
3083 return NULL;
3084 }
3085 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003086
3087#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3089 * start waking up. Note that Tcl_FindExecutable will do this, this
3090 * code must be above it! The original warning from
3091 * tkMacOSXAppInit.c is copied below.
3092 *
3093 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3094 * Tcl interpreter for now. It probably should work to do this
3095 * in the other order, but for now it doesn't seem to.
3096 *
3097 */
3098 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003099#endif
3100
3101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003102 /* This helps the dynamic loader; in Unicode aware Tcl versions
3103 it also helps Tcl find its encodings. */
3104 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3105 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003106 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003107 if (cexe)
3108 Tcl_FindExecutable(PyBytes_AsString(cexe));
3109 Py_XDECREF(cexe);
3110 Py_DECREF(uexe);
3111 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003112
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003113 if (PyErr_Occurred()) {
3114 Py_DECREF(m);
3115 return NULL;
3116 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003117
Guido van Rossum43ff8681998-07-14 18:02:13 +00003118#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003119 /* This was not a good idea; through <Destroy> bindings,
3120 Tcl_Finalize() may invoke Python code but at that point the
3121 interpreter and thread state have already been destroyed! */
3122 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003123#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003125}