blob: d5396f6f0dcd42d67bbca03e99f40b63e1e3d08b [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Serhiy Storchaka6716d602014-07-30 19:19:21 +030012 Only Tcl/Tk 8.4 and later are supported. Older versions are not
13 supported. Use Python 3.4 or older if you cannot upgrade your
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000014 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030036#define CHECK_SIZE(size, elemsize) \
37 ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
38
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000039/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
40 it always; if Tcl is not threaded, the thread functions in
41 Tcl are empty. */
42#define TCL_THREADS
43
Jack Jansencb852442001-12-09 23:15:56 +000044#ifdef TK_FRAMEWORK
45#include <Tcl/tcl.h>
46#include <Tk/tk.h>
47#else
Guido van Rossum18468821994-06-20 07:49:28 +000048#include <tcl.h>
49#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000050#endif
Guido van Rossum18468821994-06-20 07:49:28 +000051
Guilherme Polo2d87e422009-04-10 22:19:09 +000052#include "tkinter.h"
53
Serhiy Storchaka6716d602014-07-30 19:19:21 +030054#if TK_VERSION_HEX < 0x08040002
55#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000056#endif
57
Jack Janseneddc1442003-11-20 01:44:59 +000058#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000059#define HAVE_CREATEFILEHANDLER
60#endif
61
Guido van Rossum00d93061998-05-28 23:06:38 +000062#ifdef HAVE_CREATEFILEHANDLER
63
Neal Norwitzd948a432006-01-08 01:08:55 +000064/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
65 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
66#ifndef TCL_UNIX_FD
67# ifdef TCL_WIN_SOCKET
68# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
69# else
70# define TCL_UNIX_FD 1
71# endif
72#endif
73
Guido van Rossum00d93061998-05-28 23:06:38 +000074/* Tcl_CreateFileHandler() changed several times; these macros deal with the
75 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
76 Unix, only because Jack added it back); when available on Windows, it only
77 applies to sockets. */
78
Guido van Rossum7bf15641998-05-22 18:28:17 +000079#ifdef MS_WINDOWS
80#define FHANDLETYPE TCL_WIN_SOCKET
81#else
82#define FHANDLETYPE TCL_UNIX_FD
83#endif
84
Guido van Rossum00d93061998-05-28 23:06:38 +000085/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
86 which uses this to handle Tcl events while the user is typing commands. */
87
88#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000089#define WAIT_FOR_STDIN
90#endif
91
Guido van Rossum00d93061998-05-28 23:06:38 +000092#endif /* HAVE_CREATEFILEHANDLER */
93
Guido van Rossumad4db171998-06-13 13:56:28 +000094#ifdef MS_WINDOWS
95#include <conio.h>
96#define WAIT_FOR_STDIN
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef WITH_THREAD
100
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000101/* The threading situation is complicated. Tcl is not thread-safe, except
102 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000103
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300104 So we need to use a lock around all uses of Tcl. Previously, the
105 Python interpreter lock was used for this. However, this causes
106 problems when other Python threads need to run while Tcl is blocked
107 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000108
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300109 To solve this problem, a separate lock for Tcl is introduced.
110 Holding it is incompatible with holding Python's interpreter lock.
111 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000112
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300113 ENTER_TCL and LEAVE_TCL are brackets, just like
114 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
115 used whenever a call into Tcl is made that could call an event
116 handler, or otherwise affect the state of a Tcl interpreter. These
117 assume that the surrounding code has the Python interpreter lock;
118 inside the brackets, the Python interpreter lock has been released
119 and the lock for Tcl has been acquired.
120
121 Sometimes, it is necessary to have both the Python lock and the Tcl
122 lock. (For example, when transferring data from the Tcl
123 interpreter result to a Python string object.) This can be done by
124 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
125 reacquires the Python lock (and restores the thread state) but
126 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
127 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000128
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000129 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300130 handlers when the handler needs to use Python. Such event handlers
131 are entered while the lock for Tcl is held; the event handler
132 presumably needs to use Python. ENTER_PYTHON releases the lock for
133 Tcl and acquires the Python interpreter lock, restoring the
134 appropriate thread state, and LEAVE_PYTHON releases the Python
135 interpreter lock and re-acquires the lock for Tcl. It is okay for
136 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
137 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000138
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300139 These locks expand to several statements and brackets; they should
140 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000141
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300142 If Tcl is threaded, this approach won't work anymore. The Tcl
143 interpreter is only valid in the thread that created it, and all Tk
144 activity must happen in this thread, also. That means that the
145 mainloop must be invoked in the thread that created the
146 interpreter. Invoking commands from other threads is possible;
147 _tkinter will queue an event for the interpreter thread, which will
148 then execute the command and pass back the result. If the main
149 thread is not in the mainloop, and invoking commands causes an
150 exception; if the main loop is running but not processing events,
151 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300153 In addition, for a threaded Tcl, a single global tcl_tstate won't
154 be sufficient anymore, since multiple Tcl interpreters may
155 simultaneously dispatch in different threads. So we use the Tcl TLS
156 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000157
Guido van Rossum00d93061998-05-28 23:06:38 +0000158*/
159
Guido van Rossum65d5b571998-12-21 19:32:43 +0000160static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000161
162#ifdef TCL_THREADS
163static Tcl_ThreadDataKey state_key;
164typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300165#define tcl_tstate \
166 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000167#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000168static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000169#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
173 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000174
175#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300176 tcl_tstate = NULL; \
177 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000178
Guido van Rossum62320c91998-06-15 04:36:09 +0000179#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000181
182#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000184
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000185#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300187 if(tcl_lock) \
188 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000189
190#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 { PyThreadState *tstate = PyEval_SaveThread(); \
192 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000193
194#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 if (((TkappObject *)self)->threaded && \
196 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300197 PyErr_SetString(PyExc_RuntimeError, \
198 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 return 0; \
200 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000201
202#else
203
204#define ENTER_TCL
205#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP
207#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000208#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000209#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000210#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000211
212#endif
213
Guido van Rossum97867b21996-08-08 19:09:53 +0000214#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000215#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000216#endif
217
Guido van Rossum18468821994-06-20 07:49:28 +0000218/**** Tkapp Object Declaration ****/
219
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300220static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000221
Guido van Rossum00d93061998-05-28 23:06:38 +0000222typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 PyObject_HEAD
224 Tcl_Interp *interp;
225 int wantobjects;
226 int threaded; /* True if tcl_platform[threaded] */
227 Tcl_ThreadId thread_id;
228 int dispatching;
229 /* We cannot include tclInt.h, as this is internal.
230 So we cache interesting types here. */
Zachary Ware037605b2014-08-05 11:54:34 -0500231 const Tcl_ObjType *BooleanType;
232 const Tcl_ObjType *ByteArrayType;
233 const Tcl_ObjType *DoubleType;
234 const Tcl_ObjType *IntType;
235 const Tcl_ObjType *ListType;
236 const Tcl_ObjType *ProcBodyType;
237 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000238} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000239
Guido van Rossum18468821994-06-20 07:49:28 +0000240#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000241#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000242
Guido van Rossum35d43371997-08-02 00:09:09 +0000243#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000244(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000245
Barry Warsawfa701a81997-01-16 00:15:11 +0000246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247
Guido van Rossum18468821994-06-20 07:49:28 +0000248/**** Error Handling ****/
249
250static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000251static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000252static int errorInCmd = 0;
253static PyObject *excInCmd;
254static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000255static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guilherme Polob681df42009-02-09 22:33:59 +0000257#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000258static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000259#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000263Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000264{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
266 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000267}
268
Barry Warsawfa701a81997-01-16 00:15:11 +0000269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270
Guido van Rossum18468821994-06-20 07:49:28 +0000271/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000272
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000273static int Tkinter_busywaitinterval = 20;
274
Guido van Rossum00d93061998-05-28 23:06:38 +0000275#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000276#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000277
Guido van Rossum00d93061998-05-28 23:06:38 +0000278/* Millisecond sleep() for Unix platforms. */
279
280static void
Fred Drake509d79a2000-07-08 04:04:38 +0000281Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000282{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283 /* XXX Too bad if you don't have select(). */
284 struct timeval t;
285 t.tv_sec = milli/1000;
286 t.tv_usec = (milli%1000) * 1000;
287 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000288}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000289#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000290
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000291/* Wait up to 1s for the mainloop to come up. */
292
293static int
294WaitForMainloop(TkappObject* self)
295{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 int i;
297 for (i = 0; i < 10; i++) {
298 if (self->dispatching)
299 return 1;
300 Py_BEGIN_ALLOW_THREADS
301 Sleep(100);
302 Py_END_ALLOW_THREADS
303 }
304 if (self->dispatching)
305 return 1;
306 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
307 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000308}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000309#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312
Guido van Rossum18468821994-06-20 07:49:28 +0000313#define ARGSZ 64
314
Barry Warsawfa701a81997-01-16 00:15:11 +0000315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316
Guido van Rossum18468821994-06-20 07:49:28 +0000317static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200318unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
319{
320 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
321 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
322 /* Tcl encodes null character as \xc0\x80 */
323 if (memchr(s, '\xc0', size)) {
324 char *buf, *q;
325 const char *e = s + size;
326 PyErr_Clear();
327 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300328 if (buf == NULL) {
329 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200330 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300331 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200332 while (s != e) {
333 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
334 *q++ = '\0';
335 s += 2;
336 }
337 else
338 *q++ = *s++;
339 }
340 s = buf;
341 size = q - s;
342 r = PyUnicode_DecodeUTF8(s, size, NULL);
343 PyMem_Free(buf);
344 }
345 }
346 return r;
347}
348
349static PyObject *
350unicodeFromTclString(const char *s)
351{
352 return unicodeFromTclStringAndSize(s, strlen(s));
353}
354
355static PyObject *
356unicodeFromTclObj(Tcl_Obj *value)
357{
358 int len;
359 char *s = Tcl_GetStringFromObj(value, &len);
360 return unicodeFromTclStringAndSize(s, len);
361}
362
363
364static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300365Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000366{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000367 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300368 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300372 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 }
Guido van Rossum18468821994-06-20 07:49:28 +0000374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000375 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
376 /* Not a list.
377 * Could be a quoted string containing funnies, e.g. {"}.
378 * Return the string itself.
379 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200380 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 }
Guido van Rossum18468821994-06-20 07:49:28 +0000382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 if (argc == 0)
384 v = PyUnicode_FromString("");
385 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200386 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 else if ((v = PyTuple_New(argc)) != NULL) {
388 int i;
389 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 for (i = 0; i < argc; i++) {
392 if ((w = Split(argv[i])) == NULL) {
393 Py_DECREF(v);
394 v = NULL;
395 break;
396 }
397 PyTuple_SetItem(v, i, w);
398 }
399 }
400 Tcl_Free(FREECAST argv);
401 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000402}
403
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300404/* In some cases, Tcl will still return strings that are supposed to
405 be lists. SplitObj walks through a nested tuple, finding string
406 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000407
Martin v. Löwis59683e82008-06-13 07:50:45 +0000408static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000409SplitObj(PyObject *arg)
410{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 if (PyTuple_Check(arg)) {
412 int i, size;
413 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 size = PyTuple_Size(arg);
416 result = NULL;
417 /* Recursively invoke SplitObj for all tuple items.
418 If this does not return a new object, no action is
419 needed. */
420 for(i = 0; i < size; i++) {
421 elem = PyTuple_GetItem(arg, i);
422 newelem = SplitObj(elem);
423 if (!newelem) {
424 Py_XDECREF(result);
425 return NULL;
426 }
427 if (!result) {
428 int k;
429 if (newelem == elem) {
430 Py_DECREF(newelem);
431 continue;
432 }
433 result = PyTuple_New(size);
434 if (!result)
435 return NULL;
436 for(k = 0; k < i; k++) {
437 elem = PyTuple_GetItem(arg, k);
438 Py_INCREF(elem);
439 PyTuple_SetItem(result, k, elem);
440 }
441 }
442 PyTuple_SetItem(result, i, newelem);
443 }
444 if (result)
445 return result;
446 /* Fall through, returning arg. */
447 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300448 else if (PyList_Check(arg)) {
449 int i, size;
450 PyObject *elem, *newelem, *result;
451
452 size = PyList_GET_SIZE(arg);
453 result = PyTuple_New(size);
454 if (!result)
455 return NULL;
456 /* Recursively invoke SplitObj for all list items. */
457 for(i = 0; i < size; i++) {
458 elem = PyList_GET_ITEM(arg, i);
459 newelem = SplitObj(elem);
460 if (!newelem) {
461 Py_XDECREF(result);
462 return NULL;
463 }
464 PyTuple_SetItem(result, i, newelem);
465 }
466 return result;
467 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300468 else if (PyUnicode_Check(arg)) {
469 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300470 const char **argv;
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300471 char *list = PyUnicode_AsUTF8(arg);
472
473 if (list == NULL ||
474 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
475 Py_INCREF(arg);
476 return arg;
477 }
478 Tcl_Free(FREECAST argv);
479 if (argc > 1)
480 return Split(list);
481 /* Fall through, returning arg. */
482 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 else if (PyBytes_Check(arg)) {
484 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300485 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
489 Py_INCREF(arg);
490 return arg;
491 }
492 Tcl_Free(FREECAST argv);
493 if (argc > 1)
494 return Split(PyBytes_AsString(arg));
495 /* Fall through, returning arg. */
496 }
497 Py_INCREF(arg);
498 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000499}
Barry Warsawfa701a81997-01-16 00:15:11 +0000500
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000501
Guido van Rossum18468821994-06-20 07:49:28 +0000502/**** Tkapp Object ****/
503
504#ifndef WITH_APPINIT
505int
Fred Drake509d79a2000-07-08 04:04:38 +0000506Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000507{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 if (Tcl_Init(interp) == TCL_ERROR) {
511 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
512 return TCL_ERROR;
513 }
Guilherme Polob681df42009-02-09 22:33:59 +0000514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 _tkinter_skip_tk_init = Tcl_GetVar(interp,
516 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
517 if (_tkinter_skip_tk_init != NULL &&
518 strcmp(_tkinter_skip_tk_init, "1") == 0) {
519 return TCL_OK;
520 }
Guilherme Polob681df42009-02-09 22:33:59 +0000521
522#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 if (tk_load_failed) {
524 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
525 return TCL_ERROR;
526 }
Guilherme Polob681df42009-02-09 22:33:59 +0000527#endif
528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000530#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000532#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
534 return TCL_ERROR;
535 }
Guilherme Polob681df42009-02-09 22:33:59 +0000536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000538}
539#endif /* !WITH_APPINIT */
540
Guido van Rossum18468821994-06-20 07:49:28 +0000541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542
Barry Warsawfa701a81997-01-16 00:15:11 +0000543
544/* Initialize the Tk application; see the `main' function in
545 * `tkMain.c'.
546 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000547
Thomas Wouters58d05102000-07-24 14:43:35 +0000548static void EnableEventHook(void); /* Forward */
549static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000550
Barry Warsawfa701a81997-01-16 00:15:11 +0000551static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300552Tkapp_New(const char *screenName, const char *className,
553 int interactive, int wantobjects, int wantTk, int sync,
554 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000555{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 TkappObject *v;
557 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000558
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300559 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 if (v == NULL)
561 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200562 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 v->interp = Tcl_CreateInterp();
565 v->wantobjects = wantobjects;
566 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
567 TCL_GLOBAL_ONLY) != NULL;
568 v->thread_id = Tcl_GetCurrentThread();
569 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000570
571#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300573 PyErr_SetString(PyExc_RuntimeError,
574 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 Py_DECREF(v);
576 return 0;
577 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000578#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000579#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 if (v->threaded && tcl_lock) {
581 /* If Tcl is threaded, we don't need the lock. */
582 PyThread_free_lock(tcl_lock);
583 tcl_lock = NULL;
584 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000585#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 v->BooleanType = Tcl_GetObjType("boolean");
588 v->ByteArrayType = Tcl_GetObjType("bytearray");
589 v->DoubleType = Tcl_GetObjType("double");
590 v->IntType = Tcl_GetObjType("int");
591 v->ListType = Tcl_GetObjType("list");
592 v->ProcBodyType = Tcl_GetObjType("procbody");
593 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 /* Delete the 'exit' command, which can screw things up */
596 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 if (screenName != NULL)
599 Tcl_SetVar2(v->interp, "env", "DISPLAY",
600 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 if (interactive)
603 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
604 else
605 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200608 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (!argv0) {
610 PyErr_NoMemory();
611 Py_DECREF(v);
612 return NULL;
613 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200616 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
617 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200619 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000620
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 if (! wantTk) {
622 Tcl_SetVar(v->interp,
623 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
624 }
Guilherme Polob681df42009-02-09 22:33:59 +0000625#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 else if (tk_load_failed) {
627 Tcl_SetVar(v->interp,
628 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
629 }
Guilherme Polob681df42009-02-09 22:33:59 +0000630#endif
David Aschere2b4b322004-02-18 05:59:53 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 /* some initial arguments need to be in argv */
633 if (sync || use) {
634 char *args;
635 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 if (sync)
638 len += sizeof "-sync";
639 if (use)
640 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000641
Victor Stinneree6c3c72014-09-11 17:50:21 +0200642 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 if (!args) {
644 PyErr_NoMemory();
645 Py_DECREF(v);
646 return NULL;
647 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 args[0] = '\0';
650 if (sync)
651 strcat(args, "-sync");
652 if (use) {
653 if (sync)
654 strcat(args, " ");
655 strcat(args, "-use ");
656 strcat(args, use);
657 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200660 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 if (Tcl_AppInit(v->interp) != TCL_OK) {
664 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000665#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 if (wantTk) {
667 const char *_tkinter_tk_failed;
668 _tkinter_tk_failed = Tcl_GetVar(v->interp,
669 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 if ( _tkinter_tk_failed != NULL &&
672 strcmp(_tkinter_tk_failed, "1") == 0) {
673 tk_load_failed = 1;
674 }
675 }
Guilherme Polob681df42009-02-09 22:33:59 +0000676#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 Py_DECREF((PyObject *)v);
678 return (TkappObject *)result;
679 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000684}
685
Barry Warsawfa701a81997-01-16 00:15:11 +0000686
Benjamin Peterson5879d412009-03-30 14:51:56 +0000687#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000688static void
689Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000691{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 Py_BEGIN_ALLOW_THREADS;
693 Tcl_MutexLock(mutex);
694 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
695 Tcl_ThreadAlert(self->thread_id);
696 Tcl_ConditionWait(cond, mutex, NULL);
697 Tcl_MutexUnlock(mutex);
698 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000700#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702
Guido van Rossum18468821994-06-20 07:49:28 +0000703/** Tcl Eval **/
704
Martin v. Löwisffad6332002-11-26 09:28:05 +0000705typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 PyObject_HEAD
707 Tcl_Obj *value;
708 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000709} PyTclObject;
710
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300711static PyObject *PyTclObject_Type;
712#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000713
714static PyObject *
715newPyTclObject(Tcl_Obj *arg)
716{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300718 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 if (self == NULL)
720 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200721 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 Tcl_IncrRefCount(arg);
723 self->value = arg;
724 self->string = NULL;
725 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000726}
727
728static void
729PyTclObject_dealloc(PyTclObject *self)
730{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200731 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 Tcl_DecrRefCount(self->value);
733 Py_XDECREF(self->string);
734 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200735 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000736}
737
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000738static char*
739PyTclObject_TclString(PyObject *self)
740{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000742}
743
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000744/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000745PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000746"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000747
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000748static PyObject *
749PyTclObject_string(PyTclObject *self, void *ignored)
750{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200752 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753 if (!self->string)
754 return NULL;
755 }
756 Py_INCREF(self->string);
757 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000758}
759
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000760static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000761PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000762{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200763 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 Py_INCREF(self->string);
765 return self->string;
766 }
767 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200768 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000769}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000770
Martin v. Löwisffad6332002-11-26 09:28:05 +0000771static PyObject *
772PyTclObject_repr(PyTclObject *self)
773{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300774 PyObject *repr, *str = PyTclObject_str(self, NULL);
775 if (str == NULL)
776 return NULL;
777 repr = PyUnicode_FromFormat("<%s object: %R>",
778 self->value->typePtr->name, str);
779 Py_DECREF(str);
780 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000781}
782
Mark Dickinson211c6252009-02-01 10:28:51 +0000783#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
784
785static PyObject *
786PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000787{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000788 int result;
789 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 /* neither argument should be NULL, unless something's gone wrong */
792 if (self == NULL || other == NULL) {
793 PyErr_BadInternalCall();
794 return NULL;
795 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 /* both arguments should be instances of PyTclObject */
798 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
799 v = Py_NotImplemented;
800 goto finished;
801 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 if (self == other)
804 /* fast path when self and other are identical */
805 result = 0;
806 else
807 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
808 Tcl_GetString(((PyTclObject *)other)->value));
809 /* Convert return value to a Boolean */
810 switch (op) {
811 case Py_EQ:
812 v = TEST_COND(result == 0);
813 break;
814 case Py_NE:
815 v = TEST_COND(result != 0);
816 break;
817 case Py_LE:
818 v = TEST_COND(result <= 0);
819 break;
820 case Py_GE:
821 v = TEST_COND(result >= 0);
822 break;
823 case Py_LT:
824 v = TEST_COND(result < 0);
825 break;
826 case Py_GT:
827 v = TEST_COND(result > 0);
828 break;
829 default:
830 PyErr_BadArgument();
831 return NULL;
832 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000833 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000834 Py_INCREF(v);
835 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000836}
837
Martin v. Löwis39195712003-01-04 00:33:13 +0000838PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
839
Martin v. Löwisffad6332002-11-26 09:28:05 +0000840static PyObject*
841get_typename(PyTclObject* obj, void* ignored)
842{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200843 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000844}
845
Martin v. Löwis39195712003-01-04 00:33:13 +0000846
Martin v. Löwisffad6332002-11-26 09:28:05 +0000847static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 {"typename", (getter)get_typename, NULL, get_typename__doc__},
849 {"string", (getter)PyTclObject_string, NULL,
850 PyTclObject_string__doc__},
851 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000852};
853
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300854static PyType_Slot PyTclObject_Type_slots[] = {
855 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
856 {Py_tp_repr, (reprfunc)PyTclObject_repr},
857 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200858 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300859 {Py_tp_richcompare, PyTclObject_richcompare},
860 {Py_tp_getset, PyTclObject_getsetlist},
861 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862};
863
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300864static PyType_Spec PyTclObject_Type_spec = {
865 "_tkinter.Tcl_Obj",
866 sizeof(PyTclObject),
867 0,
868 Py_TPFLAGS_DEFAULT,
869 PyTclObject_Type_slots,
870};
871
872
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300873#if PY_SIZE_MAX > INT_MAX
874#define CHECK_STRING_LENGTH(s) do { \
875 if (s != NULL && strlen(s) >= INT_MAX) { \
876 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
877 return NULL; \
878 } } while(0)
879#else
880#define CHECK_STRING_LENGTH(s)
881#endif
882
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000883static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000884AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000885{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000886 Tcl_Obj *result;
887 long longVal;
888 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000890 if (PyBytes_Check(value))
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300891 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
892 PyBytes_GET_SIZE(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000893 else if (PyBool_Check(value))
894 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
895 else if (PyLong_CheckExact(value) &&
896 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
897 !overflow)) {
898 /* If there is an overflow in the long conversion,
899 fall through to default object handling. */
900 return Tcl_NewLongObj(longVal);
901 }
902 else if (PyFloat_Check(value))
903 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300904 else if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300905 Tcl_Obj **argv;
906 Py_ssize_t size, i;
907
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300908 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300909 if (size == 0)
910 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300911 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300912 PyErr_SetString(PyExc_OverflowError,
913 PyTuple_Check(value) ? "tuple is too long" :
914 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300915 return NULL;
916 }
Victor Stinneree6c3c72014-09-11 17:50:21 +0200917 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
918 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +0200919 PyErr_NoMemory();
920 return NULL;
921 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300922 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300923 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
924 result = Tcl_NewListObj(size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200925 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000926 return result;
927 }
928 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200929 void *inbuf;
930 Py_ssize_t size;
931 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 Tcl_UniChar *outbuf = NULL;
933 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200934 size_t allocsize;
935
936 if (PyUnicode_READY(value) == -1)
937 return NULL;
938
939 inbuf = PyUnicode_DATA(value);
940 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300941 if (size == 0)
942 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300943 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
944 PyErr_SetString(PyExc_OverflowError, "string is too long");
945 return NULL;
946 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200947 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200948 if (kind == sizeof(Tcl_UniChar))
949 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200950 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200951 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 /* Else overflow occurred, and we take the next exit */
953 if (!outbuf) {
954 PyErr_NoMemory();
955 return NULL;
956 }
957 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200958 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
959 /* We cannot test for sizeof(Tcl_UniChar) directly,
960 so we test for UTF-8 size instead. */
961#if TCL_UTF_MAX == 3
962 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000963 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200964 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100965 "character U+%x is above the range "
966 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100967 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200968 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000969 return NULL;
970 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300971#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200972 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000973 }
974 result = Tcl_NewUnicodeObj(outbuf, size);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200975 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000977 }
978 else if(PyTclObject_Check(value)) {
979 Tcl_Obj *v = ((PyTclObject*)value)->value;
980 Tcl_IncrRefCount(v);
981 return v;
982 }
983 else {
984 PyObject *v = PyObject_Str(value);
985 if (!v)
986 return 0;
987 result = AsObj(v);
988 Py_DECREF(v);
989 return result;
990 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000991}
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;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001000 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001003 if (value->typePtr == app->BooleanType) {
1004 result = value->internalRep.longValue ? Py_True : Py_False;
1005 Py_INCREF(result);
1006 return result;
1007 }
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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1030 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++) {
1036 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1037 value, i, &tcl_elem);
1038 if (status == TCL_ERROR) {
1039 Py_DECREF(result);
1040 return Tkinter_Error(tkapp);
1041 }
1042 elem = FromObj(tkapp, tcl_elem);
1043 if (!elem) {
1044 Py_DECREF(result);
1045 return NULL;
1046 }
1047 PyTuple_SetItem(result, i, elem);
1048 }
1049 return result;
1050 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001051
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 if (value->typePtr == app->ProcBodyType) {
1053 /* fall through: return tcl object. */
1054 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001057 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001058 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001059 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001063}
1064
Benjamin Peterson5879d412009-03-30 14:51:56 +00001065#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001066/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001067TCL_DECLARE_MUTEX(call_mutex)
1068
1069typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 Tcl_Event ev; /* Must be first */
1071 TkappObject *self;
1072 PyObject *args;
1073 int flags;
1074 PyObject **res;
1075 PyObject **exc_type, **exc_value, **exc_tb;
1076 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001077} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001078#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001079
1080void
1081Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001082{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001083 int i;
1084 for (i = 0; i < objc; i++)
1085 Tcl_DecrRefCount(objv[i]);
1086 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001087 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001088}
Guido van Rossum18468821994-06-20 07:49:28 +00001089
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001090/* Convert Python objects to Tcl objects. This must happen in the
1091 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001092
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001093static Tcl_Obj**
1094Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1095{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001097 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001098 if (args == NULL)
1099 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001100
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001101 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001102 objv[0] = AsObj(args);
1103 if (objv[0] == 0)
1104 goto finally;
1105 objc = 1;
1106 Tcl_IncrRefCount(objv[0]);
1107 }
1108 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001109 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001110
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001111 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001112 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001113 PyErr_SetString(PyExc_OverflowError,
1114 PyTuple_Check(args) ? "tuple is too long" :
1115 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001116 return NULL;
1117 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001118 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 if (objv == NULL) {
1120 PyErr_NoMemory();
1121 objc = 0;
1122 goto finally;
1123 }
1124 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001126 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001127 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 if (v == Py_None) {
1129 objc = i;
1130 break;
1131 }
1132 objv[i] = AsObj(v);
1133 if (!objv[i]) {
1134 /* Reset objc, so it attempts to clear
1135 objects only up to i. */
1136 objc = i;
1137 goto finally;
1138 }
1139 Tcl_IncrRefCount(objv[i]);
1140 }
1141 }
1142 *pobjc = objc;
1143 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 Tkapp_CallDeallocArgs(objv, objStore, objc);
1146 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001147}
Guido van Rossum212643f1998-04-29 16:22:14 +00001148
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001149/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001150
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001151static PyObject*
1152Tkapp_CallResult(TkappObject *self)
1153{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001154 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001155 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 /* Not sure whether the IncrRef is necessary, but something
1158 may overwrite the interpreter result while we are
1159 converting it. */
1160 Tcl_IncrRefCount(value);
1161 res = FromObj((PyObject*)self, value);
1162 Tcl_DecrRefCount(value);
1163 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001164 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001165 }
1166 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001167}
Guido van Rossum632de272000-03-29 00:19:50 +00001168
Benjamin Peterson5879d412009-03-30 14:51:56 +00001169#ifdef WITH_THREAD
1170
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001171/* Tkapp_CallProc is the event procedure that is executed in the context of
1172 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1173 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001174
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175static int
1176Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1177{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001178 Tcl_Obj *objStore[ARGSZ];
1179 Tcl_Obj **objv;
1180 int objc;
1181 int i;
1182 ENTER_PYTHON
1183 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1184 if (!objv) {
1185 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1186 *(e->res) = NULL;
1187 }
1188 LEAVE_PYTHON
1189 if (!objv)
1190 goto done;
1191 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1192 ENTER_PYTHON
1193 if (i == TCL_ERROR) {
1194 *(e->res) = NULL;
1195 *(e->exc_type) = NULL;
1196 *(e->exc_tb) = NULL;
1197 *(e->exc_value) = PyObject_CallFunction(
1198 Tkinter_TclError, "s",
1199 Tcl_GetStringResult(e->self->interp));
1200 }
1201 else {
1202 *(e->res) = Tkapp_CallResult(e->self);
1203 }
1204 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001206 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001207done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 /* Wake up calling thread. */
1209 Tcl_MutexLock(&call_mutex);
1210 Tcl_ConditionNotify(e->done);
1211 Tcl_MutexUnlock(&call_mutex);
1212 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213}
1214
Benjamin Peterson5879d412009-03-30 14:51:56 +00001215#endif
1216
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001217/* This is the main entry point for calling a Tcl command.
1218 It supports three cases, with regard to threading:
1219 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1220 the context of the calling thread.
1221 2. Tcl is threaded, caller of the command is in the interpreter thread:
1222 Execute the command in the calling thread. Since the Tcl lock will
1223 not be used, we can merge that with case 1.
1224 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1225 the interpreter thread. Allocation of Tcl objects needs to occur in the
1226 interpreter thread, so we ship the PyObject* args to the target thread,
1227 and perform processing there. */
1228
1229static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001230Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001231{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001232 Tcl_Obj *objStore[ARGSZ];
1233 Tcl_Obj **objv = NULL;
1234 int objc, i;
1235 PyObject *res = NULL;
1236 TkappObject *self = (TkappObject*)selfptr;
1237 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 /* If args is a single tuple, replace with contents of tuple */
1240 if (1 == PyTuple_Size(args)){
1241 PyObject* item = PyTuple_GetItem(args, 0);
1242 if (PyTuple_Check(item))
1243 args = item;
1244 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001245#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001246 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1247 /* We cannot call the command directly. Instead, we must
1248 marshal the parameters to the interpreter thread. */
1249 Tkapp_CallEvent *ev;
1250 Tcl_Condition cond = NULL;
1251 PyObject *exc_type, *exc_value, *exc_tb;
1252 if (!WaitForMainloop(self))
1253 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001254 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1255 if (ev == NULL) {
1256 PyErr_NoMemory();
1257 return NULL;
1258 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1260 ev->self = self;
1261 ev->args = args;
1262 ev->res = &res;
1263 ev->exc_type = &exc_type;
1264 ev->exc_value = &exc_value;
1265 ev->exc_tb = &exc_tb;
1266 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 if (res == NULL) {
1271 if (exc_type)
1272 PyErr_Restore(exc_type, exc_value, exc_tb);
1273 else
1274 PyErr_SetObject(Tkinter_TclError, exc_value);
1275 }
1276 Tcl_ConditionFinalize(&cond);
1277 }
1278 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001279#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 objv = Tkapp_CallArgs(args, objStore, &objc);
1283 if (!objv)
1284 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 if (i == TCL_ERROR)
1293 Tkinter_Error(selfptr);
1294 else
1295 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001299 Tkapp_CallDeallocArgs(objv, objStore, objc);
1300 }
1301 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001302}
1303
1304
1305static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001306Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001307{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 char *script;
1309 PyObject *res = NULL;
1310 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 if (!PyArg_ParseTuple(args, "s:eval", &script))
1313 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001314
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001315 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 ENTER_TCL
1319 err = Tcl_Eval(Tkapp_Interp(self), script);
1320 ENTER_OVERLAP
1321 if (err == TCL_ERROR)
1322 res = Tkinter_Error(self);
1323 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001324 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 LEAVE_OVERLAP_TCL
1326 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001327}
1328
1329static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001330Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001331{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001332 char *fileName;
1333 PyObject *res = NULL;
1334 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001336 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1337 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001338
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001339 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 ENTER_TCL
1343 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1344 ENTER_OVERLAP
1345 if (err == TCL_ERROR)
1346 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001348 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 LEAVE_OVERLAP_TCL
1350 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001351}
1352
1353static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001354Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001355{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001356 char *script;
1357 PyObject *res = NULL;
1358 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001359
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001360 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001362
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001363 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 ENTER_TCL
1367 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1368 ENTER_OVERLAP
1369 if (err == TCL_ERROR)
1370 res = Tkinter_Error(self);
1371 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001372 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001373 LEAVE_OVERLAP_TCL
1374 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001375}
1376
1377static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001378Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001379{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001380 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1383 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001384 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001387 ENTER_TCL
1388 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1389 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001390
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001391 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001392}
1393
Barry Warsawfa701a81997-01-16 00:15:11 +00001394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395
Guido van Rossum18468821994-06-20 07:49:28 +00001396/** Tcl Variable **/
1397
Benjamin Peterson5879d412009-03-30 14:51:56 +00001398typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1399
1400#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001401TCL_DECLARE_MUTEX(var_mutex)
1402
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001403typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001404 Tcl_Event ev; /* must be first */
1405 PyObject *self;
1406 PyObject *args;
1407 int flags;
1408 EventFunc func;
1409 PyObject **res;
1410 PyObject **exc_type;
1411 PyObject **exc_val;
1412 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001414#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001415
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001416static int
1417varname_converter(PyObject *in, void *_out)
1418{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001419 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 char **out = (char**)_out;
1421 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001422 if (PyBytes_Size(in) > INT_MAX) {
1423 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1424 return 0;
1425 }
1426 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001427 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001428 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001429 return 0;
1430 }
1431 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 return 1;
1433 }
1434 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001435 Py_ssize_t size;
1436 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001437 if (s == NULL) {
1438 return 0;
1439 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001440 if (size > INT_MAX) {
1441 PyErr_SetString(PyExc_OverflowError, "string is too long");
1442 return 0;
1443 }
Victor Stinner706768c2014-08-16 01:03:39 +02001444 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001445 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001446 return 0;
1447 }
1448 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001449 return 1;
1450 }
1451 if (PyTclObject_Check(in)) {
1452 *out = PyTclObject_TclString(in);
1453 return 1;
1454 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001455 PyErr_Format(PyExc_TypeError,
1456 "must be str, bytes or Tcl_Obj, not %.50s",
1457 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001458 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001459}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001460
Benjamin Peterson5879d412009-03-30 14:51:56 +00001461#ifdef WITH_THREAD
1462
Martin v. Löwis59683e82008-06-13 07:50:45 +00001463static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001464var_perform(VarEvent *ev)
1465{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001466 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1467 if (!*(ev->res)) {
1468 PyObject *exc, *val, *tb;
1469 PyErr_Fetch(&exc, &val, &tb);
1470 PyErr_NormalizeException(&exc, &val, &tb);
1471 *(ev->exc_type) = exc;
1472 *(ev->exc_val) = val;
1473 Py_DECREF(tb);
1474 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001475
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476}
1477
1478static int
1479var_proc(VarEvent* ev, int flags)
1480{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 ENTER_PYTHON
1482 var_perform(ev);
1483 Tcl_MutexLock(&var_mutex);
1484 Tcl_ConditionNotify(ev->cond);
1485 Tcl_MutexUnlock(&var_mutex);
1486 LEAVE_PYTHON
1487 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488}
1489
Benjamin Peterson5879d412009-03-30 14:51:56 +00001490#endif
1491
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001493var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001494{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001495#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 TkappObject *self = (TkappObject*)selfptr;
1497 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1498 TkappObject *self = (TkappObject*)selfptr;
1499 VarEvent *ev;
1500 PyObject *res, *exc_type, *exc_val;
1501 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001503 /* The current thread is not the interpreter thread. Marshal
1504 the call to the interpreter thread, then wait for
1505 completion. */
1506 if (!WaitForMainloop(self))
1507 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001508
Serhiy Storchaka07940882014-09-11 10:38:54 +03001509 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1510 if (ev == NULL) {
1511 PyErr_NoMemory();
1512 return NULL;
1513 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514 ev->self = selfptr;
1515 ev->args = args;
1516 ev->flags = flags;
1517 ev->func = func;
1518 ev->res = &res;
1519 ev->exc_type = &exc_type;
1520 ev->exc_val = &exc_val;
1521 ev->cond = &cond;
1522 ev->ev.proc = (Tcl_EventProc*)var_proc;
1523 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1524 Tcl_ConditionFinalize(&cond);
1525 if (!res) {
1526 PyErr_SetObject(exc_type, exc_val);
1527 Py_DECREF(exc_type);
1528 Py_DECREF(exc_val);
1529 return NULL;
1530 }
1531 return res;
1532 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001533#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001534 /* Tcl is not threaded, or this is the interpreter thread. */
1535 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536}
1537
Guido van Rossum18468821994-06-20 07:49:28 +00001538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001539SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001540{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 char *name1, *name2;
1542 PyObject *newValue;
1543 PyObject *res = NULL;
1544 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001545
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001546 switch (PyTuple_GET_SIZE(args)) {
1547 case 2:
1548 if (!PyArg_ParseTuple(args, "O&O:setvar",
1549 varname_converter, &name1, &newValue))
1550 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001551 /* XXX Acquire tcl lock??? */
1552 newval = AsObj(newValue);
1553 if (newval == NULL)
1554 return NULL;
1555 ENTER_TCL
1556 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1557 newval, flags);
1558 ENTER_OVERLAP
1559 if (!ok)
1560 Tkinter_Error(self);
1561 else {
1562 res = Py_None;
1563 Py_INCREF(res);
1564 }
1565 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001566 break;
1567 case 3:
1568 if (!PyArg_ParseTuple(args, "ssO:setvar",
1569 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001571 CHECK_STRING_LENGTH(name1);
1572 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001573 /* XXX must hold tcl lock already??? */
1574 newval = AsObj(newValue);
1575 ENTER_TCL
1576 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1577 ENTER_OVERLAP
1578 if (!ok)
1579 Tkinter_Error(self);
1580 else {
1581 res = Py_None;
1582 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001584 LEAVE_OVERLAP_TCL
1585 break;
1586 default:
1587 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1588 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001589 }
1590 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001591}
1592
1593static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001594Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001595{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001597}
1598
1599static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001600Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001601{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001603}
1604
Barry Warsawfa701a81997-01-16 00:15:11 +00001605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606
Guido van Rossum18468821994-06-20 07:49:28 +00001607static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001608GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001609{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 char *name1, *name2=NULL;
1611 PyObject *res = NULL;
1612 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1615 varname_converter, &name1, &name2))
1616 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001617
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001618 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 ENTER_TCL
1620 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1621 ENTER_OVERLAP
1622 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001623 PyErr_SetString(Tkinter_TclError,
1624 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001625 } else {
1626 if (((TkappObject*)self)->wantobjects) {
1627 res = FromObj(self, tres);
1628 }
1629 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001630 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 }
1632 }
1633 LEAVE_OVERLAP_TCL
1634 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001635}
1636
1637static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001638Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001639{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001640 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001641}
1642
1643static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001644Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001645{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001646 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001647}
1648
Barry Warsawfa701a81997-01-16 00:15:11 +00001649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001650
Guido van Rossum18468821994-06-20 07:49:28 +00001651static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001652UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001653{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 char *name1, *name2=NULL;
1655 int code;
1656 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1659 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001660
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001661 CHECK_STRING_LENGTH(name1);
1662 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001663 ENTER_TCL
1664 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1665 ENTER_OVERLAP
1666 if (code == TCL_ERROR)
1667 res = Tkinter_Error(self);
1668 else {
1669 Py_INCREF(Py_None);
1670 res = Py_None;
1671 }
1672 LEAVE_OVERLAP_TCL
1673 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001674}
1675
1676static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001677Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001678{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001679 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001680}
1681
1682static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001683Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001684{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001685 return var_invoke(UnsetVar, self, args,
1686 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001687}
1688
Barry Warsawfa701a81997-01-16 00:15:11 +00001689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001690
Guido van Rossum18468821994-06-20 07:49:28 +00001691/** Tcl to Python **/
1692
1693static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001694Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001695{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 char *s;
1697 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001699 if (PyTuple_Size(args) == 1) {
1700 PyObject* o = PyTuple_GetItem(args, 0);
1701 if (PyLong_Check(o)) {
1702 Py_INCREF(o);
1703 return o;
1704 }
1705 }
1706 if (!PyArg_ParseTuple(args, "s:getint", &s))
1707 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001708 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001709 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1710 return Tkinter_Error(self);
1711 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001712}
1713
1714static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001715Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001716{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717 char *s;
1718 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 if (PyTuple_Size(args) == 1) {
1721 PyObject *o = PyTuple_GetItem(args, 0);
1722 if (PyFloat_Check(o)) {
1723 Py_INCREF(o);
1724 return o;
1725 }
1726 }
1727 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1728 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001729 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001730 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1731 return Tkinter_Error(self);
1732 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001733}
1734
1735static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001736Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 char *s;
1739 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001741 if (PyTuple_Size(args) == 1) {
1742 PyObject *o = PyTuple_GetItem(args, 0);
1743 if (PyLong_Check(o)) {
1744 Py_INCREF(o);
1745 return o;
1746 }
1747 }
1748 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1749 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001750 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001751 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1752 return Tkinter_Error(self);
1753 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001754}
1755
1756static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 char *s;
1760 PyObject *res = NULL;
1761 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1764 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001765
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001766 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 ENTER_TCL
1770 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1771 ENTER_OVERLAP
1772 if (retval == TCL_ERROR)
1773 res = Tkinter_Error(self);
1774 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001775 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 LEAVE_OVERLAP_TCL
1777 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001778}
1779
1780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001783 char *s;
1784 PyObject *res = NULL;
1785 int retval;
1786 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1789 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001790
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001791 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001794 ENTER_TCL
1795 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1796 ENTER_OVERLAP
1797 if (retval == TCL_ERROR)
1798 res = Tkinter_Error(self);
1799 else
1800 res = Py_BuildValue("l", v);
1801 LEAVE_OVERLAP_TCL
1802 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001803}
1804
1805static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001806Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001807{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 char *s;
1809 PyObject *res = NULL;
1810 double v;
1811 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1814 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001815 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 CHECK_TCL_APPARTMENT;
1817 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1818 ENTER_TCL
1819 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1820 ENTER_OVERLAP
1821 PyFPE_END_PROTECT(retval)
1822 if (retval == TCL_ERROR)
1823 res = Tkinter_Error(self);
1824 else
1825 res = Py_BuildValue("d", v);
1826 LEAVE_OVERLAP_TCL
1827 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001828}
1829
1830static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001831Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001832{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001833 char *s;
1834 PyObject *res = NULL;
1835 int retval;
1836 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001838 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1839 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001840 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 CHECK_TCL_APPARTMENT;
1842 ENTER_TCL
1843 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1844 ENTER_OVERLAP
1845 if (retval == TCL_ERROR)
1846 res = Tkinter_Error(self);
1847 else
1848 res = Py_BuildValue("i", v);
1849 LEAVE_OVERLAP_TCL
1850 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001851}
1852
Barry Warsawfa701a81997-01-16 00:15:11 +00001853
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001854
Guido van Rossum18468821994-06-20 07:49:28 +00001855static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001856Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001857{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001858 char *list;
1859 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001860 const char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001861 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001862 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001863
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001864 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1865 return NULL;
1866 if (PyTclObject_Check(arg)) {
1867 int objc;
1868 Tcl_Obj **objv;
1869 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1870 ((PyTclObject*)arg)->value,
1871 &objc, &objv) == TCL_ERROR) {
1872 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001874 if (!(v = PyTuple_New(objc)))
1875 return NULL;
1876 for (i = 0; i < objc; i++) {
1877 PyObject *s = FromObj(self, objv[i]);
1878 if (!s || PyTuple_SetItem(v, i, s)) {
1879 Py_DECREF(v);
1880 return NULL;
1881 }
1882 }
1883 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001885 if (PyTuple_Check(arg)) {
1886 Py_INCREF(arg);
1887 return arg;
1888 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001889 if (PyList_Check(arg)) {
1890 return PySequence_Tuple(arg);
1891 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001893 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1894 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001895
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001896 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 if (Tcl_SplitList(Tkapp_Interp(self), list,
1898 &argc, &argv) == TCL_ERROR) {
1899 PyMem_Free(list);
1900 return Tkinter_Error(self);
1901 }
Guido van Rossum18468821994-06-20 07:49:28 +00001902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 if (!(v = PyTuple_New(argc)))
1904 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001906 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001907 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 if (!s || PyTuple_SetItem(v, i, s)) {
1909 Py_DECREF(v);
1910 v = NULL;
1911 goto finally;
1912 }
1913 }
Guido van Rossum18468821994-06-20 07:49:28 +00001914
Barry Warsawfa701a81997-01-16 00:15:11 +00001915 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001916 ckfree(FREECAST argv);
1917 PyMem_Free(list);
1918 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001919}
1920
1921static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001922Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001923{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001924 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001926
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001927 if (!PyArg_ParseTuple(args, "O:split", &arg))
1928 return NULL;
1929 if (PyTclObject_Check(arg)) {
1930 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1931 int objc;
1932 Tcl_Obj **objv;
1933 int i;
1934 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1935 &objc, &objv) == TCL_ERROR) {
1936 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001937 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001938 if (objc == 0)
1939 return PyUnicode_FromString("");
1940 if (objc == 1)
1941 return FromObj(self, objv[0]);
1942 if (!(v = PyTuple_New(objc)))
1943 return NULL;
1944 for (i = 0; i < objc; i++) {
1945 PyObject *s = FromObj(self, objv[i]);
1946 if (!s || PyTuple_SetItem(v, i, s)) {
1947 Py_DECREF(v);
1948 return NULL;
1949 }
1950 }
1951 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001952 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001953 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001954 return SplitObj(arg);
1955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1957 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001958 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001959 v = Split(list);
1960 PyMem_Free(list);
1961 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001962}
1963
Barry Warsawfa701a81997-01-16 00:15:11 +00001964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965
Guido van Rossum18468821994-06-20 07:49:28 +00001966/** Tcl Command **/
1967
Guido van Rossum00d93061998-05-28 23:06:38 +00001968/* Client data struct */
1969typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970 PyObject *self;
1971 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001972} PythonCmd_ClientData;
1973
1974static int
Fred Drake509d79a2000-07-08 04:04:38 +00001975PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 errorInCmd = 1;
1978 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1979 LEAVE_PYTHON
1980 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001981}
1982
Guido van Rossum18468821994-06-20 07:49:28 +00001983/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001984 * function or method.
1985 */
Guido van Rossum18468821994-06-20 07:49:28 +00001986static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03001987PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001988{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001990 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001991 int i, rv;
1992 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996 /* TBD: no error checking here since we know, via the
1997 * Tkapp_CreateCommand() that the client data is a two-tuple
1998 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001999 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 /* Create argument list (argv1, ..., argvN) */
2002 if (!(arg = PyTuple_New(argc - 1)))
2003 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002006 PyObject *s = unicodeFromTclString(argv[i + 1]);
2007 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 Py_DECREF(arg);
2009 return PythonCmd_Error(interp);
2010 }
2011 }
2012 res = PyEval_CallObject(func, arg);
2013 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 if (res == NULL)
2016 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 obj_res = AsObj(res);
2019 if (obj_res == NULL) {
2020 Py_DECREF(res);
2021 return PythonCmd_Error(interp);
2022 }
2023 else {
2024 Tcl_SetObjResult(interp, obj_res);
2025 rv = TCL_OK;
2026 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002028 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002030 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002032 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002033}
2034
2035static void
Fred Drake509d79a2000-07-08 04:04:38 +00002036PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002038 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002040 ENTER_PYTHON
2041 Py_XDECREF(data->self);
2042 Py_XDECREF(data->func);
2043 PyMem_DEL(data);
2044 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002045}
2046
Barry Warsawfa701a81997-01-16 00:15:11 +00002047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002049
Benjamin Peterson5879d412009-03-30 14:51:56 +00002050#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002051TCL_DECLARE_MUTEX(command_mutex)
2052
2053typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002054 Tcl_Event ev;
2055 Tcl_Interp* interp;
2056 char *name;
2057 int create;
2058 int *status;
2059 ClientData *data;
2060 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002061} CommandEvent;
2062
2063static int
2064Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002065{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002066 if (ev->create)
2067 *ev->status = Tcl_CreateCommand(
2068 ev->interp, ev->name, PythonCmd,
2069 ev->data, PythonCmdDelete) == NULL;
2070 else
2071 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2072 Tcl_MutexLock(&command_mutex);
2073 Tcl_ConditionNotify(ev->done);
2074 Tcl_MutexUnlock(&command_mutex);
2075 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002076}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002077#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002078
2079static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002080Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002082 TkappObject *self = (TkappObject*)selfptr;
2083 PythonCmd_ClientData *data;
2084 char *cmdName;
2085 PyObject *func;
2086 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2089 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002090 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002091 if (!PyCallable_Check(func)) {
2092 PyErr_SetString(PyExc_TypeError, "command not callable");
2093 return NULL;
2094 }
Guido van Rossum18468821994-06-20 07:49:28 +00002095
Martin v. Löwisa9656492003-03-30 08:44:58 +00002096#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002097 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2098 !WaitForMainloop(self))
2099 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002100#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 data = PyMem_NEW(PythonCmd_ClientData, 1);
2103 if (!data)
2104 return PyErr_NoMemory();
2105 Py_INCREF(self);
2106 Py_INCREF(func);
2107 data->self = selfptr;
2108 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002109#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2111 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002112 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2113 if (ev == NULL) {
2114 PyErr_NoMemory();
2115 PyMem_DEL(data);
2116 return NULL;
2117 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002118 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2119 ev->interp = self->interp;
2120 ev->create = 1;
2121 ev->name = cmdName;
2122 ev->data = (ClientData)data;
2123 ev->status = &err;
2124 ev->done = &cond;
2125 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2126 Tcl_ConditionFinalize(&cond);
2127 }
2128 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002129#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002130 {
2131 ENTER_TCL
2132 err = Tcl_CreateCommand(
2133 Tkapp_Interp(self), cmdName, PythonCmd,
2134 (ClientData)data, PythonCmdDelete) == NULL;
2135 LEAVE_TCL
2136 }
2137 if (err) {
2138 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2139 PyMem_DEL(data);
2140 return NULL;
2141 }
Guido van Rossum18468821994-06-20 07:49:28 +00002142
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002143 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002144}
2145
Barry Warsawfa701a81997-01-16 00:15:11 +00002146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002147
Guido van Rossum18468821994-06-20 07:49:28 +00002148static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002149Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002150{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002151 TkappObject *self = (TkappObject*)selfptr;
2152 char *cmdName;
2153 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002154
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002155 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2156 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002157 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002158
2159#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2161 Tcl_Condition cond = NULL;
2162 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002163 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2164 if (ev == NULL) {
2165 PyErr_NoMemory();
2166 return NULL;
2167 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2169 ev->interp = self->interp;
2170 ev->create = 0;
2171 ev->name = cmdName;
2172 ev->status = &err;
2173 ev->done = &cond;
2174 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2175 &command_mutex);
2176 Tcl_ConditionFinalize(&cond);
2177 }
2178 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002179#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002180 {
2181 ENTER_TCL
2182 err = Tcl_DeleteCommand(self->interp, cmdName);
2183 LEAVE_TCL
2184 }
2185 if (err == -1) {
2186 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2187 return NULL;
2188 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002189 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002190}
2191
Barry Warsawfa701a81997-01-16 00:15:11 +00002192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193
Guido van Rossum00d93061998-05-28 23:06:38 +00002194#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002195/** File Handler **/
2196
Guido van Rossum00d93061998-05-28 23:06:38 +00002197typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198 PyObject *func;
2199 PyObject *file;
2200 int id;
2201 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002202} FileHandler_ClientData;
2203
2204static FileHandler_ClientData *HeadFHCD;
2205
2206static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002207NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002208{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002209 FileHandler_ClientData *p;
2210 p = PyMem_NEW(FileHandler_ClientData, 1);
2211 if (p != NULL) {
2212 Py_XINCREF(func);
2213 Py_XINCREF(file);
2214 p->func = func;
2215 p->file = file;
2216 p->id = id;
2217 p->next = HeadFHCD;
2218 HeadFHCD = p;
2219 }
2220 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002221}
2222
2223static void
Fred Drake509d79a2000-07-08 04:04:38 +00002224DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002227
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002228 pp = &HeadFHCD;
2229 while ((p = *pp) != NULL) {
2230 if (p->id == id) {
2231 *pp = p->next;
2232 Py_XDECREF(p->func);
2233 Py_XDECREF(p->file);
2234 PyMem_DEL(p);
2235 }
2236 else
2237 pp = &p->next;
2238 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002239}
2240
Guido van Rossuma597dde1995-01-10 20:56:29 +00002241static void
Fred Drake509d79a2000-07-08 04:04:38 +00002242FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002243{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2245 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 ENTER_PYTHON
2248 func = data->func;
2249 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251 arg = Py_BuildValue("(Oi)", file, (long) mask);
2252 res = PyEval_CallObject(func, arg);
2253 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 if (res == NULL) {
2256 errorInCmd = 1;
2257 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2258 }
2259 Py_XDECREF(res);
2260 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002261}
2262
Guido van Rossum18468821994-06-20 07:49:28 +00002263static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002264Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2265 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002266{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 FileHandler_ClientData *data;
2268 PyObject *file, *func;
2269 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2272 &file, &mask, &func))
2273 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 tfile = PyObject_AsFileDescriptor(file);
2278 if (tfile < 0)
2279 return NULL;
2280 if (!PyCallable_Check(func)) {
2281 PyErr_SetString(PyExc_TypeError, "bad argument list");
2282 return NULL;
2283 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285 data = NewFHCD(func, file, tfile);
2286 if (data == NULL)
2287 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 /* Ought to check for null Tcl_File object... */
2290 ENTER_TCL
2291 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2292 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002293 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002294}
2295
2296static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002297Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002298{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 PyObject *file;
2300 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2303 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002305 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 tfile = PyObject_AsFileDescriptor(file);
2308 if (tfile < 0)
2309 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 /* Ought to check for null Tcl_File object... */
2314 ENTER_TCL
2315 Tcl_DeleteFileHandler(tfile);
2316 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002317 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002318}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002319#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322/**** Tktt Object (timer token) ****/
2323
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002324static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002325
Guido van Rossum00d93061998-05-28 23:06:38 +00002326typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 PyObject_HEAD
2328 Tcl_TimerToken token;
2329 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002330} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331
2332static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002333Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002335 TkttObject *v = (TkttObject *)self;
2336 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2339 return NULL;
2340 if (v->token != NULL) {
2341 Tcl_DeleteTimerHandler(v->token);
2342 v->token = NULL;
2343 }
2344 if (func != NULL) {
2345 v->func = NULL;
2346 Py_DECREF(func);
2347 Py_DECREF(v); /* See Tktt_New() */
2348 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002349 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002350}
2351
2352static PyMethodDef Tktt_methods[] =
2353{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002354 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2355 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356};
2357
2358static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002359Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002362
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002363 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 if (v == NULL)
2365 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002366 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002368 Py_INCREF(func);
2369 v->token = NULL;
2370 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372 /* Extra reference, deleted when called or when handler is deleted */
2373 Py_INCREF(v);
2374 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375}
2376
2377static void
Fred Drake509d79a2000-07-08 04:04:38 +00002378Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002379{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 TkttObject *v = (TkttObject *)self;
2381 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002382 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002387 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388}
2389
Guido van Rossum597ac201998-05-12 14:36:19 +00002390static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002391Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002392{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002393 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002394 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2395 v,
2396 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397}
2398
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002399static PyType_Slot Tktt_Type_slots[] = {
2400 {Py_tp_dealloc, Tktt_Dealloc},
2401 {Py_tp_repr, Tktt_Repr},
2402 {Py_tp_methods, Tktt_methods},
2403 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404};
2405
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002406static PyType_Spec Tktt_Type_spec = {
2407 "tktimertoken",
2408 sizeof(TkttObject),
2409 0,
2410 Py_TPFLAGS_DEFAULT,
2411 Tktt_Type_slots,
2412};
Barry Warsawfa701a81997-01-16 00:15:11 +00002413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002415/** Timer Handler **/
2416
2417static void
Fred Drake509d79a2000-07-08 04:04:38 +00002418TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002419{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 TkttObject *v = (TkttObject *)clientData;
2421 PyObject *func = v->func;
2422 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 if (func == NULL)
2425 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002431 res = PyEval_CallObject(func, NULL);
2432 Py_DECREF(func);
2433 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002435 if (res == NULL) {
2436 errorInCmd = 1;
2437 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2438 }
2439 else
2440 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002443}
2444
2445static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002446Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002447{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 int milliseconds;
2449 PyObject *func;
2450 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2453 &milliseconds, &func))
2454 return NULL;
2455 if (!PyCallable_Check(func)) {
2456 PyErr_SetString(PyExc_TypeError, "bad argument list");
2457 return NULL;
2458 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 v = Tktt_New(func);
2463 if (v) {
2464 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2465 (ClientData)v);
2466 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002469}
2470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471
Guido van Rossum18468821994-06-20 07:49:28 +00002472/** Event Loop **/
2473
Guido van Rossum18468821994-06-20 07:49:28 +00002474static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002475Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002476{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 int threshold = 0;
2478 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002479#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002480 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002481#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002483 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2484 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 CHECK_TCL_APPARTMENT;
2487 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002489 quitMainLoop = 0;
2490 while (Tk_GetNumMainWindows() > threshold &&
2491 !quitMainLoop &&
2492 !errorInCmd)
2493 {
2494 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002495
2496#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002497 if (self->threaded) {
2498 /* Allow other Python threads to run. */
2499 ENTER_TCL
2500 result = Tcl_DoOneEvent(0);
2501 LEAVE_TCL
2502 }
2503 else {
2504 Py_BEGIN_ALLOW_THREADS
2505 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2506 tcl_tstate = tstate;
2507 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2508 tcl_tstate = NULL;
2509 if(tcl_lock)PyThread_release_lock(tcl_lock);
2510 if (result == 0)
2511 Sleep(Tkinter_busywaitinterval);
2512 Py_END_ALLOW_THREADS
2513 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002514#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002515 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002516#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 if (PyErr_CheckSignals() != 0) {
2519 self->dispatching = 0;
2520 return NULL;
2521 }
2522 if (result < 0)
2523 break;
2524 }
2525 self->dispatching = 0;
2526 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528 if (errorInCmd) {
2529 errorInCmd = 0;
2530 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2531 excInCmd = valInCmd = trbInCmd = NULL;
2532 return NULL;
2533 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002534 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002535}
2536
2537static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002538Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002539{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002540 int flags = 0;
2541 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002543 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2544 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 ENTER_TCL
2547 rv = Tcl_DoOneEvent(flags);
2548 LEAVE_TCL
2549 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002550}
2551
2552static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002553Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002554{
2555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556 if (!PyArg_ParseTuple(args, ":quit"))
2557 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002560 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002561}
2562
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002563static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002564Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002565{
2566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 if (!PyArg_ParseTuple(args, ":interpaddr"))
2568 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002569
Victor Stinnere1040e22013-09-05 00:22:24 +02002570 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002571}
2572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002573static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002574Tkapp_TkInit(PyObject *self, PyObject *args)
2575{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576 Tcl_Interp *interp = Tkapp_Interp(self);
2577 const char * _tk_exists = NULL;
2578 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002579
Guilherme Polob681df42009-02-09 22:33:59 +00002580#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2582 * first call failed.
2583 * To avoid the deadlock, we just refuse the second call through
2584 * a static variable.
2585 */
2586 if (tk_load_failed) {
2587 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2588 return NULL;
2589 }
Guilherme Polob681df42009-02-09 22:33:59 +00002590#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 /* We want to guard against calling Tk_Init() multiple times */
2593 CHECK_TCL_APPARTMENT;
2594 ENTER_TCL
2595 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2596 ENTER_OVERLAP
2597 if (err == TCL_ERROR) {
2598 /* This sets an exception, but we cannot return right
2599 away because we need to exit the overlap first. */
2600 Tkinter_Error(self);
2601 } else {
2602 _tk_exists = Tkapp_Result(self);
2603 }
2604 LEAVE_OVERLAP_TCL
2605 if (err == TCL_ERROR) {
2606 return NULL;
2607 }
2608 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2609 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002610 PyErr_SetString(Tkinter_TclError,
2611 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002612#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002614#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002615 return NULL;
2616 }
2617 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002618 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002619}
Barry Warsawfa701a81997-01-16 00:15:11 +00002620
Martin v. Löwisffad6332002-11-26 09:28:05 +00002621static PyObject *
2622Tkapp_WantObjects(PyObject *self, PyObject *args)
2623{
2624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 int wantobjects = -1;
2626 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2627 return NULL;
2628 if (wantobjects == -1)
2629 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2630 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002631
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002632 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002633}
2634
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002635static PyObject *
2636Tkapp_WillDispatch(PyObject *self, PyObject *args)
2637{
2638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002639 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002640
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002641 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002642}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002644
Guido van Rossum18468821994-06-20 07:49:28 +00002645/**** Tkapp Method List ****/
2646
2647static PyMethodDef Tkapp_methods[] =
2648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2650 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2651 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002652 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002653 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2654 {"record", Tkapp_Record, METH_VARARGS},
2655 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2656 {"setvar", Tkapp_SetVar, METH_VARARGS},
2657 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2658 {"getvar", Tkapp_GetVar, METH_VARARGS},
2659 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2660 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2661 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2662 {"getint", Tkapp_GetInt, METH_VARARGS},
2663 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2664 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2665 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2666 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2667 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2668 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2669 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2670 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2672 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002673#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2675 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002676#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002677 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2678 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2679 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2680 {"quit", Tkapp_Quit, METH_VARARGS},
2681 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2682 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2683 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002684};
2685
Barry Warsawfa701a81997-01-16 00:15:11 +00002686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687
Guido van Rossum18468821994-06-20 07:49:28 +00002688/**** Tkapp Type Methods ****/
2689
2690static void
Fred Drake509d79a2000-07-08 04:04:38 +00002691Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002692{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002693 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002694 /*CHECK_TCL_APPARTMENT;*/
2695 ENTER_TCL
2696 Tcl_DeleteInterp(Tkapp_Interp(self));
2697 LEAVE_TCL
2698 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002699 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002701}
2702
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002703static PyType_Slot Tkapp_Type_slots[] = {
2704 {Py_tp_dealloc, Tkapp_Dealloc},
2705 {Py_tp_methods, Tkapp_methods},
2706 {0, 0}
2707};
2708
2709
2710static PyType_Spec Tkapp_Type_spec = {
2711 "tkapp",
2712 sizeof(TkappObject),
2713 0,
2714 Py_TPFLAGS_DEFAULT,
2715 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002716};
2717
Barry Warsawfa701a81997-01-16 00:15:11 +00002718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719
Guido van Rossum18468821994-06-20 07:49:28 +00002720/**** Tkinter Module ****/
2721
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002722typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 PyObject* tuple;
2724 int size; /* current size */
2725 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002726} FlattenContext;
2727
2728static int
2729_bump(FlattenContext* context, int size)
2730{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002731 /* expand tuple to hold (at least) size new items.
2732 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002733
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002734 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002736 if (maxsize < context->size + size)
2737 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002742}
2743
2744static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002745_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002746{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002747 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002749 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751 if (depth > 1000) {
2752 PyErr_SetString(PyExc_ValueError,
2753 "nesting too deep in _flatten");
2754 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002755 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2756 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 /* preallocate (assume no nesting) */
2758 if (context->size + size > context->maxsize &&
2759 !_bump(context, size))
2760 return 0;
2761 /* copy items to output tuple */
2762 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002763 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002764 if (PyList_Check(o) || PyTuple_Check(o)) {
2765 if (!_flatten1(context, o, depth + 1))
2766 return 0;
2767 } else if (o != Py_None) {
2768 if (context->size + 1 > context->maxsize &&
2769 !_bump(context, 1))
2770 return 0;
2771 Py_INCREF(o);
2772 PyTuple_SET_ITEM(context->tuple,
2773 context->size++, o);
2774 }
2775 }
2776 } else {
2777 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2778 return 0;
2779 }
2780 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002781}
2782
2783static PyObject *
2784Tkinter_Flatten(PyObject* self, PyObject* args)
2785{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 FlattenContext context;
2787 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002789 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2790 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002791
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002792 context.maxsize = PySequence_Size(item);
2793 if (context.maxsize < 0)
2794 return NULL;
2795 if (context.maxsize == 0)
2796 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 context.tuple = PyTuple_New(context.maxsize);
2799 if (!context.tuple)
2800 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002804 if (!_flatten1(&context, item,0))
2805 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 if (_PyTuple_Resize(&context.tuple, context.size))
2808 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811}
2812
Guido van Rossum18468821994-06-20 07:49:28 +00002813static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002814Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002815{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 char *screenName = NULL;
2817 char *baseName = NULL; /* XXX this is not used anymore;
2818 try getting rid of it. */
2819 char *className = NULL;
2820 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03002821 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2823 int sync = 0; /* pass -sync to wish */
2824 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002826 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2829 &screenName, &baseName, &className,
2830 &interactive, &wantobjects, &wantTk,
2831 &sync, &use))
2832 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002833 CHECK_STRING_LENGTH(screenName);
2834 CHECK_STRING_LENGTH(baseName);
2835 CHECK_STRING_LENGTH(className);
2836 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002839 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002841}
2842
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002843static PyObject *
2844Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2845{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 int new_val;
2847 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2848 return NULL;
2849 if (new_val < 0) {
2850 PyErr_SetString(PyExc_ValueError,
2851 "busywaitinterval must be >= 0");
2852 return NULL;
2853 }
2854 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002855 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002856}
2857
2858static char setbusywaitinterval_doc[] =
2859"setbusywaitinterval(n) -> None\n\
2860\n\
2861Set the busy-wait interval in milliseconds between successive\n\
2862calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2863It should be set to a divisor of the maximum time between\n\
2864frames in an animation.";
2865
2866static PyObject *
2867Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2868{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002870}
2871
2872static char getbusywaitinterval_doc[] =
2873"getbusywaitinterval() -> int\n\
2874\n\
2875Return the current busy-wait interval between successive\n\
2876calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2877
Guido van Rossum18468821994-06-20 07:49:28 +00002878static PyMethodDef moduleMethods[] =
2879{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2881 {"create", Tkinter_Create, METH_VARARGS},
2882 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2883 setbusywaitinterval_doc},
2884 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2885 METH_NOARGS, getbusywaitinterval_doc},
2886 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002887};
2888
Guido van Rossum7bf15641998-05-22 18:28:17 +00002889#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002890
2891static int stdin_ready = 0;
2892
Guido van Rossumad4db171998-06-13 13:56:28 +00002893#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002894static void
Fred Drake509d79a2000-07-08 04:04:38 +00002895MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002896{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002897 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002898}
Guido van Rossumad4db171998-06-13 13:56:28 +00002899#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002900
Martin v. Löwisa9656492003-03-30 08:44:58 +00002901#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002902static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002903#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002904
Guido van Rossum18468821994-06-20 07:49:28 +00002905static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002906EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002907{
Guido van Rossumad4db171998-06-13 13:56:28 +00002908#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002909 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002910#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002911#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002912 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002913#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 stdin_ready = 0;
2915 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002916#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 tfile = fileno(stdin);
2918 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002919#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002920 while (!errorInCmd && !stdin_ready) {
2921 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002922#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002923 if (_kbhit()) {
2924 stdin_ready = 1;
2925 break;
2926 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002927#endif
2928#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002929 Py_BEGIN_ALLOW_THREADS
2930 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2931 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 tcl_tstate = NULL;
2936 if(tcl_lock)PyThread_release_lock(tcl_lock);
2937 if (result == 0)
2938 Sleep(Tkinter_busywaitinterval);
2939 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002940#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002941 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002942#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002944 if (result < 0)
2945 break;
2946 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002947#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002949#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 if (errorInCmd) {
2951 errorInCmd = 0;
2952 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2953 excInCmd = valInCmd = trbInCmd = NULL;
2954 PyErr_Print();
2955 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002956#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002957 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002958#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002959 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002960}
Guido van Rossum18468821994-06-20 07:49:28 +00002961
Guido van Rossum00d93061998-05-28 23:06:38 +00002962#endif
2963
Guido van Rossum7bf15641998-05-22 18:28:17 +00002964static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002965EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002966{
Guido van Rossum00d93061998-05-28 23:06:38 +00002967#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002968 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002969#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002970 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002971#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002972 PyOS_InputHook = EventHook;
2973 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002974#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002975}
2976
2977static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002978DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002979{
Guido van Rossum00d93061998-05-28 23:06:38 +00002980#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002981 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2982 PyOS_InputHook = NULL;
2983 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002984#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002985}
2986
Barry Warsawfa701a81997-01-16 00:15:11 +00002987
Martin v. Löwis1a214512008-06-11 05:26:20 +00002988static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002989 PyModuleDef_HEAD_INIT,
2990 "_tkinter",
2991 NULL,
2992 -1,
2993 moduleMethods,
2994 NULL,
2995 NULL,
2996 NULL,
2997 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002998};
2999
Mark Hammond62b1ab12002-07-23 06:31:15 +00003000PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003001PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003002{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003003 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003004
Guido van Rossum00d93061998-05-28 23:06:38 +00003005#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003006 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003007 if (tcl_lock == NULL)
3008 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003009#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003010
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003011 m = PyModule_Create(&_tkintermodule);
3012 if (m == NULL)
3013 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003014
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003015 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3016 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003017 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003018 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003019 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003020 Py_INCREF(o);
3021 if (PyModule_AddObject(m, "TclError", o)) {
3022 Py_DECREF(o);
3023 Py_DECREF(m);
3024 return NULL;
3025 }
3026 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003027
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003028 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3029 Py_DECREF(m);
3030 return NULL;
3031 }
3032 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3033 Py_DECREF(m);
3034 return NULL;
3035 }
3036 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3037 Py_DECREF(m);
3038 return NULL;
3039 }
3040 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3041 Py_DECREF(m);
3042 return NULL;
3043 }
3044 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3045 Py_DECREF(m);
3046 return NULL;
3047 }
3048 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3049 Py_DECREF(m);
3050 return NULL;
3051 }
3052 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3053 Py_DECREF(m);
3054 return NULL;
3055 }
3056 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3057 Py_DECREF(m);
3058 return NULL;
3059 }
3060 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3061 Py_DECREF(m);
3062 return NULL;
3063 }
3064 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3065 Py_DECREF(m);
3066 return NULL;
3067 }
3068 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3069 Py_DECREF(m);
3070 return NULL;
3071 }
3072
3073 o = PyType_FromSpec(&Tkapp_Type_spec);
3074 if (o == NULL) {
3075 Py_DECREF(m);
3076 return NULL;
3077 }
3078 if (PyModule_AddObject(m, "TkappType", o)) {
3079 Py_DECREF(o);
3080 Py_DECREF(m);
3081 return NULL;
3082 }
3083 Tkapp_Type = o;
3084
3085 o = PyType_FromSpec(&Tktt_Type_spec);
3086 if (o == NULL) {
3087 Py_DECREF(m);
3088 return NULL;
3089 }
3090 if (PyModule_AddObject(m, "TkttType", o)) {
3091 Py_DECREF(o);
3092 Py_DECREF(m);
3093 return NULL;
3094 }
3095 Tktt_Type = o;
3096
3097 o = PyType_FromSpec(&PyTclObject_Type_spec);
3098 if (o == NULL) {
3099 Py_DECREF(m);
3100 return NULL;
3101 }
3102 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3103 Py_DECREF(o);
3104 Py_DECREF(m);
3105 return NULL;
3106 }
3107 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003108
3109#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003110 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3111 * start waking up. Note that Tcl_FindExecutable will do this, this
3112 * code must be above it! The original warning from
3113 * tkMacOSXAppInit.c is copied below.
3114 *
3115 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3116 * Tcl interpreter for now. It probably should work to do this
3117 * in the other order, but for now it doesn't seem to.
3118 *
3119 */
3120 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003121#endif
3122
3123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 /* This helps the dynamic loader; in Unicode aware Tcl versions
3125 it also helps Tcl find its encodings. */
3126 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3127 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003128 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 if (cexe)
3130 Tcl_FindExecutable(PyBytes_AsString(cexe));
3131 Py_XDECREF(cexe);
3132 Py_DECREF(uexe);
3133 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 if (PyErr_Occurred()) {
3136 Py_DECREF(m);
3137 return NULL;
3138 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003139
Guido van Rossum43ff8681998-07-14 18:02:13 +00003140#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 /* This was not a good idea; through <Destroy> bindings,
3142 Tcl_Finalize() may invoke Python code but at that point the
3143 interpreter and thread state have already been destroyed! */
3144 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003145#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003146 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003147}