blob: 43ee6786ae7c5e391f4e6d7ca389cd204c622227 [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) \
Serhiy Storchaka35840562015-02-16 20:54:03 +020037 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030038
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. */
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300245 const Tcl_ObjType *OldBooleanType;
246 const Tcl_ObjType *BooleanType;
247 const Tcl_ObjType *ByteArrayType;
248 const Tcl_ObjType *DoubleType;
249 const Tcl_ObjType *IntType;
250 const Tcl_ObjType *ListType;
251 const Tcl_ObjType *ProcBodyType;
252 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000253} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000254
Guido van Rossum18468821994-06-20 07:49:28 +0000255#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000256#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000257
Guido van Rossum35d43371997-08-02 00:09:09 +0000258#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000259(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000260
Barry Warsawfa701a81997-01-16 00:15:11 +0000261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262
Guido van Rossum18468821994-06-20 07:49:28 +0000263/**** Error Handling ****/
264
265static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000266static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000267static int errorInCmd = 0;
268static PyObject *excInCmd;
269static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000270static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Guilherme Polob681df42009-02-09 22:33:59 +0000272#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000273static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000274#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276
Guido van Rossum18468821994-06-20 07:49:28 +0000277static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000278Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000279{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000280 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
281 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000282}
283
Barry Warsawfa701a81997-01-16 00:15:11 +0000284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285
Guido van Rossum18468821994-06-20 07:49:28 +0000286/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000287
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000288static int Tkinter_busywaitinterval = 20;
289
Guido van Rossum00d93061998-05-28 23:06:38 +0000290#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000291#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000292
Guido van Rossum00d93061998-05-28 23:06:38 +0000293/* Millisecond sleep() for Unix platforms. */
294
295static void
Fred Drake509d79a2000-07-08 04:04:38 +0000296Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 /* XXX Too bad if you don't have select(). */
299 struct timeval t;
300 t.tv_sec = milli/1000;
301 t.tv_usec = (milli%1000) * 1000;
302 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000303}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000304#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000305
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000306/* Wait up to 1s for the mainloop to come up. */
307
308static int
309WaitForMainloop(TkappObject* self)
310{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311 int i;
312 for (i = 0; i < 10; i++) {
313 if (self->dispatching)
314 return 1;
315 Py_BEGIN_ALLOW_THREADS
316 Sleep(100);
317 Py_END_ALLOW_THREADS
318 }
319 if (self->dispatching)
320 return 1;
321 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
322 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000323}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000324#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000327
Guido van Rossum18468821994-06-20 07:49:28 +0000328#define ARGSZ 64
329
Barry Warsawfa701a81997-01-16 00:15:11 +0000330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000331
Guido van Rossum18468821994-06-20 07:49:28 +0000332static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200333unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
334{
335 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
336 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
337 /* Tcl encodes null character as \xc0\x80 */
338 if (memchr(s, '\xc0', size)) {
339 char *buf, *q;
340 const char *e = s + size;
341 PyErr_Clear();
342 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300343 if (buf == NULL) {
344 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200345 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300346 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200347 while (s != e) {
348 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
349 *q++ = '\0';
350 s += 2;
351 }
352 else
353 *q++ = *s++;
354 }
355 s = buf;
356 size = q - s;
357 r = PyUnicode_DecodeUTF8(s, size, NULL);
358 PyMem_Free(buf);
359 }
360 }
361 return r;
362}
363
364static PyObject *
365unicodeFromTclString(const char *s)
366{
367 return unicodeFromTclStringAndSize(s, strlen(s));
368}
369
370static PyObject *
371unicodeFromTclObj(Tcl_Obj *value)
372{
373 int len;
374 char *s = Tcl_GetStringFromObj(value, &len);
375 return unicodeFromTclStringAndSize(s, len);
376}
377
378
379static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000380Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000381{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 int argc;
383 char **argv;
384 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000386 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300387 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 }
Guido van Rossum18468821994-06-20 07:49:28 +0000389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000390 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
391 /* Not a list.
392 * Could be a quoted string containing funnies, e.g. {"}.
393 * Return the string itself.
394 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200395 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 }
Guido van Rossum18468821994-06-20 07:49:28 +0000397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 if (argc == 0)
399 v = PyUnicode_FromString("");
400 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200401 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000402 else if ((v = PyTuple_New(argc)) != NULL) {
403 int i;
404 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000406 for (i = 0; i < argc; i++) {
407 if ((w = Split(argv[i])) == NULL) {
408 Py_DECREF(v);
409 v = NULL;
410 break;
411 }
412 PyTuple_SetItem(v, i, w);
413 }
414 }
415 Tcl_Free(FREECAST argv);
416 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000417}
418
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300419/* In some cases, Tcl will still return strings that are supposed to
420 be lists. SplitObj walks through a nested tuple, finding string
421 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000422
Martin v. Löwis59683e82008-06-13 07:50:45 +0000423static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000424SplitObj(PyObject *arg)
425{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000426 if (PyTuple_Check(arg)) {
427 int i, size;
428 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 size = PyTuple_Size(arg);
431 result = NULL;
432 /* Recursively invoke SplitObj for all tuple items.
433 If this does not return a new object, no action is
434 needed. */
435 for(i = 0; i < size; i++) {
436 elem = PyTuple_GetItem(arg, i);
437 newelem = SplitObj(elem);
438 if (!newelem) {
439 Py_XDECREF(result);
440 return NULL;
441 }
442 if (!result) {
443 int k;
444 if (newelem == elem) {
445 Py_DECREF(newelem);
446 continue;
447 }
448 result = PyTuple_New(size);
449 if (!result)
450 return NULL;
451 for(k = 0; k < i; k++) {
452 elem = PyTuple_GetItem(arg, k);
453 Py_INCREF(elem);
454 PyTuple_SetItem(result, k, elem);
455 }
456 }
457 PyTuple_SetItem(result, i, newelem);
458 }
459 if (result)
460 return result;
461 /* Fall through, returning arg. */
462 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300463 else if (PyUnicode_Check(arg)) {
464 int argc;
465 char **argv;
466 char *list = PyUnicode_AsUTF8(arg);
467
468 if (list == NULL ||
469 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
470 Py_INCREF(arg);
471 return arg;
472 }
473 Tcl_Free(FREECAST argv);
474 if (argc > 1)
475 return Split(list);
476 /* Fall through, returning arg. */
477 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 else if (PyBytes_Check(arg)) {
479 int argc;
480 char **argv;
481 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
484 Py_INCREF(arg);
485 return arg;
486 }
487 Tcl_Free(FREECAST argv);
488 if (argc > 1)
489 return Split(PyBytes_AsString(arg));
490 /* Fall through, returning arg. */
491 }
492 Py_INCREF(arg);
493 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000494}
Barry Warsawfa701a81997-01-16 00:15:11 +0000495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496
Guido van Rossum18468821994-06-20 07:49:28 +0000497/**** Tkapp Object ****/
498
499#ifndef WITH_APPINIT
500int
Fred Drake509d79a2000-07-08 04:04:38 +0000501Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000502{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000505 if (Tcl_Init(interp) == TCL_ERROR) {
506 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
507 return TCL_ERROR;
508 }
Guilherme Polob681df42009-02-09 22:33:59 +0000509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 _tkinter_skip_tk_init = Tcl_GetVar(interp,
511 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
512 if (_tkinter_skip_tk_init != NULL &&
513 strcmp(_tkinter_skip_tk_init, "1") == 0) {
514 return TCL_OK;
515 }
Guilherme Polob681df42009-02-09 22:33:59 +0000516
517#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 if (tk_load_failed) {
519 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
520 return TCL_ERROR;
521 }
Guilherme Polob681df42009-02-09 22:33:59 +0000522#endif
523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000525#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000526 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000527#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
529 return TCL_ERROR;
530 }
Guilherme Polob681df42009-02-09 22:33:59 +0000531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000533}
534#endif /* !WITH_APPINIT */
535
Guido van Rossum18468821994-06-20 07:49:28 +0000536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537
Barry Warsawfa701a81997-01-16 00:15:11 +0000538
539/* Initialize the Tk application; see the `main' function in
540 * `tkMain.c'.
541 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000542
Thomas Wouters58d05102000-07-24 14:43:35 +0000543static void EnableEventHook(void); /* Forward */
544static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000545
Barry Warsawfa701a81997-01-16 00:15:11 +0000546static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000547Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000549{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 TkappObject *v;
551 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000552
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300553 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 if (v == NULL)
555 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200556 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 v->interp = Tcl_CreateInterp();
559 v->wantobjects = wantobjects;
560 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
561 TCL_GLOBAL_ONLY) != NULL;
562 v->thread_id = Tcl_GetCurrentThread();
563 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000564
565#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300567 PyErr_SetString(PyExc_RuntimeError,
568 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 Py_DECREF(v);
570 return 0;
571 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000572#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000573#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 if (v->threaded && tcl_lock) {
575 /* If Tcl is threaded, we don't need the lock. */
576 PyThread_free_lock(tcl_lock);
577 tcl_lock = NULL;
578 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000579#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000580
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300581 v->OldBooleanType = Tcl_GetObjType("boolean");
582 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 v->ByteArrayType = Tcl_GetObjType("bytearray");
584 v->DoubleType = Tcl_GetObjType("double");
585 v->IntType = Tcl_GetObjType("int");
586 v->ListType = Tcl_GetObjType("list");
587 v->ProcBodyType = Tcl_GetObjType("procbody");
588 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 /* Delete the 'exit' command, which can screw things up */
591 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (screenName != NULL)
594 Tcl_SetVar2(v->interp, "env", "DISPLAY",
595 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 if (interactive)
598 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
599 else
600 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka07940882014-09-11 10:38:54 +0300603 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000604 if (!argv0) {
605 PyErr_NoMemory();
606 Py_DECREF(v);
607 return NULL;
608 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200611 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
612 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
614 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 if (! wantTk) {
617 Tcl_SetVar(v->interp,
618 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
619 }
Guilherme Polob681df42009-02-09 22:33:59 +0000620#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 else if (tk_load_failed) {
622 Tcl_SetVar(v->interp,
623 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
624 }
Guilherme Polob681df42009-02-09 22:33:59 +0000625#endif
David Aschere2b4b322004-02-18 05:59:53 +0000626
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 /* some initial arguments need to be in argv */
628 if (sync || use) {
629 char *args;
630 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 if (sync)
633 len += sizeof "-sync";
634 if (use)
635 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000636
Serhiy Storchaka07940882014-09-11 10:38:54 +0300637 args = (char*)attemptckalloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 if (!args) {
639 PyErr_NoMemory();
640 Py_DECREF(v);
641 return NULL;
642 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 args[0] = '\0';
645 if (sync)
646 strcat(args, "-sync");
647 if (use) {
648 if (sync)
649 strcat(args, " ");
650 strcat(args, "-use ");
651 strcat(args, use);
652 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
655 ckfree(args);
656 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 if (Tcl_AppInit(v->interp) != TCL_OK) {
659 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000660#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 if (wantTk) {
662 const char *_tkinter_tk_failed;
663 _tkinter_tk_failed = Tcl_GetVar(v->interp,
664 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 if ( _tkinter_tk_failed != NULL &&
667 strcmp(_tkinter_tk_failed, "1") == 0) {
668 tk_load_failed = 1;
669 }
670 }
Guilherme Polob681df42009-02-09 22:33:59 +0000671#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 Py_DECREF((PyObject *)v);
673 return (TkappObject *)result;
674 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000679}
680
Barry Warsawfa701a81997-01-16 00:15:11 +0000681
Benjamin Peterson5879d412009-03-30 14:51:56 +0000682#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000683static void
684Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000686{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 Py_BEGIN_ALLOW_THREADS;
688 Tcl_MutexLock(mutex);
689 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
690 Tcl_ThreadAlert(self->thread_id);
691 Tcl_ConditionWait(cond, mutex, NULL);
692 Tcl_MutexUnlock(mutex);
693 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000694}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000695#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697
Guido van Rossum18468821994-06-20 07:49:28 +0000698/** Tcl Eval **/
699
Martin v. Löwisffad6332002-11-26 09:28:05 +0000700typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 PyObject_HEAD
702 Tcl_Obj *value;
703 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000704} PyTclObject;
705
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300706static PyObject *PyTclObject_Type;
707#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000708
709static PyObject *
710newPyTclObject(Tcl_Obj *arg)
711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300713 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 if (self == NULL)
715 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200716 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 Tcl_IncrRefCount(arg);
718 self->value = arg;
719 self->string = NULL;
720 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000721}
722
723static void
724PyTclObject_dealloc(PyTclObject *self)
725{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200726 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 Tcl_DecrRefCount(self->value);
728 Py_XDECREF(self->string);
729 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200730 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000731}
732
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000733static char*
734PyTclObject_TclString(PyObject *self)
735{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000737}
738
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000739/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000740PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000741"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000742
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000743static PyObject *
744PyTclObject_string(PyTclObject *self, void *ignored)
745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200747 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 if (!self->string)
749 return NULL;
750 }
751 Py_INCREF(self->string);
752 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000753}
754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000756PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000757{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200758 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000759 Py_INCREF(self->string);
760 return self->string;
761 }
762 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200763 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000764}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000765
Martin v. Löwisffad6332002-11-26 09:28:05 +0000766static PyObject *
767PyTclObject_repr(PyTclObject *self)
768{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300769 PyObject *repr, *str = PyTclObject_str(self, NULL);
770 if (str == NULL)
771 return NULL;
772 repr = PyUnicode_FromFormat("<%s object: %R>",
773 self->value->typePtr->name, str);
774 Py_DECREF(str);
775 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000776}
777
Mark Dickinson211c6252009-02-01 10:28:51 +0000778#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
779
780static PyObject *
781PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000782{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000783 int result;
784 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786 /* neither argument should be NULL, unless something's gone wrong */
787 if (self == NULL || other == NULL) {
788 PyErr_BadInternalCall();
789 return NULL;
790 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 /* both arguments should be instances of PyTclObject */
793 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
794 v = Py_NotImplemented;
795 goto finished;
796 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 if (self == other)
799 /* fast path when self and other are identical */
800 result = 0;
801 else
802 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
803 Tcl_GetString(((PyTclObject *)other)->value));
804 /* Convert return value to a Boolean */
805 switch (op) {
806 case Py_EQ:
807 v = TEST_COND(result == 0);
808 break;
809 case Py_NE:
810 v = TEST_COND(result != 0);
811 break;
812 case Py_LE:
813 v = TEST_COND(result <= 0);
814 break;
815 case Py_GE:
816 v = TEST_COND(result >= 0);
817 break;
818 case Py_LT:
819 v = TEST_COND(result < 0);
820 break;
821 case Py_GT:
822 v = TEST_COND(result > 0);
823 break;
824 default:
825 PyErr_BadArgument();
826 return NULL;
827 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000828 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000829 Py_INCREF(v);
830 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000831}
832
Martin v. Löwis39195712003-01-04 00:33:13 +0000833PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
834
Martin v. Löwisffad6332002-11-26 09:28:05 +0000835static PyObject*
836get_typename(PyTclObject* obj, void* ignored)
837{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200838 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000839}
840
Martin v. Löwis39195712003-01-04 00:33:13 +0000841
Martin v. Löwisffad6332002-11-26 09:28:05 +0000842static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 {"typename", (getter)get_typename, NULL, get_typename__doc__},
844 {"string", (getter)PyTclObject_string, NULL,
845 PyTclObject_string__doc__},
846 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000847};
848
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300849static PyType_Slot PyTclObject_Type_slots[] = {
850 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
851 {Py_tp_repr, (reprfunc)PyTclObject_repr},
852 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200853 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300854 {Py_tp_richcompare, PyTclObject_richcompare},
855 {Py_tp_getset, PyTclObject_getsetlist},
856 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000857};
858
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300859static PyType_Spec PyTclObject_Type_spec = {
860 "_tkinter.Tcl_Obj",
861 sizeof(PyTclObject),
862 0,
863 Py_TPFLAGS_DEFAULT,
864 PyTclObject_Type_slots,
865};
866
867
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300868#if PY_SIZE_MAX > INT_MAX
869#define CHECK_STRING_LENGTH(s) do { \
870 if (s != NULL && strlen(s) >= INT_MAX) { \
871 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
872 return NULL; \
873 } } while(0)
874#else
875#define CHECK_STRING_LENGTH(s)
876#endif
877
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000878static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000879AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000880{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 Tcl_Obj *result;
882 long longVal;
883 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000884
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000885 if (PyBytes_Check(value))
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300886 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
887 PyBytes_GET_SIZE(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000888 else if (PyBool_Check(value))
889 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
890 else if (PyLong_CheckExact(value) &&
891 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
892 !overflow)) {
893 /* If there is an overflow in the long conversion,
894 fall through to default object handling. */
895 return Tcl_NewLongObj(longVal);
896 }
897 else if (PyFloat_Check(value))
898 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
899 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300900 Tcl_Obj **argv;
901 Py_ssize_t size, i;
902
903 size = PyTuple_Size(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300904 if (size == 0)
905 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300906 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
907 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
908 return NULL;
909 }
Serhiy Storchaka07940882014-09-11 10:38:54 +0300910 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000911 if(!argv)
912 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300913 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 argv[i] = AsObj(PyTuple_GetItem(value,i));
915 result = Tcl_NewListObj(PyTuple_Size(value), argv);
916 ckfree(FREECAST argv);
917 return result;
918 }
919 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200920 void *inbuf;
921 Py_ssize_t size;
922 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000923 Tcl_UniChar *outbuf = NULL;
924 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200925 size_t allocsize;
926
927 if (PyUnicode_READY(value) == -1)
928 return NULL;
929
930 inbuf = PyUnicode_DATA(value);
931 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300932 if (size == 0)
933 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300934 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
935 PyErr_SetString(PyExc_OverflowError, "string is too long");
936 return NULL;
937 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200938 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200939 if (kind == sizeof(Tcl_UniChar))
940 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200941 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Serhiy Storchaka07940882014-09-11 10:38:54 +0300942 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000943 /* Else overflow occurred, and we take the next exit */
944 if (!outbuf) {
945 PyErr_NoMemory();
946 return NULL;
947 }
948 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200949 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
950 /* We cannot test for sizeof(Tcl_UniChar) directly,
951 so we test for UTF-8 size instead. */
952#if TCL_UTF_MAX == 3
953 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200955 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100956 "character U+%x is above the range "
957 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100958 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000959 ckfree(FREECAST outbuf);
960 return NULL;
961 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300962#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200963 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000964 }
965 result = Tcl_NewUnicodeObj(outbuf, size);
966 ckfree(FREECAST outbuf);
967 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000968 }
969 else if(PyTclObject_Check(value)) {
970 Tcl_Obj *v = ((PyTclObject*)value)->value;
971 Tcl_IncrRefCount(v);
972 return v;
973 }
974 else {
975 PyObject *v = PyObject_Str(value);
976 if (!v)
977 return 0;
978 result = AsObj(v);
979 Py_DECREF(v);
980 return result;
981 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000982}
983
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300984static PyObject *
985fromBoolean(PyObject* tkapp, Tcl_Obj *value)
986{
987 int boolValue;
988 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
989 return Tkinter_Error(tkapp);
990 return PyBool_FromLong(boolValue);
991}
992
Martin v. Löwisffad6332002-11-26 09:28:05 +0000993static PyObject*
994FromObj(PyObject* tkapp, Tcl_Obj *value)
995{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000996 PyObject *result = NULL;
997 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300998 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000999
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001001 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001004 if (value->typePtr == app->BooleanType ||
1005 value->typePtr == app->OldBooleanType) {
1006 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001007 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 if (value->typePtr == app->ByteArrayType) {
1010 int size;
1011 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1012 return PyBytes_FromStringAndSize(data, size);
1013 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001015 if (value->typePtr == app->DoubleType) {
1016 return PyFloat_FromDouble(value->internalRep.doubleValue);
1017 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001019 if (value->typePtr == app->IntType) {
1020 return PyLong_FromLong(value->internalRep.longValue);
1021 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001023 if (value->typePtr == app->ListType) {
1024 int size;
1025 int i, status;
1026 PyObject *elem;
1027 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001029 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001030 if (status == TCL_ERROR)
1031 return Tkinter_Error(tkapp);
1032 result = PyTuple_New(size);
1033 if (!result)
1034 return NULL;
1035 for (i = 0; i < size; i++) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001036 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037 if (status == TCL_ERROR) {
1038 Py_DECREF(result);
1039 return Tkinter_Error(tkapp);
1040 }
1041 elem = FromObj(tkapp, tcl_elem);
1042 if (!elem) {
1043 Py_DECREF(result);
1044 return NULL;
1045 }
1046 PyTuple_SetItem(result, i, elem);
1047 }
1048 return result;
1049 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 if (value->typePtr == app->ProcBodyType) {
1052 /* fall through: return tcl object. */
1053 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001056 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001057 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001058 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001060
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001061#if TK_VERSION_HEX >= 0x08050000
1062 if (app->BooleanType == NULL &&
1063 strcmp(value->typePtr->name, "booleanString") == 0) {
1064 /* booleanString type is not registered in Tcl */
1065 app->BooleanType = value->typePtr;
1066 return fromBoolean(tkapp, value);
1067 }
1068#endif
1069
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001071}
1072
Benjamin Peterson5879d412009-03-30 14:51:56 +00001073#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001074/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001075TCL_DECLARE_MUTEX(call_mutex)
1076
1077typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001078 Tcl_Event ev; /* Must be first */
1079 TkappObject *self;
1080 PyObject *args;
1081 int flags;
1082 PyObject **res;
1083 PyObject **exc_type, **exc_value, **exc_tb;
1084 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001085} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001086#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001087
1088void
1089Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 int i;
1092 for (i = 0; i < objc; i++)
1093 Tcl_DecrRefCount(objv[i]);
1094 if (objv != objStore)
1095 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001096}
Guido van Rossum18468821994-06-20 07:49:28 +00001097
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001098/* Convert Python objects to Tcl objects. This must happen in the
1099 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001100
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001101static Tcl_Obj**
1102Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001104 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001105 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 if (args == NULL)
1107 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001109 else if (!PyTuple_Check(args)) {
1110 objv[0] = AsObj(args);
1111 if (objv[0] == 0)
1112 goto finally;
1113 objc = 1;
1114 Tcl_IncrRefCount(objv[0]);
1115 }
1116 else {
1117 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001120 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1121 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1122 return NULL;
1123 }
Serhiy Storchaka07940882014-09-11 10:38:54 +03001124 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001125 if (objv == NULL) {
1126 PyErr_NoMemory();
1127 objc = 0;
1128 goto finally;
1129 }
1130 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 for (i = 0; i < objc; i++) {
1133 PyObject *v = PyTuple_GetItem(args, i);
1134 if (v == Py_None) {
1135 objc = i;
1136 break;
1137 }
1138 objv[i] = AsObj(v);
1139 if (!objv[i]) {
1140 /* Reset objc, so it attempts to clear
1141 objects only up to i. */
1142 objc = i;
1143 goto finally;
1144 }
1145 Tcl_IncrRefCount(objv[i]);
1146 }
1147 }
1148 *pobjc = objc;
1149 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001150finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 Tkapp_CallDeallocArgs(objv, objStore, objc);
1152 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001153}
Guido van Rossum212643f1998-04-29 16:22:14 +00001154
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001155/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001156
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001157static PyObject*
1158Tkapp_CallResult(TkappObject *self)
1159{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001161 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 /* Not sure whether the IncrRef is necessary, but something
1164 may overwrite the interpreter result while we are
1165 converting it. */
1166 Tcl_IncrRefCount(value);
1167 res = FromObj((PyObject*)self, value);
1168 Tcl_DecrRefCount(value);
1169 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001170 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001171 }
1172 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173}
Guido van Rossum632de272000-03-29 00:19:50 +00001174
Benjamin Peterson5879d412009-03-30 14:51:56 +00001175#ifdef WITH_THREAD
1176
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177/* Tkapp_CallProc is the event procedure that is executed in the context of
1178 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1179 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001180
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181static int
1182Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1183{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001184 Tcl_Obj *objStore[ARGSZ];
1185 Tcl_Obj **objv;
1186 int objc;
1187 int i;
1188 ENTER_PYTHON
1189 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1190 if (!objv) {
1191 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1192 *(e->res) = NULL;
1193 }
1194 LEAVE_PYTHON
1195 if (!objv)
1196 goto done;
1197 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1198 ENTER_PYTHON
1199 if (i == TCL_ERROR) {
1200 *(e->res) = NULL;
1201 *(e->exc_type) = NULL;
1202 *(e->exc_tb) = NULL;
1203 *(e->exc_value) = PyObject_CallFunction(
1204 Tkinter_TclError, "s",
1205 Tcl_GetStringResult(e->self->interp));
1206 }
1207 else {
1208 *(e->res) = Tkapp_CallResult(e->self);
1209 }
1210 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001213done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001214 /* Wake up calling thread. */
1215 Tcl_MutexLock(&call_mutex);
1216 Tcl_ConditionNotify(e->done);
1217 Tcl_MutexUnlock(&call_mutex);
1218 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219}
1220
Benjamin Peterson5879d412009-03-30 14:51:56 +00001221#endif
1222
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223/* This is the main entry point for calling a Tcl command.
1224 It supports three cases, with regard to threading:
1225 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1226 the context of the calling thread.
1227 2. Tcl is threaded, caller of the command is in the interpreter thread:
1228 Execute the command in the calling thread. Since the Tcl lock will
1229 not be used, we can merge that with case 1.
1230 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1231 the interpreter thread. Allocation of Tcl objects needs to occur in the
1232 interpreter thread, so we ship the PyObject* args to the target thread,
1233 and perform processing there. */
1234
1235static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001236Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001237{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001238 Tcl_Obj *objStore[ARGSZ];
1239 Tcl_Obj **objv = NULL;
1240 int objc, i;
1241 PyObject *res = NULL;
1242 TkappObject *self = (TkappObject*)selfptr;
1243 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001245 /* If args is a single tuple, replace with contents of tuple */
1246 if (1 == PyTuple_Size(args)){
1247 PyObject* item = PyTuple_GetItem(args, 0);
1248 if (PyTuple_Check(item))
1249 args = item;
1250 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001251#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001252 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1253 /* We cannot call the command directly. Instead, we must
1254 marshal the parameters to the interpreter thread. */
1255 Tkapp_CallEvent *ev;
1256 Tcl_Condition cond = NULL;
1257 PyObject *exc_type, *exc_value, *exc_tb;
1258 if (!WaitForMainloop(self))
1259 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001260 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1261 if (ev == NULL) {
1262 PyErr_NoMemory();
1263 return NULL;
1264 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1266 ev->self = self;
1267 ev->args = args;
1268 ev->res = &res;
1269 ev->exc_type = &exc_type;
1270 ev->exc_value = &exc_value;
1271 ev->exc_tb = &exc_tb;
1272 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 if (res == NULL) {
1277 if (exc_type)
1278 PyErr_Restore(exc_type, exc_value, exc_tb);
1279 else
1280 PyErr_SetObject(Tkinter_TclError, exc_value);
1281 }
1282 Tcl_ConditionFinalize(&cond);
1283 }
1284 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001285#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 objv = Tkapp_CallArgs(args, objStore, &objc);
1289 if (!objv)
1290 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001296 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 if (i == TCL_ERROR)
1299 Tkinter_Error(selfptr);
1300 else
1301 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001305 Tkapp_CallDeallocArgs(objv, objStore, objc);
1306 }
1307 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001308}
1309
1310
1311static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001312Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001313{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 char *script;
1315 PyObject *res = NULL;
1316 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 if (!PyArg_ParseTuple(args, "s:eval", &script))
1319 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001320
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001321 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 ENTER_TCL
1325 err = Tcl_Eval(Tkapp_Interp(self), script);
1326 ENTER_OVERLAP
1327 if (err == TCL_ERROR)
1328 res = Tkinter_Error(self);
1329 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001330 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 LEAVE_OVERLAP_TCL
1332 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001333}
1334
1335static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001336Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001337{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 char *fileName;
1339 PyObject *res = NULL;
1340 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1343 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001344
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001345 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001348 ENTER_TCL
1349 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1350 ENTER_OVERLAP
1351 if (err == TCL_ERROR)
1352 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001354 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 LEAVE_OVERLAP_TCL
1356 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001357}
1358
1359static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001360Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 char *script;
1363 PyObject *res = NULL;
1364 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001365
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001366 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001368
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001369 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 ENTER_TCL
1373 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1374 ENTER_OVERLAP
1375 if (err == TCL_ERROR)
1376 res = Tkinter_Error(self);
1377 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001378 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 LEAVE_OVERLAP_TCL
1380 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001381}
1382
1383static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001384Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001385{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001386 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1389 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001390 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 ENTER_TCL
1394 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1395 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001396
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001397 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001398}
1399
Barry Warsawfa701a81997-01-16 00:15:11 +00001400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401
Guido van Rossum18468821994-06-20 07:49:28 +00001402/** Tcl Variable **/
1403
Benjamin Peterson5879d412009-03-30 14:51:56 +00001404typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1405
1406#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001407TCL_DECLARE_MUTEX(var_mutex)
1408
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 Tcl_Event ev; /* must be first */
1411 PyObject *self;
1412 PyObject *args;
1413 int flags;
1414 EventFunc func;
1415 PyObject **res;
1416 PyObject **exc_type;
1417 PyObject **exc_val;
1418 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001419} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001420#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001421
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001422static int
1423varname_converter(PyObject *in, void *_out)
1424{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001425 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 char **out = (char**)_out;
1427 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001428 if (PyBytes_Size(in) > INT_MAX) {
1429 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1430 return 0;
1431 }
1432 s = PyBytes_AsString(in);
1433 if (strlen(s) != PyBytes_Size(in)) {
1434 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1435 return 0;
1436 }
1437 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 return 1;
1439 }
1440 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001441 Py_ssize_t size;
1442 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001443 if (s == NULL) {
1444 return 0;
1445 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001446 if (size > INT_MAX) {
1447 PyErr_SetString(PyExc_OverflowError, "string is too long");
1448 return 0;
1449 }
1450 if (strlen(s) != size) {
1451 PyErr_SetString(PyExc_ValueError, "null character in string");
1452 return 0;
1453 }
1454 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001455 return 1;
1456 }
1457 if (PyTclObject_Check(in)) {
1458 *out = PyTclObject_TclString(in);
1459 return 1;
1460 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001461 PyErr_Format(PyExc_TypeError,
1462 "must be str, bytes or Tcl_Obj, not %.50s",
1463 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001465}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001466
Benjamin Peterson5879d412009-03-30 14:51:56 +00001467#ifdef WITH_THREAD
1468
Martin v. Löwis59683e82008-06-13 07:50:45 +00001469static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001470var_perform(VarEvent *ev)
1471{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1473 if (!*(ev->res)) {
1474 PyObject *exc, *val, *tb;
1475 PyErr_Fetch(&exc, &val, &tb);
1476 PyErr_NormalizeException(&exc, &val, &tb);
1477 *(ev->exc_type) = exc;
1478 *(ev->exc_val) = val;
1479 Py_DECREF(tb);
1480 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001481
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482}
1483
1484static int
1485var_proc(VarEvent* ev, int flags)
1486{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 ENTER_PYTHON
1488 var_perform(ev);
1489 Tcl_MutexLock(&var_mutex);
1490 Tcl_ConditionNotify(ev->cond);
1491 Tcl_MutexUnlock(&var_mutex);
1492 LEAVE_PYTHON
1493 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001494}
1495
Benjamin Peterson5879d412009-03-30 14:51:56 +00001496#endif
1497
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001499var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001501#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 TkappObject *self = (TkappObject*)selfptr;
1503 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1504 TkappObject *self = (TkappObject*)selfptr;
1505 VarEvent *ev;
1506 PyObject *res, *exc_type, *exc_val;
1507 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001509 /* The current thread is not the interpreter thread. Marshal
1510 the call to the interpreter thread, then wait for
1511 completion. */
1512 if (!WaitForMainloop(self))
1513 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001514
Serhiy Storchaka07940882014-09-11 10:38:54 +03001515 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1516 if (ev == NULL) {
1517 PyErr_NoMemory();
1518 return NULL;
1519 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 ev->self = selfptr;
1521 ev->args = args;
1522 ev->flags = flags;
1523 ev->func = func;
1524 ev->res = &res;
1525 ev->exc_type = &exc_type;
1526 ev->exc_val = &exc_val;
1527 ev->cond = &cond;
1528 ev->ev.proc = (Tcl_EventProc*)var_proc;
1529 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1530 Tcl_ConditionFinalize(&cond);
1531 if (!res) {
1532 PyErr_SetObject(exc_type, exc_val);
1533 Py_DECREF(exc_type);
1534 Py_DECREF(exc_val);
1535 return NULL;
1536 }
1537 return res;
1538 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001539#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001540 /* Tcl is not threaded, or this is the interpreter thread. */
1541 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542}
1543
Guido van Rossum18468821994-06-20 07:49:28 +00001544static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001545SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001546{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 char *name1, *name2;
1548 PyObject *newValue;
1549 PyObject *res = NULL;
1550 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001551
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001552 switch (PyTuple_GET_SIZE(args)) {
1553 case 2:
1554 if (!PyArg_ParseTuple(args, "O&O:setvar",
1555 varname_converter, &name1, &newValue))
1556 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 /* XXX Acquire tcl lock??? */
1558 newval = AsObj(newValue);
1559 if (newval == NULL)
1560 return NULL;
1561 ENTER_TCL
1562 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1563 newval, flags);
1564 ENTER_OVERLAP
1565 if (!ok)
1566 Tkinter_Error(self);
1567 else {
1568 res = Py_None;
1569 Py_INCREF(res);
1570 }
1571 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001572 break;
1573 case 3:
1574 if (!PyArg_ParseTuple(args, "ssO:setvar",
1575 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001577 CHECK_STRING_LENGTH(name1);
1578 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001579 /* XXX must hold tcl lock already??? */
1580 newval = AsObj(newValue);
1581 ENTER_TCL
1582 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1583 ENTER_OVERLAP
1584 if (!ok)
1585 Tkinter_Error(self);
1586 else {
1587 res = Py_None;
1588 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001589 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001590 LEAVE_OVERLAP_TCL
1591 break;
1592 default:
1593 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1594 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001595 }
1596 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001597}
1598
1599static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001600Tkapp_SetVar(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);
Guido van Rossum18468821994-06-20 07:49:28 +00001603}
1604
1605static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001606Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001607{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001609}
1610
Barry Warsawfa701a81997-01-16 00:15:11 +00001611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612
Guido van Rossum18468821994-06-20 07:49:28 +00001613static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001614GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001615{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001616 char *name1, *name2=NULL;
1617 PyObject *res = NULL;
1618 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001620 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1621 varname_converter, &name1, &name2))
1622 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001623
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001624 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 ENTER_TCL
1626 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1627 ENTER_OVERLAP
1628 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001629 PyErr_SetString(Tkinter_TclError,
1630 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 } else {
1632 if (((TkappObject*)self)->wantobjects) {
1633 res = FromObj(self, tres);
1634 }
1635 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001636 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 }
1638 }
1639 LEAVE_OVERLAP_TCL
1640 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001641}
1642
1643static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001644Tkapp_GetVar(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);
Guido van Rossum18468821994-06-20 07:49:28 +00001647}
1648
1649static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001650Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001651{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001652 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001653}
1654
Barry Warsawfa701a81997-01-16 00:15:11 +00001655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001656
Guido van Rossum18468821994-06-20 07:49:28 +00001657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001658UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 char *name1, *name2=NULL;
1661 int code;
1662 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1665 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001666
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001667 CHECK_STRING_LENGTH(name1);
1668 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 ENTER_TCL
1670 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1671 ENTER_OVERLAP
1672 if (code == TCL_ERROR)
1673 res = Tkinter_Error(self);
1674 else {
1675 Py_INCREF(Py_None);
1676 res = Py_None;
1677 }
1678 LEAVE_OVERLAP_TCL
1679 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001680}
1681
1682static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001683Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001684{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001686}
1687
1688static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001689Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001690{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001691 return var_invoke(UnsetVar, self, args,
1692 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001693}
1694
Barry Warsawfa701a81997-01-16 00:15:11 +00001695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696
Guido van Rossum18468821994-06-20 07:49:28 +00001697/** Tcl to Python **/
1698
1699static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001700Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001701{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001702 char *s;
1703 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001705 if (PyTuple_Size(args) == 1) {
1706 PyObject* o = PyTuple_GetItem(args, 0);
1707 if (PyLong_Check(o)) {
1708 Py_INCREF(o);
1709 return o;
1710 }
1711 }
1712 if (!PyArg_ParseTuple(args, "s:getint", &s))
1713 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001714 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1716 return Tkinter_Error(self);
1717 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001718}
1719
1720static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001721Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001722{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001723 char *s;
1724 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 if (PyTuple_Size(args) == 1) {
1727 PyObject *o = PyTuple_GetItem(args, 0);
1728 if (PyFloat_Check(o)) {
1729 Py_INCREF(o);
1730 return o;
1731 }
1732 }
1733 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1734 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001735 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1737 return Tkinter_Error(self);
1738 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001739}
1740
1741static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001742Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001743{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001744 char *s;
1745 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001746
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001747 if (PyTuple_Size(args) == 1) {
1748 PyObject *o = PyTuple_GetItem(args, 0);
1749 if (PyLong_Check(o)) {
1750 Py_INCREF(o);
1751 return o;
1752 }
1753 }
1754 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1755 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001756 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1758 return Tkinter_Error(self);
1759 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001760}
1761
1762static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001763Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001764{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001765 char *s;
1766 PyObject *res = NULL;
1767 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1770 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001771
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001772 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001774
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 ENTER_TCL
1776 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1777 ENTER_OVERLAP
1778 if (retval == TCL_ERROR)
1779 res = Tkinter_Error(self);
1780 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001781 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 LEAVE_OVERLAP_TCL
1783 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001784}
1785
1786static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001787Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001788{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 char *s;
1790 PyObject *res = NULL;
1791 int retval;
1792 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001794 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1795 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001796
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001797 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001798 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001800 ENTER_TCL
1801 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1802 ENTER_OVERLAP
1803 if (retval == TCL_ERROR)
1804 res = Tkinter_Error(self);
1805 else
1806 res = Py_BuildValue("l", v);
1807 LEAVE_OVERLAP_TCL
1808 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001809}
1810
1811static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001812Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001813{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001814 char *s;
1815 PyObject *res = NULL;
1816 double v;
1817 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001818
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1820 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001821 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 CHECK_TCL_APPARTMENT;
1823 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1824 ENTER_TCL
1825 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1826 ENTER_OVERLAP
1827 PyFPE_END_PROTECT(retval)
1828 if (retval == TCL_ERROR)
1829 res = Tkinter_Error(self);
1830 else
1831 res = Py_BuildValue("d", v);
1832 LEAVE_OVERLAP_TCL
1833 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
1836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001837Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001838{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001839 char *s;
1840 PyObject *res = NULL;
1841 int retval;
1842 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001844 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1845 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001846 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 CHECK_TCL_APPARTMENT;
1848 ENTER_TCL
1849 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1850 ENTER_OVERLAP
1851 if (retval == TCL_ERROR)
1852 res = Tkinter_Error(self);
1853 else
1854 res = Py_BuildValue("i", v);
1855 LEAVE_OVERLAP_TCL
1856 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001857}
1858
Barry Warsawfa701a81997-01-16 00:15:11 +00001859
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860
Guido van Rossum18468821994-06-20 07:49:28 +00001861static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001862Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001863{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 char *list;
1865 int argc;
1866 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001867 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001869
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001870 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1871 return NULL;
1872 if (PyTclObject_Check(arg)) {
1873 int objc;
1874 Tcl_Obj **objv;
1875 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1876 ((PyTclObject*)arg)->value,
1877 &objc, &objv) == TCL_ERROR) {
1878 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001879 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001880 if (!(v = PyTuple_New(objc)))
1881 return NULL;
1882 for (i = 0; i < objc; i++) {
1883 PyObject *s = FromObj(self, objv[i]);
1884 if (!s || PyTuple_SetItem(v, i, s)) {
1885 Py_DECREF(v);
1886 return NULL;
1887 }
1888 }
1889 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001891 if (PyTuple_Check(arg)) {
1892 Py_INCREF(arg);
1893 return arg;
1894 }
1895
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1897 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001898
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001899 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001900 if (Tcl_SplitList(Tkapp_Interp(self), list,
1901 &argc, &argv) == TCL_ERROR) {
1902 PyMem_Free(list);
1903 return Tkinter_Error(self);
1904 }
Guido van Rossum18468821994-06-20 07:49:28 +00001905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001906 if (!(v = PyTuple_New(argc)))
1907 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001909 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001910 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001911 if (!s || PyTuple_SetItem(v, i, s)) {
1912 Py_DECREF(v);
1913 v = NULL;
1914 goto finally;
1915 }
1916 }
Guido van Rossum18468821994-06-20 07:49:28 +00001917
Barry Warsawfa701a81997-01-16 00:15:11 +00001918 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001919 ckfree(FREECAST argv);
1920 PyMem_Free(list);
1921 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001922}
1923
1924static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001925Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001926{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001927 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001928 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001930 if (!PyArg_ParseTuple(args, "O:split", &arg))
1931 return NULL;
1932 if (PyTclObject_Check(arg)) {
1933 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1934 int objc;
1935 Tcl_Obj **objv;
1936 int i;
1937 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1938 &objc, &objv) == TCL_ERROR) {
1939 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001941 if (objc == 0)
1942 return PyUnicode_FromString("");
1943 if (objc == 1)
1944 return FromObj(self, objv[0]);
1945 if (!(v = PyTuple_New(objc)))
1946 return NULL;
1947 for (i = 0; i < objc; i++) {
1948 PyObject *s = FromObj(self, objv[i]);
1949 if (!s || PyTuple_SetItem(v, i, s)) {
1950 Py_DECREF(v);
1951 return NULL;
1952 }
1953 }
1954 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001955 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001956 if (PyTuple_Check(arg))
1957 return SplitObj(arg);
1958
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001959 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1960 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001961 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962 v = Split(list);
1963 PyMem_Free(list);
1964 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001965}
1966
Barry Warsawfa701a81997-01-16 00:15:11 +00001967
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968
Guido van Rossum18468821994-06-20 07:49:28 +00001969/** Tcl Command **/
1970
Guido van Rossum00d93061998-05-28 23:06:38 +00001971/* Client data struct */
1972typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001973 PyObject *self;
1974 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001975} PythonCmd_ClientData;
1976
1977static int
Fred Drake509d79a2000-07-08 04:04:38 +00001978PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001979{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001980 errorInCmd = 1;
1981 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1982 LEAVE_PYTHON
1983 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001984}
1985
Guido van Rossum18468821994-06-20 07:49:28 +00001986/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001987 * function or method.
1988 */
Guido van Rossum18468821994-06-20 07:49:28 +00001989static int
Fred Drake509d79a2000-07-08 04:04:38 +00001990PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001991{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001992 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001993 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 int i, rv;
1995 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 /* TBD: no error checking here since we know, via the
2000 * Tkapp_CreateCommand() that the client data is a two-tuple
2001 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002002 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002004 /* Create argument list (argv1, ..., argvN) */
2005 if (!(arg = PyTuple_New(argc - 1)))
2006 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002009 PyObject *s = unicodeFromTclString(argv[i + 1]);
2010 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002011 Py_DECREF(arg);
2012 return PythonCmd_Error(interp);
2013 }
2014 }
2015 res = PyEval_CallObject(func, arg);
2016 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 if (res == NULL)
2019 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002020
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002021 obj_res = AsObj(res);
2022 if (obj_res == NULL) {
2023 Py_DECREF(res);
2024 return PythonCmd_Error(interp);
2025 }
2026 else {
2027 Tcl_SetObjResult(interp, obj_res);
2028 rv = TCL_OK;
2029 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002031 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002032
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002036}
2037
2038static void
Fred Drake509d79a2000-07-08 04:04:38 +00002039PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002040{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002043 ENTER_PYTHON
2044 Py_XDECREF(data->self);
2045 Py_XDECREF(data->func);
2046 PyMem_DEL(data);
2047 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002048}
2049
Barry Warsawfa701a81997-01-16 00:15:11 +00002050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002052
Benjamin Peterson5879d412009-03-30 14:51:56 +00002053#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054TCL_DECLARE_MUTEX(command_mutex)
2055
2056typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002057 Tcl_Event ev;
2058 Tcl_Interp* interp;
2059 char *name;
2060 int create;
2061 int *status;
2062 ClientData *data;
2063 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002064} CommandEvent;
2065
2066static int
2067Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 if (ev->create)
2070 *ev->status = Tcl_CreateCommand(
2071 ev->interp, ev->name, PythonCmd,
2072 ev->data, PythonCmdDelete) == NULL;
2073 else
2074 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2075 Tcl_MutexLock(&command_mutex);
2076 Tcl_ConditionNotify(ev->done);
2077 Tcl_MutexUnlock(&command_mutex);
2078 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002079}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002080#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081
2082static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002083Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 TkappObject *self = (TkappObject*)selfptr;
2086 PythonCmd_ClientData *data;
2087 char *cmdName;
2088 PyObject *func;
2089 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002091 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2092 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002093 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002094 if (!PyCallable_Check(func)) {
2095 PyErr_SetString(PyExc_TypeError, "command not callable");
2096 return NULL;
2097 }
Guido van Rossum18468821994-06-20 07:49:28 +00002098
Martin v. Löwisa9656492003-03-30 08:44:58 +00002099#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2101 !WaitForMainloop(self))
2102 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002103#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002105 data = PyMem_NEW(PythonCmd_ClientData, 1);
2106 if (!data)
2107 return PyErr_NoMemory();
2108 Py_INCREF(self);
2109 Py_INCREF(func);
2110 data->self = selfptr;
2111 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002112#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2114 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002115 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2116 if (ev == NULL) {
2117 PyErr_NoMemory();
2118 PyMem_DEL(data);
2119 return NULL;
2120 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002121 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2122 ev->interp = self->interp;
2123 ev->create = 1;
2124 ev->name = cmdName;
2125 ev->data = (ClientData)data;
2126 ev->status = &err;
2127 ev->done = &cond;
2128 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2129 Tcl_ConditionFinalize(&cond);
2130 }
2131 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002132#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002133 {
2134 ENTER_TCL
2135 err = Tcl_CreateCommand(
2136 Tkapp_Interp(self), cmdName, PythonCmd,
2137 (ClientData)data, PythonCmdDelete) == NULL;
2138 LEAVE_TCL
2139 }
2140 if (err) {
2141 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2142 PyMem_DEL(data);
2143 return NULL;
2144 }
Guido van Rossum18468821994-06-20 07:49:28 +00002145
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002146 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002147}
2148
Barry Warsawfa701a81997-01-16 00:15:11 +00002149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150
Guido van Rossum18468821994-06-20 07:49:28 +00002151static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002152Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002153{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002154 TkappObject *self = (TkappObject*)selfptr;
2155 char *cmdName;
2156 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2159 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002160 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002161
2162#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2164 Tcl_Condition cond = NULL;
2165 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002166 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2167 if (ev == NULL) {
2168 PyErr_NoMemory();
2169 return NULL;
2170 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2172 ev->interp = self->interp;
2173 ev->create = 0;
2174 ev->name = cmdName;
2175 ev->status = &err;
2176 ev->done = &cond;
2177 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2178 &command_mutex);
2179 Tcl_ConditionFinalize(&cond);
2180 }
2181 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002182#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002183 {
2184 ENTER_TCL
2185 err = Tcl_DeleteCommand(self->interp, cmdName);
2186 LEAVE_TCL
2187 }
2188 if (err == -1) {
2189 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2190 return NULL;
2191 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002192 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002193}
2194
Barry Warsawfa701a81997-01-16 00:15:11 +00002195
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002196
Guido van Rossum00d93061998-05-28 23:06:38 +00002197#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002198/** File Handler **/
2199
Guido van Rossum00d93061998-05-28 23:06:38 +00002200typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002201 PyObject *func;
2202 PyObject *file;
2203 int id;
2204 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002205} FileHandler_ClientData;
2206
2207static FileHandler_ClientData *HeadFHCD;
2208
2209static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002210NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002211{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002212 FileHandler_ClientData *p;
2213 p = PyMem_NEW(FileHandler_ClientData, 1);
2214 if (p != NULL) {
2215 Py_XINCREF(func);
2216 Py_XINCREF(file);
2217 p->func = func;
2218 p->file = file;
2219 p->id = id;
2220 p->next = HeadFHCD;
2221 HeadFHCD = p;
2222 }
2223 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002224}
2225
2226static void
Fred Drake509d79a2000-07-08 04:04:38 +00002227DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002228{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 pp = &HeadFHCD;
2232 while ((p = *pp) != NULL) {
2233 if (p->id == id) {
2234 *pp = p->next;
2235 Py_XDECREF(p->func);
2236 Py_XDECREF(p->file);
2237 PyMem_DEL(p);
2238 }
2239 else
2240 pp = &p->next;
2241 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002242}
2243
Guido van Rossuma597dde1995-01-10 20:56:29 +00002244static void
Fred Drake509d79a2000-07-08 04:04:38 +00002245FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002246{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2248 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 ENTER_PYTHON
2251 func = data->func;
2252 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002253
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002254 arg = Py_BuildValue("(Oi)", file, (long) mask);
2255 res = PyEval_CallObject(func, arg);
2256 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 if (res == NULL) {
2259 errorInCmd = 1;
2260 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2261 }
2262 Py_XDECREF(res);
2263 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002264}
2265
Guido van Rossum18468821994-06-20 07:49:28 +00002266static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002267Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2268 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002269{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002270 FileHandler_ClientData *data;
2271 PyObject *file, *func;
2272 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002274 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2275 &file, &mask, &func))
2276 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002278 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 tfile = PyObject_AsFileDescriptor(file);
2281 if (tfile < 0)
2282 return NULL;
2283 if (!PyCallable_Check(func)) {
2284 PyErr_SetString(PyExc_TypeError, "bad argument list");
2285 return NULL;
2286 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002288 data = NewFHCD(func, file, tfile);
2289 if (data == NULL)
2290 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 /* Ought to check for null Tcl_File object... */
2293 ENTER_TCL
2294 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2295 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002296 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002297}
2298
2299static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002300Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002301{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 PyObject *file;
2303 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2306 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002309
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 tfile = PyObject_AsFileDescriptor(file);
2311 if (tfile < 0)
2312 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 /* Ought to check for null Tcl_File object... */
2317 ENTER_TCL
2318 Tcl_DeleteFileHandler(tfile);
2319 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002320 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002321}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002322#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002325/**** Tktt Object (timer token) ****/
2326
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002327static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328
Guido van Rossum00d93061998-05-28 23:06:38 +00002329typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 PyObject_HEAD
2331 Tcl_TimerToken token;
2332 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002333} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
2335static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002336Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338 TkttObject *v = (TkttObject *)self;
2339 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002341 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2342 return NULL;
2343 if (v->token != NULL) {
2344 Tcl_DeleteTimerHandler(v->token);
2345 v->token = NULL;
2346 }
2347 if (func != NULL) {
2348 v->func = NULL;
2349 Py_DECREF(func);
2350 Py_DECREF(v); /* See Tktt_New() */
2351 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002352 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002353}
2354
2355static PyMethodDef Tktt_methods[] =
2356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2358 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359};
2360
2361static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002362Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002365
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002366 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002367 if (v == NULL)
2368 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002369 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 Py_INCREF(func);
2372 v->token = NULL;
2373 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 /* Extra reference, deleted when called or when handler is deleted */
2376 Py_INCREF(v);
2377 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002378}
2379
2380static void
Fred Drake509d79a2000-07-08 04:04:38 +00002381Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002383 TkttObject *v = (TkttObject *)self;
2384 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002385 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002387 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002390 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002391}
2392
Guido van Rossum597ac201998-05-12 14:36:19 +00002393static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002394Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002397 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2398 v,
2399 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002400}
2401
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002402static PyType_Slot Tktt_Type_slots[] = {
2403 {Py_tp_dealloc, Tktt_Dealloc},
2404 {Py_tp_repr, Tktt_Repr},
2405 {Py_tp_methods, Tktt_methods},
2406 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002407};
2408
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002409static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002410 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002411 sizeof(TkttObject),
2412 0,
2413 Py_TPFLAGS_DEFAULT,
2414 Tktt_Type_slots,
2415};
Barry Warsawfa701a81997-01-16 00:15:11 +00002416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002417
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002418/** Timer Handler **/
2419
2420static void
Fred Drake509d79a2000-07-08 04:04:38 +00002421TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002422{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002423 TkttObject *v = (TkttObject *)clientData;
2424 PyObject *func = v->func;
2425 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 if (func == NULL)
2428 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002434 res = PyEval_CallObject(func, NULL);
2435 Py_DECREF(func);
2436 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 if (res == NULL) {
2439 errorInCmd = 1;
2440 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2441 }
2442 else
2443 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002446}
2447
2448static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002449Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002450{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451 int milliseconds;
2452 PyObject *func;
2453 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002455 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2456 &milliseconds, &func))
2457 return NULL;
2458 if (!PyCallable_Check(func)) {
2459 PyErr_SetString(PyExc_TypeError, "bad argument list");
2460 return NULL;
2461 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002463 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 v = Tktt_New(func);
2466 if (v) {
2467 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2468 (ClientData)v);
2469 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472}
2473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474
Guido van Rossum18468821994-06-20 07:49:28 +00002475/** Event Loop **/
2476
Guido van Rossum18468821994-06-20 07:49:28 +00002477static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002478Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002479{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480 int threshold = 0;
2481 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002482#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002483 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002484#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2487 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002489 CHECK_TCL_APPARTMENT;
2490 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 quitMainLoop = 0;
2493 while (Tk_GetNumMainWindows() > threshold &&
2494 !quitMainLoop &&
2495 !errorInCmd)
2496 {
2497 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002498
2499#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002500 if (self->threaded) {
2501 /* Allow other Python threads to run. */
2502 ENTER_TCL
2503 result = Tcl_DoOneEvent(0);
2504 LEAVE_TCL
2505 }
2506 else {
2507 Py_BEGIN_ALLOW_THREADS
2508 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2509 tcl_tstate = tstate;
2510 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2511 tcl_tstate = NULL;
2512 if(tcl_lock)PyThread_release_lock(tcl_lock);
2513 if (result == 0)
2514 Sleep(Tkinter_busywaitinterval);
2515 Py_END_ALLOW_THREADS
2516 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002517#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002519#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002520
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521 if (PyErr_CheckSignals() != 0) {
2522 self->dispatching = 0;
2523 return NULL;
2524 }
2525 if (result < 0)
2526 break;
2527 }
2528 self->dispatching = 0;
2529 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 if (errorInCmd) {
2532 errorInCmd = 0;
2533 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2534 excInCmd = valInCmd = trbInCmd = NULL;
2535 return NULL;
2536 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002537 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002538}
2539
2540static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002541Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002542{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 int flags = 0;
2544 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2547 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002549 ENTER_TCL
2550 rv = Tcl_DoOneEvent(flags);
2551 LEAVE_TCL
2552 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002553}
2554
2555static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002556Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002557{
2558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559 if (!PyArg_ParseTuple(args, ":quit"))
2560 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002563 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002564}
2565
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002566static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002567Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002568{
2569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 if (!PyArg_ParseTuple(args, ":interpaddr"))
2571 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002572
Victor Stinnere1040e22013-09-05 00:22:24 +02002573 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002574}
2575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002577Tkapp_TkInit(PyObject *self, PyObject *args)
2578{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 Tcl_Interp *interp = Tkapp_Interp(self);
2580 const char * _tk_exists = NULL;
2581 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002582
Guilherme Polob681df42009-02-09 22:33:59 +00002583#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2585 * first call failed.
2586 * To avoid the deadlock, we just refuse the second call through
2587 * a static variable.
2588 */
2589 if (tk_load_failed) {
2590 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2591 return NULL;
2592 }
Guilherme Polob681df42009-02-09 22:33:59 +00002593#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002595 /* We want to guard against calling Tk_Init() multiple times */
2596 CHECK_TCL_APPARTMENT;
2597 ENTER_TCL
2598 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2599 ENTER_OVERLAP
2600 if (err == TCL_ERROR) {
2601 /* This sets an exception, but we cannot return right
2602 away because we need to exit the overlap first. */
2603 Tkinter_Error(self);
2604 } else {
2605 _tk_exists = Tkapp_Result(self);
2606 }
2607 LEAVE_OVERLAP_TCL
2608 if (err == TCL_ERROR) {
2609 return NULL;
2610 }
2611 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2612 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002613 PyErr_SetString(Tkinter_TclError,
2614 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002615#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002616 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002617#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002618 return NULL;
2619 }
2620 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002621 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002622}
Barry Warsawfa701a81997-01-16 00:15:11 +00002623
Martin v. Löwisffad6332002-11-26 09:28:05 +00002624static PyObject *
2625Tkapp_WantObjects(PyObject *self, PyObject *args)
2626{
2627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 int wantobjects = -1;
2629 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2630 return NULL;
2631 if (wantobjects == -1)
2632 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2633 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002634
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002635 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002636}
2637
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002638static PyObject *
2639Tkapp_WillDispatch(PyObject *self, PyObject *args)
2640{
2641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002642 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002643
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002644 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002645}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002647
Guido van Rossum18468821994-06-20 07:49:28 +00002648/**** Tkapp Method List ****/
2649
2650static PyMethodDef Tkapp_methods[] =
2651{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002652 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2653 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2654 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002655 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002656 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2657 {"record", Tkapp_Record, METH_VARARGS},
2658 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2659 {"setvar", Tkapp_SetVar, METH_VARARGS},
2660 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2661 {"getvar", Tkapp_GetVar, METH_VARARGS},
2662 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2663 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2664 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2665 {"getint", Tkapp_GetInt, METH_VARARGS},
2666 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2667 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2668 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2669 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2670 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2671 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2672 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2673 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2675 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002676#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002677 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2678 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002679#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002680 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2681 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2682 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2683 {"quit", Tkapp_Quit, METH_VARARGS},
2684 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2685 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2686 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002687};
2688
Barry Warsawfa701a81997-01-16 00:15:11 +00002689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690
Guido van Rossum18468821994-06-20 07:49:28 +00002691/**** Tkapp Type Methods ****/
2692
2693static void
Fred Drake509d79a2000-07-08 04:04:38 +00002694Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002695{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002696 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002697 /*CHECK_TCL_APPARTMENT;*/
2698 ENTER_TCL
2699 Tcl_DeleteInterp(Tkapp_Interp(self));
2700 LEAVE_TCL
2701 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002702 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002704}
2705
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002706static PyType_Slot Tkapp_Type_slots[] = {
2707 {Py_tp_dealloc, Tkapp_Dealloc},
2708 {Py_tp_methods, Tkapp_methods},
2709 {0, 0}
2710};
2711
2712
2713static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002714 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002715 sizeof(TkappObject),
2716 0,
2717 Py_TPFLAGS_DEFAULT,
2718 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002719};
2720
Barry Warsawfa701a81997-01-16 00:15:11 +00002721
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002722
Guido van Rossum18468821994-06-20 07:49:28 +00002723/**** Tkinter Module ****/
2724
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002725typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002726 PyObject* tuple;
2727 int size; /* current size */
2728 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002729} FlattenContext;
2730
2731static int
2732_bump(FlattenContext* context, int size)
2733{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002734 /* expand tuple to hold (at least) size new items.
2735 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 if (maxsize < context->size + size)
2740 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002744 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002745}
2746
2747static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002748_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002749{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002750 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 if (depth > 1000) {
2755 PyErr_SetString(PyExc_ValueError,
2756 "nesting too deep in _flatten");
2757 return 0;
2758 } else if (PyList_Check(item)) {
2759 size = PyList_GET_SIZE(item);
2760 /* preallocate (assume no nesting) */
2761 if (context->size + size > context->maxsize &&
2762 !_bump(context, size))
2763 return 0;
2764 /* copy items to output tuple */
2765 for (i = 0; i < size; i++) {
2766 PyObject *o = PyList_GET_ITEM(item, i);
2767 if (PyList_Check(o) || PyTuple_Check(o)) {
2768 if (!_flatten1(context, o, depth + 1))
2769 return 0;
2770 } else if (o != Py_None) {
2771 if (context->size + 1 > context->maxsize &&
2772 !_bump(context, 1))
2773 return 0;
2774 Py_INCREF(o);
2775 PyTuple_SET_ITEM(context->tuple,
2776 context->size++, o);
2777 }
2778 }
2779 } else if (PyTuple_Check(item)) {
2780 /* same, for tuples */
2781 size = PyTuple_GET_SIZE(item);
2782 if (context->size + size > context->maxsize &&
2783 !_bump(context, size))
2784 return 0;
2785 for (i = 0; i < size; i++) {
2786 PyObject *o = PyTuple_GET_ITEM(item, i);
2787 if (PyList_Check(o) || PyTuple_Check(o)) {
2788 if (!_flatten1(context, o, depth + 1))
2789 return 0;
2790 } else if (o != Py_None) {
2791 if (context->size + 1 > context->maxsize &&
2792 !_bump(context, 1))
2793 return 0;
2794 Py_INCREF(o);
2795 PyTuple_SET_ITEM(context->tuple,
2796 context->size++, o);
2797 }
2798 }
2799 } else {
2800 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2801 return 0;
2802 }
2803 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804}
2805
2806static PyObject *
2807Tkinter_Flatten(PyObject* self, PyObject* args)
2808{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002809 FlattenContext context;
2810 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2813 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 context.maxsize = PySequence_Size(item);
2816 if (context.maxsize < 0)
2817 return NULL;
2818 if (context.maxsize == 0)
2819 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002820
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002821 context.tuple = PyTuple_New(context.maxsize);
2822 if (!context.tuple)
2823 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002824
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002825 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002826
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002827 if (!_flatten1(&context, item,0))
2828 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002830 if (_PyTuple_Resize(&context.tuple, context.size))
2831 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002834}
2835
Guido van Rossum18468821994-06-20 07:49:28 +00002836static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002837Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002838{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002839 char *screenName = NULL;
2840 char *baseName = NULL; /* XXX this is not used anymore;
2841 try getting rid of it. */
2842 char *className = NULL;
2843 int interactive = 0;
2844 int wantobjects = 0;
2845 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2846 int sync = 0; /* pass -sync to wish */
2847 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2852 &screenName, &baseName, &className,
2853 &interactive, &wantobjects, &wantTk,
2854 &sync, &use))
2855 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002856 CHECK_STRING_LENGTH(screenName);
2857 CHECK_STRING_LENGTH(baseName);
2858 CHECK_STRING_LENGTH(className);
2859 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002860
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002861 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002862 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002863 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002864}
2865
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002866static PyObject *
2867Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2868{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 int new_val;
2870 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2871 return NULL;
2872 if (new_val < 0) {
2873 PyErr_SetString(PyExc_ValueError,
2874 "busywaitinterval must be >= 0");
2875 return NULL;
2876 }
2877 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002878 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002879}
2880
2881static char setbusywaitinterval_doc[] =
2882"setbusywaitinterval(n) -> None\n\
2883\n\
2884Set the busy-wait interval in milliseconds between successive\n\
2885calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2886It should be set to a divisor of the maximum time between\n\
2887frames in an animation.";
2888
2889static PyObject *
2890Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2891{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002893}
2894
2895static char getbusywaitinterval_doc[] =
2896"getbusywaitinterval() -> int\n\
2897\n\
2898Return the current busy-wait interval between successive\n\
2899calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2900
Guido van Rossum18468821994-06-20 07:49:28 +00002901static PyMethodDef moduleMethods[] =
2902{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2904 {"create", Tkinter_Create, METH_VARARGS},
2905 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2906 setbusywaitinterval_doc},
2907 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2908 METH_NOARGS, getbusywaitinterval_doc},
2909 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002910};
2911
Guido van Rossum7bf15641998-05-22 18:28:17 +00002912#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002913
2914static int stdin_ready = 0;
2915
Guido van Rossumad4db171998-06-13 13:56:28 +00002916#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002917static void
Fred Drake509d79a2000-07-08 04:04:38 +00002918MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002919{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002920 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002921}
Guido van Rossumad4db171998-06-13 13:56:28 +00002922#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002923
Martin v. Löwisa9656492003-03-30 08:44:58 +00002924#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002925static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002926#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002927
Guido van Rossum18468821994-06-20 07:49:28 +00002928static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002929EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002930{
Guido van Rossumad4db171998-06-13 13:56:28 +00002931#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002933#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002934#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002936#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 stdin_ready = 0;
2938 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002939#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 tfile = fileno(stdin);
2941 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002942#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002943 while (!errorInCmd && !stdin_ready) {
2944 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002945#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 if (_kbhit()) {
2947 stdin_ready = 1;
2948 break;
2949 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002950#endif
2951#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002952 Py_BEGIN_ALLOW_THREADS
2953 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2954 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002956 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002958 tcl_tstate = NULL;
2959 if(tcl_lock)PyThread_release_lock(tcl_lock);
2960 if (result == 0)
2961 Sleep(Tkinter_busywaitinterval);
2962 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002963#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002964 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002965#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002966
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002967 if (result < 0)
2968 break;
2969 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002970#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002972#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 if (errorInCmd) {
2974 errorInCmd = 0;
2975 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2976 excInCmd = valInCmd = trbInCmd = NULL;
2977 PyErr_Print();
2978 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002979#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002980 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002981#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002982 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002983}
Guido van Rossum18468821994-06-20 07:49:28 +00002984
Guido van Rossum00d93061998-05-28 23:06:38 +00002985#endif
2986
Guido van Rossum7bf15641998-05-22 18:28:17 +00002987static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002988EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002989{
Guido van Rossum00d93061998-05-28 23:06:38 +00002990#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002991 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002992#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002994#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 PyOS_InputHook = EventHook;
2996 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002997#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002998}
2999
3000static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003001DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003002{
Guido van Rossum00d93061998-05-28 23:06:38 +00003003#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3005 PyOS_InputHook = NULL;
3006 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003007#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003008}
3009
Barry Warsawfa701a81997-01-16 00:15:11 +00003010
Martin v. Löwis1a214512008-06-11 05:26:20 +00003011static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 PyModuleDef_HEAD_INIT,
3013 "_tkinter",
3014 NULL,
3015 -1,
3016 moduleMethods,
3017 NULL,
3018 NULL,
3019 NULL,
3020 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003021};
3022
Mark Hammond62b1ab12002-07-23 06:31:15 +00003023PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003024PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003025{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003026 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003027
Guido van Rossum00d93061998-05-28 23:06:38 +00003028#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003030 if (tcl_lock == NULL)
3031 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003032#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 m = PyModule_Create(&_tkintermodule);
3035 if (m == NULL)
3036 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003037
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003038 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3039 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003040 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003041 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003042 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003043 Py_INCREF(o);
3044 if (PyModule_AddObject(m, "TclError", o)) {
3045 Py_DECREF(o);
3046 Py_DECREF(m);
3047 return NULL;
3048 }
3049 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003050
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003051 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3052 Py_DECREF(m);
3053 return NULL;
3054 }
3055 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3056 Py_DECREF(m);
3057 return NULL;
3058 }
3059 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3060 Py_DECREF(m);
3061 return NULL;
3062 }
3063 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3064 Py_DECREF(m);
3065 return NULL;
3066 }
3067 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3068 Py_DECREF(m);
3069 return NULL;
3070 }
3071 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3072 Py_DECREF(m);
3073 return NULL;
3074 }
3075 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3076 Py_DECREF(m);
3077 return NULL;
3078 }
3079 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3080 Py_DECREF(m);
3081 return NULL;
3082 }
3083 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3084 Py_DECREF(m);
3085 return NULL;
3086 }
3087 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3088 Py_DECREF(m);
3089 return NULL;
3090 }
3091 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3092 Py_DECREF(m);
3093 return NULL;
3094 }
3095
3096 o = PyType_FromSpec(&Tkapp_Type_spec);
3097 if (o == NULL) {
3098 Py_DECREF(m);
3099 return NULL;
3100 }
3101 if (PyModule_AddObject(m, "TkappType", o)) {
3102 Py_DECREF(o);
3103 Py_DECREF(m);
3104 return NULL;
3105 }
3106 Tkapp_Type = o;
3107
3108 o = PyType_FromSpec(&Tktt_Type_spec);
3109 if (o == NULL) {
3110 Py_DECREF(m);
3111 return NULL;
3112 }
3113 if (PyModule_AddObject(m, "TkttType", o)) {
3114 Py_DECREF(o);
3115 Py_DECREF(m);
3116 return NULL;
3117 }
3118 Tktt_Type = o;
3119
3120 o = PyType_FromSpec(&PyTclObject_Type_spec);
3121 if (o == NULL) {
3122 Py_DECREF(m);
3123 return NULL;
3124 }
3125 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3126 Py_DECREF(o);
3127 Py_DECREF(m);
3128 return NULL;
3129 }
3130 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003131
3132#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3134 * start waking up. Note that Tcl_FindExecutable will do this, this
3135 * code must be above it! The original warning from
3136 * tkMacOSXAppInit.c is copied below.
3137 *
3138 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3139 * Tcl interpreter for now. It probably should work to do this
3140 * in the other order, but for now it doesn't seem to.
3141 *
3142 */
3143 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003144#endif
3145
3146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 /* This helps the dynamic loader; in Unicode aware Tcl versions
3148 it also helps Tcl find its encodings. */
3149 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3150 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003151 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003152 if (cexe)
3153 Tcl_FindExecutable(PyBytes_AsString(cexe));
3154 Py_XDECREF(cexe);
3155 Py_DECREF(uexe);
3156 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 if (PyErr_Occurred()) {
3159 Py_DECREF(m);
3160 return NULL;
3161 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003162
Guido van Rossum43ff8681998-07-14 18:02:13 +00003163#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003164 /* This was not a good idea; through <Destroy> bindings,
3165 Tcl_Finalize() may invoke Python code but at that point the
3166 interpreter and thread state have already been destroyed! */
3167 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003168#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003169 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003170}