blob: 0acded3ede9cbc6b885ad7e72ddae5d265295907 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030036#define CHECK_SIZE(size, elemsize) \
37 ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
38
Martin v. Löwis71e25a02002-10-01 18:08:06 +000039/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
40 making _tkinter correct for this API means to break earlier
41 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
42 earlier versions. Once Tcl releases before 8.4 don't need to be supported
43 anymore, this should go. */
44#define USE_COMPAT_CONST
45
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000046/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
47 it always; if Tcl is not threaded, the thread functions in
48 Tcl are empty. */
49#define TCL_THREADS
50
Jack Jansencb852442001-12-09 23:15:56 +000051#ifdef TK_FRAMEWORK
52#include <Tcl/tcl.h>
53#include <Tk/tk.h>
54#else
Guido van Rossum18468821994-06-20 07:49:28 +000055#include <tcl.h>
56#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000057#endif
Guido van Rossum18468821994-06-20 07:49:28 +000058
Guilherme Polo2d87e422009-04-10 22:19:09 +000059#include "tkinter.h"
60
Jason Tishlerbbe89612002-12-31 20:30:46 +000061/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000062#ifndef CONST84_RETURN
63#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000064#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000065#define CONST
66#endif
67
Guilherme Polo66917722009-02-09 22:35:27 +000068#if TK_VERSION_HEX < 0x08030102
69#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000070#endif
71
Jack Janseneddc1442003-11-20 01:44:59 +000072#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000073#define HAVE_CREATEFILEHANDLER
74#endif
75
Guido van Rossum00d93061998-05-28 23:06:38 +000076#ifdef HAVE_CREATEFILEHANDLER
77
Neal Norwitzd948a432006-01-08 01:08:55 +000078/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
79 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
80#ifndef TCL_UNIX_FD
81# ifdef TCL_WIN_SOCKET
82# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
83# else
84# define TCL_UNIX_FD 1
85# endif
86#endif
87
Guido van Rossum00d93061998-05-28 23:06:38 +000088/* Tcl_CreateFileHandler() changed several times; these macros deal with the
89 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
90 Unix, only because Jack added it back); when available on Windows, it only
91 applies to sockets. */
92
Guido van Rossum7bf15641998-05-22 18:28:17 +000093#ifdef MS_WINDOWS
94#define FHANDLETYPE TCL_WIN_SOCKET
95#else
96#define FHANDLETYPE TCL_UNIX_FD
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
100 which uses this to handle Tcl events while the user is typing commands. */
101
102#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000103#define WAIT_FOR_STDIN
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106#endif /* HAVE_CREATEFILEHANDLER */
107
Guido van Rossumad4db171998-06-13 13:56:28 +0000108#ifdef MS_WINDOWS
109#include <conio.h>
110#define WAIT_FOR_STDIN
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113#ifdef WITH_THREAD
114
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000115/* The threading situation is complicated. Tcl is not thread-safe, except
116 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000117
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300118 So we need to use a lock around all uses of Tcl. Previously, the
119 Python interpreter lock was used for this. However, this causes
120 problems when other Python threads need to run while Tcl is blocked
121 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000122
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300123 To solve this problem, a separate lock for Tcl is introduced.
124 Holding it is incompatible with holding Python's interpreter lock.
125 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000126
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300127 ENTER_TCL and LEAVE_TCL are brackets, just like
128 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
129 used whenever a call into Tcl is made that could call an event
130 handler, or otherwise affect the state of a Tcl interpreter. These
131 assume that the surrounding code has the Python interpreter lock;
132 inside the brackets, the Python interpreter lock has been released
133 and the lock for Tcl has been acquired.
134
135 Sometimes, it is necessary to have both the Python lock and the Tcl
136 lock. (For example, when transferring data from the Tcl
137 interpreter result to a Python string object.) This can be done by
138 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
139 reacquires the Python lock (and restores the thread state) but
140 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
141 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000142
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000143 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300144 handlers when the handler needs to use Python. Such event handlers
145 are entered while the lock for Tcl is held; the event handler
146 presumably needs to use Python. ENTER_PYTHON releases the lock for
147 Tcl and acquires the Python interpreter lock, restoring the
148 appropriate thread state, and LEAVE_PYTHON releases the Python
149 interpreter lock and re-acquires the lock for Tcl. It is okay for
150 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
151 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000152
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300153 These locks expand to several statements and brackets; they should
154 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000155
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300156 If Tcl is threaded, this approach won't work anymore. The Tcl
157 interpreter is only valid in the thread that created it, and all Tk
158 activity must happen in this thread, also. That means that the
159 mainloop must be invoked in the thread that created the
160 interpreter. Invoking commands from other threads is possible;
161 _tkinter will queue an event for the interpreter thread, which will
162 then execute the command and pass back the result. If the main
163 thread is not in the mainloop, and invoking commands causes an
164 exception; if the main loop is running but not processing events,
165 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000166
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300167 In addition, for a threaded Tcl, a single global tcl_tstate won't
168 be sufficient anymore, since multiple Tcl interpreters may
169 simultaneously dispatch in different threads. So we use the Tcl TLS
170 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000171
Guido van Rossum00d93061998-05-28 23:06:38 +0000172*/
173
Guido van Rossum65d5b571998-12-21 19:32:43 +0000174static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000175
176#ifdef TCL_THREADS
177static Tcl_ThreadDataKey state_key;
178typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300179#define tcl_tstate \
180 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000182static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000183#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000184
185#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
187 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
189#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300190 tcl_tstate = NULL; \
191 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
Guido van Rossum62320c91998-06-15 04:36:09 +0000193#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000195
196#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000198
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000199#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300201 if(tcl_lock) \
202 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
204#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 { PyThreadState *tstate = PyEval_SaveThread(); \
206 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000207
208#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 if (((TkappObject *)self)->threaded && \
210 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300211 PyErr_SetString(PyExc_RuntimeError, \
212 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 return 0; \
214 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#else
217
218#define ENTER_TCL
219#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000220#define ENTER_OVERLAP
221#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000222#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000223#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000224#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000225
226#endif
227
Guido van Rossum97867b21996-08-08 19:09:53 +0000228#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000229#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000230#endif
231
Guido van Rossum18468821994-06-20 07:49:28 +0000232/**** Tkapp Object Declaration ****/
233
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300234static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000235
Guido van Rossum00d93061998-05-28 23:06:38 +0000236typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 PyObject_HEAD
238 Tcl_Interp *interp;
239 int wantobjects;
240 int threaded; /* True if tcl_platform[threaded] */
241 Tcl_ThreadId thread_id;
242 int dispatching;
243 /* We cannot include tclInt.h, as this is internal.
244 So we cache interesting types here. */
245 Tcl_ObjType *BooleanType;
246 Tcl_ObjType *ByteArrayType;
247 Tcl_ObjType *DoubleType;
248 Tcl_ObjType *IntType;
249 Tcl_ObjType *ListType;
250 Tcl_ObjType *ProcBodyType;
251 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000252} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000253
Guido van Rossum18468821994-06-20 07:49:28 +0000254#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000255#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guido van Rossum35d43371997-08-02 00:09:09 +0000257#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000258(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000259
Barry Warsawfa701a81997-01-16 00:15:11 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262/**** Error Handling ****/
263
264static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000265static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000266static int errorInCmd = 0;
267static PyObject *excInCmd;
268static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000269static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guilherme Polob681df42009-02-09 22:33:59 +0000271#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000272static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000273#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275
Guido van Rossum18468821994-06-20 07:49:28 +0000276static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000277Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
280 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000281}
282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284
Guido van Rossum18468821994-06-20 07:49:28 +0000285/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000286
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000287static int Tkinter_busywaitinterval = 20;
288
Guido van Rossum00d93061998-05-28 23:06:38 +0000289#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000290#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000291
Guido van Rossum00d93061998-05-28 23:06:38 +0000292/* Millisecond sleep() for Unix platforms. */
293
294static void
Fred Drake509d79a2000-07-08 04:04:38 +0000295Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000296{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 /* XXX Too bad if you don't have select(). */
298 struct timeval t;
299 t.tv_sec = milli/1000;
300 t.tv_usec = (milli%1000) * 1000;
301 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000302}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000303#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000304
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000305/* Wait up to 1s for the mainloop to come up. */
306
307static int
308WaitForMainloop(TkappObject* self)
309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 int i;
311 for (i = 0; i < 10; i++) {
312 if (self->dispatching)
313 return 1;
314 Py_BEGIN_ALLOW_THREADS
315 Sleep(100);
316 Py_END_ALLOW_THREADS
317 }
318 if (self->dispatching)
319 return 1;
320 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
321 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000322}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000323#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326
Guido van Rossum18468821994-06-20 07:49:28 +0000327#define ARGSZ 64
328
Barry Warsawfa701a81997-01-16 00:15:11 +0000329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330
Guido van Rossum18468821994-06-20 07:49:28 +0000331static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200332unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
333{
334 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
335 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
336 /* Tcl encodes null character as \xc0\x80 */
337 if (memchr(s, '\xc0', size)) {
338 char *buf, *q;
339 const char *e = s + size;
340 PyErr_Clear();
341 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300342 if (buf == NULL) {
343 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200344 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300345 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200346 while (s != e) {
347 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
348 *q++ = '\0';
349 s += 2;
350 }
351 else
352 *q++ = *s++;
353 }
354 s = buf;
355 size = q - s;
356 r = PyUnicode_DecodeUTF8(s, size, NULL);
357 PyMem_Free(buf);
358 }
359 }
360 return r;
361}
362
363static PyObject *
364unicodeFromTclString(const char *s)
365{
366 return unicodeFromTclStringAndSize(s, strlen(s));
367}
368
369static PyObject *
370unicodeFromTclObj(Tcl_Obj *value)
371{
372 int len;
373 char *s = Tcl_GetStringFromObj(value, &len);
374 return unicodeFromTclStringAndSize(s, len);
375}
376
377
378static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000379Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000380{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 int argc;
382 char **argv;
383 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300386 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 }
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
390 /* Not a list.
391 * Could be a quoted string containing funnies, e.g. {"}.
392 * Return the string itself.
393 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200394 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 }
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 if (argc == 0)
398 v = PyUnicode_FromString("");
399 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200400 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401 else if ((v = PyTuple_New(argc)) != NULL) {
402 int i;
403 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000405 for (i = 0; i < argc; i++) {
406 if ((w = Split(argv[i])) == NULL) {
407 Py_DECREF(v);
408 v = NULL;
409 break;
410 }
411 PyTuple_SetItem(v, i, w);
412 }
413 }
414 Tcl_Free(FREECAST argv);
415 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000416}
417
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300418/* In some cases, Tcl will still return strings that are supposed to
419 be lists. SplitObj walks through a nested tuple, finding string
420 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000421
Martin v. Löwis59683e82008-06-13 07:50:45 +0000422static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000423SplitObj(PyObject *arg)
424{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 if (PyTuple_Check(arg)) {
426 int i, size;
427 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 size = PyTuple_Size(arg);
430 result = NULL;
431 /* Recursively invoke SplitObj for all tuple items.
432 If this does not return a new object, no action is
433 needed. */
434 for(i = 0; i < size; i++) {
435 elem = PyTuple_GetItem(arg, i);
436 newelem = SplitObj(elem);
437 if (!newelem) {
438 Py_XDECREF(result);
439 return NULL;
440 }
441 if (!result) {
442 int k;
443 if (newelem == elem) {
444 Py_DECREF(newelem);
445 continue;
446 }
447 result = PyTuple_New(size);
448 if (!result)
449 return NULL;
450 for(k = 0; k < i; k++) {
451 elem = PyTuple_GetItem(arg, k);
452 Py_INCREF(elem);
453 PyTuple_SetItem(result, k, elem);
454 }
455 }
456 PyTuple_SetItem(result, i, newelem);
457 }
458 if (result)
459 return result;
460 /* Fall through, returning arg. */
461 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300462 else if (PyList_Check(arg)) {
463 int i, size;
464 PyObject *elem, *newelem, *result;
465
466 size = PyList_GET_SIZE(arg);
467 result = PyTuple_New(size);
468 if (!result)
469 return NULL;
470 /* Recursively invoke SplitObj for all list items. */
471 for(i = 0; i < size; i++) {
472 elem = PyList_GET_ITEM(arg, i);
473 newelem = SplitObj(elem);
474 if (!newelem) {
475 Py_XDECREF(result);
476 return NULL;
477 }
478 PyTuple_SetItem(result, i, newelem);
479 }
480 return result;
481 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300482 else if (PyUnicode_Check(arg)) {
483 int argc;
484 char **argv;
485 char *list = PyUnicode_AsUTF8(arg);
486
487 if (list == NULL ||
488 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(list);
495 /* Fall through, returning arg. */
496 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 else if (PyBytes_Check(arg)) {
498 int argc;
499 char **argv;
500 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
503 Py_INCREF(arg);
504 return arg;
505 }
506 Tcl_Free(FREECAST argv);
507 if (argc > 1)
508 return Split(PyBytes_AsString(arg));
509 /* Fall through, returning arg. */
510 }
511 Py_INCREF(arg);
512 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000513}
Barry Warsawfa701a81997-01-16 00:15:11 +0000514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515
Guido van Rossum18468821994-06-20 07:49:28 +0000516/**** Tkapp Object ****/
517
518#ifndef WITH_APPINIT
519int
Fred Drake509d79a2000-07-08 04:04:38 +0000520Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000521{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 if (Tcl_Init(interp) == TCL_ERROR) {
525 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
526 return TCL_ERROR;
527 }
Guilherme Polob681df42009-02-09 22:33:59 +0000528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 _tkinter_skip_tk_init = Tcl_GetVar(interp,
530 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
531 if (_tkinter_skip_tk_init != NULL &&
532 strcmp(_tkinter_skip_tk_init, "1") == 0) {
533 return TCL_OK;
534 }
Guilherme Polob681df42009-02-09 22:33:59 +0000535
536#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 if (tk_load_failed) {
538 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
539 return TCL_ERROR;
540 }
Guilherme Polob681df42009-02-09 22:33:59 +0000541#endif
542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000544#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000546#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
548 return TCL_ERROR;
549 }
Guilherme Polob681df42009-02-09 22:33:59 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000552}
553#endif /* !WITH_APPINIT */
554
Guido van Rossum18468821994-06-20 07:49:28 +0000555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556
Barry Warsawfa701a81997-01-16 00:15:11 +0000557
558/* Initialize the Tk application; see the `main' function in
559 * `tkMain.c'.
560 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000561
Thomas Wouters58d05102000-07-24 14:43:35 +0000562static void EnableEventHook(void); /* Forward */
563static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000564
Barry Warsawfa701a81997-01-16 00:15:11 +0000565static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000566Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000568{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 TkappObject *v;
570 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000571
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300572 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 if (v == NULL)
574 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200575 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 v->interp = Tcl_CreateInterp();
578 v->wantobjects = wantobjects;
579 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
580 TCL_GLOBAL_ONLY) != NULL;
581 v->thread_id = Tcl_GetCurrentThread();
582 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000583
584#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000585 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300586 PyErr_SetString(PyExc_RuntimeError,
587 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 Py_DECREF(v);
589 return 0;
590 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000591#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000592#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (v->threaded && tcl_lock) {
594 /* If Tcl is threaded, we don't need the lock. */
595 PyThread_free_lock(tcl_lock);
596 tcl_lock = NULL;
597 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000598#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 v->BooleanType = Tcl_GetObjType("boolean");
601 v->ByteArrayType = Tcl_GetObjType("bytearray");
602 v->DoubleType = Tcl_GetObjType("double");
603 v->IntType = Tcl_GetObjType("int");
604 v->ListType = Tcl_GetObjType("list");
605 v->ProcBodyType = Tcl_GetObjType("procbody");
606 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 /* Delete the 'exit' command, which can screw things up */
609 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 if (screenName != NULL)
612 Tcl_SetVar2(v->interp, "env", "DISPLAY",
613 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 if (interactive)
616 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
617 else
618 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 /* This is used to get the application class for Tk 4.1 and up */
621 argv0 = (char*)ckalloc(strlen(className) + 1);
622 if (!argv0) {
623 PyErr_NoMemory();
624 Py_DECREF(v);
625 return NULL;
626 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200629 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
630 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
632 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 if (! wantTk) {
635 Tcl_SetVar(v->interp,
636 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
637 }
Guilherme Polob681df42009-02-09 22:33:59 +0000638#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 else if (tk_load_failed) {
640 Tcl_SetVar(v->interp,
641 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
642 }
Guilherme Polob681df42009-02-09 22:33:59 +0000643#endif
David Aschere2b4b322004-02-18 05:59:53 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 /* some initial arguments need to be in argv */
646 if (sync || use) {
647 char *args;
648 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 if (sync)
651 len += sizeof "-sync";
652 if (use)
653 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000654
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 args = (char*)ckalloc(len);
656 if (!args) {
657 PyErr_NoMemory();
658 Py_DECREF(v);
659 return NULL;
660 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 args[0] = '\0';
663 if (sync)
664 strcat(args, "-sync");
665 if (use) {
666 if (sync)
667 strcat(args, " ");
668 strcat(args, "-use ");
669 strcat(args, use);
670 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
673 ckfree(args);
674 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 if (Tcl_AppInit(v->interp) != TCL_OK) {
677 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000678#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 if (wantTk) {
680 const char *_tkinter_tk_failed;
681 _tkinter_tk_failed = Tcl_GetVar(v->interp,
682 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 if ( _tkinter_tk_failed != NULL &&
685 strcmp(_tkinter_tk_failed, "1") == 0) {
686 tk_load_failed = 1;
687 }
688 }
Guilherme Polob681df42009-02-09 22:33:59 +0000689#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 Py_DECREF((PyObject *)v);
691 return (TkappObject *)result;
692 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000697}
698
Barry Warsawfa701a81997-01-16 00:15:11 +0000699
Benjamin Peterson5879d412009-03-30 14:51:56 +0000700#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000701static void
702Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000704{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 Py_BEGIN_ALLOW_THREADS;
706 Tcl_MutexLock(mutex);
707 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
708 Tcl_ThreadAlert(self->thread_id);
709 Tcl_ConditionWait(cond, mutex, NULL);
710 Tcl_MutexUnlock(mutex);
711 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000712}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000713#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715
Guido van Rossum18468821994-06-20 07:49:28 +0000716/** Tcl Eval **/
717
Martin v. Löwisffad6332002-11-26 09:28:05 +0000718typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 PyObject_HEAD
720 Tcl_Obj *value;
721 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000722} PyTclObject;
723
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300724static PyObject *PyTclObject_Type;
725#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000726
727static PyObject *
728newPyTclObject(Tcl_Obj *arg)
729{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300731 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 if (self == NULL)
733 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200734 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 Tcl_IncrRefCount(arg);
736 self->value = arg;
737 self->string = NULL;
738 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000739}
740
741static void
742PyTclObject_dealloc(PyTclObject *self)
743{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200744 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745 Tcl_DecrRefCount(self->value);
746 Py_XDECREF(self->string);
747 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200748 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000749}
750
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000751static char*
752PyTclObject_TclString(PyObject *self)
753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000755}
756
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000757/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000758PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000759"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000760
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000761static PyObject *
762PyTclObject_string(PyTclObject *self, void *ignored)
763{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200765 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 if (!self->string)
767 return NULL;
768 }
769 Py_INCREF(self->string);
770 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000771}
772
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000773static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000774PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000775{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200776 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 Py_INCREF(self->string);
778 return self->string;
779 }
780 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200781 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000782}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000783
Martin v. Löwisffad6332002-11-26 09:28:05 +0000784static PyObject *
785PyTclObject_repr(PyTclObject *self)
786{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300787 PyObject *repr, *str = PyTclObject_str(self, NULL);
788 if (str == NULL)
789 return NULL;
790 repr = PyUnicode_FromFormat("<%s object: %R>",
791 self->value->typePtr->name, str);
792 Py_DECREF(str);
793 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794}
795
Mark Dickinson211c6252009-02-01 10:28:51 +0000796#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
797
798static PyObject *
799PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 int result;
802 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 /* neither argument should be NULL, unless something's gone wrong */
805 if (self == NULL || other == NULL) {
806 PyErr_BadInternalCall();
807 return NULL;
808 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000810 /* both arguments should be instances of PyTclObject */
811 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
812 v = Py_NotImplemented;
813 goto finished;
814 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 if (self == other)
817 /* fast path when self and other are identical */
818 result = 0;
819 else
820 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
821 Tcl_GetString(((PyTclObject *)other)->value));
822 /* Convert return value to a Boolean */
823 switch (op) {
824 case Py_EQ:
825 v = TEST_COND(result == 0);
826 break;
827 case Py_NE:
828 v = TEST_COND(result != 0);
829 break;
830 case Py_LE:
831 v = TEST_COND(result <= 0);
832 break;
833 case Py_GE:
834 v = TEST_COND(result >= 0);
835 break;
836 case Py_LT:
837 v = TEST_COND(result < 0);
838 break;
839 case Py_GT:
840 v = TEST_COND(result > 0);
841 break;
842 default:
843 PyErr_BadArgument();
844 return NULL;
845 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000846 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000847 Py_INCREF(v);
848 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000849}
850
Martin v. Löwis39195712003-01-04 00:33:13 +0000851PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
852
Martin v. Löwisffad6332002-11-26 09:28:05 +0000853static PyObject*
854get_typename(PyTclObject* obj, void* ignored)
855{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200856 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000857}
858
Martin v. Löwis39195712003-01-04 00:33:13 +0000859
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000861 {"typename", (getter)get_typename, NULL, get_typename__doc__},
862 {"string", (getter)PyTclObject_string, NULL,
863 PyTclObject_string__doc__},
864 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865};
866
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300867static PyType_Slot PyTclObject_Type_slots[] = {
868 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
869 {Py_tp_repr, (reprfunc)PyTclObject_repr},
870 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200871 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300872 {Py_tp_richcompare, PyTclObject_richcompare},
873 {Py_tp_getset, PyTclObject_getsetlist},
874 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000875};
876
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300877static PyType_Spec PyTclObject_Type_spec = {
878 "_tkinter.Tcl_Obj",
879 sizeof(PyTclObject),
880 0,
881 Py_TPFLAGS_DEFAULT,
882 PyTclObject_Type_slots,
883};
884
885
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300886#if PY_SIZE_MAX > INT_MAX
887#define CHECK_STRING_LENGTH(s) do { \
888 if (s != NULL && strlen(s) >= INT_MAX) { \
889 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
890 return NULL; \
891 } } while(0)
892#else
893#define CHECK_STRING_LENGTH(s)
894#endif
895
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000896static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000897AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000898{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 Tcl_Obj *result;
900 long longVal;
901 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 if (PyBytes_Check(value))
904 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
905 PyBytes_GET_SIZE(value));
906 else if (PyBool_Check(value))
907 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
908 else if (PyLong_CheckExact(value) &&
909 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
910 !overflow)) {
911 /* If there is an overflow in the long conversion,
912 fall through to default object handling. */
913 return Tcl_NewLongObj(longVal);
914 }
915 else if (PyFloat_Check(value))
916 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300917 else if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300918 Tcl_Obj **argv;
919 Py_ssize_t size, i;
920
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300921 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300922 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300923 PyErr_SetString(PyExc_OverflowError,
924 PyTuple_Check(value) ? "tuple is too long" :
925 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300926 return NULL;
927 }
928 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929 if(!argv)
930 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300931 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300932 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
933 result = Tcl_NewListObj(size, argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000934 ckfree(FREECAST argv);
935 return result;
936 }
937 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200938 void *inbuf;
939 Py_ssize_t size;
940 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000941 Tcl_UniChar *outbuf = NULL;
942 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200943 size_t allocsize;
944
945 if (PyUnicode_READY(value) == -1)
946 return NULL;
947
948 inbuf = PyUnicode_DATA(value);
949 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300950 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
951 PyErr_SetString(PyExc_OverflowError, "string is too long");
952 return NULL;
953 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200954 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200955 if (kind == sizeof(Tcl_UniChar))
956 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200957 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
958 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000959 /* Else overflow occurred, and we take the next exit */
960 if (!outbuf) {
961 PyErr_NoMemory();
962 return NULL;
963 }
964 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200965 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
966 /* We cannot test for sizeof(Tcl_UniChar) directly,
967 so we test for UTF-8 size instead. */
968#if TCL_UTF_MAX == 3
969 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000970 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200971 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100972 "character U+%x is above the range "
973 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100974 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975 ckfree(FREECAST outbuf);
976 return NULL;
977 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300978#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200979 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000980 }
981 result = Tcl_NewUnicodeObj(outbuf, size);
982 ckfree(FREECAST outbuf);
983 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 }
985 else if(PyTclObject_Check(value)) {
986 Tcl_Obj *v = ((PyTclObject*)value)->value;
987 Tcl_IncrRefCount(v);
988 return v;
989 }
990 else {
991 PyObject *v = PyObject_Str(value);
992 if (!v)
993 return 0;
994 result = AsObj(v);
995 Py_DECREF(v);
996 return result;
997 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000998}
999
Martin v. Löwisffad6332002-11-26 09:28:05 +00001000static PyObject*
1001FromObj(PyObject* tkapp, Tcl_Obj *value)
1002{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001003 PyObject *result = NULL;
1004 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001005
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001007 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001010 if (value->typePtr == app->BooleanType) {
1011 result = value->internalRep.longValue ? Py_True : Py_False;
1012 Py_INCREF(result);
1013 return result;
1014 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001016 if (value->typePtr == app->ByteArrayType) {
1017 int size;
1018 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1019 return PyBytes_FromStringAndSize(data, size);
1020 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001022 if (value->typePtr == app->DoubleType) {
1023 return PyFloat_FromDouble(value->internalRep.doubleValue);
1024 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001026 if (value->typePtr == app->IntType) {
1027 return PyLong_FromLong(value->internalRep.longValue);
1028 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001030 if (value->typePtr == app->ListType) {
1031 int size;
1032 int i, status;
1033 PyObject *elem;
1034 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001035
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001036 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1037 if (status == TCL_ERROR)
1038 return Tkinter_Error(tkapp);
1039 result = PyTuple_New(size);
1040 if (!result)
1041 return NULL;
1042 for (i = 0; i < size; i++) {
1043 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1044 value, i, &tcl_elem);
1045 if (status == TCL_ERROR) {
1046 Py_DECREF(result);
1047 return Tkinter_Error(tkapp);
1048 }
1049 elem = FromObj(tkapp, tcl_elem);
1050 if (!elem) {
1051 Py_DECREF(result);
1052 return NULL;
1053 }
1054 PyTuple_SetItem(result, i, elem);
1055 }
1056 return result;
1057 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 if (value->typePtr == app->ProcBodyType) {
1060 /* fall through: return tcl object. */
1061 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001063 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001064 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001065 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001066 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001067 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001070}
1071
Benjamin Peterson5879d412009-03-30 14:51:56 +00001072#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001074TCL_DECLARE_MUTEX(call_mutex)
1075
1076typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 Tcl_Event ev; /* Must be first */
1078 TkappObject *self;
1079 PyObject *args;
1080 int flags;
1081 PyObject **res;
1082 PyObject **exc_type, **exc_value, **exc_tb;
1083 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001085#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001086
1087void
1088Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001089{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001090 int i;
1091 for (i = 0; i < objc; i++)
1092 Tcl_DecrRefCount(objv[i]);
1093 if (objv != objStore)
1094 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001095}
Guido van Rossum18468821994-06-20 07:49:28 +00001096
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001097/* Convert Python objects to Tcl objects. This must happen in the
1098 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001099
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001100static Tcl_Obj**
1101Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1102{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001103 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001104 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 if (args == NULL)
1106 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001107
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001108 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001109 objv[0] = AsObj(args);
1110 if (objv[0] == 0)
1111 goto finally;
1112 objc = 1;
1113 Tcl_IncrRefCount(objv[0]);
1114 }
1115 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001116 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001118 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001119 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001120 PyErr_SetString(PyExc_OverflowError,
1121 PyTuple_Check(args) ? "tuple is too long" :
1122 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001123 return NULL;
1124 }
1125 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001126 if (objv == NULL) {
1127 PyErr_NoMemory();
1128 objc = 0;
1129 goto finally;
1130 }
1131 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001134 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 if (v == Py_None) {
1136 objc = i;
1137 break;
1138 }
1139 objv[i] = AsObj(v);
1140 if (!objv[i]) {
1141 /* Reset objc, so it attempts to clear
1142 objects only up to i. */
1143 objc = i;
1144 goto finally;
1145 }
1146 Tcl_IncrRefCount(objv[i]);
1147 }
1148 }
1149 *pobjc = objc;
1150 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001151finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 Tkapp_CallDeallocArgs(objv, objStore, objc);
1153 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154}
Guido van Rossum212643f1998-04-29 16:22:14 +00001155
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001157
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001158static PyObject*
1159Tkapp_CallResult(TkappObject *self)
1160{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001161 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001162 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001164 /* Not sure whether the IncrRef is necessary, but something
1165 may overwrite the interpreter result while we are
1166 converting it. */
1167 Tcl_IncrRefCount(value);
1168 res = FromObj((PyObject*)self, value);
1169 Tcl_DecrRefCount(value);
1170 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001171 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001172 }
1173 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001174}
Guido van Rossum632de272000-03-29 00:19:50 +00001175
Benjamin Peterson5879d412009-03-30 14:51:56 +00001176#ifdef WITH_THREAD
1177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178/* Tkapp_CallProc is the event procedure that is executed in the context of
1179 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1180 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001181
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001182static int
1183Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1184{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001185 Tcl_Obj *objStore[ARGSZ];
1186 Tcl_Obj **objv;
1187 int objc;
1188 int i;
1189 ENTER_PYTHON
1190 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1191 if (!objv) {
1192 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1193 *(e->res) = NULL;
1194 }
1195 LEAVE_PYTHON
1196 if (!objv)
1197 goto done;
1198 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1199 ENTER_PYTHON
1200 if (i == TCL_ERROR) {
1201 *(e->res) = NULL;
1202 *(e->exc_type) = NULL;
1203 *(e->exc_tb) = NULL;
1204 *(e->exc_value) = PyObject_CallFunction(
1205 Tkinter_TclError, "s",
1206 Tcl_GetStringResult(e->self->interp));
1207 }
1208 else {
1209 *(e->res) = Tkapp_CallResult(e->self);
1210 }
1211 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001214done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 /* Wake up calling thread. */
1216 Tcl_MutexLock(&call_mutex);
1217 Tcl_ConditionNotify(e->done);
1218 Tcl_MutexUnlock(&call_mutex);
1219 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220}
1221
Benjamin Peterson5879d412009-03-30 14:51:56 +00001222#endif
1223
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224/* This is the main entry point for calling a Tcl command.
1225 It supports three cases, with regard to threading:
1226 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1227 the context of the calling thread.
1228 2. Tcl is threaded, caller of the command is in the interpreter thread:
1229 Execute the command in the calling thread. Since the Tcl lock will
1230 not be used, we can merge that with case 1.
1231 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1232 the interpreter thread. Allocation of Tcl objects needs to occur in the
1233 interpreter thread, so we ship the PyObject* args to the target thread,
1234 and perform processing there. */
1235
1236static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001237Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001238{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 Tcl_Obj *objStore[ARGSZ];
1240 Tcl_Obj **objv = NULL;
1241 int objc, i;
1242 PyObject *res = NULL;
1243 TkappObject *self = (TkappObject*)selfptr;
1244 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 /* If args is a single tuple, replace with contents of tuple */
1247 if (1 == PyTuple_Size(args)){
1248 PyObject* item = PyTuple_GetItem(args, 0);
1249 if (PyTuple_Check(item))
1250 args = item;
1251 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001252#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1254 /* We cannot call the command directly. Instead, we must
1255 marshal the parameters to the interpreter thread. */
1256 Tkapp_CallEvent *ev;
1257 Tcl_Condition cond = NULL;
1258 PyObject *exc_type, *exc_value, *exc_tb;
1259 if (!WaitForMainloop(self))
1260 return NULL;
1261 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1262 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1263 ev->self = self;
1264 ev->args = args;
1265 ev->res = &res;
1266 ev->exc_type = &exc_type;
1267 ev->exc_value = &exc_value;
1268 ev->exc_tb = &exc_tb;
1269 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001273 if (res == NULL) {
1274 if (exc_type)
1275 PyErr_Restore(exc_type, exc_value, exc_tb);
1276 else
1277 PyErr_SetObject(Tkinter_TclError, exc_value);
1278 }
1279 Tcl_ConditionFinalize(&cond);
1280 }
1281 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001282#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 objv = Tkapp_CallArgs(args, objStore, &objc);
1286 if (!objv)
1287 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 if (i == TCL_ERROR)
1296 Tkinter_Error(selfptr);
1297 else
1298 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001300 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 Tkapp_CallDeallocArgs(objv, objStore, objc);
1303 }
1304 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001305}
1306
1307
1308static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001309Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001310{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 char *script;
1312 PyObject *res = NULL;
1313 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 if (!PyArg_ParseTuple(args, "s:eval", &script))
1316 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001317
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001318 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 ENTER_TCL
1322 err = Tcl_Eval(Tkapp_Interp(self), script);
1323 ENTER_OVERLAP
1324 if (err == TCL_ERROR)
1325 res = Tkinter_Error(self);
1326 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001327 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 LEAVE_OVERLAP_TCL
1329 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001330}
1331
1332static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001333Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001334{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 char *fileName;
1336 PyObject *res = NULL;
1337 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001338
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1340 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001341
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001342 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001345 ENTER_TCL
1346 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1347 ENTER_OVERLAP
1348 if (err == TCL_ERROR)
1349 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001351 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 LEAVE_OVERLAP_TCL
1353 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001354}
1355
1356static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001357Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001358{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 char *script;
1360 PyObject *res = NULL;
1361 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001362
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001363 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001365
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001366 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 ENTER_TCL
1370 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1371 ENTER_OVERLAP
1372 if (err == TCL_ERROR)
1373 res = Tkinter_Error(self);
1374 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001375 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 LEAVE_OVERLAP_TCL
1377 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001378}
1379
1380static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001381Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001382{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1386 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001387 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 ENTER_TCL
1391 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1392 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001393
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001394 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001395}
1396
Barry Warsawfa701a81997-01-16 00:15:11 +00001397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398
Guido van Rossum18468821994-06-20 07:49:28 +00001399/** Tcl Variable **/
1400
Benjamin Peterson5879d412009-03-30 14:51:56 +00001401typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1402
1403#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001404TCL_DECLARE_MUTEX(var_mutex)
1405
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001406typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 Tcl_Event ev; /* must be first */
1408 PyObject *self;
1409 PyObject *args;
1410 int flags;
1411 EventFunc func;
1412 PyObject **res;
1413 PyObject **exc_type;
1414 PyObject **exc_val;
1415 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001416} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001417#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001418
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001419static int
1420varname_converter(PyObject *in, void *_out)
1421{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001422 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001423 char **out = (char**)_out;
1424 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001425 if (PyBytes_Size(in) > INT_MAX) {
1426 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1427 return 0;
1428 }
1429 s = PyBytes_AsString(in);
1430 if (strlen(s) != PyBytes_Size(in)) {
1431 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1432 return 0;
1433 }
1434 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 return 1;
1436 }
1437 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001438 Py_ssize_t size;
1439 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001440 if (s == NULL) {
1441 return 0;
1442 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001443 if (size > INT_MAX) {
1444 PyErr_SetString(PyExc_OverflowError, "string is too long");
1445 return 0;
1446 }
1447 if (strlen(s) != size) {
1448 PyErr_SetString(PyExc_ValueError, "null character in string");
1449 return 0;
1450 }
1451 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 return 1;
1453 }
1454 if (PyTclObject_Check(in)) {
1455 *out = PyTclObject_TclString(in);
1456 return 1;
1457 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001458 PyErr_Format(PyExc_TypeError,
1459 "must be str, bytes or Tcl_Obj, not %.50s",
1460 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001462}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001463
Benjamin Peterson5879d412009-03-30 14:51:56 +00001464#ifdef WITH_THREAD
1465
Martin v. Löwis59683e82008-06-13 07:50:45 +00001466static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467var_perform(VarEvent *ev)
1468{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001469 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1470 if (!*(ev->res)) {
1471 PyObject *exc, *val, *tb;
1472 PyErr_Fetch(&exc, &val, &tb);
1473 PyErr_NormalizeException(&exc, &val, &tb);
1474 *(ev->exc_type) = exc;
1475 *(ev->exc_val) = val;
1476 Py_DECREF(tb);
1477 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001478
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001479}
1480
1481static int
1482var_proc(VarEvent* ev, int flags)
1483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 ENTER_PYTHON
1485 var_perform(ev);
1486 Tcl_MutexLock(&var_mutex);
1487 Tcl_ConditionNotify(ev->cond);
1488 Tcl_MutexUnlock(&var_mutex);
1489 LEAVE_PYTHON
1490 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001491}
1492
Benjamin Peterson5879d412009-03-30 14:51:56 +00001493#endif
1494
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001496var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001497{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001498#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001499 TkappObject *self = (TkappObject*)selfptr;
1500 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1501 TkappObject *self = (TkappObject*)selfptr;
1502 VarEvent *ev;
1503 PyObject *res, *exc_type, *exc_val;
1504 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 /* The current thread is not the interpreter thread. Marshal
1507 the call to the interpreter thread, then wait for
1508 completion. */
1509 if (!WaitForMainloop(self))
1510 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514 ev->self = selfptr;
1515 ev->args = args;
1516 ev->flags = flags;
1517 ev->func = func;
1518 ev->res = &res;
1519 ev->exc_type = &exc_type;
1520 ev->exc_val = &exc_val;
1521 ev->cond = &cond;
1522 ev->ev.proc = (Tcl_EventProc*)var_proc;
1523 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1524 Tcl_ConditionFinalize(&cond);
1525 if (!res) {
1526 PyErr_SetObject(exc_type, exc_val);
1527 Py_DECREF(exc_type);
1528 Py_DECREF(exc_val);
1529 return NULL;
1530 }
1531 return res;
1532 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001533#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001534 /* Tcl is not threaded, or this is the interpreter thread. */
1535 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536}
1537
Guido van Rossum18468821994-06-20 07:49:28 +00001538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001539SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001540{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 char *name1, *name2;
1542 PyObject *newValue;
1543 PyObject *res = NULL;
1544 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001545
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001546 switch (PyTuple_GET_SIZE(args)) {
1547 case 2:
1548 if (!PyArg_ParseTuple(args, "O&O:setvar",
1549 varname_converter, &name1, &newValue))
1550 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001551 /* XXX Acquire tcl lock??? */
1552 newval = AsObj(newValue);
1553 if (newval == NULL)
1554 return NULL;
1555 ENTER_TCL
1556 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1557 newval, flags);
1558 ENTER_OVERLAP
1559 if (!ok)
1560 Tkinter_Error(self);
1561 else {
1562 res = Py_None;
1563 Py_INCREF(res);
1564 }
1565 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001566 break;
1567 case 3:
1568 if (!PyArg_ParseTuple(args, "ssO:setvar",
1569 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001571 CHECK_STRING_LENGTH(name1);
1572 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001573 /* XXX must hold tcl lock already??? */
1574 newval = AsObj(newValue);
1575 ENTER_TCL
1576 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1577 ENTER_OVERLAP
1578 if (!ok)
1579 Tkinter_Error(self);
1580 else {
1581 res = Py_None;
1582 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001584 LEAVE_OVERLAP_TCL
1585 break;
1586 default:
1587 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1588 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001589 }
1590 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001591}
1592
1593static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001594Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001595{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001597}
1598
1599static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001600Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001601{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001603}
1604
Barry Warsawfa701a81997-01-16 00:15:11 +00001605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606
Guido van Rossum18468821994-06-20 07:49:28 +00001607static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001608GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001609{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 char *name1, *name2=NULL;
1611 PyObject *res = NULL;
1612 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1615 varname_converter, &name1, &name2))
1616 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001617
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001618 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 ENTER_TCL
1620 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1621 ENTER_OVERLAP
1622 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001623 PyErr_SetString(Tkinter_TclError,
1624 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 } else {
1626 if (((TkappObject*)self)->wantobjects) {
1627 res = FromObj(self, tres);
1628 }
1629 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001630 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 }
1632 }
1633 LEAVE_OVERLAP_TCL
1634 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001635}
1636
1637static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001638Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001639{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001640 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001641}
1642
1643static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001644Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001645{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001646 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001647}
1648
Barry Warsawfa701a81997-01-16 00:15:11 +00001649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001650
Guido van Rossum18468821994-06-20 07:49:28 +00001651static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001652UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001653{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 char *name1, *name2=NULL;
1655 int code;
1656 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1659 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001660
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001661 CHECK_STRING_LENGTH(name1);
1662 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001663 ENTER_TCL
1664 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1665 ENTER_OVERLAP
1666 if (code == TCL_ERROR)
1667 res = Tkinter_Error(self);
1668 else {
1669 Py_INCREF(Py_None);
1670 res = Py_None;
1671 }
1672 LEAVE_OVERLAP_TCL
1673 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001674}
1675
1676static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001677Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001678{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001679 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001680}
1681
1682static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001683Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001684{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001685 return var_invoke(UnsetVar, self, args,
1686 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001687}
1688
Barry Warsawfa701a81997-01-16 00:15:11 +00001689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001690
Guido van Rossum18468821994-06-20 07:49:28 +00001691/** Tcl to Python **/
1692
1693static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001694Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001695{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 char *s;
1697 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001699 if (PyTuple_Size(args) == 1) {
1700 PyObject* o = PyTuple_GetItem(args, 0);
1701 if (PyLong_Check(o)) {
1702 Py_INCREF(o);
1703 return o;
1704 }
1705 }
1706 if (!PyArg_ParseTuple(args, "s:getint", &s))
1707 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001708 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001709 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1710 return Tkinter_Error(self);
1711 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001712}
1713
1714static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001715Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001716{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717 char *s;
1718 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 if (PyTuple_Size(args) == 1) {
1721 PyObject *o = PyTuple_GetItem(args, 0);
1722 if (PyFloat_Check(o)) {
1723 Py_INCREF(o);
1724 return o;
1725 }
1726 }
1727 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1728 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001729 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001730 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1731 return Tkinter_Error(self);
1732 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
1735static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001736Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 char *s;
1739 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001741 if (PyTuple_Size(args) == 1) {
1742 PyObject *o = PyTuple_GetItem(args, 0);
1743 if (PyLong_Check(o)) {
1744 Py_INCREF(o);
1745 return o;
1746 }
1747 }
1748 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1749 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001750 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001751 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1752 return Tkinter_Error(self);
1753 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001754}
1755
1756static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 char *s;
1760 PyObject *res = NULL;
1761 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1764 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001765
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001766 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 ENTER_TCL
1770 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1771 ENTER_OVERLAP
1772 if (retval == TCL_ERROR)
1773 res = Tkinter_Error(self);
1774 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001775 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 LEAVE_OVERLAP_TCL
1777 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001778}
1779
1780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001783 char *s;
1784 PyObject *res = NULL;
1785 int retval;
1786 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1789 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001790
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001791 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001794 ENTER_TCL
1795 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1796 ENTER_OVERLAP
1797 if (retval == TCL_ERROR)
1798 res = Tkinter_Error(self);
1799 else
1800 res = Py_BuildValue("l", v);
1801 LEAVE_OVERLAP_TCL
1802 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001803}
1804
1805static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001806Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001807{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 char *s;
1809 PyObject *res = NULL;
1810 double v;
1811 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1814 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001815 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 CHECK_TCL_APPARTMENT;
1817 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1818 ENTER_TCL
1819 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1820 ENTER_OVERLAP
1821 PyFPE_END_PROTECT(retval)
1822 if (retval == TCL_ERROR)
1823 res = Tkinter_Error(self);
1824 else
1825 res = Py_BuildValue("d", v);
1826 LEAVE_OVERLAP_TCL
1827 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001828}
1829
1830static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001831Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001832{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001833 char *s;
1834 PyObject *res = NULL;
1835 int retval;
1836 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001838 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1839 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001840 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 CHECK_TCL_APPARTMENT;
1842 ENTER_TCL
1843 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1844 ENTER_OVERLAP
1845 if (retval == TCL_ERROR)
1846 res = Tkinter_Error(self);
1847 else
1848 res = Py_BuildValue("i", v);
1849 LEAVE_OVERLAP_TCL
1850 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001851}
1852
Barry Warsawfa701a81997-01-16 00:15:11 +00001853
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001854
Guido van Rossum18468821994-06-20 07:49:28 +00001855static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001856Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001857{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001858 char *list;
1859 int argc;
1860 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001861 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001862 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001863
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001864 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1865 return NULL;
1866 if (PyTclObject_Check(arg)) {
1867 int objc;
1868 Tcl_Obj **objv;
1869 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1870 ((PyTclObject*)arg)->value,
1871 &objc, &objv) == TCL_ERROR) {
1872 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001874 if (!(v = PyTuple_New(objc)))
1875 return NULL;
1876 for (i = 0; i < objc; i++) {
1877 PyObject *s = FromObj(self, objv[i]);
1878 if (!s || PyTuple_SetItem(v, i, s)) {
1879 Py_DECREF(v);
1880 return NULL;
1881 }
1882 }
1883 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001885 if (PyTuple_Check(arg)) {
1886 Py_INCREF(arg);
1887 return arg;
1888 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001889 if (PyList_Check(arg)) {
1890 return PySequence_Tuple(arg);
1891 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001893 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1894 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001895
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001896 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 if (Tcl_SplitList(Tkapp_Interp(self), list,
1898 &argc, &argv) == TCL_ERROR) {
1899 PyMem_Free(list);
1900 return Tkinter_Error(self);
1901 }
Guido van Rossum18468821994-06-20 07:49:28 +00001902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 if (!(v = PyTuple_New(argc)))
1904 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001906 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001907 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 if (!s || PyTuple_SetItem(v, i, s)) {
1909 Py_DECREF(v);
1910 v = NULL;
1911 goto finally;
1912 }
1913 }
Guido van Rossum18468821994-06-20 07:49:28 +00001914
Barry Warsawfa701a81997-01-16 00:15:11 +00001915 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001916 ckfree(FREECAST argv);
1917 PyMem_Free(list);
1918 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001919}
1920
1921static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001922Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001923{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001924 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001926
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001927 if (!PyArg_ParseTuple(args, "O:split", &arg))
1928 return NULL;
1929 if (PyTclObject_Check(arg)) {
1930 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1931 int objc;
1932 Tcl_Obj **objv;
1933 int i;
1934 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1935 &objc, &objv) == TCL_ERROR) {
1936 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001937 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001938 if (objc == 0)
1939 return PyUnicode_FromString("");
1940 if (objc == 1)
1941 return FromObj(self, objv[0]);
1942 if (!(v = PyTuple_New(objc)))
1943 return NULL;
1944 for (i = 0; i < objc; i++) {
1945 PyObject *s = FromObj(self, objv[i]);
1946 if (!s || PyTuple_SetItem(v, i, s)) {
1947 Py_DECREF(v);
1948 return NULL;
1949 }
1950 }
1951 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001952 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001953 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001954 return SplitObj(arg);
1955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1957 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001958 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001959 v = Split(list);
1960 PyMem_Free(list);
1961 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001962}
1963
Barry Warsawfa701a81997-01-16 00:15:11 +00001964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965
Guido van Rossum18468821994-06-20 07:49:28 +00001966/** Tcl Command **/
1967
Guido van Rossum00d93061998-05-28 23:06:38 +00001968/* Client data struct */
1969typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970 PyObject *self;
1971 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001972} PythonCmd_ClientData;
1973
1974static int
Fred Drake509d79a2000-07-08 04:04:38 +00001975PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 errorInCmd = 1;
1978 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1979 LEAVE_PYTHON
1980 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001981}
1982
Guido van Rossum18468821994-06-20 07:49:28 +00001983/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001984 * function or method.
1985 */
Guido van Rossum18468821994-06-20 07:49:28 +00001986static int
Fred Drake509d79a2000-07-08 04:04:38 +00001987PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001988{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001990 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001991 int i, rv;
1992 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996 /* TBD: no error checking here since we know, via the
1997 * Tkapp_CreateCommand() that the client data is a two-tuple
1998 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 /* Create argument list (argv1, ..., argvN) */
2002 if (!(arg = PyTuple_New(argc - 1)))
2003 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002006 PyObject *s = unicodeFromTclString(argv[i + 1]);
2007 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 Py_DECREF(arg);
2009 return PythonCmd_Error(interp);
2010 }
2011 }
2012 res = PyEval_CallObject(func, arg);
2013 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 if (res == NULL)
2016 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 obj_res = AsObj(res);
2019 if (obj_res == NULL) {
2020 Py_DECREF(res);
2021 return PythonCmd_Error(interp);
2022 }
2023 else {
2024 Tcl_SetObjResult(interp, obj_res);
2025 rv = TCL_OK;
2026 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002028 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002030 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002032 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002033}
2034
2035static void
Fred Drake509d79a2000-07-08 04:04:38 +00002036PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002038 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002040 ENTER_PYTHON
2041 Py_XDECREF(data->self);
2042 Py_XDECREF(data->func);
2043 PyMem_DEL(data);
2044 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002045}
2046
Barry Warsawfa701a81997-01-16 00:15:11 +00002047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002049
Benjamin Peterson5879d412009-03-30 14:51:56 +00002050#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002051TCL_DECLARE_MUTEX(command_mutex)
2052
2053typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002054 Tcl_Event ev;
2055 Tcl_Interp* interp;
2056 char *name;
2057 int create;
2058 int *status;
2059 ClientData *data;
2060 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002061} CommandEvent;
2062
2063static int
2064Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002065{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002066 if (ev->create)
2067 *ev->status = Tcl_CreateCommand(
2068 ev->interp, ev->name, PythonCmd,
2069 ev->data, PythonCmdDelete) == NULL;
2070 else
2071 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2072 Tcl_MutexLock(&command_mutex);
2073 Tcl_ConditionNotify(ev->done);
2074 Tcl_MutexUnlock(&command_mutex);
2075 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002076}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002077#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002078
2079static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002080Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002082 TkappObject *self = (TkappObject*)selfptr;
2083 PythonCmd_ClientData *data;
2084 char *cmdName;
2085 PyObject *func;
2086 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2089 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002090 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002091 if (!PyCallable_Check(func)) {
2092 PyErr_SetString(PyExc_TypeError, "command not callable");
2093 return NULL;
2094 }
Guido van Rossum18468821994-06-20 07:49:28 +00002095
Martin v. Löwisa9656492003-03-30 08:44:58 +00002096#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002097 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2098 !WaitForMainloop(self))
2099 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002100#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 data = PyMem_NEW(PythonCmd_ClientData, 1);
2103 if (!data)
2104 return PyErr_NoMemory();
2105 Py_INCREF(self);
2106 Py_INCREF(func);
2107 data->self = selfptr;
2108 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002109#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2111 Tcl_Condition cond = NULL;
2112 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2113 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2114 ev->interp = self->interp;
2115 ev->create = 1;
2116 ev->name = cmdName;
2117 ev->data = (ClientData)data;
2118 ev->status = &err;
2119 ev->done = &cond;
2120 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2121 Tcl_ConditionFinalize(&cond);
2122 }
2123 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002124#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002125 {
2126 ENTER_TCL
2127 err = Tcl_CreateCommand(
2128 Tkapp_Interp(self), cmdName, PythonCmd,
2129 (ClientData)data, PythonCmdDelete) == NULL;
2130 LEAVE_TCL
2131 }
2132 if (err) {
2133 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2134 PyMem_DEL(data);
2135 return NULL;
2136 }
Guido van Rossum18468821994-06-20 07:49:28 +00002137
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002138 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002139}
2140
Barry Warsawfa701a81997-01-16 00:15:11 +00002141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142
Guido van Rossum18468821994-06-20 07:49:28 +00002143static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002144Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002145{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002146 TkappObject *self = (TkappObject*)selfptr;
2147 char *cmdName;
2148 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2151 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002152 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002153
2154#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002155 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2156 Tcl_Condition cond = NULL;
2157 CommandEvent *ev;
2158 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2159 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2160 ev->interp = self->interp;
2161 ev->create = 0;
2162 ev->name = cmdName;
2163 ev->status = &err;
2164 ev->done = &cond;
2165 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2166 &command_mutex);
2167 Tcl_ConditionFinalize(&cond);
2168 }
2169 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002170#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 {
2172 ENTER_TCL
2173 err = Tcl_DeleteCommand(self->interp, cmdName);
2174 LEAVE_TCL
2175 }
2176 if (err == -1) {
2177 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2178 return NULL;
2179 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002180 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002181}
2182
Barry Warsawfa701a81997-01-16 00:15:11 +00002183
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002184
Guido van Rossum00d93061998-05-28 23:06:38 +00002185#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002186/** File Handler **/
2187
Guido van Rossum00d93061998-05-28 23:06:38 +00002188typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002189 PyObject *func;
2190 PyObject *file;
2191 int id;
2192 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002193} FileHandler_ClientData;
2194
2195static FileHandler_ClientData *HeadFHCD;
2196
2197static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002198NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002199{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 FileHandler_ClientData *p;
2201 p = PyMem_NEW(FileHandler_ClientData, 1);
2202 if (p != NULL) {
2203 Py_XINCREF(func);
2204 Py_XINCREF(file);
2205 p->func = func;
2206 p->file = file;
2207 p->id = id;
2208 p->next = HeadFHCD;
2209 HeadFHCD = p;
2210 }
2211 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002212}
2213
2214static void
Fred Drake509d79a2000-07-08 04:04:38 +00002215DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002216{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002219 pp = &HeadFHCD;
2220 while ((p = *pp) != NULL) {
2221 if (p->id == id) {
2222 *pp = p->next;
2223 Py_XDECREF(p->func);
2224 Py_XDECREF(p->file);
2225 PyMem_DEL(p);
2226 }
2227 else
2228 pp = &p->next;
2229 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002230}
2231
Guido van Rossuma597dde1995-01-10 20:56:29 +00002232static void
Fred Drake509d79a2000-07-08 04:04:38 +00002233FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002234{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2236 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002237
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002238 ENTER_PYTHON
2239 func = data->func;
2240 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002242 arg = Py_BuildValue("(Oi)", file, (long) mask);
2243 res = PyEval_CallObject(func, arg);
2244 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002246 if (res == NULL) {
2247 errorInCmd = 1;
2248 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2249 }
2250 Py_XDECREF(res);
2251 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002252}
2253
Guido van Rossum18468821994-06-20 07:49:28 +00002254static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002255Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2256 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002257{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 FileHandler_ClientData *data;
2259 PyObject *file, *func;
2260 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002262 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2263 &file, &mask, &func))
2264 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002266 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268 tfile = PyObject_AsFileDescriptor(file);
2269 if (tfile < 0)
2270 return NULL;
2271 if (!PyCallable_Check(func)) {
2272 PyErr_SetString(PyExc_TypeError, "bad argument list");
2273 return NULL;
2274 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002276 data = NewFHCD(func, file, tfile);
2277 if (data == NULL)
2278 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 /* Ought to check for null Tcl_File object... */
2281 ENTER_TCL
2282 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2283 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002284 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002285}
2286
2287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002288Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002289{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002290 PyObject *file;
2291 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002293 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2294 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002296 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 tfile = PyObject_AsFileDescriptor(file);
2299 if (tfile < 0)
2300 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 /* Ought to check for null Tcl_File object... */
2305 ENTER_TCL
2306 Tcl_DeleteFileHandler(tfile);
2307 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002308 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002309}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002310#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002313/**** Tktt Object (timer token) ****/
2314
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002315static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002316
Guido van Rossum00d93061998-05-28 23:06:38 +00002317typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002318 PyObject_HEAD
2319 Tcl_TimerToken token;
2320 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002321} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322
2323static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002324Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002325{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 TkttObject *v = (TkttObject *)self;
2327 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002329 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2330 return NULL;
2331 if (v->token != NULL) {
2332 Tcl_DeleteTimerHandler(v->token);
2333 v->token = NULL;
2334 }
2335 if (func != NULL) {
2336 v->func = NULL;
2337 Py_DECREF(func);
2338 Py_DECREF(v); /* See Tktt_New() */
2339 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002340 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002341}
2342
2343static PyMethodDef Tktt_methods[] =
2344{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2346 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347};
2348
2349static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002350Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002353
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002354 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002355 if (v == NULL)
2356 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002357 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 Py_INCREF(func);
2360 v->token = NULL;
2361 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002362
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 /* Extra reference, deleted when called or when handler is deleted */
2364 Py_INCREF(v);
2365 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366}
2367
2368static void
Fred Drake509d79a2000-07-08 04:04:38 +00002369Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 TkttObject *v = (TkttObject *)self;
2372 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002373 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002377 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002378 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002379}
2380
Guido van Rossum597ac201998-05-12 14:36:19 +00002381static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002382Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002385 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2386 v,
2387 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388}
2389
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002390static PyType_Slot Tktt_Type_slots[] = {
2391 {Py_tp_dealloc, Tktt_Dealloc},
2392 {Py_tp_repr, Tktt_Repr},
2393 {Py_tp_methods, Tktt_methods},
2394 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395};
2396
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002397static PyType_Spec Tktt_Type_spec = {
2398 "tktimertoken",
2399 sizeof(TkttObject),
2400 0,
2401 Py_TPFLAGS_DEFAULT,
2402 Tktt_Type_slots,
2403};
Barry Warsawfa701a81997-01-16 00:15:11 +00002404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002405
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406/** Timer Handler **/
2407
2408static void
Fred Drake509d79a2000-07-08 04:04:38 +00002409TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002410{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 TkttObject *v = (TkttObject *)clientData;
2412 PyObject *func = v->func;
2413 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 if (func == NULL)
2416 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422 res = PyEval_CallObject(func, NULL);
2423 Py_DECREF(func);
2424 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 if (res == NULL) {
2427 errorInCmd = 1;
2428 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2429 }
2430 else
2431 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002433 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434}
2435
2436static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002437Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002438{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439 int milliseconds;
2440 PyObject *func;
2441 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2444 &milliseconds, &func))
2445 return NULL;
2446 if (!PyCallable_Check(func)) {
2447 PyErr_SetString(PyExc_TypeError, "bad argument list");
2448 return NULL;
2449 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 v = Tktt_New(func);
2454 if (v) {
2455 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2456 (ClientData)v);
2457 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002460}
2461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462
Guido van Rossum18468821994-06-20 07:49:28 +00002463/** Event Loop **/
2464
Guido van Rossum18468821994-06-20 07:49:28 +00002465static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002466Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468 int threshold = 0;
2469 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002470#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002472#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2475 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 CHECK_TCL_APPARTMENT;
2478 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480 quitMainLoop = 0;
2481 while (Tk_GetNumMainWindows() > threshold &&
2482 !quitMainLoop &&
2483 !errorInCmd)
2484 {
2485 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002486
2487#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 if (self->threaded) {
2489 /* Allow other Python threads to run. */
2490 ENTER_TCL
2491 result = Tcl_DoOneEvent(0);
2492 LEAVE_TCL
2493 }
2494 else {
2495 Py_BEGIN_ALLOW_THREADS
2496 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2497 tcl_tstate = tstate;
2498 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2499 tcl_tstate = NULL;
2500 if(tcl_lock)PyThread_release_lock(tcl_lock);
2501 if (result == 0)
2502 Sleep(Tkinter_busywaitinterval);
2503 Py_END_ALLOW_THREADS
2504 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002505#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002507#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 if (PyErr_CheckSignals() != 0) {
2510 self->dispatching = 0;
2511 return NULL;
2512 }
2513 if (result < 0)
2514 break;
2515 }
2516 self->dispatching = 0;
2517 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002519 if (errorInCmd) {
2520 errorInCmd = 0;
2521 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2522 excInCmd = valInCmd = trbInCmd = NULL;
2523 return NULL;
2524 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002525 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002526}
2527
2528static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002529Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002530{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 int flags = 0;
2532 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002533
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2535 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537 ENTER_TCL
2538 rv = Tcl_DoOneEvent(flags);
2539 LEAVE_TCL
2540 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002541}
2542
2543static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002544Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002545{
2546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 if (!PyArg_ParseTuple(args, ":quit"))
2548 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002550 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002551 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002552}
2553
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002554static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002555Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002556{
2557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002558 if (!PyArg_ParseTuple(args, ":interpaddr"))
2559 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002560
Victor Stinnere1040e22013-09-05 00:22:24 +02002561 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002562}
2563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002565Tkapp_TkInit(PyObject *self, PyObject *args)
2566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 Tcl_Interp *interp = Tkapp_Interp(self);
2568 const char * _tk_exists = NULL;
2569 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002570
Guilherme Polob681df42009-02-09 22:33:59 +00002571#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2573 * first call failed.
2574 * To avoid the deadlock, we just refuse the second call through
2575 * a static variable.
2576 */
2577 if (tk_load_failed) {
2578 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2579 return NULL;
2580 }
Guilherme Polob681df42009-02-09 22:33:59 +00002581#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 /* We want to guard against calling Tk_Init() multiple times */
2584 CHECK_TCL_APPARTMENT;
2585 ENTER_TCL
2586 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2587 ENTER_OVERLAP
2588 if (err == TCL_ERROR) {
2589 /* This sets an exception, but we cannot return right
2590 away because we need to exit the overlap first. */
2591 Tkinter_Error(self);
2592 } else {
2593 _tk_exists = Tkapp_Result(self);
2594 }
2595 LEAVE_OVERLAP_TCL
2596 if (err == TCL_ERROR) {
2597 return NULL;
2598 }
2599 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2600 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002601 PyErr_SetString(Tkinter_TclError,
2602 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002603#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002605#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002606 return NULL;
2607 }
2608 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002609 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002610}
Barry Warsawfa701a81997-01-16 00:15:11 +00002611
Martin v. Löwisffad6332002-11-26 09:28:05 +00002612static PyObject *
2613Tkapp_WantObjects(PyObject *self, PyObject *args)
2614{
2615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002616 int wantobjects = -1;
2617 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2618 return NULL;
2619 if (wantobjects == -1)
2620 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2621 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002622
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002623 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002624}
2625
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002626static PyObject *
2627Tkapp_WillDispatch(PyObject *self, PyObject *args)
2628{
2629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002631
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002632 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002633}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635
Guido van Rossum18468821994-06-20 07:49:28 +00002636/**** Tkapp Method List ****/
2637
2638static PyMethodDef Tkapp_methods[] =
2639{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002640 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2641 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2642 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002643 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002644 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2645 {"record", Tkapp_Record, METH_VARARGS},
2646 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2647 {"setvar", Tkapp_SetVar, METH_VARARGS},
2648 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2649 {"getvar", Tkapp_GetVar, METH_VARARGS},
2650 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2651 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2652 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2653 {"getint", Tkapp_GetInt, METH_VARARGS},
2654 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2655 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2656 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2657 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2658 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2659 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2660 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2661 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002662 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2663 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002664#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002665 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2666 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002667#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2669 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2670 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2671 {"quit", Tkapp_Quit, METH_VARARGS},
2672 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2673 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2674 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002675};
2676
Barry Warsawfa701a81997-01-16 00:15:11 +00002677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678
Guido van Rossum18468821994-06-20 07:49:28 +00002679/**** Tkapp Type Methods ****/
2680
2681static void
Fred Drake509d79a2000-07-08 04:04:38 +00002682Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002683{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002684 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002685 /*CHECK_TCL_APPARTMENT;*/
2686 ENTER_TCL
2687 Tcl_DeleteInterp(Tkapp_Interp(self));
2688 LEAVE_TCL
2689 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002690 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002691 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002692}
2693
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002694static PyType_Slot Tkapp_Type_slots[] = {
2695 {Py_tp_dealloc, Tkapp_Dealloc},
2696 {Py_tp_methods, Tkapp_methods},
2697 {0, 0}
2698};
2699
2700
2701static PyType_Spec Tkapp_Type_spec = {
2702 "tkapp",
2703 sizeof(TkappObject),
2704 0,
2705 Py_TPFLAGS_DEFAULT,
2706 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002707};
2708
Barry Warsawfa701a81997-01-16 00:15:11 +00002709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002710
Guido van Rossum18468821994-06-20 07:49:28 +00002711/**** Tkinter Module ****/
2712
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002713typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002714 PyObject* tuple;
2715 int size; /* current size */
2716 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002717} FlattenContext;
2718
2719static int
2720_bump(FlattenContext* context, int size)
2721{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002722 /* expand tuple to hold (at least) size new items.
2723 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 if (maxsize < context->size + size)
2728 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002729
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002730 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002732 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002733}
2734
2735static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002736_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002740 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 if (depth > 1000) {
2743 PyErr_SetString(PyExc_ValueError,
2744 "nesting too deep in _flatten");
2745 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002746 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2747 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002748 /* preallocate (assume no nesting) */
2749 if (context->size + size > context->maxsize &&
2750 !_bump(context, size))
2751 return 0;
2752 /* copy items to output tuple */
2753 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002754 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755 if (PyList_Check(o) || PyTuple_Check(o)) {
2756 if (!_flatten1(context, o, depth + 1))
2757 return 0;
2758 } else if (o != Py_None) {
2759 if (context->size + 1 > context->maxsize &&
2760 !_bump(context, 1))
2761 return 0;
2762 Py_INCREF(o);
2763 PyTuple_SET_ITEM(context->tuple,
2764 context->size++, o);
2765 }
2766 }
2767 } else {
2768 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2769 return 0;
2770 }
2771 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772}
2773
2774static PyObject *
2775Tkinter_Flatten(PyObject* self, PyObject* args)
2776{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 FlattenContext context;
2778 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2781 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002782
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002783 context.maxsize = PySequence_Size(item);
2784 if (context.maxsize < 0)
2785 return NULL;
2786 if (context.maxsize == 0)
2787 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002789 context.tuple = PyTuple_New(context.maxsize);
2790 if (!context.tuple)
2791 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002794
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 if (!_flatten1(&context, item,0))
2796 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 if (_PyTuple_Resize(&context.tuple, context.size))
2799 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002802}
2803
Guido van Rossum18468821994-06-20 07:49:28 +00002804static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002805Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002806{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 char *screenName = NULL;
2808 char *baseName = NULL; /* XXX this is not used anymore;
2809 try getting rid of it. */
2810 char *className = NULL;
2811 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03002812 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2814 int sync = 0; /* pass -sync to wish */
2815 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002818
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2820 &screenName, &baseName, &className,
2821 &interactive, &wantobjects, &wantTk,
2822 &sync, &use))
2823 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002824 CHECK_STRING_LENGTH(screenName);
2825 CHECK_STRING_LENGTH(baseName);
2826 CHECK_STRING_LENGTH(className);
2827 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002828
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002829 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002830 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002832}
2833
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002834static PyObject *
2835Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2836{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 int new_val;
2838 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2839 return NULL;
2840 if (new_val < 0) {
2841 PyErr_SetString(PyExc_ValueError,
2842 "busywaitinterval must be >= 0");
2843 return NULL;
2844 }
2845 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002846 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002847}
2848
2849static char setbusywaitinterval_doc[] =
2850"setbusywaitinterval(n) -> None\n\
2851\n\
2852Set the busy-wait interval in milliseconds between successive\n\
2853calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2854It should be set to a divisor of the maximum time between\n\
2855frames in an animation.";
2856
2857static PyObject *
2858Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2859{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002860 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002861}
2862
2863static char getbusywaitinterval_doc[] =
2864"getbusywaitinterval() -> int\n\
2865\n\
2866Return the current busy-wait interval between successive\n\
2867calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2868
Guido van Rossum18468821994-06-20 07:49:28 +00002869static PyMethodDef moduleMethods[] =
2870{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2872 {"create", Tkinter_Create, METH_VARARGS},
2873 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2874 setbusywaitinterval_doc},
2875 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2876 METH_NOARGS, getbusywaitinterval_doc},
2877 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002878};
2879
Guido van Rossum7bf15641998-05-22 18:28:17 +00002880#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002881
2882static int stdin_ready = 0;
2883
Guido van Rossumad4db171998-06-13 13:56:28 +00002884#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002885static void
Fred Drake509d79a2000-07-08 04:04:38 +00002886MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002887{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002889}
Guido van Rossumad4db171998-06-13 13:56:28 +00002890#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002891
Martin v. Löwisa9656492003-03-30 08:44:58 +00002892#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002893static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002894#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002895
Guido van Rossum18468821994-06-20 07:49:28 +00002896static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002897EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002898{
Guido van Rossumad4db171998-06-13 13:56:28 +00002899#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002901#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002902#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002904#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002905 stdin_ready = 0;
2906 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002907#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002908 tfile = fileno(stdin);
2909 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002910#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002911 while (!errorInCmd && !stdin_ready) {
2912 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002913#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 if (_kbhit()) {
2915 stdin_ready = 1;
2916 break;
2917 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002918#endif
2919#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002920 Py_BEGIN_ALLOW_THREADS
2921 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2922 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002924 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 tcl_tstate = NULL;
2927 if(tcl_lock)PyThread_release_lock(tcl_lock);
2928 if (result == 0)
2929 Sleep(Tkinter_busywaitinterval);
2930 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002931#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002933#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 if (result < 0)
2936 break;
2937 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002938#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002940#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002941 if (errorInCmd) {
2942 errorInCmd = 0;
2943 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2944 excInCmd = valInCmd = trbInCmd = NULL;
2945 PyErr_Print();
2946 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002947#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002949#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002951}
Guido van Rossum18468821994-06-20 07:49:28 +00002952
Guido van Rossum00d93061998-05-28 23:06:38 +00002953#endif
2954
Guido van Rossum7bf15641998-05-22 18:28:17 +00002955static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002956EnableEventHook(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 (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002960#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002962#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963 PyOS_InputHook = EventHook;
2964 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002965#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002966}
2967
2968static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002969DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002970{
Guido van Rossum00d93061998-05-28 23:06:38 +00002971#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002972 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2973 PyOS_InputHook = NULL;
2974 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002975#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002976}
2977
Barry Warsawfa701a81997-01-16 00:15:11 +00002978
Martin v. Löwis1a214512008-06-11 05:26:20 +00002979static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002980 PyModuleDef_HEAD_INIT,
2981 "_tkinter",
2982 NULL,
2983 -1,
2984 moduleMethods,
2985 NULL,
2986 NULL,
2987 NULL,
2988 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002989};
2990
Mark Hammond62b1ab12002-07-23 06:31:15 +00002991PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002992PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002993{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002994 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002995
Guido van Rossum00d93061998-05-28 23:06:38 +00002996#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002997 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002998 if (tcl_lock == NULL)
2999 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003000#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003001
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003002 m = PyModule_Create(&_tkintermodule);
3003 if (m == NULL)
3004 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003005
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003006 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3007 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003008 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003009 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003010 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003011 Py_INCREF(o);
3012 if (PyModule_AddObject(m, "TclError", o)) {
3013 Py_DECREF(o);
3014 Py_DECREF(m);
3015 return NULL;
3016 }
3017 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003018
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003019 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3020 Py_DECREF(m);
3021 return NULL;
3022 }
3023 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3024 Py_DECREF(m);
3025 return NULL;
3026 }
3027 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3028 Py_DECREF(m);
3029 return NULL;
3030 }
3031 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3032 Py_DECREF(m);
3033 return NULL;
3034 }
3035 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3036 Py_DECREF(m);
3037 return NULL;
3038 }
3039 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3040 Py_DECREF(m);
3041 return NULL;
3042 }
3043 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3044 Py_DECREF(m);
3045 return NULL;
3046 }
3047 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3048 Py_DECREF(m);
3049 return NULL;
3050 }
3051 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3052 Py_DECREF(m);
3053 return NULL;
3054 }
3055 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3056 Py_DECREF(m);
3057 return NULL;
3058 }
3059 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3060 Py_DECREF(m);
3061 return NULL;
3062 }
3063
3064 o = PyType_FromSpec(&Tkapp_Type_spec);
3065 if (o == NULL) {
3066 Py_DECREF(m);
3067 return NULL;
3068 }
3069 if (PyModule_AddObject(m, "TkappType", o)) {
3070 Py_DECREF(o);
3071 Py_DECREF(m);
3072 return NULL;
3073 }
3074 Tkapp_Type = o;
3075
3076 o = PyType_FromSpec(&Tktt_Type_spec);
3077 if (o == NULL) {
3078 Py_DECREF(m);
3079 return NULL;
3080 }
3081 if (PyModule_AddObject(m, "TkttType", o)) {
3082 Py_DECREF(o);
3083 Py_DECREF(m);
3084 return NULL;
3085 }
3086 Tktt_Type = o;
3087
3088 o = PyType_FromSpec(&PyTclObject_Type_spec);
3089 if (o == NULL) {
3090 Py_DECREF(m);
3091 return NULL;
3092 }
3093 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3094 Py_DECREF(o);
3095 Py_DECREF(m);
3096 return NULL;
3097 }
3098 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003099
3100#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3102 * start waking up. Note that Tcl_FindExecutable will do this, this
3103 * code must be above it! The original warning from
3104 * tkMacOSXAppInit.c is copied below.
3105 *
3106 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3107 * Tcl interpreter for now. It probably should work to do this
3108 * in the other order, but for now it doesn't seem to.
3109 *
3110 */
3111 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003112#endif
3113
3114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 /* This helps the dynamic loader; in Unicode aware Tcl versions
3116 it also helps Tcl find its encodings. */
3117 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3118 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003119 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003120 if (cexe)
3121 Tcl_FindExecutable(PyBytes_AsString(cexe));
3122 Py_XDECREF(cexe);
3123 Py_DECREF(uexe);
3124 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003126 if (PyErr_Occurred()) {
3127 Py_DECREF(m);
3128 return NULL;
3129 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003130
Guido van Rossum43ff8681998-07-14 18:02:13 +00003131#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003132 /* This was not a good idea; through <Destroy> bindings,
3133 Tcl_Finalize() may invoke Python code but at that point the
3134 interpreter and thread state have already been destroyed! */
3135 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003136#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003137 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003138}