blob: 7871dec8d4186a35436dec5f4aab578c109085af [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030036#define CHECK_SIZE(size, elemsize) \
37 ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
38
Martin v. Löwis71e25a02002-10-01 18:08:06 +000039/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
40 making _tkinter correct for this API means to break earlier
41 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
42 earlier versions. Once Tcl releases before 8.4 don't need to be supported
43 anymore, this should go. */
44#define USE_COMPAT_CONST
45
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000046/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
47 it always; if Tcl is not threaded, the thread functions in
48 Tcl are empty. */
49#define TCL_THREADS
50
Jack Jansencb852442001-12-09 23:15:56 +000051#ifdef TK_FRAMEWORK
52#include <Tcl/tcl.h>
53#include <Tk/tk.h>
54#else
Guido van Rossum18468821994-06-20 07:49:28 +000055#include <tcl.h>
56#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000057#endif
Guido van Rossum18468821994-06-20 07:49:28 +000058
Guilherme Polo2d87e422009-04-10 22:19:09 +000059#include "tkinter.h"
60
Jason Tishlerbbe89612002-12-31 20:30:46 +000061/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000062#ifndef CONST84_RETURN
63#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000064#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000065#define CONST
66#endif
67
Guilherme Polo66917722009-02-09 22:35:27 +000068#if TK_VERSION_HEX < 0x08030102
69#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000070#endif
71
Jack Janseneddc1442003-11-20 01:44:59 +000072#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000073#define HAVE_CREATEFILEHANDLER
74#endif
75
Guido van Rossum00d93061998-05-28 23:06:38 +000076#ifdef HAVE_CREATEFILEHANDLER
77
Neal Norwitzd948a432006-01-08 01:08:55 +000078/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
79 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
80#ifndef TCL_UNIX_FD
81# ifdef TCL_WIN_SOCKET
82# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
83# else
84# define TCL_UNIX_FD 1
85# endif
86#endif
87
Guido van Rossum00d93061998-05-28 23:06:38 +000088/* Tcl_CreateFileHandler() changed several times; these macros deal with the
89 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
90 Unix, only because Jack added it back); when available on Windows, it only
91 applies to sockets. */
92
Guido van Rossum7bf15641998-05-22 18:28:17 +000093#ifdef MS_WINDOWS
94#define FHANDLETYPE TCL_WIN_SOCKET
95#else
96#define FHANDLETYPE TCL_UNIX_FD
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
100 which uses this to handle Tcl events while the user is typing commands. */
101
102#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000103#define WAIT_FOR_STDIN
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106#endif /* HAVE_CREATEFILEHANDLER */
107
Guido van Rossumad4db171998-06-13 13:56:28 +0000108#ifdef MS_WINDOWS
109#include <conio.h>
110#define WAIT_FOR_STDIN
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113#ifdef WITH_THREAD
114
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000115/* The threading situation is complicated. Tcl is not thread-safe, except
116 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000117
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300118 So we need to use a lock around all uses of Tcl. Previously, the
119 Python interpreter lock was used for this. However, this causes
120 problems when other Python threads need to run while Tcl is blocked
121 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000122
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300123 To solve this problem, a separate lock for Tcl is introduced.
124 Holding it is incompatible with holding Python's interpreter lock.
125 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000126
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300127 ENTER_TCL and LEAVE_TCL are brackets, just like
128 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
129 used whenever a call into Tcl is made that could call an event
130 handler, or otherwise affect the state of a Tcl interpreter. These
131 assume that the surrounding code has the Python interpreter lock;
132 inside the brackets, the Python interpreter lock has been released
133 and the lock for Tcl has been acquired.
134
135 Sometimes, it is necessary to have both the Python lock and the Tcl
136 lock. (For example, when transferring data from the Tcl
137 interpreter result to a Python string object.) This can be done by
138 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
139 reacquires the Python lock (and restores the thread state) but
140 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
141 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000142
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000143 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300144 handlers when the handler needs to use Python. Such event handlers
145 are entered while the lock for Tcl is held; the event handler
146 presumably needs to use Python. ENTER_PYTHON releases the lock for
147 Tcl and acquires the Python interpreter lock, restoring the
148 appropriate thread state, and LEAVE_PYTHON releases the Python
149 interpreter lock and re-acquires the lock for Tcl. It is okay for
150 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
151 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000152
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300153 These locks expand to several statements and brackets; they should
154 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000155
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300156 If Tcl is threaded, this approach won't work anymore. The Tcl
157 interpreter is only valid in the thread that created it, and all Tk
158 activity must happen in this thread, also. That means that the
159 mainloop must be invoked in the thread that created the
160 interpreter. Invoking commands from other threads is possible;
161 _tkinter will queue an event for the interpreter thread, which will
162 then execute the command and pass back the result. If the main
163 thread is not in the mainloop, and invoking commands causes an
164 exception; if the main loop is running but not processing events,
165 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000166
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300167 In addition, for a threaded Tcl, a single global tcl_tstate won't
168 be sufficient anymore, since multiple Tcl interpreters may
169 simultaneously dispatch in different threads. So we use the Tcl TLS
170 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000171
Guido van Rossum00d93061998-05-28 23:06:38 +0000172*/
173
Guido van Rossum65d5b571998-12-21 19:32:43 +0000174static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000175
176#ifdef TCL_THREADS
177static Tcl_ThreadDataKey state_key;
178typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300179#define tcl_tstate \
180 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000182static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000183#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000184
185#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
187 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
189#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300190 tcl_tstate = NULL; \
191 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
Guido van Rossum62320c91998-06-15 04:36:09 +0000193#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000195
196#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000198
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000199#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300201 if(tcl_lock) \
202 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
204#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 { PyThreadState *tstate = PyEval_SaveThread(); \
206 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000207
208#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 if (((TkappObject *)self)->threaded && \
210 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300211 PyErr_SetString(PyExc_RuntimeError, \
212 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 return 0; \
214 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#else
217
218#define ENTER_TCL
219#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000220#define ENTER_OVERLAP
221#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000222#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000223#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000224#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000225
226#endif
227
Guido van Rossum97867b21996-08-08 19:09:53 +0000228#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000229#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000230#endif
231
Guido van Rossum18468821994-06-20 07:49:28 +0000232/**** Tkapp Object Declaration ****/
233
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300234static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000235
Guido van Rossum00d93061998-05-28 23:06:38 +0000236typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 PyObject_HEAD
238 Tcl_Interp *interp;
239 int wantobjects;
240 int threaded; /* True if tcl_platform[threaded] */
241 Tcl_ThreadId thread_id;
242 int dispatching;
243 /* We cannot include tclInt.h, as this is internal.
244 So we cache interesting types here. */
245 Tcl_ObjType *BooleanType;
246 Tcl_ObjType *ByteArrayType;
247 Tcl_ObjType *DoubleType;
248 Tcl_ObjType *IntType;
249 Tcl_ObjType *ListType;
250 Tcl_ObjType *ProcBodyType;
251 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000252} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000253
Guido van Rossum18468821994-06-20 07:49:28 +0000254#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000255#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guido van Rossum35d43371997-08-02 00:09:09 +0000257#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000258(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000259
Barry Warsawfa701a81997-01-16 00:15:11 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262/**** Error Handling ****/
263
264static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000265static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000266static int errorInCmd = 0;
267static PyObject *excInCmd;
268static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000269static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guilherme Polob681df42009-02-09 22:33:59 +0000271#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000272static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000273#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275
Guido van Rossum18468821994-06-20 07:49:28 +0000276static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000277Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
280 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000281}
282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284
Guido van Rossum18468821994-06-20 07:49:28 +0000285/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000286
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000287static int Tkinter_busywaitinterval = 20;
288
Guido van Rossum00d93061998-05-28 23:06:38 +0000289#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000290#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000291
Guido van Rossum00d93061998-05-28 23:06:38 +0000292/* Millisecond sleep() for Unix platforms. */
293
294static void
Fred Drake509d79a2000-07-08 04:04:38 +0000295Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000296{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 /* XXX Too bad if you don't have select(). */
298 struct timeval t;
299 t.tv_sec = milli/1000;
300 t.tv_usec = (milli%1000) * 1000;
301 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000302}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000303#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000304
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000305/* Wait up to 1s for the mainloop to come up. */
306
307static int
308WaitForMainloop(TkappObject* self)
309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 int i;
311 for (i = 0; i < 10; i++) {
312 if (self->dispatching)
313 return 1;
314 Py_BEGIN_ALLOW_THREADS
315 Sleep(100);
316 Py_END_ALLOW_THREADS
317 }
318 if (self->dispatching)
319 return 1;
320 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
321 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000322}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000323#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326
Guido van Rossum18468821994-06-20 07:49:28 +0000327#define ARGSZ 64
328
Barry Warsawfa701a81997-01-16 00:15:11 +0000329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330
Guido van Rossum18468821994-06-20 07:49:28 +0000331static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200332unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
333{
334 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
335 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
336 /* Tcl encodes null character as \xc0\x80 */
337 if (memchr(s, '\xc0', size)) {
338 char *buf, *q;
339 const char *e = s + size;
340 PyErr_Clear();
341 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300342 if (buf == NULL) {
343 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200344 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300345 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200346 while (s != e) {
347 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
348 *q++ = '\0';
349 s += 2;
350 }
351 else
352 *q++ = *s++;
353 }
354 s = buf;
355 size = q - s;
356 r = PyUnicode_DecodeUTF8(s, size, NULL);
357 PyMem_Free(buf);
358 }
359 }
360 return r;
361}
362
363static PyObject *
364unicodeFromTclString(const char *s)
365{
366 return unicodeFromTclStringAndSize(s, strlen(s));
367}
368
369static PyObject *
370unicodeFromTclObj(Tcl_Obj *value)
371{
372 int len;
373 char *s = Tcl_GetStringFromObj(value, &len);
374 return unicodeFromTclStringAndSize(s, len);
375}
376
377
378static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000379Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000380{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 int argc;
382 char **argv;
383 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300386 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 }
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
390 /* Not a list.
391 * Could be a quoted string containing funnies, e.g. {"}.
392 * Return the string itself.
393 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200394 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 }
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 if (argc == 0)
398 v = PyUnicode_FromString("");
399 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200400 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401 else if ((v = PyTuple_New(argc)) != NULL) {
402 int i;
403 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000405 for (i = 0; i < argc; i++) {
406 if ((w = Split(argv[i])) == NULL) {
407 Py_DECREF(v);
408 v = NULL;
409 break;
410 }
411 PyTuple_SetItem(v, i, w);
412 }
413 }
414 Tcl_Free(FREECAST argv);
415 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000416}
417
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300418/* In some cases, Tcl will still return strings that are supposed to
419 be lists. SplitObj walks through a nested tuple, finding string
420 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000421
Martin v. Löwis59683e82008-06-13 07:50:45 +0000422static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000423SplitObj(PyObject *arg)
424{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 if (PyTuple_Check(arg)) {
426 int i, size;
427 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 size = PyTuple_Size(arg);
430 result = NULL;
431 /* Recursively invoke SplitObj for all tuple items.
432 If this does not return a new object, no action is
433 needed. */
434 for(i = 0; i < size; i++) {
435 elem = PyTuple_GetItem(arg, i);
436 newelem = SplitObj(elem);
437 if (!newelem) {
438 Py_XDECREF(result);
439 return NULL;
440 }
441 if (!result) {
442 int k;
443 if (newelem == elem) {
444 Py_DECREF(newelem);
445 continue;
446 }
447 result = PyTuple_New(size);
448 if (!result)
449 return NULL;
450 for(k = 0; k < i; k++) {
451 elem = PyTuple_GetItem(arg, k);
452 Py_INCREF(elem);
453 PyTuple_SetItem(result, k, elem);
454 }
455 }
456 PyTuple_SetItem(result, i, newelem);
457 }
458 if (result)
459 return result;
460 /* Fall through, returning arg. */
461 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300462 else if (PyUnicode_Check(arg)) {
463 int argc;
464 char **argv;
465 char *list = PyUnicode_AsUTF8(arg);
466
467 if (list == NULL ||
468 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
469 Py_INCREF(arg);
470 return arg;
471 }
472 Tcl_Free(FREECAST argv);
473 if (argc > 1)
474 return Split(list);
475 /* Fall through, returning arg. */
476 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000477 else if (PyBytes_Check(arg)) {
478 int argc;
479 char **argv;
480 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
483 Py_INCREF(arg);
484 return arg;
485 }
486 Tcl_Free(FREECAST argv);
487 if (argc > 1)
488 return Split(PyBytes_AsString(arg));
489 /* Fall through, returning arg. */
490 }
491 Py_INCREF(arg);
492 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000493}
Barry Warsawfa701a81997-01-16 00:15:11 +0000494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495
Guido van Rossum18468821994-06-20 07:49:28 +0000496/**** Tkapp Object ****/
497
498#ifndef WITH_APPINIT
499int
Fred Drake509d79a2000-07-08 04:04:38 +0000500Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000504 if (Tcl_Init(interp) == TCL_ERROR) {
505 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
506 return TCL_ERROR;
507 }
Guilherme Polob681df42009-02-09 22:33:59 +0000508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000509 _tkinter_skip_tk_init = Tcl_GetVar(interp,
510 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
511 if (_tkinter_skip_tk_init != NULL &&
512 strcmp(_tkinter_skip_tk_init, "1") == 0) {
513 return TCL_OK;
514 }
Guilherme Polob681df42009-02-09 22:33:59 +0000515
516#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 if (tk_load_failed) {
518 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
519 return TCL_ERROR;
520 }
Guilherme Polob681df42009-02-09 22:33:59 +0000521#endif
522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000524#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000526#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
528 return TCL_ERROR;
529 }
Guilherme Polob681df42009-02-09 22:33:59 +0000530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000532}
533#endif /* !WITH_APPINIT */
534
Guido van Rossum18468821994-06-20 07:49:28 +0000535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000536
Barry Warsawfa701a81997-01-16 00:15:11 +0000537
538/* Initialize the Tk application; see the `main' function in
539 * `tkMain.c'.
540 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000541
Thomas Wouters58d05102000-07-24 14:43:35 +0000542static void EnableEventHook(void); /* Forward */
543static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000544
Barry Warsawfa701a81997-01-16 00:15:11 +0000545static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000546Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000548{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 TkappObject *v;
550 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000551
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300552 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553 if (v == NULL)
554 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200555 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000556
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 v->interp = Tcl_CreateInterp();
558 v->wantobjects = wantobjects;
559 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
560 TCL_GLOBAL_ONLY) != NULL;
561 v->thread_id = Tcl_GetCurrentThread();
562 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000563
564#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000565 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300566 PyErr_SetString(PyExc_RuntimeError,
567 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 Py_DECREF(v);
569 return 0;
570 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000571#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000572#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 if (v->threaded && tcl_lock) {
574 /* If Tcl is threaded, we don't need the lock. */
575 PyThread_free_lock(tcl_lock);
576 tcl_lock = NULL;
577 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000578#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 v->BooleanType = Tcl_GetObjType("boolean");
581 v->ByteArrayType = Tcl_GetObjType("bytearray");
582 v->DoubleType = Tcl_GetObjType("double");
583 v->IntType = Tcl_GetObjType("int");
584 v->ListType = Tcl_GetObjType("list");
585 v->ProcBodyType = Tcl_GetObjType("procbody");
586 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 /* Delete the 'exit' command, which can screw things up */
589 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 if (screenName != NULL)
592 Tcl_SetVar2(v->interp, "env", "DISPLAY",
593 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 if (interactive)
596 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
597 else
598 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka07940882014-09-11 10:38:54 +0300601 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 if (!argv0) {
603 PyErr_NoMemory();
604 Py_DECREF(v);
605 return NULL;
606 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200609 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
610 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
612 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 if (! wantTk) {
615 Tcl_SetVar(v->interp,
616 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
617 }
Guilherme Polob681df42009-02-09 22:33:59 +0000618#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 else if (tk_load_failed) {
620 Tcl_SetVar(v->interp,
621 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
622 }
Guilherme Polob681df42009-02-09 22:33:59 +0000623#endif
David Aschere2b4b322004-02-18 05:59:53 +0000624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 /* some initial arguments need to be in argv */
626 if (sync || use) {
627 char *args;
628 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 if (sync)
631 len += sizeof "-sync";
632 if (use)
633 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000634
Serhiy Storchaka07940882014-09-11 10:38:54 +0300635 args = (char*)attemptckalloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 if (!args) {
637 PyErr_NoMemory();
638 Py_DECREF(v);
639 return NULL;
640 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 args[0] = '\0';
643 if (sync)
644 strcat(args, "-sync");
645 if (use) {
646 if (sync)
647 strcat(args, " ");
648 strcat(args, "-use ");
649 strcat(args, use);
650 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
653 ckfree(args);
654 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 if (Tcl_AppInit(v->interp) != TCL_OK) {
657 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000658#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 if (wantTk) {
660 const char *_tkinter_tk_failed;
661 _tkinter_tk_failed = Tcl_GetVar(v->interp,
662 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 if ( _tkinter_tk_failed != NULL &&
665 strcmp(_tkinter_tk_failed, "1") == 0) {
666 tk_load_failed = 1;
667 }
668 }
Guilherme Polob681df42009-02-09 22:33:59 +0000669#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 Py_DECREF((PyObject *)v);
671 return (TkappObject *)result;
672 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000677}
678
Barry Warsawfa701a81997-01-16 00:15:11 +0000679
Benjamin Peterson5879d412009-03-30 14:51:56 +0000680#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000681static void
682Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000684{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 Py_BEGIN_ALLOW_THREADS;
686 Tcl_MutexLock(mutex);
687 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
688 Tcl_ThreadAlert(self->thread_id);
689 Tcl_ConditionWait(cond, mutex, NULL);
690 Tcl_MutexUnlock(mutex);
691 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000692}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000693#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695
Guido van Rossum18468821994-06-20 07:49:28 +0000696/** Tcl Eval **/
697
Martin v. Löwisffad6332002-11-26 09:28:05 +0000698typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 PyObject_HEAD
700 Tcl_Obj *value;
701 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000702} PyTclObject;
703
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300704static PyObject *PyTclObject_Type;
705#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000706
707static PyObject *
708newPyTclObject(Tcl_Obj *arg)
709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300711 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 if (self == NULL)
713 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200714 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 Tcl_IncrRefCount(arg);
716 self->value = arg;
717 self->string = NULL;
718 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000719}
720
721static void
722PyTclObject_dealloc(PyTclObject *self)
723{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200724 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 Tcl_DecrRefCount(self->value);
726 Py_XDECREF(self->string);
727 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200728 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000729}
730
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000731static char*
732PyTclObject_TclString(PyObject *self)
733{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000734 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000735}
736
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000737/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000738PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000739"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000740
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000741static PyObject *
742PyTclObject_string(PyTclObject *self, void *ignored)
743{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200745 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 if (!self->string)
747 return NULL;
748 }
749 Py_INCREF(self->string);
750 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751}
752
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000753static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000754PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200756 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 Py_INCREF(self->string);
758 return self->string;
759 }
760 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200761 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000762}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000763
Martin v. Löwisffad6332002-11-26 09:28:05 +0000764static PyObject *
765PyTclObject_repr(PyTclObject *self)
766{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300767 PyObject *repr, *str = PyTclObject_str(self, NULL);
768 if (str == NULL)
769 return NULL;
770 repr = PyUnicode_FromFormat("<%s object: %R>",
771 self->value->typePtr->name, str);
772 Py_DECREF(str);
773 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000774}
775
Mark Dickinson211c6252009-02-01 10:28:51 +0000776#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
777
778static PyObject *
779PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 int result;
782 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000783
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000784 /* neither argument should be NULL, unless something's gone wrong */
785 if (self == NULL || other == NULL) {
786 PyErr_BadInternalCall();
787 return NULL;
788 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000789
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000790 /* both arguments should be instances of PyTclObject */
791 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
792 v = Py_NotImplemented;
793 goto finished;
794 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 if (self == other)
797 /* fast path when self and other are identical */
798 result = 0;
799 else
800 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
801 Tcl_GetString(((PyTclObject *)other)->value));
802 /* Convert return value to a Boolean */
803 switch (op) {
804 case Py_EQ:
805 v = TEST_COND(result == 0);
806 break;
807 case Py_NE:
808 v = TEST_COND(result != 0);
809 break;
810 case Py_LE:
811 v = TEST_COND(result <= 0);
812 break;
813 case Py_GE:
814 v = TEST_COND(result >= 0);
815 break;
816 case Py_LT:
817 v = TEST_COND(result < 0);
818 break;
819 case Py_GT:
820 v = TEST_COND(result > 0);
821 break;
822 default:
823 PyErr_BadArgument();
824 return NULL;
825 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000826 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000827 Py_INCREF(v);
828 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000829}
830
Martin v. Löwis39195712003-01-04 00:33:13 +0000831PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
832
Martin v. Löwisffad6332002-11-26 09:28:05 +0000833static PyObject*
834get_typename(PyTclObject* obj, void* ignored)
835{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200836 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837}
838
Martin v. Löwis39195712003-01-04 00:33:13 +0000839
Martin v. Löwisffad6332002-11-26 09:28:05 +0000840static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 {"typename", (getter)get_typename, NULL, get_typename__doc__},
842 {"string", (getter)PyTclObject_string, NULL,
843 PyTclObject_string__doc__},
844 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000845};
846
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300847static PyType_Slot PyTclObject_Type_slots[] = {
848 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
849 {Py_tp_repr, (reprfunc)PyTclObject_repr},
850 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200851 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300852 {Py_tp_richcompare, PyTclObject_richcompare},
853 {Py_tp_getset, PyTclObject_getsetlist},
854 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855};
856
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300857static PyType_Spec PyTclObject_Type_spec = {
858 "_tkinter.Tcl_Obj",
859 sizeof(PyTclObject),
860 0,
861 Py_TPFLAGS_DEFAULT,
862 PyTclObject_Type_slots,
863};
864
865
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300866#if PY_SIZE_MAX > INT_MAX
867#define CHECK_STRING_LENGTH(s) do { \
868 if (s != NULL && strlen(s) >= INT_MAX) { \
869 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
870 return NULL; \
871 } } while(0)
872#else
873#define CHECK_STRING_LENGTH(s)
874#endif
875
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000876static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000877AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000878{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 Tcl_Obj *result;
880 long longVal;
881 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 if (PyBytes_Check(value))
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300884 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
885 PyBytes_GET_SIZE(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000886 else if (PyBool_Check(value))
887 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
888 else if (PyLong_CheckExact(value) &&
889 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
890 !overflow)) {
891 /* If there is an overflow in the long conversion,
892 fall through to default object handling. */
893 return Tcl_NewLongObj(longVal);
894 }
895 else if (PyFloat_Check(value))
896 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
897 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300898 Tcl_Obj **argv;
899 Py_ssize_t size, i;
900
901 size = PyTuple_Size(value);
902 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
903 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
904 return NULL;
905 }
Serhiy Storchaka07940882014-09-11 10:38:54 +0300906 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000907 if(!argv)
908 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300909 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000910 argv[i] = AsObj(PyTuple_GetItem(value,i));
911 result = Tcl_NewListObj(PyTuple_Size(value), argv);
912 ckfree(FREECAST argv);
913 return result;
914 }
915 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200916 void *inbuf;
917 Py_ssize_t size;
918 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000919 Tcl_UniChar *outbuf = NULL;
920 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200921 size_t allocsize;
922
923 if (PyUnicode_READY(value) == -1)
924 return NULL;
925
926 inbuf = PyUnicode_DATA(value);
927 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300928 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
929 PyErr_SetString(PyExc_OverflowError, "string is too long");
930 return NULL;
931 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200932 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200933 if (kind == sizeof(Tcl_UniChar))
934 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200935 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Serhiy Storchaka07940882014-09-11 10:38:54 +0300936 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000937 /* Else overflow occurred, and we take the next exit */
938 if (!outbuf) {
939 PyErr_NoMemory();
940 return NULL;
941 }
942 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200943 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
944 /* We cannot test for sizeof(Tcl_UniChar) directly,
945 so we test for UTF-8 size instead. */
946#if TCL_UTF_MAX == 3
947 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200949 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100950 "character U+%x is above the range "
951 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100952 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000953 ckfree(FREECAST outbuf);
954 return NULL;
955 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300956#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200957 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000958 }
959 result = Tcl_NewUnicodeObj(outbuf, size);
960 ckfree(FREECAST outbuf);
961 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 }
963 else if(PyTclObject_Check(value)) {
964 Tcl_Obj *v = ((PyTclObject*)value)->value;
965 Tcl_IncrRefCount(v);
966 return v;
967 }
968 else {
969 PyObject *v = PyObject_Str(value);
970 if (!v)
971 return 0;
972 result = AsObj(v);
973 Py_DECREF(v);
974 return result;
975 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000976}
977
Martin v. Löwisffad6332002-11-26 09:28:05 +0000978static PyObject*
979FromObj(PyObject* tkapp, Tcl_Obj *value)
980{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 PyObject *result = NULL;
982 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000983
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200985 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000986 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000987
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 if (value->typePtr == app->BooleanType) {
989 result = value->internalRep.longValue ? Py_True : Py_False;
990 Py_INCREF(result);
991 return result;
992 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000994 if (value->typePtr == app->ByteArrayType) {
995 int size;
996 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
997 return PyBytes_FromStringAndSize(data, size);
998 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000999
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 if (value->typePtr == app->DoubleType) {
1001 return PyFloat_FromDouble(value->internalRep.doubleValue);
1002 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 if (value->typePtr == app->IntType) {
1005 return PyLong_FromLong(value->internalRep.longValue);
1006 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 if (value->typePtr == app->ListType) {
1009 int size;
1010 int i, status;
1011 PyObject *elem;
1012 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001014 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1015 if (status == TCL_ERROR)
1016 return Tkinter_Error(tkapp);
1017 result = PyTuple_New(size);
1018 if (!result)
1019 return NULL;
1020 for (i = 0; i < size; i++) {
1021 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1022 value, i, &tcl_elem);
1023 if (status == TCL_ERROR) {
1024 Py_DECREF(result);
1025 return Tkinter_Error(tkapp);
1026 }
1027 elem = FromObj(tkapp, tcl_elem);
1028 if (!elem) {
1029 Py_DECREF(result);
1030 return NULL;
1031 }
1032 PyTuple_SetItem(result, i, elem);
1033 }
1034 return result;
1035 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037 if (value->typePtr == app->ProcBodyType) {
1038 /* fall through: return tcl object. */
1039 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001041 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001042 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001043 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001044 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001048}
1049
Benjamin Peterson5879d412009-03-30 14:51:56 +00001050#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001051/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001052TCL_DECLARE_MUTEX(call_mutex)
1053
1054typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 Tcl_Event ev; /* Must be first */
1056 TkappObject *self;
1057 PyObject *args;
1058 int flags;
1059 PyObject **res;
1060 PyObject **exc_type, **exc_value, **exc_tb;
1061 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001062} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001063#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001064
1065void
1066Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001067{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 int i;
1069 for (i = 0; i < objc; i++)
1070 Tcl_DecrRefCount(objv[i]);
1071 if (objv != objStore)
1072 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073}
Guido van Rossum18468821994-06-20 07:49:28 +00001074
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001075/* Convert Python objects to Tcl objects. This must happen in the
1076 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001077
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001078static Tcl_Obj**
1079Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1080{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001081 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001082 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001083 if (args == NULL)
1084 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001085
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 else if (!PyTuple_Check(args)) {
1087 objv[0] = AsObj(args);
1088 if (objv[0] == 0)
1089 goto finally;
1090 objc = 1;
1091 Tcl_IncrRefCount(objv[0]);
1092 }
1093 else {
1094 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001097 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1098 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1099 return NULL;
1100 }
Serhiy Storchaka07940882014-09-11 10:38:54 +03001101 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001102 if (objv == NULL) {
1103 PyErr_NoMemory();
1104 objc = 0;
1105 goto finally;
1106 }
1107 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001109 for (i = 0; i < objc; i++) {
1110 PyObject *v = PyTuple_GetItem(args, i);
1111 if (v == Py_None) {
1112 objc = i;
1113 break;
1114 }
1115 objv[i] = AsObj(v);
1116 if (!objv[i]) {
1117 /* Reset objc, so it attempts to clear
1118 objects only up to i. */
1119 objc = i;
1120 goto finally;
1121 }
1122 Tcl_IncrRefCount(objv[i]);
1123 }
1124 }
1125 *pobjc = objc;
1126 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001127finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 Tkapp_CallDeallocArgs(objv, objStore, objc);
1129 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001130}
Guido van Rossum212643f1998-04-29 16:22:14 +00001131
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001132/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001133
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001134static PyObject*
1135Tkapp_CallResult(TkappObject *self)
1136{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001138 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 /* Not sure whether the IncrRef is necessary, but something
1141 may overwrite the interpreter result while we are
1142 converting it. */
1143 Tcl_IncrRefCount(value);
1144 res = FromObj((PyObject*)self, value);
1145 Tcl_DecrRefCount(value);
1146 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001147 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 }
1149 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001150}
Guido van Rossum632de272000-03-29 00:19:50 +00001151
Benjamin Peterson5879d412009-03-30 14:51:56 +00001152#ifdef WITH_THREAD
1153
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154/* Tkapp_CallProc is the event procedure that is executed in the context of
1155 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1156 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001157
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001158static int
1159Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1160{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001161 Tcl_Obj *objStore[ARGSZ];
1162 Tcl_Obj **objv;
1163 int objc;
1164 int i;
1165 ENTER_PYTHON
1166 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1167 if (!objv) {
1168 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1169 *(e->res) = NULL;
1170 }
1171 LEAVE_PYTHON
1172 if (!objv)
1173 goto done;
1174 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1175 ENTER_PYTHON
1176 if (i == TCL_ERROR) {
1177 *(e->res) = NULL;
1178 *(e->exc_type) = NULL;
1179 *(e->exc_tb) = NULL;
1180 *(e->exc_value) = PyObject_CallFunction(
1181 Tkinter_TclError, "s",
1182 Tcl_GetStringResult(e->self->interp));
1183 }
1184 else {
1185 *(e->res) = Tkapp_CallResult(e->self);
1186 }
1187 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001188
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001189 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001190done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001191 /* Wake up calling thread. */
1192 Tcl_MutexLock(&call_mutex);
1193 Tcl_ConditionNotify(e->done);
1194 Tcl_MutexUnlock(&call_mutex);
1195 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001196}
1197
Benjamin Peterson5879d412009-03-30 14:51:56 +00001198#endif
1199
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001200/* This is the main entry point for calling a Tcl command.
1201 It supports three cases, with regard to threading:
1202 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1203 the context of the calling thread.
1204 2. Tcl is threaded, caller of the command is in the interpreter thread:
1205 Execute the command in the calling thread. Since the Tcl lock will
1206 not be used, we can merge that with case 1.
1207 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1208 the interpreter thread. Allocation of Tcl objects needs to occur in the
1209 interpreter thread, so we ship the PyObject* args to the target thread,
1210 and perform processing there. */
1211
1212static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001213Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 Tcl_Obj *objStore[ARGSZ];
1216 Tcl_Obj **objv = NULL;
1217 int objc, i;
1218 PyObject *res = NULL;
1219 TkappObject *self = (TkappObject*)selfptr;
1220 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001221
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001222 /* If args is a single tuple, replace with contents of tuple */
1223 if (1 == PyTuple_Size(args)){
1224 PyObject* item = PyTuple_GetItem(args, 0);
1225 if (PyTuple_Check(item))
1226 args = item;
1227 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001228#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001229 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1230 /* We cannot call the command directly. Instead, we must
1231 marshal the parameters to the interpreter thread. */
1232 Tkapp_CallEvent *ev;
1233 Tcl_Condition cond = NULL;
1234 PyObject *exc_type, *exc_value, *exc_tb;
1235 if (!WaitForMainloop(self))
1236 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001237 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1238 if (ev == NULL) {
1239 PyErr_NoMemory();
1240 return NULL;
1241 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1243 ev->self = self;
1244 ev->args = args;
1245 ev->res = &res;
1246 ev->exc_type = &exc_type;
1247 ev->exc_value = &exc_value;
1248 ev->exc_tb = &exc_tb;
1249 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001251 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 if (res == NULL) {
1254 if (exc_type)
1255 PyErr_Restore(exc_type, exc_value, exc_tb);
1256 else
1257 PyErr_SetObject(Tkinter_TclError, exc_value);
1258 }
1259 Tcl_ConditionFinalize(&cond);
1260 }
1261 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001262#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 objv = Tkapp_CallArgs(args, objStore, &objc);
1266 if (!objv)
1267 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001273 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 if (i == TCL_ERROR)
1276 Tkinter_Error(selfptr);
1277 else
1278 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 Tkapp_CallDeallocArgs(objv, objStore, objc);
1283 }
1284 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001285}
1286
1287
1288static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001289Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 char *script;
1292 PyObject *res = NULL;
1293 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 if (!PyArg_ParseTuple(args, "s:eval", &script))
1296 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001297
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001298 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001299 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001301 ENTER_TCL
1302 err = Tcl_Eval(Tkapp_Interp(self), script);
1303 ENTER_OVERLAP
1304 if (err == TCL_ERROR)
1305 res = Tkinter_Error(self);
1306 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001307 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 LEAVE_OVERLAP_TCL
1309 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001310}
1311
1312static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001313Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001314{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 char *fileName;
1316 PyObject *res = NULL;
1317 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1320 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001321
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001322 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 ENTER_TCL
1326 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1327 ENTER_OVERLAP
1328 if (err == TCL_ERROR)
1329 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001330 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001331 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001332 LEAVE_OVERLAP_TCL
1333 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001334}
1335
1336static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001337Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001338{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 char *script;
1340 PyObject *res = NULL;
1341 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001342
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001343 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001345
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001346 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 ENTER_TCL
1350 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1351 ENTER_OVERLAP
1352 if (err == TCL_ERROR)
1353 res = Tkinter_Error(self);
1354 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001355 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001356 LEAVE_OVERLAP_TCL
1357 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001358}
1359
1360static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001361Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001362{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1366 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001367 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 ENTER_TCL
1371 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1372 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001373
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001374 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001375}
1376
Barry Warsawfa701a81997-01-16 00:15:11 +00001377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378
Guido van Rossum18468821994-06-20 07:49:28 +00001379/** Tcl Variable **/
1380
Benjamin Peterson5879d412009-03-30 14:51:56 +00001381typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1382
1383#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001384TCL_DECLARE_MUTEX(var_mutex)
1385
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001386typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001387 Tcl_Event ev; /* must be first */
1388 PyObject *self;
1389 PyObject *args;
1390 int flags;
1391 EventFunc func;
1392 PyObject **res;
1393 PyObject **exc_type;
1394 PyObject **exc_val;
1395 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001396} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001397#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001398
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001399static int
1400varname_converter(PyObject *in, void *_out)
1401{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001402 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 char **out = (char**)_out;
1404 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001405 if (PyBytes_Size(in) > INT_MAX) {
1406 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1407 return 0;
1408 }
1409 s = PyBytes_AsString(in);
1410 if (strlen(s) != PyBytes_Size(in)) {
1411 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1412 return 0;
1413 }
1414 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001415 return 1;
1416 }
1417 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001418 Py_ssize_t size;
1419 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001420 if (s == NULL) {
1421 return 0;
1422 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001423 if (size > INT_MAX) {
1424 PyErr_SetString(PyExc_OverflowError, "string is too long");
1425 return 0;
1426 }
1427 if (strlen(s) != size) {
1428 PyErr_SetString(PyExc_ValueError, "null character in string");
1429 return 0;
1430 }
1431 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 return 1;
1433 }
1434 if (PyTclObject_Check(in)) {
1435 *out = PyTclObject_TclString(in);
1436 return 1;
1437 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001438 PyErr_Format(PyExc_TypeError,
1439 "must be str, bytes or Tcl_Obj, not %.50s",
1440 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001442}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001443
Benjamin Peterson5879d412009-03-30 14:51:56 +00001444#ifdef WITH_THREAD
1445
Martin v. Löwis59683e82008-06-13 07:50:45 +00001446static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001447var_perform(VarEvent *ev)
1448{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001449 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1450 if (!*(ev->res)) {
1451 PyObject *exc, *val, *tb;
1452 PyErr_Fetch(&exc, &val, &tb);
1453 PyErr_NormalizeException(&exc, &val, &tb);
1454 *(ev->exc_type) = exc;
1455 *(ev->exc_val) = val;
1456 Py_DECREF(tb);
1457 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001458
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001459}
1460
1461static int
1462var_proc(VarEvent* ev, int flags)
1463{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 ENTER_PYTHON
1465 var_perform(ev);
1466 Tcl_MutexLock(&var_mutex);
1467 Tcl_ConditionNotify(ev->cond);
1468 Tcl_MutexUnlock(&var_mutex);
1469 LEAVE_PYTHON
1470 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471}
1472
Benjamin Peterson5879d412009-03-30 14:51:56 +00001473#endif
1474
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001475static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001476var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001477{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001478#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479 TkappObject *self = (TkappObject*)selfptr;
1480 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1481 TkappObject *self = (TkappObject*)selfptr;
1482 VarEvent *ev;
1483 PyObject *res, *exc_type, *exc_val;
1484 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001486 /* The current thread is not the interpreter thread. Marshal
1487 the call to the interpreter thread, then wait for
1488 completion. */
1489 if (!WaitForMainloop(self))
1490 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001491
Serhiy Storchaka07940882014-09-11 10:38:54 +03001492 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1493 if (ev == NULL) {
1494 PyErr_NoMemory();
1495 return NULL;
1496 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 ev->self = selfptr;
1498 ev->args = args;
1499 ev->flags = flags;
1500 ev->func = func;
1501 ev->res = &res;
1502 ev->exc_type = &exc_type;
1503 ev->exc_val = &exc_val;
1504 ev->cond = &cond;
1505 ev->ev.proc = (Tcl_EventProc*)var_proc;
1506 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1507 Tcl_ConditionFinalize(&cond);
1508 if (!res) {
1509 PyErr_SetObject(exc_type, exc_val);
1510 Py_DECREF(exc_type);
1511 Py_DECREF(exc_val);
1512 return NULL;
1513 }
1514 return res;
1515 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001516#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 /* Tcl is not threaded, or this is the interpreter thread. */
1518 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001519}
1520
Guido van Rossum18468821994-06-20 07:49:28 +00001521static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001522SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001523{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001524 char *name1, *name2;
1525 PyObject *newValue;
1526 PyObject *res = NULL;
1527 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001528
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001529 switch (PyTuple_GET_SIZE(args)) {
1530 case 2:
1531 if (!PyArg_ParseTuple(args, "O&O:setvar",
1532 varname_converter, &name1, &newValue))
1533 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001534 /* XXX Acquire tcl lock??? */
1535 newval = AsObj(newValue);
1536 if (newval == NULL)
1537 return NULL;
1538 ENTER_TCL
1539 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1540 newval, flags);
1541 ENTER_OVERLAP
1542 if (!ok)
1543 Tkinter_Error(self);
1544 else {
1545 res = Py_None;
1546 Py_INCREF(res);
1547 }
1548 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001549 break;
1550 case 3:
1551 if (!PyArg_ParseTuple(args, "ssO:setvar",
1552 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001554 CHECK_STRING_LENGTH(name1);
1555 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001556 /* XXX must hold tcl lock already??? */
1557 newval = AsObj(newValue);
1558 ENTER_TCL
1559 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1560 ENTER_OVERLAP
1561 if (!ok)
1562 Tkinter_Error(self);
1563 else {
1564 res = Py_None;
1565 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001567 LEAVE_OVERLAP_TCL
1568 break;
1569 default:
1570 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1571 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 }
1573 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001574}
1575
1576static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001577Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001578{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001580}
1581
1582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001583Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001584{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001585 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001586}
1587
Barry Warsawfa701a81997-01-16 00:15:11 +00001588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001589
Guido van Rossum18468821994-06-20 07:49:28 +00001590static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001591GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001592{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593 char *name1, *name2=NULL;
1594 PyObject *res = NULL;
1595 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1598 varname_converter, &name1, &name2))
1599 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001600
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001601 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 ENTER_TCL
1603 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1604 ENTER_OVERLAP
1605 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001606 PyErr_SetString(Tkinter_TclError,
1607 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 } else {
1609 if (((TkappObject*)self)->wantobjects) {
1610 res = FromObj(self, tres);
1611 }
1612 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001613 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 }
1615 }
1616 LEAVE_OVERLAP_TCL
1617 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001618}
1619
1620static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001621Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001622{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001623 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001624}
1625
1626static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001627Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001628{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001630}
1631
Barry Warsawfa701a81997-01-16 00:15:11 +00001632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633
Guido van Rossum18468821994-06-20 07:49:28 +00001634static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001635UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001636{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 char *name1, *name2=NULL;
1638 int code;
1639 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1642 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001643
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001644 CHECK_STRING_LENGTH(name1);
1645 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001646 ENTER_TCL
1647 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1648 ENTER_OVERLAP
1649 if (code == TCL_ERROR)
1650 res = Tkinter_Error(self);
1651 else {
1652 Py_INCREF(Py_None);
1653 res = Py_None;
1654 }
1655 LEAVE_OVERLAP_TCL
1656 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001657}
1658
1659static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001660Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001661{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001662 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001663}
1664
1665static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001666Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001667{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001668 return var_invoke(UnsetVar, self, args,
1669 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001670}
1671
Barry Warsawfa701a81997-01-16 00:15:11 +00001672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673
Guido van Rossum18468821994-06-20 07:49:28 +00001674/** Tcl to Python **/
1675
1676static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001677Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001678{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001679 char *s;
1680 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001682 if (PyTuple_Size(args) == 1) {
1683 PyObject* o = PyTuple_GetItem(args, 0);
1684 if (PyLong_Check(o)) {
1685 Py_INCREF(o);
1686 return o;
1687 }
1688 }
1689 if (!PyArg_ParseTuple(args, "s:getint", &s))
1690 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001691 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1693 return Tkinter_Error(self);
1694 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001695}
1696
1697static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001698Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001699{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001700 char *s;
1701 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001702
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001703 if (PyTuple_Size(args) == 1) {
1704 PyObject *o = PyTuple_GetItem(args, 0);
1705 if (PyFloat_Check(o)) {
1706 Py_INCREF(o);
1707 return o;
1708 }
1709 }
1710 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1711 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001712 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001713 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1714 return Tkinter_Error(self);
1715 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001716}
1717
1718static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001719Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001720{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 char *s;
1722 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001724 if (PyTuple_Size(args) == 1) {
1725 PyObject *o = PyTuple_GetItem(args, 0);
1726 if (PyLong_Check(o)) {
1727 Py_INCREF(o);
1728 return o;
1729 }
1730 }
1731 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1732 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001733 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001734 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1735 return Tkinter_Error(self);
1736 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001737}
1738
1739static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001740Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 char *s;
1743 PyObject *res = NULL;
1744 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001745
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001746 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1747 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001748
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001749 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001752 ENTER_TCL
1753 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1754 ENTER_OVERLAP
1755 if (retval == TCL_ERROR)
1756 res = Tkinter_Error(self);
1757 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001758 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 LEAVE_OVERLAP_TCL
1760 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001761}
1762
1763static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001764Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001765{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001766 char *s;
1767 PyObject *res = NULL;
1768 int retval;
1769 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001770
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001771 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1772 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001773
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001774 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001777 ENTER_TCL
1778 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1779 ENTER_OVERLAP
1780 if (retval == TCL_ERROR)
1781 res = Tkinter_Error(self);
1782 else
1783 res = Py_BuildValue("l", v);
1784 LEAVE_OVERLAP_TCL
1785 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001786}
1787
1788static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001789Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001790{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001791 char *s;
1792 PyObject *res = NULL;
1793 double v;
1794 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001796 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1797 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001798 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001799 CHECK_TCL_APPARTMENT;
1800 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1801 ENTER_TCL
1802 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1803 ENTER_OVERLAP
1804 PyFPE_END_PROTECT(retval)
1805 if (retval == TCL_ERROR)
1806 res = Tkinter_Error(self);
1807 else
1808 res = Py_BuildValue("d", v);
1809 LEAVE_OVERLAP_TCL
1810 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001811}
1812
1813static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001814Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001815{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 char *s;
1817 PyObject *res = NULL;
1818 int retval;
1819 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001820
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1822 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001823 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001824 CHECK_TCL_APPARTMENT;
1825 ENTER_TCL
1826 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1827 ENTER_OVERLAP
1828 if (retval == TCL_ERROR)
1829 res = Tkinter_Error(self);
1830 else
1831 res = Py_BuildValue("i", v);
1832 LEAVE_OVERLAP_TCL
1833 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
Barry Warsawfa701a81997-01-16 00:15:11 +00001836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001837
Guido van Rossum18468821994-06-20 07:49:28 +00001838static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001839Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001840{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 char *list;
1842 int argc;
1843 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001844 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001845 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001846
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001847 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1848 return NULL;
1849 if (PyTclObject_Check(arg)) {
1850 int objc;
1851 Tcl_Obj **objv;
1852 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1853 ((PyTclObject*)arg)->value,
1854 &objc, &objv) == TCL_ERROR) {
1855 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001856 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001857 if (!(v = PyTuple_New(objc)))
1858 return NULL;
1859 for (i = 0; i < objc; i++) {
1860 PyObject *s = FromObj(self, objv[i]);
1861 if (!s || PyTuple_SetItem(v, i, s)) {
1862 Py_DECREF(v);
1863 return NULL;
1864 }
1865 }
1866 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001868 if (PyTuple_Check(arg)) {
1869 Py_INCREF(arg);
1870 return arg;
1871 }
1872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1874 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001876 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 if (Tcl_SplitList(Tkapp_Interp(self), list,
1878 &argc, &argv) == TCL_ERROR) {
1879 PyMem_Free(list);
1880 return Tkinter_Error(self);
1881 }
Guido van Rossum18468821994-06-20 07:49:28 +00001882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001883 if (!(v = PyTuple_New(argc)))
1884 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001887 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888 if (!s || PyTuple_SetItem(v, i, s)) {
1889 Py_DECREF(v);
1890 v = NULL;
1891 goto finally;
1892 }
1893 }
Guido van Rossum18468821994-06-20 07:49:28 +00001894
Barry Warsawfa701a81997-01-16 00:15:11 +00001895 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 ckfree(FREECAST argv);
1897 PyMem_Free(list);
1898 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001899}
1900
1901static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001902Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001903{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001904 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001905 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001906
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001907 if (!PyArg_ParseTuple(args, "O:split", &arg))
1908 return NULL;
1909 if (PyTclObject_Check(arg)) {
1910 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1911 int objc;
1912 Tcl_Obj **objv;
1913 int i;
1914 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1915 &objc, &objv) == TCL_ERROR) {
1916 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001918 if (objc == 0)
1919 return PyUnicode_FromString("");
1920 if (objc == 1)
1921 return FromObj(self, objv[0]);
1922 if (!(v = PyTuple_New(objc)))
1923 return NULL;
1924 for (i = 0; i < objc; i++) {
1925 PyObject *s = FromObj(self, objv[i]);
1926 if (!s || PyTuple_SetItem(v, i, s)) {
1927 Py_DECREF(v);
1928 return NULL;
1929 }
1930 }
1931 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001933 if (PyTuple_Check(arg))
1934 return SplitObj(arg);
1935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1937 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001938 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 v = Split(list);
1940 PyMem_Free(list);
1941 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001942}
1943
Barry Warsawfa701a81997-01-16 00:15:11 +00001944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001945
Guido van Rossum18468821994-06-20 07:49:28 +00001946/** Tcl Command **/
1947
Guido van Rossum00d93061998-05-28 23:06:38 +00001948/* Client data struct */
1949typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001950 PyObject *self;
1951 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001952} PythonCmd_ClientData;
1953
1954static int
Fred Drake509d79a2000-07-08 04:04:38 +00001955PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001956{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001957 errorInCmd = 1;
1958 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1959 LEAVE_PYTHON
1960 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001961}
1962
Guido van Rossum18468821994-06-20 07:49:28 +00001963/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001964 * function or method.
1965 */
Guido van Rossum18468821994-06-20 07:49:28 +00001966static int
Fred Drake509d79a2000-07-08 04:04:38 +00001967PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001968{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001970 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971 int i, rv;
1972 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001976 /* TBD: no error checking here since we know, via the
1977 * Tkapp_CreateCommand() that the client data is a two-tuple
1978 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 /* Create argument list (argv1, ..., argvN) */
1982 if (!(arg = PyTuple_New(argc - 1)))
1983 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001984
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001986 PyObject *s = unicodeFromTclString(argv[i + 1]);
1987 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 Py_DECREF(arg);
1989 return PythonCmd_Error(interp);
1990 }
1991 }
1992 res = PyEval_CallObject(func, arg);
1993 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 if (res == NULL)
1996 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 obj_res = AsObj(res);
1999 if (obj_res == NULL) {
2000 Py_DECREF(res);
2001 return PythonCmd_Error(interp);
2002 }
2003 else {
2004 Tcl_SetObjResult(interp, obj_res);
2005 rv = TCL_OK;
2006 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002012 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002013}
2014
2015static void
Fred Drake509d79a2000-07-08 04:04:38 +00002016PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002017{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 ENTER_PYTHON
2021 Py_XDECREF(data->self);
2022 Py_XDECREF(data->func);
2023 PyMem_DEL(data);
2024 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002025}
2026
Barry Warsawfa701a81997-01-16 00:15:11 +00002027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002028
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002029
Benjamin Peterson5879d412009-03-30 14:51:56 +00002030#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002031TCL_DECLARE_MUTEX(command_mutex)
2032
2033typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002034 Tcl_Event ev;
2035 Tcl_Interp* interp;
2036 char *name;
2037 int create;
2038 int *status;
2039 ClientData *data;
2040 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002041} CommandEvent;
2042
2043static int
2044Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002045{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046 if (ev->create)
2047 *ev->status = Tcl_CreateCommand(
2048 ev->interp, ev->name, PythonCmd,
2049 ev->data, PythonCmdDelete) == NULL;
2050 else
2051 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2052 Tcl_MutexLock(&command_mutex);
2053 Tcl_ConditionNotify(ev->done);
2054 Tcl_MutexUnlock(&command_mutex);
2055 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002057#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002058
2059static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002060Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002061{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002062 TkappObject *self = (TkappObject*)selfptr;
2063 PythonCmd_ClientData *data;
2064 char *cmdName;
2065 PyObject *func;
2066 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002068 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2069 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002070 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 if (!PyCallable_Check(func)) {
2072 PyErr_SetString(PyExc_TypeError, "command not callable");
2073 return NULL;
2074 }
Guido van Rossum18468821994-06-20 07:49:28 +00002075
Martin v. Löwisa9656492003-03-30 08:44:58 +00002076#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002077 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2078 !WaitForMainloop(self))
2079 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002080#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002081
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002082 data = PyMem_NEW(PythonCmd_ClientData, 1);
2083 if (!data)
2084 return PyErr_NoMemory();
2085 Py_INCREF(self);
2086 Py_INCREF(func);
2087 data->self = selfptr;
2088 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002089#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002090 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2091 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002092 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2093 if (ev == NULL) {
2094 PyErr_NoMemory();
2095 PyMem_DEL(data);
2096 return NULL;
2097 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002098 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2099 ev->interp = self->interp;
2100 ev->create = 1;
2101 ev->name = cmdName;
2102 ev->data = (ClientData)data;
2103 ev->status = &err;
2104 ev->done = &cond;
2105 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2106 Tcl_ConditionFinalize(&cond);
2107 }
2108 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002109#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 {
2111 ENTER_TCL
2112 err = Tcl_CreateCommand(
2113 Tkapp_Interp(self), cmdName, PythonCmd,
2114 (ClientData)data, PythonCmdDelete) == NULL;
2115 LEAVE_TCL
2116 }
2117 if (err) {
2118 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2119 PyMem_DEL(data);
2120 return NULL;
2121 }
Guido van Rossum18468821994-06-20 07:49:28 +00002122
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002123 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002124}
2125
Barry Warsawfa701a81997-01-16 00:15:11 +00002126
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002127
Guido van Rossum18468821994-06-20 07:49:28 +00002128static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002129Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 TkappObject *self = (TkappObject*)selfptr;
2132 char *cmdName;
2133 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002135 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2136 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002137 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002138
2139#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2141 Tcl_Condition cond = NULL;
2142 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002143 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2144 if (ev == NULL) {
2145 PyErr_NoMemory();
2146 return NULL;
2147 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002148 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2149 ev->interp = self->interp;
2150 ev->create = 0;
2151 ev->name = cmdName;
2152 ev->status = &err;
2153 ev->done = &cond;
2154 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2155 &command_mutex);
2156 Tcl_ConditionFinalize(&cond);
2157 }
2158 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002159#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 {
2161 ENTER_TCL
2162 err = Tcl_DeleteCommand(self->interp, cmdName);
2163 LEAVE_TCL
2164 }
2165 if (err == -1) {
2166 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2167 return NULL;
2168 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002169 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002170}
2171
Barry Warsawfa701a81997-01-16 00:15:11 +00002172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173
Guido van Rossum00d93061998-05-28 23:06:38 +00002174#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002175/** File Handler **/
2176
Guido van Rossum00d93061998-05-28 23:06:38 +00002177typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002178 PyObject *func;
2179 PyObject *file;
2180 int id;
2181 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002182} FileHandler_ClientData;
2183
2184static FileHandler_ClientData *HeadFHCD;
2185
2186static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002187NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002188{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002189 FileHandler_ClientData *p;
2190 p = PyMem_NEW(FileHandler_ClientData, 1);
2191 if (p != NULL) {
2192 Py_XINCREF(func);
2193 Py_XINCREF(file);
2194 p->func = func;
2195 p->file = file;
2196 p->id = id;
2197 p->next = HeadFHCD;
2198 HeadFHCD = p;
2199 }
2200 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002201}
2202
2203static void
Fred Drake509d79a2000-07-08 04:04:38 +00002204DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002205{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 pp = &HeadFHCD;
2209 while ((p = *pp) != NULL) {
2210 if (p->id == id) {
2211 *pp = p->next;
2212 Py_XDECREF(p->func);
2213 Py_XDECREF(p->file);
2214 PyMem_DEL(p);
2215 }
2216 else
2217 pp = &p->next;
2218 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002219}
2220
Guido van Rossuma597dde1995-01-10 20:56:29 +00002221static void
Fred Drake509d79a2000-07-08 04:04:38 +00002222FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002223{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002224 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2225 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002226
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002227 ENTER_PYTHON
2228 func = data->func;
2229 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 arg = Py_BuildValue("(Oi)", file, (long) mask);
2232 res = PyEval_CallObject(func, arg);
2233 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 if (res == NULL) {
2236 errorInCmd = 1;
2237 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2238 }
2239 Py_XDECREF(res);
2240 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002241}
2242
Guido van Rossum18468821994-06-20 07:49:28 +00002243static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002244Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2245 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002246{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 FileHandler_ClientData *data;
2248 PyObject *file, *func;
2249 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2252 &file, &mask, &func))
2253 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002257 tfile = PyObject_AsFileDescriptor(file);
2258 if (tfile < 0)
2259 return NULL;
2260 if (!PyCallable_Check(func)) {
2261 PyErr_SetString(PyExc_TypeError, "bad argument list");
2262 return NULL;
2263 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 data = NewFHCD(func, file, tfile);
2266 if (data == NULL)
2267 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 /* Ought to check for null Tcl_File object... */
2270 ENTER_TCL
2271 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2272 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002273 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002274}
2275
2276static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002277Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 PyObject *file;
2280 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2283 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002287 tfile = PyObject_AsFileDescriptor(file);
2288 if (tfile < 0)
2289 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002293 /* Ought to check for null Tcl_File object... */
2294 ENTER_TCL
2295 Tcl_DeleteFileHandler(tfile);
2296 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002297 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002298}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002299#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302/**** Tktt Object (timer token) ****/
2303
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002304static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002305
Guido van Rossum00d93061998-05-28 23:06:38 +00002306typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 PyObject_HEAD
2308 Tcl_TimerToken token;
2309 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002310} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002311
2312static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002313Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315 TkttObject *v = (TkttObject *)self;
2316 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002318 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2319 return NULL;
2320 if (v->token != NULL) {
2321 Tcl_DeleteTimerHandler(v->token);
2322 v->token = NULL;
2323 }
2324 if (func != NULL) {
2325 v->func = NULL;
2326 Py_DECREF(func);
2327 Py_DECREF(v); /* See Tktt_New() */
2328 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002329 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330}
2331
2332static PyMethodDef Tktt_methods[] =
2333{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002334 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2335 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002336};
2337
2338static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002339Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002341 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002342
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002343 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002344 if (v == NULL)
2345 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002346 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 Py_INCREF(func);
2349 v->token = NULL;
2350 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 /* Extra reference, deleted when called or when handler is deleted */
2353 Py_INCREF(v);
2354 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355}
2356
2357static void
Fred Drake509d79a2000-07-08 04:04:38 +00002358Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002359{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002360 TkttObject *v = (TkttObject *)self;
2361 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002362 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002367 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368}
2369
Guido van Rossum597ac201998-05-12 14:36:19 +00002370static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002371Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002372{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002374 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2375 v,
2376 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377}
2378
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002379static PyType_Slot Tktt_Type_slots[] = {
2380 {Py_tp_dealloc, Tktt_Dealloc},
2381 {Py_tp_repr, Tktt_Repr},
2382 {Py_tp_methods, Tktt_methods},
2383 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384};
2385
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002386static PyType_Spec Tktt_Type_spec = {
2387 "tktimertoken",
2388 sizeof(TkttObject),
2389 0,
2390 Py_TPFLAGS_DEFAULT,
2391 Tktt_Type_slots,
2392};
Barry Warsawfa701a81997-01-16 00:15:11 +00002393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395/** Timer Handler **/
2396
2397static void
Fred Drake509d79a2000-07-08 04:04:38 +00002398TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 TkttObject *v = (TkttObject *)clientData;
2401 PyObject *func = v->func;
2402 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 if (func == NULL)
2405 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 res = PyEval_CallObject(func, NULL);
2412 Py_DECREF(func);
2413 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 if (res == NULL) {
2416 errorInCmd = 1;
2417 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2418 }
2419 else
2420 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002422 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423}
2424
2425static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002426Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002427{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002428 int milliseconds;
2429 PyObject *func;
2430 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2433 &milliseconds, &func))
2434 return NULL;
2435 if (!PyCallable_Check(func)) {
2436 PyErr_SetString(PyExc_TypeError, "bad argument list");
2437 return NULL;
2438 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002440 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 v = Tktt_New(func);
2443 if (v) {
2444 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2445 (ClientData)v);
2446 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002449}
2450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002451
Guido van Rossum18468821994-06-20 07:49:28 +00002452/** Event Loop **/
2453
Guido van Rossum18468821994-06-20 07:49:28 +00002454static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002455Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002456{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002457 int threshold = 0;
2458 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002459#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002461#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002463 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2464 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002466 CHECK_TCL_APPARTMENT;
2467 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 quitMainLoop = 0;
2470 while (Tk_GetNumMainWindows() > threshold &&
2471 !quitMainLoop &&
2472 !errorInCmd)
2473 {
2474 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002475
2476#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (self->threaded) {
2478 /* Allow other Python threads to run. */
2479 ENTER_TCL
2480 result = Tcl_DoOneEvent(0);
2481 LEAVE_TCL
2482 }
2483 else {
2484 Py_BEGIN_ALLOW_THREADS
2485 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2486 tcl_tstate = tstate;
2487 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2488 tcl_tstate = NULL;
2489 if(tcl_lock)PyThread_release_lock(tcl_lock);
2490 if (result == 0)
2491 Sleep(Tkinter_busywaitinterval);
2492 Py_END_ALLOW_THREADS
2493 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002494#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002495 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002496#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002498 if (PyErr_CheckSignals() != 0) {
2499 self->dispatching = 0;
2500 return NULL;
2501 }
2502 if (result < 0)
2503 break;
2504 }
2505 self->dispatching = 0;
2506 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 if (errorInCmd) {
2509 errorInCmd = 0;
2510 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2511 excInCmd = valInCmd = trbInCmd = NULL;
2512 return NULL;
2513 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002514 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002515}
2516
2517static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002518Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002519{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 int flags = 0;
2521 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002523 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2524 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002525
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002526 ENTER_TCL
2527 rv = Tcl_DoOneEvent(flags);
2528 LEAVE_TCL
2529 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002530}
2531
2532static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002533Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002534{
2535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 if (!PyArg_ParseTuple(args, ":quit"))
2537 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002539 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002540 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002541}
2542
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002543static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002544Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002545{
2546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002547 if (!PyArg_ParseTuple(args, ":interpaddr"))
2548 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002549
Victor Stinnere1040e22013-09-05 00:22:24 +02002550 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002551}
2552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002553static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002554Tkapp_TkInit(PyObject *self, PyObject *args)
2555{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556 Tcl_Interp *interp = Tkapp_Interp(self);
2557 const char * _tk_exists = NULL;
2558 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002559
Guilherme Polob681df42009-02-09 22:33:59 +00002560#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002561 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2562 * first call failed.
2563 * To avoid the deadlock, we just refuse the second call through
2564 * a static variable.
2565 */
2566 if (tk_load_failed) {
2567 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2568 return NULL;
2569 }
Guilherme Polob681df42009-02-09 22:33:59 +00002570#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 /* We want to guard against calling Tk_Init() multiple times */
2573 CHECK_TCL_APPARTMENT;
2574 ENTER_TCL
2575 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2576 ENTER_OVERLAP
2577 if (err == TCL_ERROR) {
2578 /* This sets an exception, but we cannot return right
2579 away because we need to exit the overlap first. */
2580 Tkinter_Error(self);
2581 } else {
2582 _tk_exists = Tkapp_Result(self);
2583 }
2584 LEAVE_OVERLAP_TCL
2585 if (err == TCL_ERROR) {
2586 return NULL;
2587 }
2588 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2589 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002590 PyErr_SetString(Tkinter_TclError,
2591 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002592#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002593 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002594#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002595 return NULL;
2596 }
2597 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002598 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002599}
Barry Warsawfa701a81997-01-16 00:15:11 +00002600
Martin v. Löwisffad6332002-11-26 09:28:05 +00002601static PyObject *
2602Tkapp_WantObjects(PyObject *self, PyObject *args)
2603{
2604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002605 int wantobjects = -1;
2606 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2607 return NULL;
2608 if (wantobjects == -1)
2609 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2610 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002611
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002612 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002613}
2614
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002615static PyObject *
2616Tkapp_WillDispatch(PyObject *self, PyObject *args)
2617{
2618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002620
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002621 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002622}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002624
Guido van Rossum18468821994-06-20 07:49:28 +00002625/**** Tkapp Method List ****/
2626
2627static PyMethodDef Tkapp_methods[] =
2628{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2630 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2631 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2634 {"record", Tkapp_Record, METH_VARARGS},
2635 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2636 {"setvar", Tkapp_SetVar, METH_VARARGS},
2637 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2638 {"getvar", Tkapp_GetVar, METH_VARARGS},
2639 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2640 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2641 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2642 {"getint", Tkapp_GetInt, METH_VARARGS},
2643 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2644 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2645 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2646 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2647 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2648 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2649 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2650 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002651 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2652 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002653#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002654 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2655 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002656#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002657 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2658 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2659 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2660 {"quit", Tkapp_Quit, METH_VARARGS},
2661 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2662 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2663 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002664};
2665
Barry Warsawfa701a81997-01-16 00:15:11 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667
Guido van Rossum18468821994-06-20 07:49:28 +00002668/**** Tkapp Type Methods ****/
2669
2670static void
Fred Drake509d79a2000-07-08 04:04:38 +00002671Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002672{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002673 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 /*CHECK_TCL_APPARTMENT;*/
2675 ENTER_TCL
2676 Tcl_DeleteInterp(Tkapp_Interp(self));
2677 LEAVE_TCL
2678 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002679 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002680 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002681}
2682
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002683static PyType_Slot Tkapp_Type_slots[] = {
2684 {Py_tp_dealloc, Tkapp_Dealloc},
2685 {Py_tp_methods, Tkapp_methods},
2686 {0, 0}
2687};
2688
2689
2690static PyType_Spec Tkapp_Type_spec = {
2691 "tkapp",
2692 sizeof(TkappObject),
2693 0,
2694 Py_TPFLAGS_DEFAULT,
2695 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002696};
2697
Barry Warsawfa701a81997-01-16 00:15:11 +00002698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699
Guido van Rossum18468821994-06-20 07:49:28 +00002700/**** Tkinter Module ****/
2701
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002702typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 PyObject* tuple;
2704 int size; /* current size */
2705 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002706} FlattenContext;
2707
2708static int
2709_bump(FlattenContext* context, int size)
2710{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002711 /* expand tuple to hold (at least) size new items.
2712 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002714 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 if (maxsize < context->size + size)
2717 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002721 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002722}
2723
2724static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002725_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002726{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002729 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002731 if (depth > 1000) {
2732 PyErr_SetString(PyExc_ValueError,
2733 "nesting too deep in _flatten");
2734 return 0;
2735 } else if (PyList_Check(item)) {
2736 size = PyList_GET_SIZE(item);
2737 /* preallocate (assume no nesting) */
2738 if (context->size + size > context->maxsize &&
2739 !_bump(context, size))
2740 return 0;
2741 /* copy items to output tuple */
2742 for (i = 0; i < size; i++) {
2743 PyObject *o = PyList_GET_ITEM(item, i);
2744 if (PyList_Check(o) || PyTuple_Check(o)) {
2745 if (!_flatten1(context, o, depth + 1))
2746 return 0;
2747 } else if (o != Py_None) {
2748 if (context->size + 1 > context->maxsize &&
2749 !_bump(context, 1))
2750 return 0;
2751 Py_INCREF(o);
2752 PyTuple_SET_ITEM(context->tuple,
2753 context->size++, o);
2754 }
2755 }
2756 } else if (PyTuple_Check(item)) {
2757 /* same, for tuples */
2758 size = PyTuple_GET_SIZE(item);
2759 if (context->size + size > context->maxsize &&
2760 !_bump(context, size))
2761 return 0;
2762 for (i = 0; i < size; i++) {
2763 PyObject *o = PyTuple_GET_ITEM(item, i);
2764 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;
2821 int wantobjects = 0;
2822 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}