blob: 83161feec34e8b76807cef1efbb8d8027eb5f9bb [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 */
601 argv0 = (char*)ckalloc(strlen(className) + 1);
602 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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 args = (char*)ckalloc(len);
636 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 }
906 argv = (Tcl_Obj **) ckalloc(((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);
936 outbuf = (Tcl_UniChar*)ckalloc(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 }
1101 objv = (Tcl_Obj **)ckalloc(((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;
1237 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1238 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1239 ev->self = self;
1240 ev->args = args;
1241 ev->res = &res;
1242 ev->exc_type = &exc_type;
1243 ev->exc_value = &exc_value;
1244 ev->exc_tb = &exc_tb;
1245 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001249 if (res == NULL) {
1250 if (exc_type)
1251 PyErr_Restore(exc_type, exc_value, exc_tb);
1252 else
1253 PyErr_SetObject(Tkinter_TclError, exc_value);
1254 }
1255 Tcl_ConditionFinalize(&cond);
1256 }
1257 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001258#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001261 objv = Tkapp_CallArgs(args, objStore, &objc);
1262 if (!objv)
1263 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001267 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 if (i == TCL_ERROR)
1272 Tkinter_Error(selfptr);
1273 else
1274 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001276 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 Tkapp_CallDeallocArgs(objv, objStore, objc);
1279 }
1280 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001281}
1282
1283
1284static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001285Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001286{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 char *script;
1288 PyObject *res = NULL;
1289 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 if (!PyArg_ParseTuple(args, "s:eval", &script))
1292 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001293
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001294 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 ENTER_TCL
1298 err = Tcl_Eval(Tkapp_Interp(self), script);
1299 ENTER_OVERLAP
1300 if (err == TCL_ERROR)
1301 res = Tkinter_Error(self);
1302 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001303 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001304 LEAVE_OVERLAP_TCL
1305 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001306}
1307
1308static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001309Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001310{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 char *fileName;
1312 PyObject *res = NULL;
1313 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1316 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001317
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001318 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 ENTER_TCL
1322 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1323 ENTER_OVERLAP
1324 if (err == TCL_ERROR)
1325 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001327 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 LEAVE_OVERLAP_TCL
1329 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001330}
1331
1332static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001333Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001334{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 char *script;
1336 PyObject *res = NULL;
1337 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001338
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001339 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001341
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001342 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001345 ENTER_TCL
1346 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1347 ENTER_OVERLAP
1348 if (err == TCL_ERROR)
1349 res = Tkinter_Error(self);
1350 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001351 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 LEAVE_OVERLAP_TCL
1353 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001354}
1355
1356static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001357Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001358{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1362 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001363 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 ENTER_TCL
1367 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1368 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001369
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001370 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001371}
1372
Barry Warsawfa701a81997-01-16 00:15:11 +00001373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374
Guido van Rossum18468821994-06-20 07:49:28 +00001375/** Tcl Variable **/
1376
Benjamin Peterson5879d412009-03-30 14:51:56 +00001377typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1378
1379#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001380TCL_DECLARE_MUTEX(var_mutex)
1381
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001382typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 Tcl_Event ev; /* must be first */
1384 PyObject *self;
1385 PyObject *args;
1386 int flags;
1387 EventFunc func;
1388 PyObject **res;
1389 PyObject **exc_type;
1390 PyObject **exc_val;
1391 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001393#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001394
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001395static int
1396varname_converter(PyObject *in, void *_out)
1397{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001398 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001399 char **out = (char**)_out;
1400 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001401 if (PyBytes_Size(in) > INT_MAX) {
1402 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1403 return 0;
1404 }
1405 s = PyBytes_AsString(in);
1406 if (strlen(s) != PyBytes_Size(in)) {
1407 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1408 return 0;
1409 }
1410 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 return 1;
1412 }
1413 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001414 Py_ssize_t size;
1415 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001416 if (s == NULL) {
1417 return 0;
1418 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001419 if (size > INT_MAX) {
1420 PyErr_SetString(PyExc_OverflowError, "string is too long");
1421 return 0;
1422 }
1423 if (strlen(s) != size) {
1424 PyErr_SetString(PyExc_ValueError, "null character in string");
1425 return 0;
1426 }
1427 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001428 return 1;
1429 }
1430 if (PyTclObject_Check(in)) {
1431 *out = PyTclObject_TclString(in);
1432 return 1;
1433 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001434 PyErr_Format(PyExc_TypeError,
1435 "must be str, bytes or Tcl_Obj, not %.50s",
1436 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001437 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001438}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001439
Benjamin Peterson5879d412009-03-30 14:51:56 +00001440#ifdef WITH_THREAD
1441
Martin v. Löwis59683e82008-06-13 07:50:45 +00001442static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001443var_perform(VarEvent *ev)
1444{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1446 if (!*(ev->res)) {
1447 PyObject *exc, *val, *tb;
1448 PyErr_Fetch(&exc, &val, &tb);
1449 PyErr_NormalizeException(&exc, &val, &tb);
1450 *(ev->exc_type) = exc;
1451 *(ev->exc_val) = val;
1452 Py_DECREF(tb);
1453 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001454
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455}
1456
1457static int
1458var_proc(VarEvent* ev, int flags)
1459{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 ENTER_PYTHON
1461 var_perform(ev);
1462 Tcl_MutexLock(&var_mutex);
1463 Tcl_ConditionNotify(ev->cond);
1464 Tcl_MutexUnlock(&var_mutex);
1465 LEAVE_PYTHON
1466 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467}
1468
Benjamin Peterson5879d412009-03-30 14:51:56 +00001469#endif
1470
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001472var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001474#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 TkappObject *self = (TkappObject*)selfptr;
1476 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1477 TkappObject *self = (TkappObject*)selfptr;
1478 VarEvent *ev;
1479 PyObject *res, *exc_type, *exc_val;
1480 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001482 /* The current thread is not the interpreter thread. Marshal
1483 the call to the interpreter thread, then wait for
1484 completion. */
1485 if (!WaitForMainloop(self))
1486 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490 ev->self = selfptr;
1491 ev->args = args;
1492 ev->flags = flags;
1493 ev->func = func;
1494 ev->res = &res;
1495 ev->exc_type = &exc_type;
1496 ev->exc_val = &exc_val;
1497 ev->cond = &cond;
1498 ev->ev.proc = (Tcl_EventProc*)var_proc;
1499 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1500 Tcl_ConditionFinalize(&cond);
1501 if (!res) {
1502 PyErr_SetObject(exc_type, exc_val);
1503 Py_DECREF(exc_type);
1504 Py_DECREF(exc_val);
1505 return NULL;
1506 }
1507 return res;
1508 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001509#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 /* Tcl is not threaded, or this is the interpreter thread. */
1511 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512}
1513
Guido van Rossum18468821994-06-20 07:49:28 +00001514static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001515SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001516{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 char *name1, *name2;
1518 PyObject *newValue;
1519 PyObject *res = NULL;
1520 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001521
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001522 switch (PyTuple_GET_SIZE(args)) {
1523 case 2:
1524 if (!PyArg_ParseTuple(args, "O&O:setvar",
1525 varname_converter, &name1, &newValue))
1526 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001527 /* XXX Acquire tcl lock??? */
1528 newval = AsObj(newValue);
1529 if (newval == NULL)
1530 return NULL;
1531 ENTER_TCL
1532 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1533 newval, flags);
1534 ENTER_OVERLAP
1535 if (!ok)
1536 Tkinter_Error(self);
1537 else {
1538 res = Py_None;
1539 Py_INCREF(res);
1540 }
1541 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001542 break;
1543 case 3:
1544 if (!PyArg_ParseTuple(args, "ssO:setvar",
1545 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001547 CHECK_STRING_LENGTH(name1);
1548 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001549 /* XXX must hold tcl lock already??? */
1550 newval = AsObj(newValue);
1551 ENTER_TCL
1552 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1553 ENTER_OVERLAP
1554 if (!ok)
1555 Tkinter_Error(self);
1556 else {
1557 res = Py_None;
1558 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001559 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001560 LEAVE_OVERLAP_TCL
1561 break;
1562 default:
1563 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1564 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 }
1566 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001567}
1568
1569static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001570Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001571{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001573}
1574
1575static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001576Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001577{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001579}
1580
Barry Warsawfa701a81997-01-16 00:15:11 +00001581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001582
Guido van Rossum18468821994-06-20 07:49:28 +00001583static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001584GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001585{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001586 char *name1, *name2=NULL;
1587 PyObject *res = NULL;
1588 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001590 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1591 varname_converter, &name1, &name2))
1592 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001593
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001594 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001595 ENTER_TCL
1596 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1597 ENTER_OVERLAP
1598 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001599 PyErr_SetString(Tkinter_TclError,
1600 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 } else {
1602 if (((TkappObject*)self)->wantobjects) {
1603 res = FromObj(self, tres);
1604 }
1605 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001606 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 }
1608 }
1609 LEAVE_OVERLAP_TCL
1610 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001611}
1612
1613static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001614Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001615{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001616 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001617}
1618
1619static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001620Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001621{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001623}
1624
Barry Warsawfa701a81997-01-16 00:15:11 +00001625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001626
Guido van Rossum18468821994-06-20 07:49:28 +00001627static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001628UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001629{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 char *name1, *name2=NULL;
1631 int code;
1632 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001634 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1635 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001636
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001637 CHECK_STRING_LENGTH(name1);
1638 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 ENTER_TCL
1640 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1641 ENTER_OVERLAP
1642 if (code == TCL_ERROR)
1643 res = Tkinter_Error(self);
1644 else {
1645 Py_INCREF(Py_None);
1646 res = Py_None;
1647 }
1648 LEAVE_OVERLAP_TCL
1649 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001650}
1651
1652static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001653Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001654{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001655 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001656}
1657
1658static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001659Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001660{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001661 return var_invoke(UnsetVar, self, args,
1662 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001663}
1664
Barry Warsawfa701a81997-01-16 00:15:11 +00001665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666
Guido van Rossum18468821994-06-20 07:49:28 +00001667/** Tcl to Python **/
1668
1669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001671{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 char *s;
1673 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001675 if (PyTuple_Size(args) == 1) {
1676 PyObject* o = PyTuple_GetItem(args, 0);
1677 if (PyLong_Check(o)) {
1678 Py_INCREF(o);
1679 return o;
1680 }
1681 }
1682 if (!PyArg_ParseTuple(args, "s:getint", &s))
1683 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001684 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1686 return Tkinter_Error(self);
1687 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001688}
1689
1690static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001691Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001692{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001693 char *s;
1694 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 if (PyTuple_Size(args) == 1) {
1697 PyObject *o = PyTuple_GetItem(args, 0);
1698 if (PyFloat_Check(o)) {
1699 Py_INCREF(o);
1700 return o;
1701 }
1702 }
1703 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1704 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001705 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001706 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1707 return Tkinter_Error(self);
1708 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
1711static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001712Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001713{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001714 char *s;
1715 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001717 if (PyTuple_Size(args) == 1) {
1718 PyObject *o = PyTuple_GetItem(args, 0);
1719 if (PyLong_Check(o)) {
1720 Py_INCREF(o);
1721 return o;
1722 }
1723 }
1724 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1725 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001726 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1728 return Tkinter_Error(self);
1729 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001730}
1731
1732static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001733Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001734{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001735 char *s;
1736 PyObject *res = NULL;
1737 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1740 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001741
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001742 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 ENTER_TCL
1746 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1747 ENTER_OVERLAP
1748 if (retval == TCL_ERROR)
1749 res = Tkinter_Error(self);
1750 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001751 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001752 LEAVE_OVERLAP_TCL
1753 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001754}
1755
1756static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 char *s;
1760 PyObject *res = NULL;
1761 int retval;
1762 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001763
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001764 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1765 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001766
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001767 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001769
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001770 ENTER_TCL
1771 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1772 ENTER_OVERLAP
1773 if (retval == TCL_ERROR)
1774 res = Tkinter_Error(self);
1775 else
1776 res = Py_BuildValue("l", v);
1777 LEAVE_OVERLAP_TCL
1778 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001779}
1780
1781static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001782Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001783{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001784 char *s;
1785 PyObject *res = NULL;
1786 double v;
1787 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1790 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001791 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001792 CHECK_TCL_APPARTMENT;
1793 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1794 ENTER_TCL
1795 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1796 ENTER_OVERLAP
1797 PyFPE_END_PROTECT(retval)
1798 if (retval == TCL_ERROR)
1799 res = Tkinter_Error(self);
1800 else
1801 res = Py_BuildValue("d", v);
1802 LEAVE_OVERLAP_TCL
1803 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001804}
1805
1806static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001807Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001808{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001809 char *s;
1810 PyObject *res = NULL;
1811 int retval;
1812 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001814 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1815 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001816 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 CHECK_TCL_APPARTMENT;
1818 ENTER_TCL
1819 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1820 ENTER_OVERLAP
1821 if (retval == TCL_ERROR)
1822 res = Tkinter_Error(self);
1823 else
1824 res = Py_BuildValue("i", v);
1825 LEAVE_OVERLAP_TCL
1826 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001827}
1828
Barry Warsawfa701a81997-01-16 00:15:11 +00001829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001830
Guido van Rossum18468821994-06-20 07:49:28 +00001831static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001832Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001833{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 char *list;
1835 int argc;
1836 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001837 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001838 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001839
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001840 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1841 return NULL;
1842 if (PyTclObject_Check(arg)) {
1843 int objc;
1844 Tcl_Obj **objv;
1845 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1846 ((PyTclObject*)arg)->value,
1847 &objc, &objv) == TCL_ERROR) {
1848 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001850 if (!(v = PyTuple_New(objc)))
1851 return NULL;
1852 for (i = 0; i < objc; i++) {
1853 PyObject *s = FromObj(self, objv[i]);
1854 if (!s || PyTuple_SetItem(v, i, s)) {
1855 Py_DECREF(v);
1856 return NULL;
1857 }
1858 }
1859 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001861 if (PyTuple_Check(arg)) {
1862 Py_INCREF(arg);
1863 return arg;
1864 }
1865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001866 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1867 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001868
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001869 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001870 if (Tcl_SplitList(Tkapp_Interp(self), list,
1871 &argc, &argv) == TCL_ERROR) {
1872 PyMem_Free(list);
1873 return Tkinter_Error(self);
1874 }
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 if (!(v = PyTuple_New(argc)))
1877 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001878
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001879 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001880 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881 if (!s || PyTuple_SetItem(v, i, s)) {
1882 Py_DECREF(v);
1883 v = NULL;
1884 goto finally;
1885 }
1886 }
Guido van Rossum18468821994-06-20 07:49:28 +00001887
Barry Warsawfa701a81997-01-16 00:15:11 +00001888 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 ckfree(FREECAST argv);
1890 PyMem_Free(list);
1891 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001892}
1893
1894static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001895Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001896{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001897 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001898 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001899
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001900 if (!PyArg_ParseTuple(args, "O:split", &arg))
1901 return NULL;
1902 if (PyTclObject_Check(arg)) {
1903 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1904 int objc;
1905 Tcl_Obj **objv;
1906 int i;
1907 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1908 &objc, &objv) == TCL_ERROR) {
1909 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001910 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001911 if (objc == 0)
1912 return PyUnicode_FromString("");
1913 if (objc == 1)
1914 return FromObj(self, objv[0]);
1915 if (!(v = PyTuple_New(objc)))
1916 return NULL;
1917 for (i = 0; i < objc; i++) {
1918 PyObject *s = FromObj(self, objv[i]);
1919 if (!s || PyTuple_SetItem(v, i, s)) {
1920 Py_DECREF(v);
1921 return NULL;
1922 }
1923 }
1924 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001926 if (PyTuple_Check(arg))
1927 return SplitObj(arg);
1928
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001929 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1930 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001931 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 v = Split(list);
1933 PyMem_Free(list);
1934 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001935}
1936
Barry Warsawfa701a81997-01-16 00:15:11 +00001937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001938
Guido van Rossum18468821994-06-20 07:49:28 +00001939/** Tcl Command **/
1940
Guido van Rossum00d93061998-05-28 23:06:38 +00001941/* Client data struct */
1942typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001943 PyObject *self;
1944 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001945} PythonCmd_ClientData;
1946
1947static int
Fred Drake509d79a2000-07-08 04:04:38 +00001948PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001949{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001950 errorInCmd = 1;
1951 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1952 LEAVE_PYTHON
1953 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001954}
1955
Guido van Rossum18468821994-06-20 07:49:28 +00001956/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001957 * function or method.
1958 */
Guido van Rossum18468821994-06-20 07:49:28 +00001959static int
Fred Drake509d79a2000-07-08 04:04:38 +00001960PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001961{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001962 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001963 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 int i, rv;
1965 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001966
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001967 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001968
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 /* TBD: no error checking here since we know, via the
1970 * Tkapp_CreateCommand() that the client data is a two-tuple
1971 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001972 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974 /* Create argument list (argv1, ..., argvN) */
1975 if (!(arg = PyTuple_New(argc - 1)))
1976 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001977
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001978 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001979 PyObject *s = unicodeFromTclString(argv[i + 1]);
1980 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 Py_DECREF(arg);
1982 return PythonCmd_Error(interp);
1983 }
1984 }
1985 res = PyEval_CallObject(func, arg);
1986 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001987
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 if (res == NULL)
1989 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001990
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001991 obj_res = AsObj(res);
1992 if (obj_res == NULL) {
1993 Py_DECREF(res);
1994 return PythonCmd_Error(interp);
1995 }
1996 else {
1997 Tcl_SetObjResult(interp, obj_res);
1998 rv = TCL_OK;
1999 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002005 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002006}
2007
2008static void
Fred Drake509d79a2000-07-08 04:04:38 +00002009PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002010{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002011 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002013 ENTER_PYTHON
2014 Py_XDECREF(data->self);
2015 Py_XDECREF(data->func);
2016 PyMem_DEL(data);
2017 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002018}
2019
Barry Warsawfa701a81997-01-16 00:15:11 +00002020
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002021
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002022
Benjamin Peterson5879d412009-03-30 14:51:56 +00002023#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002024TCL_DECLARE_MUTEX(command_mutex)
2025
2026typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 Tcl_Event ev;
2028 Tcl_Interp* interp;
2029 char *name;
2030 int create;
2031 int *status;
2032 ClientData *data;
2033 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002034} CommandEvent;
2035
2036static int
2037Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002038{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 if (ev->create)
2040 *ev->status = Tcl_CreateCommand(
2041 ev->interp, ev->name, PythonCmd,
2042 ev->data, PythonCmdDelete) == NULL;
2043 else
2044 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2045 Tcl_MutexLock(&command_mutex);
2046 Tcl_ConditionNotify(ev->done);
2047 Tcl_MutexUnlock(&command_mutex);
2048 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002049}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002050#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002051
2052static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002053Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002054{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055 TkappObject *self = (TkappObject*)selfptr;
2056 PythonCmd_ClientData *data;
2057 char *cmdName;
2058 PyObject *func;
2059 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2062 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002063 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002064 if (!PyCallable_Check(func)) {
2065 PyErr_SetString(PyExc_TypeError, "command not callable");
2066 return NULL;
2067 }
Guido van Rossum18468821994-06-20 07:49:28 +00002068
Martin v. Löwisa9656492003-03-30 08:44:58 +00002069#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002070 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2071 !WaitForMainloop(self))
2072 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002073#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002074
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002075 data = PyMem_NEW(PythonCmd_ClientData, 1);
2076 if (!data)
2077 return PyErr_NoMemory();
2078 Py_INCREF(self);
2079 Py_INCREF(func);
2080 data->self = selfptr;
2081 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002082#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002083 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2084 Tcl_Condition cond = NULL;
2085 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2086 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2087 ev->interp = self->interp;
2088 ev->create = 1;
2089 ev->name = cmdName;
2090 ev->data = (ClientData)data;
2091 ev->status = &err;
2092 ev->done = &cond;
2093 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2094 Tcl_ConditionFinalize(&cond);
2095 }
2096 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002097#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002098 {
2099 ENTER_TCL
2100 err = Tcl_CreateCommand(
2101 Tkapp_Interp(self), cmdName, PythonCmd,
2102 (ClientData)data, PythonCmdDelete) == NULL;
2103 LEAVE_TCL
2104 }
2105 if (err) {
2106 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2107 PyMem_DEL(data);
2108 return NULL;
2109 }
Guido van Rossum18468821994-06-20 07:49:28 +00002110
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002111 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002112}
2113
Barry Warsawfa701a81997-01-16 00:15:11 +00002114
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115
Guido van Rossum18468821994-06-20 07:49:28 +00002116static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002117Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002118{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 TkappObject *self = (TkappObject*)selfptr;
2120 char *cmdName;
2121 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2124 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002125 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002126
2127#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002128 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2129 Tcl_Condition cond = NULL;
2130 CommandEvent *ev;
2131 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2132 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2133 ev->interp = self->interp;
2134 ev->create = 0;
2135 ev->name = cmdName;
2136 ev->status = &err;
2137 ev->done = &cond;
2138 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2139 &command_mutex);
2140 Tcl_ConditionFinalize(&cond);
2141 }
2142 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002143#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002144 {
2145 ENTER_TCL
2146 err = Tcl_DeleteCommand(self->interp, cmdName);
2147 LEAVE_TCL
2148 }
2149 if (err == -1) {
2150 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2151 return NULL;
2152 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002153 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002154}
2155
Barry Warsawfa701a81997-01-16 00:15:11 +00002156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002157
Guido van Rossum00d93061998-05-28 23:06:38 +00002158#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002159/** File Handler **/
2160
Guido van Rossum00d93061998-05-28 23:06:38 +00002161typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002162 PyObject *func;
2163 PyObject *file;
2164 int id;
2165 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002166} FileHandler_ClientData;
2167
2168static FileHandler_ClientData *HeadFHCD;
2169
2170static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002171NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173 FileHandler_ClientData *p;
2174 p = PyMem_NEW(FileHandler_ClientData, 1);
2175 if (p != NULL) {
2176 Py_XINCREF(func);
2177 Py_XINCREF(file);
2178 p->func = func;
2179 p->file = file;
2180 p->id = id;
2181 p->next = HeadFHCD;
2182 HeadFHCD = p;
2183 }
2184 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002185}
2186
2187static void
Fred Drake509d79a2000-07-08 04:04:38 +00002188DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002189{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 pp = &HeadFHCD;
2193 while ((p = *pp) != NULL) {
2194 if (p->id == id) {
2195 *pp = p->next;
2196 Py_XDECREF(p->func);
2197 Py_XDECREF(p->file);
2198 PyMem_DEL(p);
2199 }
2200 else
2201 pp = &p->next;
2202 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002203}
2204
Guido van Rossuma597dde1995-01-10 20:56:29 +00002205static void
Fred Drake509d79a2000-07-08 04:04:38 +00002206FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002207{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2209 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002211 ENTER_PYTHON
2212 func = data->func;
2213 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002215 arg = Py_BuildValue("(Oi)", file, (long) mask);
2216 res = PyEval_CallObject(func, arg);
2217 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002219 if (res == NULL) {
2220 errorInCmd = 1;
2221 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2222 }
2223 Py_XDECREF(res);
2224 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002225}
2226
Guido van Rossum18468821994-06-20 07:49:28 +00002227static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002228Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2229 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002230{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 FileHandler_ClientData *data;
2232 PyObject *file, *func;
2233 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002235 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2236 &file, &mask, &func))
2237 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002241 tfile = PyObject_AsFileDescriptor(file);
2242 if (tfile < 0)
2243 return NULL;
2244 if (!PyCallable_Check(func)) {
2245 PyErr_SetString(PyExc_TypeError, "bad argument list");
2246 return NULL;
2247 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002249 data = NewFHCD(func, file, tfile);
2250 if (data == NULL)
2251 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002253 /* Ought to check for null Tcl_File object... */
2254 ENTER_TCL
2255 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2256 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002257 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002258}
2259
2260static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002261Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002262{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002263 PyObject *file;
2264 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002266 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2267 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 tfile = PyObject_AsFileDescriptor(file);
2272 if (tfile < 0)
2273 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 /* Ought to check for null Tcl_File object... */
2278 ENTER_TCL
2279 Tcl_DeleteFileHandler(tfile);
2280 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002281 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002282}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002283#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002285
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002286/**** Tktt Object (timer token) ****/
2287
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002288static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002289
Guido van Rossum00d93061998-05-28 23:06:38 +00002290typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 PyObject_HEAD
2292 Tcl_TimerToken token;
2293 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002294} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002295
2296static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002297Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002298{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 TkttObject *v = (TkttObject *)self;
2300 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002302 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2303 return NULL;
2304 if (v->token != NULL) {
2305 Tcl_DeleteTimerHandler(v->token);
2306 v->token = NULL;
2307 }
2308 if (func != NULL) {
2309 v->func = NULL;
2310 Py_DECREF(func);
2311 Py_DECREF(v); /* See Tktt_New() */
2312 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002313 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002314}
2315
2316static PyMethodDef Tktt_methods[] =
2317{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002318 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2319 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320};
2321
2322static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002323Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002325 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002326
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002327 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 if (v == NULL)
2329 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002330 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 Py_INCREF(func);
2333 v->token = NULL;
2334 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 /* Extra reference, deleted when called or when handler is deleted */
2337 Py_INCREF(v);
2338 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339}
2340
2341static void
Fred Drake509d79a2000-07-08 04:04:38 +00002342Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002344 TkttObject *v = (TkttObject *)self;
2345 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002346 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002351 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002352}
2353
Guido van Rossum597ac201998-05-12 14:36:19 +00002354static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002355Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002358 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2359 v,
2360 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002361}
2362
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002363static PyType_Slot Tktt_Type_slots[] = {
2364 {Py_tp_dealloc, Tktt_Dealloc},
2365 {Py_tp_repr, Tktt_Repr},
2366 {Py_tp_methods, Tktt_methods},
2367 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368};
2369
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002370static PyType_Spec Tktt_Type_spec = {
2371 "tktimertoken",
2372 sizeof(TkttObject),
2373 0,
2374 Py_TPFLAGS_DEFAULT,
2375 Tktt_Type_slots,
2376};
Barry Warsawfa701a81997-01-16 00:15:11 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002379/** Timer Handler **/
2380
2381static void
Fred Drake509d79a2000-07-08 04:04:38 +00002382TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 TkttObject *v = (TkttObject *)clientData;
2385 PyObject *func = v->func;
2386 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 if (func == NULL)
2389 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002391 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002393 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 res = PyEval_CallObject(func, NULL);
2396 Py_DECREF(func);
2397 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002399 if (res == NULL) {
2400 errorInCmd = 1;
2401 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2402 }
2403 else
2404 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002407}
2408
2409static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002410Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002411{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 int milliseconds;
2413 PyObject *func;
2414 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002416 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2417 &milliseconds, &func))
2418 return NULL;
2419 if (!PyCallable_Check(func)) {
2420 PyErr_SetString(PyExc_TypeError, "bad argument list");
2421 return NULL;
2422 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 v = Tktt_New(func);
2427 if (v) {
2428 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2429 (ClientData)v);
2430 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002433}
2434
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002435
Guido van Rossum18468821994-06-20 07:49:28 +00002436/** Event Loop **/
2437
Guido van Rossum18468821994-06-20 07:49:28 +00002438static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002439Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002440{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002441 int threshold = 0;
2442 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002443#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002444 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002445#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2448 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 CHECK_TCL_APPARTMENT;
2451 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 quitMainLoop = 0;
2454 while (Tk_GetNumMainWindows() > threshold &&
2455 !quitMainLoop &&
2456 !errorInCmd)
2457 {
2458 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002459
2460#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 if (self->threaded) {
2462 /* Allow other Python threads to run. */
2463 ENTER_TCL
2464 result = Tcl_DoOneEvent(0);
2465 LEAVE_TCL
2466 }
2467 else {
2468 Py_BEGIN_ALLOW_THREADS
2469 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2470 tcl_tstate = tstate;
2471 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2472 tcl_tstate = NULL;
2473 if(tcl_lock)PyThread_release_lock(tcl_lock);
2474 if (result == 0)
2475 Sleep(Tkinter_busywaitinterval);
2476 Py_END_ALLOW_THREADS
2477 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002478#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002479 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002480#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 if (PyErr_CheckSignals() != 0) {
2483 self->dispatching = 0;
2484 return NULL;
2485 }
2486 if (result < 0)
2487 break;
2488 }
2489 self->dispatching = 0;
2490 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 if (errorInCmd) {
2493 errorInCmd = 0;
2494 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2495 excInCmd = valInCmd = trbInCmd = NULL;
2496 return NULL;
2497 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002498 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002499}
2500
2501static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002502Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002503{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 int flags = 0;
2505 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002506
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002507 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2508 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 ENTER_TCL
2511 rv = Tcl_DoOneEvent(flags);
2512 LEAVE_TCL
2513 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002514}
2515
2516static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002517Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002518{
2519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 if (!PyArg_ParseTuple(args, ":quit"))
2521 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002523 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002524 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002525}
2526
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002527static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002528Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002529{
2530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 if (!PyArg_ParseTuple(args, ":interpaddr"))
2532 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002533
Victor Stinnere1040e22013-09-05 00:22:24 +02002534 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002535}
2536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002538Tkapp_TkInit(PyObject *self, PyObject *args)
2539{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002540 Tcl_Interp *interp = Tkapp_Interp(self);
2541 const char * _tk_exists = NULL;
2542 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002543
Guilherme Polob681df42009-02-09 22:33:59 +00002544#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002545 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2546 * first call failed.
2547 * To avoid the deadlock, we just refuse the second call through
2548 * a static variable.
2549 */
2550 if (tk_load_failed) {
2551 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2552 return NULL;
2553 }
Guilherme Polob681df42009-02-09 22:33:59 +00002554#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556 /* We want to guard against calling Tk_Init() multiple times */
2557 CHECK_TCL_APPARTMENT;
2558 ENTER_TCL
2559 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2560 ENTER_OVERLAP
2561 if (err == TCL_ERROR) {
2562 /* This sets an exception, but we cannot return right
2563 away because we need to exit the overlap first. */
2564 Tkinter_Error(self);
2565 } else {
2566 _tk_exists = Tkapp_Result(self);
2567 }
2568 LEAVE_OVERLAP_TCL
2569 if (err == TCL_ERROR) {
2570 return NULL;
2571 }
2572 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2573 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002574 PyErr_SetString(Tkinter_TclError,
2575 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002576#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002578#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 return NULL;
2580 }
2581 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002582 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002583}
Barry Warsawfa701a81997-01-16 00:15:11 +00002584
Martin v. Löwisffad6332002-11-26 09:28:05 +00002585static PyObject *
2586Tkapp_WantObjects(PyObject *self, PyObject *args)
2587{
2588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 int wantobjects = -1;
2590 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2591 return NULL;
2592 if (wantobjects == -1)
2593 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2594 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002595
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002596 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002597}
2598
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002599static PyObject *
2600Tkapp_WillDispatch(PyObject *self, PyObject *args)
2601{
2602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002603 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002604
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002605 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002606}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002608
Guido van Rossum18468821994-06-20 07:49:28 +00002609/**** Tkapp Method List ****/
2610
2611static PyMethodDef Tkapp_methods[] =
2612{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2614 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2615 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002616 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2618 {"record", Tkapp_Record, METH_VARARGS},
2619 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2620 {"setvar", Tkapp_SetVar, METH_VARARGS},
2621 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2622 {"getvar", Tkapp_GetVar, METH_VARARGS},
2623 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2624 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2625 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2626 {"getint", Tkapp_GetInt, METH_VARARGS},
2627 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2628 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2629 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2630 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2631 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2632 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2633 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2634 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2636 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002637#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002638 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2639 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002640#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002641 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2642 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2643 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2644 {"quit", Tkapp_Quit, METH_VARARGS},
2645 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2646 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2647 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002648};
2649
Barry Warsawfa701a81997-01-16 00:15:11 +00002650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002651
Guido van Rossum18468821994-06-20 07:49:28 +00002652/**** Tkapp Type Methods ****/
2653
2654static void
Fred Drake509d79a2000-07-08 04:04:38 +00002655Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002656{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002657 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 /*CHECK_TCL_APPARTMENT;*/
2659 ENTER_TCL
2660 Tcl_DeleteInterp(Tkapp_Interp(self));
2661 LEAVE_TCL
2662 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002663 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002664 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002665}
2666
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002667static PyType_Slot Tkapp_Type_slots[] = {
2668 {Py_tp_dealloc, Tkapp_Dealloc},
2669 {Py_tp_methods, Tkapp_methods},
2670 {0, 0}
2671};
2672
2673
2674static PyType_Spec Tkapp_Type_spec = {
2675 "tkapp",
2676 sizeof(TkappObject),
2677 0,
2678 Py_TPFLAGS_DEFAULT,
2679 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002680};
2681
Barry Warsawfa701a81997-01-16 00:15:11 +00002682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002683
Guido van Rossum18468821994-06-20 07:49:28 +00002684/**** Tkinter Module ****/
2685
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002686typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687 PyObject* tuple;
2688 int size; /* current size */
2689 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002690} FlattenContext;
2691
2692static int
2693_bump(FlattenContext* context, int size)
2694{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 /* expand tuple to hold (at least) size new items.
2696 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 if (maxsize < context->size + size)
2701 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002702
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002705 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002706}
2707
2708static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002709_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002710{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002711 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002715 if (depth > 1000) {
2716 PyErr_SetString(PyExc_ValueError,
2717 "nesting too deep in _flatten");
2718 return 0;
2719 } else if (PyList_Check(item)) {
2720 size = PyList_GET_SIZE(item);
2721 /* preallocate (assume no nesting) */
2722 if (context->size + size > context->maxsize &&
2723 !_bump(context, size))
2724 return 0;
2725 /* copy items to output tuple */
2726 for (i = 0; i < size; i++) {
2727 PyObject *o = PyList_GET_ITEM(item, i);
2728 if (PyList_Check(o) || PyTuple_Check(o)) {
2729 if (!_flatten1(context, o, depth + 1))
2730 return 0;
2731 } else if (o != Py_None) {
2732 if (context->size + 1 > context->maxsize &&
2733 !_bump(context, 1))
2734 return 0;
2735 Py_INCREF(o);
2736 PyTuple_SET_ITEM(context->tuple,
2737 context->size++, o);
2738 }
2739 }
2740 } else if (PyTuple_Check(item)) {
2741 /* same, for tuples */
2742 size = PyTuple_GET_SIZE(item);
2743 if (context->size + size > context->maxsize &&
2744 !_bump(context, size))
2745 return 0;
2746 for (i = 0; i < size; i++) {
2747 PyObject *o = PyTuple_GET_ITEM(item, i);
2748 if (PyList_Check(o) || PyTuple_Check(o)) {
2749 if (!_flatten1(context, o, depth + 1))
2750 return 0;
2751 } else if (o != Py_None) {
2752 if (context->size + 1 > context->maxsize &&
2753 !_bump(context, 1))
2754 return 0;
2755 Py_INCREF(o);
2756 PyTuple_SET_ITEM(context->tuple,
2757 context->size++, o);
2758 }
2759 }
2760 } else {
2761 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2762 return 0;
2763 }
2764 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002765}
2766
2767static PyObject *
2768Tkinter_Flatten(PyObject* self, PyObject* args)
2769{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002770 FlattenContext context;
2771 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002773 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2774 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 context.maxsize = PySequence_Size(item);
2777 if (context.maxsize < 0)
2778 return NULL;
2779 if (context.maxsize == 0)
2780 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002782 context.tuple = PyTuple_New(context.maxsize);
2783 if (!context.tuple)
2784 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 if (!_flatten1(&context, item,0))
2789 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 if (_PyTuple_Resize(&context.tuple, context.size))
2792 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002795}
2796
Guido van Rossum18468821994-06-20 07:49:28 +00002797static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002798Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002799{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002800 char *screenName = NULL;
2801 char *baseName = NULL; /* XXX this is not used anymore;
2802 try getting rid of it. */
2803 char *className = NULL;
2804 int interactive = 0;
2805 int wantobjects = 0;
2806 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2807 int sync = 0; /* pass -sync to wish */
2808 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2813 &screenName, &baseName, &className,
2814 &interactive, &wantobjects, &wantTk,
2815 &sync, &use))
2816 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002817 CHECK_STRING_LENGTH(screenName);
2818 CHECK_STRING_LENGTH(baseName);
2819 CHECK_STRING_LENGTH(className);
2820 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00002821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002823 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002824 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002825}
2826
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002827static PyObject *
2828Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2829{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002830 int new_val;
2831 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2832 return NULL;
2833 if (new_val < 0) {
2834 PyErr_SetString(PyExc_ValueError,
2835 "busywaitinterval must be >= 0");
2836 return NULL;
2837 }
2838 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002839 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002840}
2841
2842static char setbusywaitinterval_doc[] =
2843"setbusywaitinterval(n) -> None\n\
2844\n\
2845Set the busy-wait interval in milliseconds between successive\n\
2846calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2847It should be set to a divisor of the maximum time between\n\
2848frames in an animation.";
2849
2850static PyObject *
2851Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2852{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002853 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002854}
2855
2856static char getbusywaitinterval_doc[] =
2857"getbusywaitinterval() -> int\n\
2858\n\
2859Return the current busy-wait interval between successive\n\
2860calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2861
Guido van Rossum18468821994-06-20 07:49:28 +00002862static PyMethodDef moduleMethods[] =
2863{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2865 {"create", Tkinter_Create, METH_VARARGS},
2866 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2867 setbusywaitinterval_doc},
2868 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2869 METH_NOARGS, getbusywaitinterval_doc},
2870 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002871};
2872
Guido van Rossum7bf15641998-05-22 18:28:17 +00002873#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002874
2875static int stdin_ready = 0;
2876
Guido van Rossumad4db171998-06-13 13:56:28 +00002877#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002878static void
Fred Drake509d79a2000-07-08 04:04:38 +00002879MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002880{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002881 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002882}
Guido van Rossumad4db171998-06-13 13:56:28 +00002883#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002884
Martin v. Löwisa9656492003-03-30 08:44:58 +00002885#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002886static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002887#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002888
Guido van Rossum18468821994-06-20 07:49:28 +00002889static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002890EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002891{
Guido van Rossumad4db171998-06-13 13:56:28 +00002892#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002893 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002894#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002895#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002896 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002897#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 stdin_ready = 0;
2899 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002900#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901 tfile = fileno(stdin);
2902 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002903#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002904 while (!errorInCmd && !stdin_ready) {
2905 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002906#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002907 if (_kbhit()) {
2908 stdin_ready = 1;
2909 break;
2910 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002911#endif
2912#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002913 Py_BEGIN_ALLOW_THREADS
2914 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2915 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002916
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002918
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002919 tcl_tstate = NULL;
2920 if(tcl_lock)PyThread_release_lock(tcl_lock);
2921 if (result == 0)
2922 Sleep(Tkinter_busywaitinterval);
2923 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002924#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002925 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002926#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002927
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002928 if (result < 0)
2929 break;
2930 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002931#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002933#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002934 if (errorInCmd) {
2935 errorInCmd = 0;
2936 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2937 excInCmd = valInCmd = trbInCmd = NULL;
2938 PyErr_Print();
2939 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002940#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002941 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002942#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002943 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002944}
Guido van Rossum18468821994-06-20 07:49:28 +00002945
Guido van Rossum00d93061998-05-28 23:06:38 +00002946#endif
2947
Guido van Rossum7bf15641998-05-22 18:28:17 +00002948static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002949EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002950{
Guido van Rossum00d93061998-05-28 23:06:38 +00002951#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002952 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002953#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002954 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002955#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002956 PyOS_InputHook = EventHook;
2957 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002958#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002959}
2960
2961static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002962DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002963{
Guido van Rossum00d93061998-05-28 23:06:38 +00002964#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002965 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2966 PyOS_InputHook = NULL;
2967 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002968#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002969}
2970
Barry Warsawfa701a81997-01-16 00:15:11 +00002971
Martin v. Löwis1a214512008-06-11 05:26:20 +00002972static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 PyModuleDef_HEAD_INIT,
2974 "_tkinter",
2975 NULL,
2976 -1,
2977 moduleMethods,
2978 NULL,
2979 NULL,
2980 NULL,
2981 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002982};
2983
Mark Hammond62b1ab12002-07-23 06:31:15 +00002984PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002985PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002986{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002987 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002988
Guido van Rossum00d93061998-05-28 23:06:38 +00002989#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002990 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002991 if (tcl_lock == NULL)
2992 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002993#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 m = PyModule_Create(&_tkintermodule);
2996 if (m == NULL)
2997 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002998
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002999 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3000 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003001 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003002 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003003 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003004 Py_INCREF(o);
3005 if (PyModule_AddObject(m, "TclError", o)) {
3006 Py_DECREF(o);
3007 Py_DECREF(m);
3008 return NULL;
3009 }
3010 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003011
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003012 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3013 Py_DECREF(m);
3014 return NULL;
3015 }
3016 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3017 Py_DECREF(m);
3018 return NULL;
3019 }
3020 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3021 Py_DECREF(m);
3022 return NULL;
3023 }
3024 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3025 Py_DECREF(m);
3026 return NULL;
3027 }
3028 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3029 Py_DECREF(m);
3030 return NULL;
3031 }
3032 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3033 Py_DECREF(m);
3034 return NULL;
3035 }
3036 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3037 Py_DECREF(m);
3038 return NULL;
3039 }
3040 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3041 Py_DECREF(m);
3042 return NULL;
3043 }
3044 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3045 Py_DECREF(m);
3046 return NULL;
3047 }
3048 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3049 Py_DECREF(m);
3050 return NULL;
3051 }
3052 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3053 Py_DECREF(m);
3054 return NULL;
3055 }
3056
3057 o = PyType_FromSpec(&Tkapp_Type_spec);
3058 if (o == NULL) {
3059 Py_DECREF(m);
3060 return NULL;
3061 }
3062 if (PyModule_AddObject(m, "TkappType", o)) {
3063 Py_DECREF(o);
3064 Py_DECREF(m);
3065 return NULL;
3066 }
3067 Tkapp_Type = o;
3068
3069 o = PyType_FromSpec(&Tktt_Type_spec);
3070 if (o == NULL) {
3071 Py_DECREF(m);
3072 return NULL;
3073 }
3074 if (PyModule_AddObject(m, "TkttType", o)) {
3075 Py_DECREF(o);
3076 Py_DECREF(m);
3077 return NULL;
3078 }
3079 Tktt_Type = o;
3080
3081 o = PyType_FromSpec(&PyTclObject_Type_spec);
3082 if (o == NULL) {
3083 Py_DECREF(m);
3084 return NULL;
3085 }
3086 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3087 Py_DECREF(o);
3088 Py_DECREF(m);
3089 return NULL;
3090 }
3091 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003092
3093#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003094 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3095 * start waking up. Note that Tcl_FindExecutable will do this, this
3096 * code must be above it! The original warning from
3097 * tkMacOSXAppInit.c is copied below.
3098 *
3099 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3100 * Tcl interpreter for now. It probably should work to do this
3101 * in the other order, but for now it doesn't seem to.
3102 *
3103 */
3104 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003105#endif
3106
3107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003108 /* This helps the dynamic loader; in Unicode aware Tcl versions
3109 it also helps Tcl find its encodings. */
3110 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3111 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003112 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003113 if (cexe)
3114 Tcl_FindExecutable(PyBytes_AsString(cexe));
3115 Py_XDECREF(cexe);
3116 Py_DECREF(uexe);
3117 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003119 if (PyErr_Occurred()) {
3120 Py_DECREF(m);
3121 return NULL;
3122 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003123
Guido van Rossum43ff8681998-07-14 18:02:13 +00003124#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003125 /* This was not a good idea; through <Destroy> bindings,
3126 Tcl_Finalize() may invoke Python code but at that point the
3127 interpreter and thread state have already been destroyed! */
3128 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003129#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003131}